chchchchch changez

This commit is contained in:
Laker Turner 2025-03-30 21:12:05 +01:00
parent 2232741e04
commit f0b541cfdc
No known key found for this signature in database
24 changed files with 175 additions and 129 deletions

View file

@ -1,6 +1,6 @@
// @ts-check
import { defineConfig } from 'astro/config';
import config from '~/site.config'
import tailwindcss from '@tailwindcss/vite';
// https://astro.build/config

View file

@ -4,12 +4,11 @@ import { getCollection } from "astro:content";
import { getPublishedAndSortedPosts } from "~/lib/blog";
interface Props {
collection: string;
limit?: number;
}
const { collection, limit } = Astro.props;
const items = getPublishedAndSortedPosts(await getCollection(collection));
const { limit } = Astro.props;
const items = getPublishedAndSortedPosts(await getCollection("blog"));
const limitedItems = limit ? items.slice(0, limit) : items;
const getPostIcon = (item: { data: { icon?: string } }) => {
@ -26,16 +25,17 @@ const getPostIcon = (item: { data: { icon?: string } }) => {
<li>
<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>
</a>
<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" />
<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) => (
<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>

View file

@ -24,7 +24,7 @@ const renderedItems = await Promise.all(
<ul class="fa-ul space-y-4 my-2">
{
renderedItems.map((item) => (
<li>
<li class="max-w-[700px] p-4 rounded-lg shadow-lg">
<i class={`fa-li ${item.data.icon}`} />
<a href={`/notes/${item.id}`}>
<Date date={item.data.date} />

View file

@ -1,5 +1,5 @@
---
import { isBirthday } from "~/lib/fun";
---
<footer class="mt-12 text-sm text-light-tx-2 dark:text-dark-tx-2">
@ -10,5 +10,12 @@
ivyturner/trellis
</a>
</p>
<p>love yourself.</p>
<p>love yourself.
{isBirthday() && (
<span class="text-light-accent dark:text-dark-accent">
{" "}
happy birthday!
</span>
)}
</p>
</footer>

View file

@ -1,30 +1,13 @@
---
import Navigation from "./Navigation.astro";
import conf from "~/site.config";
import { isBlog } from "~/lib/metadata";
let headertext = conf.siteName;
let headertext = conf.site.title;
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">
<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>
</h1>
<Navigation />

View file

@ -23,7 +23,7 @@ const headerLinks = [
{
label: "Blog",
href: "/blog",
icon: "fa-solid fa-blog",
icon: "fa-solid fa-star",
},
{
label: "Contact",
@ -36,12 +36,11 @@ const headerLinks = [
<nav class="flex flex-row gap-4">
{
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`} />
<a
href={link.href}
class="underline decoration-wavy underline-offset-4 decoration-1.5
decoration-light-pu dark:decoration-dark-pu"
class=""
>
{link.label}
</a>

View file

@ -4,21 +4,27 @@ import { clsx } from "clsx";
interface Props {
level: number;
icon?: string;
heading?: string;
xstyle?: string;
}
// level 0: info/note
// level 1: warning
// level 2: attn needed: oh fuck
const { level } = Astro.props;
const { level, icon, heading, xstyle } = Astro.props;
---
<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-or dark:bg-dark-or": level === 1,
"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 />
</div>

View file

@ -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 />
</div>

View file

@ -15,7 +15,7 @@ const { title, description, icon, date } = Astro.props;
if (date) {
return (
<p class="mt-2 text-sm text-light-tx-2 dark:text-dark-tx-2">
last updated: <Date date={date} />
<Date date={date} />
</p>
);
}

View file

@ -1,5 +1,5 @@
---
import siteConfig from "~/site.config";
import conf from "~/site.config";
import { getClacks } from "~/lib/fun";
import { descriptionConstructor, titleConstructor } from "~/lib/metadata";
@ -7,38 +7,36 @@ const { title, description } = Astro.props;
---
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{titleConstructor(title, Astro.url.pathname)}</title>
<meta name="description" content={descriptionConstructor(description)} />
<meta name="author" content="Ivy Turner" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{titleConstructor(title)}</title>
<meta name="description" content={descriptionConstructor(description)} />
<meta name="author" content="Ivy Turner" />
{/* og */}
<meta
property="og:title"
content={titleConstructor(title, Astro.url.pathname)}
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://ivyneeds.rest" />
<meta property="og:image" content="https://ivyneeds.rest/image.jpg" />
<link rel="icon" href="https://fav.farm/%F0%9F%92%9C" />
{/* og */}
<meta property="og:title" content={titleConstructor(title)} />
<meta property="og:description" content={descriptionConstructor(description)}/>
<meta property="og:type" content="website" />
<meta property="og:url" content={conf.site.url} />
<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" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<meta name="theme-color" content="#5E409D" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
{/* font awesone */}
<link
href="https://cdn.laker.tech/web/fa/css/fontawesome.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" />
{/* font awesone */}
<link
href="https://cdn.laker.tech/web/fa/css/fontawesome.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" />
{/* analytics */}
{/* analytics */}
{/* astro generator */}
<meta name="generator" content={Astro.generator} />
{/* astro generator */}
<meta name="generator" content={Astro.generator} />
{/* clacks */}
<meta http-equiv="X-Clacks-Overhead" content={`GNU ${getClacks()}`} />
{/* clacks */}
<meta http-equiv="X-Clacks-Overhead" content={`GNU ${getClacks()}`} />
</head>

View file

@ -11,9 +11,9 @@ const blog = defineCollection({
title: z.string(),
description: z.string(),
date: z.date().default(new Date()),
tags: z.array(z.string()).optional(),
tags: z.array(z.string()),
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
.object({
src: z.string(),

View file

@ -1,4 +1,4 @@
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.

View file

@ -3,6 +3,7 @@ title: meow
description: meow meow meow
date: 2025-03-17
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

View file

@ -3,4 +3,8 @@ title: "/now: 2025-W13"
description: "its now"
date: 2025-03-24
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
View 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"
]

View file

@ -9,7 +9,7 @@ const { title, description, icon, date } = Astro.props;
<Layout title={title} description={description} date={date}>
<div>
<Header />
<main>
<main class="pr-48">
<Strapline title={title} description={description} icon={icon} date={date} />
<slot />
</main>

View file

@ -1,28 +1,13 @@
// all the code for making fun stuff happen
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",
];
import flavourText from "~/data/flavourtext.json";
export function getFlavourText() {
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 birthday = new Date(today.getFullYear(), 3, 13);
const birthday = new Date(today.getFullYear(), 9, 16); // October 16
const check =
today.getMonth() === birthday.getMonth() &&
today.getDate() === birthday.getDate();
@ -30,7 +15,14 @@ export function isBirthday() {
return check;
}
// https://gnuterrypratchett.com/index.php
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(", ");
}

View file

@ -1,25 +1,18 @@
import conf from "~/site.config";
let siteName = conf.site.title;
let siteDescription = conf.site.description;
export const isBlog = (pathname: string) => {
return pathname.startsWith("/blog");
};
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 titleConstructor = (title: string) => {
if (!title) return siteName;
return `${title} | ${siteName}`;
};
export const descriptionConstructor = (description: string) => {
if (!description) return conf.description;
if (!description) return siteDescription;
return `${description}`;
};
export const noteTitleConstructor = (title: string, date: Date) => {
if (title) return title;
if (title) return `A note titled ${title}`;
return `A note from ${date.toLocaleDateString()}`;
};

View file

@ -4,10 +4,10 @@ import BlogPostList from "~/components/lists/BlogPostList.astro";
---
<Page
title="Post index"
title="Blog thing yes yes"
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" />
</Page>

View 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>

View file

@ -6,12 +6,15 @@ const allPosts = await getCollection("blog");
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">
{
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>
<span class="text-sm text-light-tx-2 dark:text-dark-tx-2">
({allPosts.filter((post) => post.data.tags.includes(tag)).length})
</span>
</li>)
}
</ul>

View file

@ -26,7 +26,7 @@ import Prose from "~/components/ui/Prose.astro";
<div class="md:flex md:flex-column gap-6">
<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" />
<StyledLink href="/blog">see more</StyledLink>
</Box>

View file

@ -1,5 +1,5 @@
---
import { getCollection } from "astro:content";
import { getCollection, render } from "astro:content";
import Page from "~/layouts/Page.astro";
// import { Content } from "~/content/now.md";
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 { 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">
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>
<Prose>
{
latestPost ? (
<div>
<h2>{latestPost.data.title}</h2>
<p>{latestPost.data.description}</p>
</div>
) : (
<p>nae now</p>
)
}
</Prose>
</Page>

View file

@ -1,7 +1,14 @@
export default {
siteName: "Ivy Turner",
description: "Ivy Turner's personal website",
fediverse: "@ivy@social.lol",
site: {
url: "https://ivyneeds.rest",
title: "Ivy Turner",
description: "Ivy Turner's personal website",
},
author: {
name: "Ivy Turner",
fedi: "@ivy@social.lol",
email: "ivy@sorbet.gay",
},
devMode: {
showDraftPages: true,
},