chchchchch changez
This commit is contained in:
parent
2232741e04
commit
f0b541cfdc
24 changed files with 175 additions and 129 deletions
|
@ -1,6 +1,6 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
|
import config from '~/site.config'
|
||||||
import tailwindcss from '@tailwindcss/vite';
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
|
|
|
@ -4,12 +4,11 @@ import { getCollection } from "astro:content";
|
||||||
import { getPublishedAndSortedPosts } from "~/lib/blog";
|
import { getPublishedAndSortedPosts } from "~/lib/blog";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
collection: string;
|
|
||||||
limit?: number;
|
limit?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { collection, limit } = Astro.props;
|
const { limit } = Astro.props;
|
||||||
const items = getPublishedAndSortedPosts(await getCollection(collection));
|
const items = getPublishedAndSortedPosts(await getCollection("blog"));
|
||||||
const limitedItems = limit ? items.slice(0, limit) : items;
|
const limitedItems = limit ? items.slice(0, limit) : items;
|
||||||
|
|
||||||
const getPostIcon = (item: { data: { icon?: string } }) => {
|
const getPostIcon = (item: { data: { icon?: string } }) => {
|
||||||
|
@ -26,16 +25,17 @@ const getPostIcon = (item: { data: { icon?: string } }) => {
|
||||||
<li>
|
<li>
|
||||||
<i class={`fa-li ${getPostIcon(item)}`} />
|
<i class={`fa-li ${getPostIcon(item)}`} />
|
||||||
|
|
||||||
<a href={`/${collection}/${item.id}`}>
|
<a href={`/blog/${item.id}`}>
|
||||||
<h3 class="font-bold mb-0.5">{item.data.title}</h3>
|
<h3 class="font-bold mb-0.5">{item.data.title}</h3>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<p class="text-sm text-light-tx-2 dark:text-dark-tx-2">
|
<p class="text-sm text-light-tx-2 dark:text-dark-tx-2">
|
||||||
<i class="fa-solid fa-calendar-alt mr-1 text-light-pu dark:text-dark-pu" />
|
<i class="fa-solid fa-calendar-alt mr-1 text-light-pu dark:text-dark-pu" />
|
||||||
<Date date={item.data.date} />
|
<Date date={item.data.date} />
|
||||||
<i class="fa-solid fa-tags mx-1 text-light-pu dark:text-dark-pu" />
|
<i class="mx-3"></i>
|
||||||
|
<i class="fa-solid fa-tags mr-1.5 text-light-pu dark:text-dark-pu" />
|
||||||
{(item.data.tags ?? []).map((tag) => (
|
{(item.data.tags ?? []).map((tag) => (
|
||||||
<a class="bg-light-pu dark:bg-dark-pu text-white px-1 py-0.5 rounded-md" href={`/${collection}/tags/${tag}`}>{tag}</a>
|
<a class="bg-light-pu dark:bg-dark-pu text-white px-1 py-0.5 rounded-md" href={`/blog/tags/${tag}`}>{tag}</a>
|
||||||
))}
|
))}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ const renderedItems = await Promise.all(
|
||||||
<ul class="fa-ul space-y-4 my-2">
|
<ul class="fa-ul space-y-4 my-2">
|
||||||
{
|
{
|
||||||
renderedItems.map((item) => (
|
renderedItems.map((item) => (
|
||||||
<li>
|
<li class="max-w-[700px] p-4 rounded-lg shadow-lg">
|
||||||
<i class={`fa-li ${item.data.icon}`} />
|
<i class={`fa-li ${item.data.icon}`} />
|
||||||
<a href={`/notes/${item.id}`}>
|
<a href={`/notes/${item.id}`}>
|
||||||
<Date date={item.data.date} />
|
<Date date={item.data.date} />
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
|
import { isBirthday } from "~/lib/fun";
|
||||||
---
|
---
|
||||||
|
|
||||||
<footer class="mt-12 text-sm text-light-tx-2 dark:text-dark-tx-2">
|
<footer class="mt-12 text-sm text-light-tx-2 dark:text-dark-tx-2">
|
||||||
|
@ -10,5 +10,12 @@
|
||||||
ivyturner/trellis
|
ivyturner/trellis
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p>love yourself.</p>
|
<p>love yourself.
|
||||||
|
{isBirthday() && (
|
||||||
|
<span class="text-light-accent dark:text-dark-accent">
|
||||||
|
{" "}
|
||||||
|
happy birthday!
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
@ -1,30 +1,13 @@
|
||||||
---
|
---
|
||||||
import Navigation from "./Navigation.astro";
|
import Navigation from "./Navigation.astro";
|
||||||
import conf from "~/site.config";
|
import conf from "~/site.config";
|
||||||
import { isBlog } from "~/lib/metadata";
|
|
||||||
|
|
||||||
let headertext = conf.siteName;
|
let headertext = conf.site.title;
|
||||||
let headerurl = "/";
|
let headerurl = "/";
|
||||||
let headerarrow = false;
|
|
||||||
|
|
||||||
if (isBlog(Astro.url.pathname)) {
|
|
||||||
headertext = "Everything And The Girl";
|
|
||||||
headerurl = "/blog";
|
|
||||||
headerarrow = true;
|
|
||||||
}
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<header class="md:flex md:justify-between md:items-center mb-4">
|
<header class="md:flex md:justify-between md:items-center mb-4">
|
||||||
<h1 class="text-2xl font-bold">
|
<h1 class="text-2xl font-bold">
|
||||||
{
|
|
||||||
headerarrow && (
|
|
||||||
<span class="mr-2">
|
|
||||||
<a href="/">
|
|
||||||
<i class="fa-solid fa-arrow-left text-light-pu dark:text-dark-pu" />
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
<a href={headerurl}>{headertext}</a>
|
<a href={headerurl}>{headertext}</a>
|
||||||
</h1>
|
</h1>
|
||||||
<Navigation />
|
<Navigation />
|
||||||
|
|
|
@ -23,7 +23,7 @@ const headerLinks = [
|
||||||
{
|
{
|
||||||
label: "Blog",
|
label: "Blog",
|
||||||
href: "/blog",
|
href: "/blog",
|
||||||
icon: "fa-solid fa-blog",
|
icon: "fa-solid fa-star",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Contact",
|
label: "Contact",
|
||||||
|
@ -36,12 +36,11 @@ const headerLinks = [
|
||||||
<nav class="flex flex-row gap-4">
|
<nav class="flex flex-row gap-4">
|
||||||
{
|
{
|
||||||
headerLinks.map((link) => (
|
headerLinks.map((link) => (
|
||||||
<span>
|
<span class="block bg-light-pu dark:bg-dark-pu text-black py-2 px-3 rounded-2xl">
|
||||||
<i class={`${link.icon} mr-0.5 text-sm`} />
|
<i class={`${link.icon} mr-0.5 text-sm`} />
|
||||||
<a
|
<a
|
||||||
href={link.href}
|
href={link.href}
|
||||||
class="underline decoration-wavy underline-offset-4 decoration-1.5
|
class=""
|
||||||
decoration-light-pu dark:decoration-dark-pu"
|
|
||||||
>
|
>
|
||||||
{link.label}
|
{link.label}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -4,21 +4,27 @@ import { clsx } from "clsx";
|
||||||
interface Props {
|
interface Props {
|
||||||
level: number;
|
level: number;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
heading?: string;
|
||||||
|
xstyle?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// level 0: info/note
|
// level 0: info/note
|
||||||
// level 1: warning
|
// level 1: warning
|
||||||
// level 2: attn needed: oh fuck
|
// level 2: attn needed: oh fuck
|
||||||
|
|
||||||
const { level } = Astro.props;
|
const { level, icon, heading, xstyle } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={clsx("sm:block md:hidden text-black", {
|
class={clsx(`sm:block md:hidden text-black ${xstyle}`, {
|
||||||
"bg-light-ye dark:bg-dark-ye": level === 0,
|
"bg-light-ye dark:bg-dark-ye": level === 0,
|
||||||
"bg-light-or dark:bg-dark-or": level === 1,
|
"bg-light-or dark:bg-dark-or": level === 1,
|
||||||
"bg-light-re dark:bg-dark-re": level === 2,
|
"bg-light-re dark:bg-dark-re": level === 2,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
<div class="flex items-center">
|
||||||
|
{icon && <i class={`${icon} text-xl mr-2`}></i>}
|
||||||
|
{heading && <h2 class="text-xl font-bold">{heading}</h2>}
|
||||||
|
</div>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="prose dark:prose-invert prose-p:text-light-tx dark:prose-p:text-dark-tx prose-h3:mt-1 prose-a:decoration-dotted prose-a:underline-offset-4 prose-a:decoration-2 prose-a:underline prose-a:decoration-light-pu dark:prose-a:decoration-dark-pu">
|
<div class="prose dark:prose-invert prose-p:text-light-tx dark:prose-p:text-dark-tx prose-h3:mt-1 prose-a:decoration-dotted prose-a:underline-offset-4 prose-a:decoration-2 prose-a:underline prose-a:decoration-light-pu dark:prose-a:decoration-dark-pu prose-ul:list-disc">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,7 +15,7 @@ const { title, description, icon, date } = Astro.props;
|
||||||
if (date) {
|
if (date) {
|
||||||
return (
|
return (
|
||||||
<p class="mt-2 text-sm text-light-tx-2 dark:text-dark-tx-2">
|
<p class="mt-2 text-sm text-light-tx-2 dark:text-dark-tx-2">
|
||||||
last updated: <Date date={date} />
|
<Date date={date} />
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
import siteConfig from "~/site.config";
|
import conf from "~/site.config";
|
||||||
import { getClacks } from "~/lib/fun";
|
import { getClacks } from "~/lib/fun";
|
||||||
import { descriptionConstructor, titleConstructor } from "~/lib/metadata";
|
import { descriptionConstructor, titleConstructor } from "~/lib/metadata";
|
||||||
|
|
||||||
|
@ -7,38 +7,36 @@ const { title, description } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>{titleConstructor(title, Astro.url.pathname)}</title>
|
<title>{titleConstructor(title)}</title>
|
||||||
<meta name="description" content={descriptionConstructor(description)} />
|
<meta name="description" content={descriptionConstructor(description)} />
|
||||||
<meta name="author" content="Ivy Turner" />
|
<meta name="author" content="Ivy Turner" />
|
||||||
|
|
||||||
{/* og */}
|
{/* og */}
|
||||||
<meta
|
<meta property="og:title" content={titleConstructor(title)} />
|
||||||
property="og:title"
|
<meta property="og:description" content={descriptionConstructor(description)}/>
|
||||||
content={titleConstructor(title, Astro.url.pathname)}
|
<meta property="og:type" content="website" />
|
||||||
/>
|
<meta property="og:url" content={conf.site.url} />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:image" content="https://ivyneeds.rest/image.jpg" />
|
||||||
<meta property="og:url" content="https://ivyneeds.rest" />
|
<link rel="icon" href="https://fav.farm/%F0%9F%92%9C" />
|
||||||
<meta property="og:image" content="https://ivyneeds.rest/image.jpg" />
|
|
||||||
<link rel="icon" href="https://fav.farm/%F0%9F%92%9C" />
|
|
||||||
|
|
||||||
<meta name="theme-color" content="#5E409D" />
|
<meta name="theme-color" content="#5E409D" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||||
|
|
||||||
{/* font awesone */}
|
{/* font awesone */}
|
||||||
<link
|
<link
|
||||||
href="https://cdn.laker.tech/web/fa/css/fontawesome.css"
|
href="https://cdn.laker.tech/web/fa/css/fontawesome.css"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<link href="https://cdn.laker.tech/web/fa/css/brands.css" rel="stylesheet" />
|
<link href="https://cdn.laker.tech/web/fa/css/brands.css" rel="stylesheet" />
|
||||||
<link href="https://cdn.laker.tech/web/fa/css/solid.css" rel="stylesheet" />
|
<link href="https://cdn.laker.tech/web/fa/css/solid.css" rel="stylesheet" />
|
||||||
|
|
||||||
{/* analytics */}
|
{/* analytics */}
|
||||||
|
|
||||||
{/* astro generator */}
|
{/* astro generator */}
|
||||||
<meta name="generator" content={Astro.generator} />
|
<meta name="generator" content={Astro.generator} />
|
||||||
|
|
||||||
{/* clacks */}
|
{/* clacks */}
|
||||||
<meta http-equiv="X-Clacks-Overhead" content={`GNU ${getClacks()}`} />
|
<meta http-equiv="X-Clacks-Overhead" content={`GNU ${getClacks()}`} />
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -11,9 +11,9 @@ const blog = defineCollection({
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
date: z.date().default(new Date()),
|
date: z.date().default(new Date()),
|
||||||
tags: z.array(z.string()).optional(),
|
tags: z.array(z.string()),
|
||||||
draft: z.boolean().default(false),
|
draft: z.boolean().default(false),
|
||||||
icon: z.string().optional().default("fa-solid fa-blog"),
|
icon: z.string().optional().default("fa-solid fa-star"),
|
||||||
image: z
|
image: z
|
||||||
.object({
|
.object({
|
||||||
src: z.string(),
|
src: z.string(),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
I'm a musician, student, part-time software developer and writer.
|
I'm a musician, student, part-time software developer and writer.
|
||||||
|
|
||||||
I like making weird noises, websites (like this one) with [Astro](https://astro.build), and going outside whenever I'm not doing either of those things.
|
I like creating websites (like this one) with [Astro](https://astro.build), and going outside whenever I'm not doing either of those things.
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ title: meow
|
||||||
description: meow meow meow
|
description: meow meow meow
|
||||||
date: 2025-03-17
|
date: 2025-03-17
|
||||||
icon: fa-solid fa-cat
|
icon: fa-solid fa-cat
|
||||||
|
tags: ["meow"]
|
||||||
---
|
---
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat
|
|
@ -3,4 +3,8 @@ title: "/now: 2025-W13"
|
||||||
description: "its now"
|
description: "its now"
|
||||||
date: 2025-03-24
|
date: 2025-03-24
|
||||||
tags: ["now"]
|
tags: ["now"]
|
||||||
|
icon: fa-calendar-days fa-solid
|
||||||
---
|
---
|
||||||
|
|
||||||
|
- I've started bullet journalling. It's fun but I'm not keeping it up enough to have any effect.
|
||||||
|
- Watched *Mickey 17* on Saturday, it's very good.
|
||||||
|
|
15
src/data/flavourtext.json
Normal file
15
src/data/flavourtext.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[
|
||||||
|
"LOVE YOURSELF",
|
||||||
|
"Hack the planet!",
|
||||||
|
"all your base are belong to us!",
|
||||||
|
"must construct additional pylons",
|
||||||
|
"Everybody's dead, Dave.",
|
||||||
|
"Stay strange and be ace -- Yard Act",
|
||||||
|
"I'm a rocketman!",
|
||||||
|
"It's a fixer-upper!",
|
||||||
|
"💜",
|
||||||
|
"Sibelius crashed",
|
||||||
|
"All toasters toast toast",
|
||||||
|
"Trans rights are human rights!",
|
||||||
|
":wq"
|
||||||
|
]
|
|
@ -9,7 +9,7 @@ const { title, description, icon, date } = Astro.props;
|
||||||
<Layout title={title} description={description} date={date}>
|
<Layout title={title} description={description} date={date}>
|
||||||
<div>
|
<div>
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main class="pr-48">
|
||||||
<Strapline title={title} description={description} icon={icon} date={date} />
|
<Strapline title={title} description={description} icon={icon} date={date} />
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -1,28 +1,13 @@
|
||||||
// all the code for making fun stuff happen
|
// all the code for making fun stuff happen
|
||||||
|
import flavourText from "~/data/flavourtext.json";
|
||||||
const flavourText = [
|
|
||||||
"LOVE YOURSELF",
|
|
||||||
"Hack the planet!",
|
|
||||||
"all your base are belong to us!",
|
|
||||||
"must construct additional pylons",
|
|
||||||
"Everybody's dead, Dave.",
|
|
||||||
"Stay strange and be ace -- Yard Act",
|
|
||||||
"I'm a rocketman!",
|
|
||||||
"It's a fixer-upper!",
|
|
||||||
"💜",
|
|
||||||
"Sibelius crashed",
|
|
||||||
"All toasters toast toast",
|
|
||||||
"Trans rights are human rights!",
|
|
||||||
":wq",
|
|
||||||
];
|
|
||||||
|
|
||||||
export function getFlavourText() {
|
export function getFlavourText() {
|
||||||
return flavourText[Math.floor(Math.random() * flavourText.length)];
|
return flavourText[Math.floor(Math.random() * flavourText.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isBirthday() {
|
// check if it's ivy's birthday at build time
|
||||||
|
export function isBirthday(): boolean {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const birthday = new Date(today.getFullYear(), 3, 13);
|
const birthday = new Date(today.getFullYear(), 9, 16); // October 16
|
||||||
const check =
|
const check =
|
||||||
today.getMonth() === birthday.getMonth() &&
|
today.getMonth() === birthday.getMonth() &&
|
||||||
today.getDate() === birthday.getDate();
|
today.getDate() === birthday.getDate();
|
||||||
|
@ -30,7 +15,14 @@ export function isBirthday() {
|
||||||
return check;
|
return check;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://gnuterrypratchett.com/index.php
|
||||||
export function getClacks(): string {
|
export function getClacks(): string {
|
||||||
const clacks: string[] = ["Terry Pratchett", "Bram Moolenaar", "Alan Turing", "Haskell Curry", "Brianna Ghey"];
|
const clacks: string[] = [
|
||||||
|
"Terry Pratchett",
|
||||||
|
"Bram Moolenaar",
|
||||||
|
"Alan Turing",
|
||||||
|
"Haskell Curry",
|
||||||
|
"Brianna Ghey",
|
||||||
|
];
|
||||||
return clacks.join(", ");
|
return clacks.join(", ");
|
||||||
}
|
}
|
|
@ -1,25 +1,18 @@
|
||||||
import conf from "~/site.config";
|
import conf from "~/site.config";
|
||||||
|
let siteName = conf.site.title;
|
||||||
|
let siteDescription = conf.site.description;
|
||||||
|
|
||||||
export const isBlog = (pathname: string) => {
|
export const titleConstructor = (title: string) => {
|
||||||
return pathname.startsWith("/blog");
|
if (!title) return siteName;
|
||||||
};
|
return `${title} | ${siteName}`;
|
||||||
|
|
||||||
export const titleConstructor = (title: string, pathname: string) => {
|
|
||||||
if (isBlog(pathname)) {
|
|
||||||
return title
|
|
||||||
? `${title} | Everything And The Girl`
|
|
||||||
: "Everything And The Girl";
|
|
||||||
}
|
|
||||||
if (!title) return conf.siteName;
|
|
||||||
return `${title} | ${conf.siteName}`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const descriptionConstructor = (description: string) => {
|
export const descriptionConstructor = (description: string) => {
|
||||||
if (!description) return conf.description;
|
if (!description) return siteDescription;
|
||||||
return `${description}`;
|
return `${description}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const noteTitleConstructor = (title: string, date: Date) => {
|
export const noteTitleConstructor = (title: string, date: Date) => {
|
||||||
if (title) return title;
|
if (title) return `A note titled ${title}`;
|
||||||
return `A note from ${date.toLocaleDateString()}`;
|
return `A note from ${date.toLocaleDateString()}`;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,10 +4,10 @@ import BlogPostList from "~/components/lists/BlogPostList.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Page
|
<Page
|
||||||
title="Post index"
|
title="Blog thing yes yes"
|
||||||
description="A list of all my blog posts."
|
description="A list of all my blog posts."
|
||||||
icon="fa-solid fa-blog"
|
icon="fa-solid fa-star"
|
||||||
>
|
>
|
||||||
|
<p class="mb-6">my personal blog is <a class="link" href="https://concorde.blog">Concorde</a>, but here has more technical things.</p>
|
||||||
<BlogPostList collection="blog" />
|
<BlogPostList collection="blog" />
|
||||||
</Page>
|
</Page>
|
||||||
|
|
44
src/pages/blog/tags/[tag].astro
Normal file
44
src/pages/blog/tags/[tag].astro
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
import { getCollection } from "astro:content";
|
||||||
|
import Page from "~/layouts/Page.astro"
|
||||||
|
import Date from "~/components/util/Date.astro";
|
||||||
|
import StyledLink from "~/components/util/StyledLink.astro";
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const allPosts = await getCollection("blog");
|
||||||
|
const uniqueTags = [
|
||||||
|
...new Set(allPosts.map((post) => post.data.tags).flat()),
|
||||||
|
];
|
||||||
|
|
||||||
|
return uniqueTags.map((tag) => {
|
||||||
|
const filteredPosts = allPosts.filter((post) =>
|
||||||
|
post.data.tags.includes(tag)
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
params: { tag },
|
||||||
|
props: { posts: filteredPosts },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { tag } = Astro.params;
|
||||||
|
const { posts } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<Page title={`Posts tagged with #${tag}`} icon="fa-solid fa-tag">
|
||||||
|
<StyledLink href="/blog/tags" icon="fa-solid fa-arrow-left">
|
||||||
|
See some more tags....
|
||||||
|
</StyledLink>
|
||||||
|
<ul class="fa-ul">
|
||||||
|
{
|
||||||
|
posts.map((post) => (
|
||||||
|
<li>
|
||||||
|
<i class={`fa-li ${post.data.icon} text-light-pu dark:text-dark-pu`}></i>
|
||||||
|
<a href={`/blog/${post.id}`}>{post.data.title}</a>
|
||||||
|
<span class="text-sm text-light-tx-2 dark:text-dark-tx-2">
|
||||||
|
(<Date date={post.data.date} />)
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</Page>
|
|
@ -6,12 +6,15 @@ const allPosts = await getCollection("blog");
|
||||||
const tags = [...new Set(allPosts.map((post) => post.data.tags).flat())];
|
const tags = [...new Set(allPosts.map((post) => post.data.tags).flat())];
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="Tags" description="">
|
<Layout title="Tags" description="all the tags i've used, and probably some spelling mistakes" icon="fa-solid fa-tags">
|
||||||
<ul class="fa-ul">
|
<ul class="fa-ul">
|
||||||
{
|
{
|
||||||
tags.map((tag) => <li>
|
tags.map((tag) => <li>
|
||||||
<i class="fa-li fa-solid fa-hashtag"></i>
|
<i class="fa-li fa-solid fa-hashtag text-light-pu dark:text-dark-pu"></i>
|
||||||
<a href={`/blog/tags/${tag}`}>{tag}</a>
|
<a href={`/blog/tags/${tag}`}>{tag}</a>
|
||||||
|
<span class="text-sm text-light-tx-2 dark:text-dark-tx-2">
|
||||||
|
({allPosts.filter((post) => post.data.tags.includes(tag)).length})
|
||||||
|
</span>
|
||||||
</li>)
|
</li>)
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -26,7 +26,7 @@ import Prose from "~/components/ui/Prose.astro";
|
||||||
|
|
||||||
<div class="md:flex md:flex-column gap-6">
|
<div class="md:flex md:flex-column gap-6">
|
||||||
<Box title="latest blog posts" icon="fa-solid fa-blog">
|
<Box title="latest blog posts" icon="fa-solid fa-blog">
|
||||||
<CollectionList collection="blog" limit={5} />
|
<CollectionList limit={5} />
|
||||||
<hr class="h-px my-8 bg-light-pu dark:bg-dark-pu" />
|
<hr class="h-px my-8 bg-light-pu dark:bg-dark-pu" />
|
||||||
<StyledLink href="/blog">see more</StyledLink>
|
<StyledLink href="/blog">see more</StyledLink>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection, render } from "astro:content";
|
||||||
import Page from "~/layouts/Page.astro";
|
import Page from "~/layouts/Page.astro";
|
||||||
// import { Content } from "~/content/now.md";
|
// import { Content } from "~/content/now.md";
|
||||||
import Prose from "~/components/ui/Prose.astro";
|
import Prose from "~/components/ui/Prose.astro";
|
||||||
|
@ -14,23 +14,17 @@ async function getLatestNowPost() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const latestPost = await getLatestNowPost(); // Fetch the first post at build time
|
const latestPost = await getLatestNowPost(); // Fetch the first post at build time
|
||||||
|
|
||||||
|
const { Content } = await render(latestPost);
|
||||||
---
|
---
|
||||||
|
|
||||||
<Page title="/now" icon="fa-solid fa-calendar-days" date="2025-03-17">
|
<Page title="/now" description="" icon="fa-solid fa-calendar-days" date={latestPost.data.date}>
|
||||||
|
<Prose>
|
||||||
|
{latestPost ? <Content /> : <p>nae now</p>}
|
||||||
|
</Prose>
|
||||||
<p class="text-light-tx-2 dark:text-dark-tx-2 mt-2">
|
<p class="text-light-tx-2 dark:text-dark-tx-2 mt-2">
|
||||||
This is a <a href="https://sive.rs/nowff">/now page</a> and
|
This is a <a href="https://sive.rs/nowff">/now page</a> and
|
||||||
<a href="https://nownownow.com/about">you should make one</a>, too.
|
<a href="https://nownownow.com/about">you should make one</a>, too. <br>
|
||||||
|
It's generated from the latest post tagged with <a href="/blog/tags/now">#now</a>, which currently is <a href={`/blog/${latestPost.id}`}>{latestPost.data.title}</a>.
|
||||||
</p>
|
</p>
|
||||||
<Prose>
|
|
||||||
{
|
|
||||||
latestPost ? (
|
|
||||||
<div>
|
|
||||||
<h2>{latestPost.data.title}</h2>
|
|
||||||
<p>{latestPost.data.description}</p>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<p>nae now</p>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</Prose>
|
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
export default {
|
export default {
|
||||||
siteName: "Ivy Turner",
|
site: {
|
||||||
description: "Ivy Turner's personal website",
|
url: "https://ivyneeds.rest",
|
||||||
fediverse: "@ivy@social.lol",
|
title: "Ivy Turner",
|
||||||
|
description: "Ivy Turner's personal website",
|
||||||
|
},
|
||||||
|
author: {
|
||||||
|
name: "Ivy Turner",
|
||||||
|
fedi: "@ivy@social.lol",
|
||||||
|
email: "ivy@sorbet.gay",
|
||||||
|
},
|
||||||
devMode: {
|
devMode: {
|
||||||
showDraftPages: true,
|
showDraftPages: true,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue