Compare commits
2 commits
9cb6ff6ed7
...
a73afacf6c
Author | SHA1 | Date | |
---|---|---|---|
a73afacf6c | |||
0dca43eb19 |
41 changed files with 3864 additions and 4890 deletions
5
.astro/settings.json
Normal file
5
.astro/settings.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"_variables": {
|
||||
"lastUpdateCheck": 1721418667135
|
||||
}
|
||||
}
|
199
.astro/types.d.ts
vendored
Normal file
199
.astro/types.d.ts
vendored
Normal file
|
@ -0,0 +1,199 @@
|
|||
declare module 'astro:content' {
|
||||
interface Render {
|
||||
'.mdx': Promise<{
|
||||
Content: import('astro').MarkdownInstance<{}>['Content'];
|
||||
headings: import('astro').MarkdownHeading[];
|
||||
remarkPluginFrontmatter: Record<string, any>;
|
||||
}>;
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'astro:content' {
|
||||
interface Render {
|
||||
'.md': Promise<{
|
||||
Content: import('astro').MarkdownInstance<{}>['Content'];
|
||||
headings: import('astro').MarkdownHeading[];
|
||||
remarkPluginFrontmatter: Record<string, any>;
|
||||
}>;
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'astro:content' {
|
||||
type Flatten<T> = T extends { [K: string]: infer U } ? U : never;
|
||||
|
||||
export type CollectionKey = keyof AnyEntryMap;
|
||||
export type CollectionEntry<C extends CollectionKey> = Flatten<AnyEntryMap[C]>;
|
||||
|
||||
export type ContentCollectionKey = keyof ContentEntryMap;
|
||||
export type DataCollectionKey = keyof DataEntryMap;
|
||||
|
||||
type AllValuesOf<T> = T extends any ? T[keyof T] : never;
|
||||
type ValidContentEntrySlug<C extends keyof ContentEntryMap> = AllValuesOf<
|
||||
ContentEntryMap[C]
|
||||
>['slug'];
|
||||
|
||||
export function getEntryBySlug<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}),
|
||||
>(
|
||||
collection: C,
|
||||
// Note that this has to accept a regular string too, for SSR
|
||||
entrySlug: E
|
||||
): E extends ValidContentEntrySlug<C>
|
||||
? Promise<CollectionEntry<C>>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
|
||||
export function getDataEntryById<C extends keyof DataEntryMap, E extends keyof DataEntryMap[C]>(
|
||||
collection: C,
|
||||
entryId: E
|
||||
): Promise<CollectionEntry<C>>;
|
||||
|
||||
export function getCollection<C extends keyof AnyEntryMap, E extends CollectionEntry<C>>(
|
||||
collection: C,
|
||||
filter?: (entry: CollectionEntry<C>) => entry is E
|
||||
): Promise<E[]>;
|
||||
export function getCollection<C extends keyof AnyEntryMap>(
|
||||
collection: C,
|
||||
filter?: (entry: CollectionEntry<C>) => unknown
|
||||
): Promise<CollectionEntry<C>[]>;
|
||||
|
||||
export function getEntry<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}),
|
||||
>(entry: {
|
||||
collection: C;
|
||||
slug: E;
|
||||
}): E extends ValidContentEntrySlug<C>
|
||||
? Promise<CollectionEntry<C>>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getEntry<
|
||||
C extends keyof DataEntryMap,
|
||||
E extends keyof DataEntryMap[C] | (string & {}),
|
||||
>(entry: {
|
||||
collection: C;
|
||||
id: E;
|
||||
}): E extends keyof DataEntryMap[C]
|
||||
? Promise<DataEntryMap[C][E]>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getEntry<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}),
|
||||
>(
|
||||
collection: C,
|
||||
slug: E
|
||||
): E extends ValidContentEntrySlug<C>
|
||||
? Promise<CollectionEntry<C>>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getEntry<
|
||||
C extends keyof DataEntryMap,
|
||||
E extends keyof DataEntryMap[C] | (string & {}),
|
||||
>(
|
||||
collection: C,
|
||||
id: E
|
||||
): E extends keyof DataEntryMap[C]
|
||||
? Promise<DataEntryMap[C][E]>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
|
||||
/** Resolve an array of entry references from the same collection */
|
||||
export function getEntries<C extends keyof ContentEntryMap>(
|
||||
entries: {
|
||||
collection: C;
|
||||
slug: ValidContentEntrySlug<C>;
|
||||
}[]
|
||||
): Promise<CollectionEntry<C>[]>;
|
||||
export function getEntries<C extends keyof DataEntryMap>(
|
||||
entries: {
|
||||
collection: C;
|
||||
id: keyof DataEntryMap[C];
|
||||
}[]
|
||||
): Promise<CollectionEntry<C>[]>;
|
||||
|
||||
export function reference<C extends keyof AnyEntryMap>(
|
||||
collection: C
|
||||
): import('astro/zod').ZodEffects<
|
||||
import('astro/zod').ZodString,
|
||||
C extends keyof ContentEntryMap
|
||||
? {
|
||||
collection: C;
|
||||
slug: ValidContentEntrySlug<C>;
|
||||
}
|
||||
: {
|
||||
collection: C;
|
||||
id: keyof DataEntryMap[C];
|
||||
}
|
||||
>;
|
||||
// Allow generic `string` to avoid excessive type errors in the config
|
||||
// if `dev` is not running to update as you edit.
|
||||
// Invalid collection names will be caught at build time.
|
||||
export function reference<C extends string>(
|
||||
collection: C
|
||||
): import('astro/zod').ZodEffects<import('astro/zod').ZodString, never>;
|
||||
|
||||
type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
|
||||
type InferEntrySchema<C extends keyof AnyEntryMap> = import('astro/zod').infer<
|
||||
ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
|
||||
>;
|
||||
|
||||
type ContentEntryMap = {
|
||||
"blog": {
|
||||
"astro-usage.md": {
|
||||
id: "astro-usage.md";
|
||||
slug: "astro-usage";
|
||||
body: string;
|
||||
collection: "blog";
|
||||
data: InferEntrySchema<"blog">
|
||||
} & { render(): Render[".md"] };
|
||||
"cernunnos-with-requiem.mdx": {
|
||||
id: "cernunnos-with-requiem.mdx";
|
||||
slug: "cernunnos-with-requiem";
|
||||
body: string;
|
||||
collection: "blog";
|
||||
data: InferEntrySchema<"blog">
|
||||
} & { render(): Render[".mdx"] };
|
||||
"deploying-this-round-2.md": {
|
||||
id: "deploying-this-round-2.md";
|
||||
slug: "deploying-this-round-2";
|
||||
body: string;
|
||||
collection: "blog";
|
||||
data: InferEntrySchema<"blog">
|
||||
} & { render(): Render[".md"] };
|
||||
"deploying-this.md": {
|
||||
id: "deploying-this.md";
|
||||
slug: "deploying-this";
|
||||
body: string;
|
||||
collection: "blog";
|
||||
data: InferEntrySchema<"blog">
|
||||
} & { render(): Render[".md"] };
|
||||
"fgo-ta.md": {
|
||||
id: "fgo-ta.md";
|
||||
slug: "fgo-ta";
|
||||
body: string;
|
||||
collection: "blog";
|
||||
data: InferEntrySchema<"blog">
|
||||
} & { render(): Render[".md"] };
|
||||
"hello-world.md": {
|
||||
id: "hello-world.md";
|
||||
slug: "hello-world";
|
||||
body: string;
|
||||
collection: "blog";
|
||||
data: InferEntrySchema<"blog">
|
||||
} & { render(): Render[".md"] };
|
||||
"instant-death.mdx": {
|
||||
id: "instant-death.mdx";
|
||||
slug: "instant-death";
|
||||
body: string;
|
||||
collection: "blog";
|
||||
data: InferEntrySchema<"blog">
|
||||
} & { render(): Render[".mdx"] };
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
type DataEntryMap = {
|
||||
|
||||
};
|
||||
|
||||
type AnyEntryMap = ContentEntryMap & DataEntryMap;
|
||||
|
||||
export type ContentConfig = typeof import("./../src/content/config.js");
|
||||
}
|
|
@ -4,14 +4,30 @@ on:
|
|||
- '[0-9]+\.[0-9]+\.[0-9]+-pre\.[0-9]+'
|
||||
|
||||
jobs:
|
||||
checking:
|
||||
check-tag:
|
||||
runs-on: docker
|
||||
container: node:lts
|
||||
steps:
|
||||
- name: Checking Out Repository Code
|
||||
uses: https://code.forgejo.org/actions/checkout@v3
|
||||
- name: Check if Version in package.json matches Tag
|
||||
run: |
|
||||
VERSION=$(cat package.json | grep "version" | sed 's/.*://' | tr -d , | tr -d \" | tr -d " " )
|
||||
if test $VERSION != "${{ github.ref_name }}"; then
|
||||
echo "Expected Version is: '${{ github.ref_name }}' actual Version is: '$VERSION'";
|
||||
exit 1
|
||||
else
|
||||
echo "Version is: '$VERSION'";
|
||||
fi
|
||||
|
||||
checking:
|
||||
needs: [ check-tag ]
|
||||
runs-on: docker
|
||||
container: forgejo.neshweb.net/ci-docker-images/node-alpine-git:latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: https://code.forgejo.org/actions/checkout@v3
|
||||
- name: Install packages
|
||||
run: npm install
|
||||
run: npm i
|
||||
- name: Run astro check (linting + static analysis)
|
||||
run: npm run astro check
|
||||
|
||||
|
@ -22,19 +38,19 @@ jobs:
|
|||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
- name: Log into Docker Package Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: forgejo.neshweb.net
|
||||
username: ${{ secrets.FORGEJO_USERNAME }}
|
||||
password: ${{ secrets.FORGEJO_TOKEN }}
|
||||
- name: Push to Package Registry
|
||||
- name: Build and push to Docker Package Registry
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
tags: forgejo.neshweb.net/firq/firq-dev-website:${{ github.ref_name }}, forgejo.neshweb.net/firq/firq-dev-website:preview
|
||||
|
||||
publish:
|
||||
create-release:
|
||||
needs: [ build-site ]
|
||||
if: success()
|
||||
runs-on: docker
|
||||
|
|
|
@ -4,14 +4,30 @@ on:
|
|||
- '[0-9]+\.[0-9]+\.[0-9]+'
|
||||
|
||||
jobs:
|
||||
checking:
|
||||
check-tag:
|
||||
runs-on: docker
|
||||
container: node:lts
|
||||
steps:
|
||||
- name: Checking Out Repository Code
|
||||
uses: https://code.forgejo.org/actions/checkout@v3
|
||||
- name: Check if Version in package.json matches Tag
|
||||
run: |
|
||||
VERSION=$(cat package.json | grep "version" | sed 's/.*://' | tr -d , | tr -d \" | tr -d " " )
|
||||
if test $VERSION != "${{ github.ref_name }}"; then
|
||||
echo "Expected Version is: '${{ github.ref_name }}' actual Version is: '$VERSION'";
|
||||
exit 1
|
||||
else
|
||||
echo "Version is: '$VERSION'";
|
||||
fi
|
||||
|
||||
checking:
|
||||
needs: [ check-tag ]
|
||||
runs-on: docker
|
||||
container: forgejo.neshweb.net/ci-docker-images/node-alpine-git:latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: https://code.forgejo.org/actions/checkout@v3
|
||||
- name: Install packages
|
||||
run: npm install
|
||||
run: npm i
|
||||
- name: Run astro check (linting + static analysis)
|
||||
run: npm run astro check
|
||||
|
||||
|
@ -22,19 +38,19 @@ jobs:
|
|||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
- name: Log into Docker Package Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: forgejo.neshweb.net
|
||||
username: ${{ secrets.FORGEJO_USERNAME }}
|
||||
password: ${{ secrets.FORGEJO_TOKEN }}
|
||||
- name: Push to Package Registry
|
||||
- name: Build and push to Docker Package Registry
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
tags: forgejo.neshweb.net/firq/firq-dev-website:${{ github.ref_name }}, forgejo.neshweb.net/firq/firq-dev-website:latest
|
||||
|
||||
release:
|
||||
create-release:
|
||||
needs: [ build-site ]
|
||||
if: success()
|
||||
runs-on: docker
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
- '**'
|
||||
|
||||
jobs:
|
||||
checking:
|
||||
astro-check:
|
||||
runs-on: docker
|
||||
container: node:lts
|
||||
container: forgejo.neshweb.net/ci-docker-images/node-alpine-git:latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: https://code.forgejo.org/actions/checkout@v3
|
||||
- name: Install packages
|
||||
run: npm install
|
||||
run: npm i
|
||||
- name: Run astro check (linting + static analysis)
|
||||
run: npm run astro check
|
||||
|
|
|
@ -11,7 +11,7 @@ jobs:
|
|||
- name: Checkout repository
|
||||
uses: https://code.forgejo.org/actions/checkout@v3
|
||||
- name: Run unlighthouse
|
||||
run: unlighthouse-ci --site "https://preview.firq.dev/"
|
||||
run: unlighthouse-ci --site "https://preview.firq.dev/" --disable-dynamic-sampling
|
||||
- name: Prepare artifacts
|
||||
run: cp serve.json unlighthouse-reports
|
||||
- name: Upload reports
|
||||
|
|
7714
package-lock.json
generated
7714
package-lock.json
generated
File diff suppressed because it is too large
Load diff
22
package.json
22
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@firq/fgosite",
|
||||
"type": "module",
|
||||
"version": "0.1.28-pre.4",
|
||||
"version": "0.2.0-pre.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
|
@ -11,15 +11,17 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astro-community/astro-embed-youtube": "^0.4.3",
|
||||
"@astrojs/check": "^0.3.3",
|
||||
"@astrojs/mdx": "^2.0.3",
|
||||
"@astrojs/sitemap": "^3.0.3",
|
||||
"astro": "^4.2.1",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"iconoir": "^7.2.0",
|
||||
"postcss-preset-env": "^9.3.0",
|
||||
"typescript": "^5.3.3"
|
||||
"@astro-community/astro-embed-youtube": "^0.5.2",
|
||||
"@astrojs/check": "^0.8.1",
|
||||
"@astrojs/mdx": "^3.1.3",
|
||||
"@astrojs/sitemap": "^3.1.6",
|
||||
"@fontsource/work-sans": "^5.0.18",
|
||||
"astro": "^4.11.5",
|
||||
"astro-meta-tags": "^0.3.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"iconoir": "^7.7.0",
|
||||
"postcss-preset-env": "^9.6.0",
|
||||
"typescript": "^5.5.3"
|
||||
},
|
||||
"browserslist": [
|
||||
"last 2 versions",
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
---
|
||||
export interface Props {
|
||||
url: string | undefined
|
||||
url: string
|
||||
slug: string
|
||||
title: string
|
||||
pubdate: string
|
||||
pubdate: Date
|
||||
description: string
|
||||
author: string
|
||||
}
|
||||
|
@ -12,11 +13,11 @@ const options_date: Intl.DateTimeFormatOptions = {
|
|||
month: 'long',
|
||||
day: '2-digit',
|
||||
}
|
||||
const { author, description, pubdate, url, title } = Astro.props
|
||||
const { author, description, pubdate, url, title, slug } = Astro.props
|
||||
const date = new Date(pubdate).toLocaleDateString('en-GB', options_date)
|
||||
---
|
||||
|
||||
<a href={url} rel="noopener noreferrer">
|
||||
<a href={`${url}/${slug}`} rel="noopener noreferrer">
|
||||
<div class="circle"></div>
|
||||
<article>
|
||||
<h2>{title}</h2>
|
||||
|
@ -29,38 +30,14 @@ const date = new Date(pubdate).toLocaleDateString('en-GB', options_date)
|
|||
.circle {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
.circle {
|
||||
margin: 1rem 1rem 1rem 0rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
visibility: visible;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
border-radius: 40%;
|
||||
background-color: var(--c-darkpurple);
|
||||
transition: transform var(--speed) var(--ease);
|
||||
}
|
||||
|
||||
a:hover > .circle {
|
||||
height: 1.75rem;
|
||||
width: 1.75rem;
|
||||
translate: -0.125rem;
|
||||
margin-right: 0.825rem;
|
||||
}
|
||||
|
||||
article {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
text-decoration: none;
|
||||
height: auto;
|
||||
margin: 0.5rem;
|
||||
height: fit-content;
|
||||
margin: 0px 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
p {
|
||||
|
@ -88,8 +65,8 @@ const date = new Date(pubdate).toLocaleDateString('en-GB', options_date)
|
|||
flex: 1;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
background-color: var(--c-darkergray);
|
||||
padding: 10px;
|
||||
|
@ -98,7 +75,47 @@ const date = new Date(pubdate).toLocaleDateString('en-GB', options_date)
|
|||
min-height: 100%;
|
||||
border-radius: 1.25rem;
|
||||
}
|
||||
|
||||
a:hover > article {
|
||||
transform: scaleY(102.5%) scaleX(101%);
|
||||
transition: transform var(--speed) var(--ease);
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.circle {
|
||||
margin: 1rem 0.5rem 1rem 0.5rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
visibility: visible;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
background-color: var(--c-darkpurple);
|
||||
border-style: solid;
|
||||
border-width: 0.25rem;
|
||||
border-color: var(--c-lightgray);
|
||||
border-radius: 40%;
|
||||
transition: transform var(--speed) var(--ease);
|
||||
}
|
||||
|
||||
a:hover > .circle {
|
||||
height: 1.25rem;
|
||||
width: 1.25rem;
|
||||
translate: -0.125rem;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
a:hover article {
|
||||
border-color: var(--c-darkpurple);
|
||||
transform: none;
|
||||
}
|
||||
|
||||
article {
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-color: var(--c-darkergray);
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
import { Image } from 'astro:assets'
|
||||
import mlb_ce from '../assets/ce/mlb.webp'
|
||||
import type { GlobImage } from '../types/generic'
|
||||
import { plsLoadImage } from '../utils/tools'
|
||||
import mlb_ce from '../../assets/ce/mlb.webp'
|
||||
import type { GlobImage } from '../../types/generic'
|
||||
import { plsLoadImage } from '../../utils/tools'
|
||||
|
||||
export interface Props {
|
||||
name: string
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import { Image } from 'astro:assets'
|
||||
import type { GlobImage } from '../types/generic'
|
||||
import { plsLoadImage } from '../utils/tools'
|
||||
import type { GlobImage } from '../../types/generic'
|
||||
import { plsLoadImage } from '../../utils/tools'
|
||||
|
||||
export interface Props {
|
||||
site: string
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import { Image } from 'astro:assets'
|
||||
import type { GlobImage } from '../types/generic'
|
||||
import { plsLoadImage } from '../utils/tools'
|
||||
import type { GlobImage } from '../../types/generic'
|
||||
import { plsLoadImage } from '../../utils/tools'
|
||||
|
||||
export interface Props {
|
||||
name: string
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import { Image } from 'astro:assets';
|
||||
import type { GlobImage } from '../types/generic'
|
||||
import { plsLoadImage } from '../utils/tools'
|
||||
import type { GlobImage } from '../../types/generic'
|
||||
import { plsLoadImage } from '../../utils/tools'
|
||||
|
||||
export interface Props {
|
||||
name: string
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import { Image } from 'astro:assets'
|
||||
import type { GlobImage } from '../types/generic'
|
||||
import { plsLoadImage } from '../utils/tools'
|
||||
import type { GlobImage } from '../../types/generic'
|
||||
import { plsLoadImage } from '../../utils/tools'
|
||||
|
||||
export interface Props {
|
||||
date: string
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import { Image } from 'astro:assets'
|
||||
import type { GlobImage } from '../types/generic'
|
||||
import { plsLoadImage } from '../utils/tools'
|
||||
import type { GlobImage } from '../../types/generic'
|
||||
import { plsLoadImage } from '../../utils/tools'
|
||||
|
||||
export interface Props {
|
||||
title: string
|
|
@ -1,4 +1,9 @@
|
|||
---
|
||||
export interface Props {
|
||||
fadeout?: boolean
|
||||
}
|
||||
const { fadeout } = Astro.props
|
||||
const display = fadeout ? "": "display: none"
|
||||
---
|
||||
|
||||
<div>
|
||||
|
@ -6,22 +11,33 @@
|
|||
I am currently working on a site to catalogue past and future TAs.<br/>
|
||||
Check it out at <a href="https://fgo-ta.com">fgo-ta.com</a>
|
||||
</span>
|
||||
<div class="fade" style={display}></div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 5em;
|
||||
background-color: var(--c-gray);
|
||||
flex-wrap: nowrap;
|
||||
flex-flow: column;
|
||||
background-color: var(--c-darkergray);
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 1.5em;
|
||||
padding: 2rem 0rem 0rem 0rem;
|
||||
}
|
||||
a {
|
||||
color: var(--c-darkpurple);
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: var(--c-darkpurple);
|
||||
}
|
||||
|
||||
.fade {
|
||||
margin-top: 3rem;
|
||||
background: linear-gradient(to bottom, transparent, var(--c-lightgray));
|
||||
height: 2.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
---
|
||||
import { Image } from 'astro:assets';
|
||||
import logo from '../assets/logo.svg'
|
||||
import { Image } from 'astro:assets'
|
||||
import logo from '../../assets/logo.svg'
|
||||
import hamburger from 'iconoir/icons/menu.svg'
|
||||
const hamburger_src_url = `url("${hamburger.src}")`;
|
||||
const hamburger_src_url = `url("${hamburger.src}")`
|
||||
---
|
||||
|
||||
<header>
|
||||
<a href="/" rel="noopener noreferrer" aria-label="Home" role="link">
|
||||
<Image src={logo} alt=""/>
|
||||
<span class="visually-hidden">Firq Logo</span>
|
||||
<a href="/" rel="noopener noreferrer" aria-label="Home" role="button">
|
||||
<Image src={logo} alt="" loading="eager"/>
|
||||
<span class="visually-hidden">Logo</span>
|
||||
</a>
|
||||
<ul class="desktop">
|
||||
<slot name="desktop" />
|
||||
</ul>
|
||||
<button class="mobile" aria-label="Navigation Button" tabindex="0" onclick="this.focus()" role="button">
|
||||
<button
|
||||
class="mobile"
|
||||
aria-label="Navigation Button"
|
||||
tabindex="0"
|
||||
onclick="this.focus()"
|
||||
role="button"
|
||||
>
|
||||
<ul>
|
||||
<slot name="mobile" />
|
||||
</ul>
|
||||
|
@ -27,12 +33,13 @@ const hamburger_src_url = `url("${hamburger.src}")`;
|
|||
z-index: 1000;
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
background-color: var(--c-darkgray);
|
||||
background-color: var(--c-darkergray);
|
||||
display: flex;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
align-items: flex-start;
|
||||
line-height: 1.5em;
|
||||
border-bottom: 2px solid var(--c-darkpurple) ;
|
||||
}
|
||||
header > a {
|
||||
margin-left: 16px;
|
||||
|
@ -61,7 +68,7 @@ const hamburger_src_url = `url("${hamburger.src}")`;
|
|||
line-height: 1.5em;
|
||||
}
|
||||
.mobile > ul {
|
||||
background-color: var(--c-darkgray);
|
||||
background-color: var(--c-darkergray);
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
|
@ -78,7 +85,7 @@ const hamburger_src_url = `url("${hamburger.src}")`;
|
|||
|
||||
.mobile {
|
||||
display: flex;
|
||||
background-color: var(--c-darkgray);
|
||||
background-color: var(--c-darkergray);
|
||||
border: 0px;
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
|
@ -108,13 +115,14 @@ const hamburger_src_url = `url("${hamburger.src}")`;
|
|||
|
||||
.hamburger-menu {
|
||||
mask: var(--hamburger_src_url) no-repeat center;
|
||||
mask-size: cover;
|
||||
background-color: white;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
position: static;
|
||||
align-self: flex-start;
|
||||
margin-right: 1rem;
|
||||
margin-top: 1rem;
|
||||
margin-top: 0.825rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1140px) {
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
export interface Props {
|
||||
currentPage?: string
|
||||
navtype: "mobile" | "desktop"
|
||||
navtype: 'mobile' | 'desktop'
|
||||
link: string
|
||||
text: string
|
||||
icon: ImageMetadata
|
||||
|
@ -18,10 +18,10 @@ if (currentPage === slug) {
|
|||
currPage = 'current'
|
||||
}
|
||||
|
||||
const icon_src_url = `url("${icon.src}")`;
|
||||
const icon_src_url = `url("${icon.src}")`
|
||||
const fulllink = `/${slug}`
|
||||
|
||||
let extraattributes = navtype === "mobile" ? { tabindex: "0"} : {}
|
||||
let extraattributes = navtype === 'mobile' ? { tabindex: '0' } : {}
|
||||
---
|
||||
|
||||
<li>
|
||||
|
@ -30,7 +30,7 @@ let extraattributes = navtype === "mobile" ? { tabindex: "0"} : {}
|
|||
rel="noopener noreferrer"
|
||||
aria-label={text}
|
||||
class={currPage}
|
||||
role="navigation"
|
||||
role="button"
|
||||
{...extraattributes}
|
||||
>
|
||||
<div class="icon"></div>
|
||||
|
@ -60,11 +60,11 @@ let extraattributes = navtype === "mobile" ? { tabindex: "0"} : {}
|
|||
}
|
||||
|
||||
li > a:hover {
|
||||
color: var(--c-purplepink);
|
||||
color: var(--c-purplepink) !important;
|
||||
}
|
||||
|
||||
li > a:hover > .icon {
|
||||
background-color: var(--c-purplepink);
|
||||
background-color: var(--c-purplepink) !important;
|
||||
}
|
||||
|
||||
.current {
|
109
src/components/titles/smallTitle.astro
Normal file
109
src/components/titles/smallTitle.astro
Normal file
|
@ -0,0 +1,109 @@
|
|||
---
|
||||
import '@fontsource/work-sans/800.css'
|
||||
import '@fontsource/work-sans/600.css'
|
||||
export interface Props {
|
||||
maintext: string
|
||||
subtext: string
|
||||
fadeout?: boolean
|
||||
baseurl?: string
|
||||
returnbutton?: boolean
|
||||
}
|
||||
const { maintext, subtext, fadeout, baseurl, returnbutton } = Astro.props
|
||||
const displayFadeout = fadeout ? "": "display: none"
|
||||
const displayBackButton = returnbutton ? "": "display: none"
|
||||
---
|
||||
|
||||
<div class="wrap">
|
||||
<div class="head">{maintext}</div>
|
||||
<div class="sub">{subtext}</div>
|
||||
<a href=`/${baseurl}` style={displayBackButton}><< Back to {baseurl}</a>
|
||||
<div class="fade" style={displayFadeout}></div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
a {
|
||||
font-weight: 600;
|
||||
font-family: 'Work Sans', 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif;
|
||||
color: white;
|
||||
margin: 1rem 0px 0px;
|
||||
padding: 0.5rem 0.75rem;
|
||||
text-decoration: none;
|
||||
background-color: var(--c-lightgray);
|
||||
border-radius: 10px;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-color: var(--c-lightgray);
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
border-color: var(--c-darkpurple);
|
||||
}
|
||||
|
||||
.wrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
color: var(--c-lighter);
|
||||
background-color: var(--c-darkergray);
|
||||
}
|
||||
|
||||
.fade {
|
||||
margin-top: 2rem;
|
||||
background: linear-gradient(to bottom, transparent, var(--c-lightgray));
|
||||
height: 2.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.head {
|
||||
hyphens: auto;
|
||||
padding-top: 2rem;
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
font-family: 'Work Sans', 'Helvetica Neue', Helvetica, Helvetica, Arial,
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
.sub {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
font-family: 'Work Sans', 'Helvetica Neue', Helvetica, Helvetica, Arial,
|
||||
sans-serif;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.head {
|
||||
color: var(--c-darkpurple);
|
||||
}
|
||||
|
||||
@supports (background-clip: text) {
|
||||
.head {
|
||||
background: linear-gradient(125deg, var(--c-darkpurple), var(--c-purplepink), var(--c-reddish) );
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 620px) {
|
||||
.head {
|
||||
hyphens: none;
|
||||
font-size: 3rem;
|
||||
}
|
||||
.sub {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1000px) {
|
||||
.head {
|
||||
font-size: 4rem;
|
||||
}
|
||||
.sub {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
75
src/components/titles/title.astro
Normal file
75
src/components/titles/title.astro
Normal file
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
import '@fontsource/work-sans/800.css'
|
||||
---
|
||||
|
||||
<div class="wrap">
|
||||
<div class="head">Hi, I'm <span class="fancy">Firq</span></div>
|
||||
<div class="sub">Nice to meet you</div>
|
||||
<div class="fade"></div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.wrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
color: var(--c-lighter);
|
||||
background-color: var(--c-darkergray);
|
||||
}
|
||||
|
||||
.fade {
|
||||
margin-top: 1.5rem;
|
||||
background: linear-gradient(to bottom, transparent, var(--c-lightgray));
|
||||
height: 2.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.head {
|
||||
padding-top: 2rem;
|
||||
font-size: 3rem;
|
||||
font-weight: 800;
|
||||
font-family: 'Work Sans', 'Helvetica Neue', Helvetica, Helvetica, Arial,
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
.sub {
|
||||
font-size: 1rem;
|
||||
font-weight: 800;
|
||||
font-family: 'Work Sans', 'Helvetica Neue', Helvetica, Helvetica, Arial,
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
.fancy {
|
||||
color: var(--c-darkpurple);
|
||||
}
|
||||
|
||||
@supports (background-clip: text) {
|
||||
.fancy {
|
||||
background: linear-gradient(125deg, var(--c-darkpurple), var(--c-purplepink), var(--c-reddish) );
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 620px) {
|
||||
.head {
|
||||
font-size: 4rem;
|
||||
}
|
||||
.sub {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1000px) {
|
||||
.head {
|
||||
font-size: 6rem;
|
||||
}
|
||||
.sub {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
16
src/content/config.ts
Normal file
16
src/content/config.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { z, defineCollection } from 'astro:content'
|
||||
|
||||
const blogCollection = defineCollection({
|
||||
type: 'content', // v2.5.0 and later
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
tags: z.array(z.string()),
|
||||
pubDate: z.date(),
|
||||
description: z.string(),
|
||||
author: z.string(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const collections = {
|
||||
blog: blogCollection,
|
||||
}
|
1
src/env.d.ts
vendored
1
src/env.d.ts
vendored
|
@ -1 +1,2 @@
|
|||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
import Navbar from '../components/navbar.astro'
|
||||
import NavbarEntry from '../components/navbarEntry.astro'
|
||||
import Navbar from '../components/navbar/navbar.astro'
|
||||
import NavbarEntry from '../components/navbar/navbarEntry.astro'
|
||||
import navdata from '../../static/data/_navdata.json'
|
||||
import embed from '../assets/embed.png'
|
||||
|
||||
|
@ -77,12 +77,22 @@ const mapped_navdata = navdata.map((item) => ({
|
|||
<Navbar>
|
||||
{
|
||||
mapped_navdata.map((item) => (
|
||||
<NavbarEntry currentPage={currentpage} navtype="desktop" {...item} slot="desktop"/>
|
||||
<NavbarEntry
|
||||
currentPage={currentpage}
|
||||
navtype="desktop"
|
||||
{...item}
|
||||
slot="desktop"
|
||||
/>
|
||||
))
|
||||
}
|
||||
{
|
||||
mapped_navdata.map((item) => (
|
||||
<NavbarEntry currentPage={currentpage} navtype="mobile" {...item} slot="mobile"/>
|
||||
<NavbarEntry
|
||||
currentPage={currentpage}
|
||||
navtype="mobile"
|
||||
{...item}
|
||||
slot="mobile"
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Navbar>
|
||||
|
@ -98,10 +108,12 @@ const mapped_navdata = navdata.map((item) => ({
|
|||
--c-darkgray: #1e1e1e;
|
||||
--c-duskgray: #242424;
|
||||
--c-gray: #2e2e2e;
|
||||
--c-lighter: #eee;
|
||||
--c-lightgray: #3e3e3e;
|
||||
--c-darkpurple: #b86cff;
|
||||
--c-purplepink: #c105ff;
|
||||
--c-darkergray: #1b1b1b;
|
||||
--c-reddish: #ff0077;
|
||||
}
|
||||
body {
|
||||
background: var(--c-lightgray);
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
---
|
||||
export interface Props {
|
||||
title: string
|
||||
}
|
||||
|
||||
const { title } = Astro.props
|
||||
---
|
||||
|
||||
<section class="base">
|
||||
<h1>{title}</h1>
|
||||
<div>
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
line-height: 48px;
|
||||
letter-spacing: -1px;
|
||||
color: white;
|
||||
font-size: 2.25rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0.25rem 0.75rem;
|
||||
max-width: max-content;
|
||||
background-color: var(--c-darkgray);
|
||||
padding: 0.25rem 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
div {
|
||||
row-gap: 1em;
|
||||
column-gap: 1em;
|
||||
justify-content: center;
|
||||
align-self: center;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
padding: 1em;
|
||||
color: white;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.base {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 400px) {
|
||||
.base {
|
||||
margin-left: 3rem;
|
||||
margin-right: 3rem;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
.base {
|
||||
margin-left: 10%;
|
||||
margin-right: 10%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 512px) {
|
||||
div {
|
||||
justify-content: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 520px) {
|
||||
h1 {
|
||||
margin: 0.5rem 0.75rem 0.5rem 0.75rem;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,4 +1,5 @@
|
|||
---
|
||||
import SmallTitle from '../components/titles/smallTitle.astro'
|
||||
import Layout from './Layout.astro'
|
||||
const { frontmatter } = Astro.props
|
||||
|
||||
|
@ -13,15 +14,12 @@ const date = new Date(frontmatter.pubDate).toLocaleDateString(
|
|||
'en-GB',
|
||||
options_date
|
||||
)
|
||||
const subtext = `Written by ${frontmatter.author} • Published on ${date}`
|
||||
---
|
||||
|
||||
<Layout title={title} currentpage="blog" descriptionOverride={description}>
|
||||
<a href="/blog"><i class="iconoir-fast-arrow-left"></i>Back to all posts</a>
|
||||
<SmallTitle maintext={frontmatter.title} subtext={subtext} fadeout={true} returnbutton={true} baseurl='blog'/>
|
||||
<div>
|
||||
<h1>
|
||||
{frontmatter.title}
|
||||
</h1>
|
||||
<p>by {frontmatter.author} • Published on {date}</p>
|
||||
<article>
|
||||
<slot />
|
||||
</article>
|
||||
|
|
|
@ -1,36 +1,59 @@
|
|||
---
|
||||
export interface Props {
|
||||
title: string
|
||||
titlehidden?: boolean
|
||||
displayLine?: boolean
|
||||
}
|
||||
|
||||
const { title } = Astro.props
|
||||
const { title, titlehidden, displayLine } = Astro.props
|
||||
const display = titlehidden ? "display: none" : ""
|
||||
const line = displayLine ? "flex" : "none"
|
||||
---
|
||||
|
||||
<section>
|
||||
<h1>{title}</h1>
|
||||
<h1 style={display}>{title}</h1>
|
||||
<div class="wrapper">
|
||||
<div class="start hightlighter"></div>
|
||||
<div class="line"></div>
|
||||
<slot />
|
||||
<div class="drop"></div>
|
||||
<div class="drop hightlighter"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.drop {
|
||||
<style define:vars={{ line }}>
|
||||
section {
|
||||
padding-left: 0.25em;
|
||||
padding-right: 0.25em;
|
||||
padding-bottom: 5rem;
|
||||
}
|
||||
|
||||
.hightlighter {
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
visibility: visible;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: -5rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
}
|
||||
|
||||
.drop {
|
||||
bottom: -5rem;
|
||||
border-radius: 0% 50% 50% 50%;
|
||||
transform: rotate(45deg);
|
||||
background-color: var(--c-darkpurple);
|
||||
}
|
||||
|
||||
.start {
|
||||
top: -2rem;
|
||||
border-radius: 40%;
|
||||
border-style: solid;
|
||||
border-width: 0.25rem;
|
||||
border-color: var(--c-lightgray);
|
||||
background-color: var(--c-darkpurple);
|
||||
}
|
||||
|
||||
.line {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
|
@ -46,30 +69,31 @@ const { title } = Astro.props
|
|||
z-index: -1;
|
||||
}
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
line-height: 48px;
|
||||
letter-spacing: -1px;
|
||||
color: white;
|
||||
font-size: 2.25rem;
|
||||
font-size: 1.6rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0.25rem 0.75rem;
|
||||
max-width: max-content;
|
||||
background-color: var(--c-darkgray);
|
||||
padding: 0.25rem 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
justify-self: center;
|
||||
text-align: center;
|
||||
}
|
||||
.wrapper {
|
||||
margin: 2rem 3rem 0.5rem 3rem;
|
||||
margin: 2rem 2rem 0.5rem 2rem;
|
||||
display: flex;
|
||||
flex-flow: column wrap;
|
||||
row-gap: 1em;
|
||||
column-gap: 1em;
|
||||
align-self: center;
|
||||
align-items: stretch;
|
||||
align-content: center;
|
||||
justify-content: space-around;
|
||||
padding: 1em;
|
||||
color: white;
|
||||
|
@ -80,21 +104,41 @@ const { title } = Astro.props
|
|||
.drop {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
.start {
|
||||
margin-left: 1.25rem;
|
||||
}
|
||||
.line {
|
||||
margin-left: 2.1rem;
|
||||
}
|
||||
h1 {
|
||||
margin-left: 3rem;
|
||||
font-size: 1.85rem;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
.wrapper {
|
||||
margin-left: 20rem;
|
||||
margin-right: 20rem;
|
||||
margin-left: 15rem;
|
||||
margin-right: 15rem;
|
||||
flex-direction: row;
|
||||
}
|
||||
section {
|
||||
padding-bottom: unset;
|
||||
}
|
||||
.drop, .start, .line {
|
||||
display: var(--line);
|
||||
margin-left: 2rem;
|
||||
}
|
||||
.start {
|
||||
margin-left: 1.75rem;
|
||||
}
|
||||
.line {
|
||||
margin-left: 2.6rem;
|
||||
height: calc(100% + 6rem);
|
||||
translate: 0px -2rem;
|
||||
}
|
||||
h1 {
|
||||
margin-left: 20rem;
|
||||
margin-right: 20rem;
|
||||
margin-left: 15rem;
|
||||
margin-right: 15rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
---
|
||||
import '@fontsource/work-sans/500.css'
|
||||
import '@fontsource/work-sans/600.css'
|
||||
import { Image } from 'astro:assets'
|
||||
import Layout from '../layouts/Layout.astro'
|
||||
import BaseSection from '../layouts/baseSection.astro'
|
||||
import sadshishou from '../assets/shishousad.webp'
|
||||
import SmallTitle from '../components/titles/smallTitle.astro'
|
||||
|
||||
const description = "Error. This shouldn't happen :/"
|
||||
---
|
||||
|
@ -12,7 +15,7 @@ const description = "Error. This shouldn't happen :/"
|
|||
currentpage="404"
|
||||
descriptionOverride={description}
|
||||
>
|
||||
<BaseSection title="FirqhundredandFirq - Not Found">
|
||||
<SmallTitle maintext='Error' subtext='FirqhundredandFirq - Not Found' fadeout={true}/>
|
||||
<div>
|
||||
<Image src={sadshishou} alt="Sad Shishou" />
|
||||
<h2>Well ... you were not supposed to end up here.</h2>
|
||||
|
@ -20,44 +23,51 @@ const description = "Error. This shouldn't happen :/"
|
|||
<< Go back home
|
||||
</a>
|
||||
</div>
|
||||
</BaseSection>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
div {
|
||||
padding: 0px 2rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
h2 {
|
||||
font-family: 'Work Sans', 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
font-size: 1.25rem;
|
||||
margin-top: 1rem;
|
||||
max-width: max-content;
|
||||
}
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 75%;
|
||||
text-align: center;
|
||||
color: white;
|
||||
background-color: var(--c-gray);
|
||||
padding: 0.5rem 0px;
|
||||
margin-bottom: 2rem;
|
||||
text-decoration: none;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
|
||||
&:hover {
|
||||
color: var(--c-darkpurple);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
a {
|
||||
text-align: center;
|
||||
width: fit-content;
|
||||
font-weight: 600;
|
||||
font-family: 'Work Sans', 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif;
|
||||
color: white;
|
||||
margin: 1rem 0px 0px;
|
||||
padding: 0.5rem 0.75rem;
|
||||
text-decoration: none;
|
||||
background-color: var(--c-darkergray);
|
||||
border-radius: 10px;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-color: var(--c-darkergray);
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
border-color: var(--c-darkpurple);
|
||||
}
|
||||
|
||||
img {
|
||||
width: 256px;
|
||||
height: 256px;
|
||||
width: 200px;
|
||||
height: auto;
|
||||
border-radius: 10%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro'
|
||||
import AboutSection from '../layouts/aboutSection.astro'
|
||||
|
||||
import ContactSection from '../layouts/contactSection.astro'
|
||||
import ContactCard from '../components/contactCard.astro'
|
||||
import ContactCard from '../components/cards/contactCard.astro'
|
||||
import contactdata from '../../static/data/_contactdata.json'
|
||||
|
||||
import CustomFooter from '../layouts/customFooter.astro'
|
||||
import TechnologyCard from '../components/technologyCard.astro'
|
||||
import TechnologyCard from '../components/cards/technologyCard.astro'
|
||||
import technologydata from '../../static/data/_technologydata.json'
|
||||
import SmallTitle from '../components/titles/smallTitle.astro'
|
||||
|
||||
const description =
|
||||
"A summary of the technologies used as well as my contact information. You'll also find disclaimers and thank you notes for the people that helped me."
|
||||
const subtext =
|
||||
"This is a small sideproject that I'm creating. First time doing webdev in general, and first project using Typescript."
|
||||
---
|
||||
|
||||
<Layout
|
||||
|
@ -19,10 +21,7 @@ const description =
|
|||
currentpage="about"
|
||||
descriptionOverride={description}
|
||||
>
|
||||
<AboutSection title="About">
|
||||
This is a small sideproject that I'm creating. First time doing webdev in
|
||||
general, and first project using Typescript.
|
||||
</AboutSection>
|
||||
<SmallTitle maintext="About" subtext={subtext} fadeout={true} />
|
||||
<ContactSection title="Technologies used">
|
||||
{technologydata.map((item) => <TechnologyCard {...item} />)}
|
||||
</ContactSection>
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro'
|
||||
import BlogCard from '../components/blogCard.astro'
|
||||
import BlogSection from '../layouts/blogSection.astro'
|
||||
|
||||
const description =
|
||||
'My own small blog. Topics include FGO, TA, Programming, web technologies and more!'
|
||||
const allPosts = await Astro.glob('../pages/blog/*.{md,mdx}')
|
||||
allPosts.sort(
|
||||
(a, b) =>
|
||||
Date.parse(b.frontmatter.pubDate) - Date.parse(a.frontmatter.pubDate)
|
||||
)
|
||||
---
|
||||
|
||||
<Layout
|
||||
title="Blog - Firq FGO Site"
|
||||
currentpage="blog"
|
||||
descriptionOverride={description}
|
||||
>
|
||||
<BlogSection title="Blog Articles">
|
||||
{
|
||||
allPosts.map((post) => (
|
||||
<BlogCard
|
||||
url={post.url}
|
||||
title={post.frontmatter.title}
|
||||
pubdate={post.frontmatter.pubDate}
|
||||
description={post.frontmatter.description}
|
||||
author={post.frontmatter.author}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</BlogSection>
|
||||
</Layout>
|
||||
|
||||
<style></style>
|
17
src/pages/blog/[...slug].astro
Normal file
17
src/pages/blog/[...slug].astro
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
import { getCollection } from 'astro:content'
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const blogEntries = await getCollection('blog')
|
||||
|
||||
return blogEntries.map((entry) => ({
|
||||
params: { slug: entry.slug },
|
||||
props: { entry },
|
||||
}))
|
||||
}
|
||||
|
||||
const { entry } = Astro.props
|
||||
const { Content } = await entry.render()
|
||||
---
|
||||
|
||||
<Content />
|
39
src/pages/blog/index.astro
Normal file
39
src/pages/blog/index.astro
Normal file
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
import Layout from '../../layouts/Layout.astro'
|
||||
import BlogCard from '../../components/cards/blogCard.astro'
|
||||
import BlogSection from '../../layouts/blogSection.astro'
|
||||
import SmallTitle from '../../components/titles/smallTitle.astro'
|
||||
import { getCollection } from 'astro:content'
|
||||
|
||||
const description =
|
||||
'My own small blog. Topics include FGO, TA, Programming, web technologies and more!'
|
||||
const blogEntries = await getCollection('blog')
|
||||
blogEntries.sort(
|
||||
(a, b) =>
|
||||
(b.data.pubDate.valueOf() - a.data.pubDate.valueOf() )
|
||||
)
|
||||
---
|
||||
|
||||
<Layout
|
||||
title="Blog - Firq FGO Site"
|
||||
currentpage="blog"
|
||||
descriptionOverride={description}
|
||||
>
|
||||
<SmallTitle maintext="Blog Articles" subtext="" fadeout={true} />
|
||||
<BlogSection title="Blog Articles" displayLine={true} titlehidden={true}>
|
||||
{
|
||||
blogEntries.map((post) => (
|
||||
<BlogCard
|
||||
url="blog"
|
||||
slug={post.slug}
|
||||
title={post.data.title}
|
||||
pubdate={post.data.pubDate}
|
||||
description={post.data.description}
|
||||
author={post.data.author}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</BlogSection>
|
||||
</Layout>
|
||||
|
||||
<style></style>
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro'
|
||||
import Hero from '../components/hero.astro'
|
||||
import BaseSection from '../layouts/baseSection.astro'
|
||||
import FavouriteCard from '../components/favouriteCard.astro'
|
||||
import FavouriteCard from '../components/cards/favouriteCard.astro'
|
||||
import favouritesdata from '../../static/data/_favouritesdata.json'
|
||||
import Hi from '../components/titles/title.astro'
|
||||
|
||||
const description =
|
||||
'The very own page of Firq for providing informating about TA servants, listing past TA achievements and hosting a blog for talking about FGO, Programming and other stuff'
|
||||
|
@ -14,7 +14,7 @@ const description =
|
|||
currentpage="home"
|
||||
descriptionOverride={description}
|
||||
>
|
||||
<Hero />
|
||||
<Hi />
|
||||
<BaseSection title="Favourites">
|
||||
{favouritesdata.map((item) => <FavouriteCard {...item} />)}
|
||||
</BaseSection>
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
import Layout from '../layouts/Layout.astro'
|
||||
import BaseSection from '../layouts/baseSection.astro'
|
||||
|
||||
import ServantCard from '../components/servantCard.astro'
|
||||
import ServantCard from '../components/cards/servantCard.astro'
|
||||
import servantdata from '../../static/data/_servantdata.json'
|
||||
|
||||
import CeCard from '../components/ceCard.astro'
|
||||
import CeCard from '../components/cards/ceCard.astro'
|
||||
import cedata from '../../static/data/_cedata.json'
|
||||
import SmallTitle from '../components/titles/smallTitle.astro'
|
||||
|
||||
const description =
|
||||
'A list of all the servants and ces that Firq can offer up on support for TA.'
|
||||
|
@ -17,6 +18,7 @@ const description =
|
|||
currentpage="servants"
|
||||
descriptionOverride={description}
|
||||
>
|
||||
<SmallTitle maintext='TA Offering' subtext='Servants and CEs I can offer for your TAs' fadeout={true}/>
|
||||
<BaseSection title="Servants">
|
||||
{servantdata.map((item) => <ServantCard {...item} />)}
|
||||
</BaseSection>
|
||||
|
|
|
@ -8,10 +8,11 @@
|
|||
import Layout from '../layouts/Layout.astro'
|
||||
|
||||
import TaSection from '../layouts/taSection.astro'
|
||||
import TaCard from '../components/taCard.astro'
|
||||
import TaCard from '../components/cards/taCard.astro'
|
||||
import tadata from '../../static/data/_tadata.json'
|
||||
import featured_data from '../../static/data/_featureddata.json'
|
||||
import FgotaHero from '../components/fgotaHero.astro'
|
||||
import SmallTitle from '../components/titles/smallTitle.astro'
|
||||
|
||||
const important_data = tadata.filter(function (el) {
|
||||
return [
|
||||
|
@ -37,7 +38,8 @@ const description = 'A collection of TAs previously completed be Firq.'
|
|||
currentpage="ta-collection"
|
||||
descriptionOverride={description}
|
||||
>
|
||||
<FgotaHero />
|
||||
<SmallTitle maintext='TA Collection' subtext=''/>
|
||||
<FgotaHero fadeout={true}/>
|
||||
<TaSection title="Notable TAs" abovetext="My most notable TAs">
|
||||
{important_data.map((item) => <TaCard {...item} />)}
|
||||
</TaSection>
|
||||
|
|
Loading…
Reference in a new issue