Adds post tags

This commit is contained in:
2026-03-11 18:29:08 -07:00
parent 0a9f425591
commit 3a33325d3a
7 changed files with 173 additions and 84 deletions

View File

@@ -1,13 +1,14 @@
--- ---
interface Props { interface Props {
fillNotches: "left" | "right" | "both" | "none"; fillNotches: "left" | "right" | "both" | "none";
color?: string;
} }
const { fillNotches = "none" } = Astro.props; const { fillNotches = "none", color = "gold" } = Astro.props;
--- ---
<div class={`container notch-${fillNotches}`}> <div class={`container notch-${fillNotches}`} style={`background-color: var(--color-${color})`}>
<div class="content"> <div class="content">
<slot /> <slot />
</div> </div>

View File

@@ -14,6 +14,7 @@ const blog = defineCollection({
pubDate: z.coerce.date().optional(), pubDate: z.coerce.date().optional(),
updatedDate: z.coerce.date().optional(), updatedDate: z.coerce.date().optional(),
heroImage: image().optional(), heroImage: image().optional(),
tags: z.array(z.string()).optional(),
}), }),
}); });

View File

@@ -2,6 +2,9 @@
title: "The Forge of God by Greg Bear" title: "The Forge of God by Greg Bear"
description: "A short review" description: "A short review"
pubDate: "Jul 18 2025" pubDate: "Jul 18 2025"
tags:
- Sci-Fi
- Book Review
--- ---
[The Forge of God](https://en.wikipedia.org/wiki/The_Forge_of_God) by [Greg Bear](https://en.wikipedia.org/wiki/Greg_Bear) is a bit of an old book to be reviewing now. It was first published in 1987 and it's 2025 now. Did I pick it up without realizing this? Was a stricken with an acute case of nostalgia? Was I trapped in an abandoned house with nothing else to read? Dear reader, I assure you that nothing so exciting happened. I simply saw it on my shelf and decided to read it. I don't need any other reason that that. [The Forge of God](https://en.wikipedia.org/wiki/The_Forge_of_God) by [Greg Bear](https://en.wikipedia.org/wiki/Greg_Bear) is a bit of an old book to be reviewing now. It was first published in 1987 and it's 2025 now. Did I pick it up without realizing this? Was a stricken with an acute case of nostalgia? Was I trapped in an abandoned house with nothing else to read? Dear reader, I assure you that nothing so exciting happened. I simply saw it on my shelf and decided to read it. I don't need any other reason that that.

View File

@@ -2,6 +2,10 @@
title: "I Forgot to Use AI On My Latest Project" title: "I Forgot to Use AI On My Latest Project"
description: "I forgot to use an LLM to assist on my latest coding project. I probably set the progress of humanity back many hours. But hey, I learned something along the way. What did I learn? That I'd rather not use an LLM on this project." description: "I forgot to use an LLM to assist on my latest coding project. I probably set the progress of humanity back many hours. But hey, I learned something along the way. What did I learn? That I'd rather not use an LLM on this project."
pubDate: "Jun 26 2025" pubDate: "Jun 26 2025"
tags:
- AI
- Tech
- Coding
--- ---
I forgot to use AI on my last project. All the tech bros are laughing at me right now. I'm sure in the time I wasted I could have launched a cloud-based passive-income app, but now I'll just have fun staying poor. I'll cry myself to sleep right after I get the satisfaction of learning something new and building something with my own mind. I forgot to use AI on my last project. All the tech bros are laughing at me right now. I'm sure in the time I wasted I could have launched a cloud-based passive-income app, but now I'll just have fun staying poor. I'll cry myself to sleep right after I get the satisfaction of learning something new and building something with my own mind.

140
src/layouts/BlogList.astro Normal file
View File

@@ -0,0 +1,140 @@
---
import NotchedBox from '../components/NotchedBox.astro';
import RootLayout from '../layouts/RootLayout.astro';
import { getCollection, type CollectionEntry } from 'astro:content';
import FormattedDate from '../components/FormattedDate.astro';
import { Image } from 'astro:assets';
interface Params {
selectedTag?: string | undefined;
}
const { selectedTag } = Astro.props;
function publishedOnly(p: CollectionEntry<'blog'>): p is (CollectionEntry<'blog'> & { data: { pubDate: Date }}) {
return p.data.pubDate !== undefined;
}
const allPosts = (await getCollection('blog', publishedOnly))
.sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
const tags = allPosts.flatMap(p => p.data.tags);
const posts =
selectedTag
? allPosts.filter(p => p.data.tags.includes(selectedTag))
: allPosts;
---
<RootLayout>
<style>
ul.tags {
list-style: none;
margin: 0;
margin-bottom: 1em;
padding: 0;
display: flex;
flex-direction: row;
gap: 8px;
align-items: baseline;
li {
padding: 1px 16px
.container {
background-color: var(--color-gray);
}
}
}
ul.posts {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 16px;
align-items: stretch;
li {
/* Required since flex won't render list-elements correctly. */
display: block;
}
a {
text-decoration: none;
.title, .description {
color: var(--color-light-text);
}
.date {
color: var(--color-gray);
}
.entry {
padding: 0.5em;
}
p {
margin: 0;
}
}
a:hover .title {
color: var(--color-accent);
}
}
</style>
<section>
<ul class="tags">
{
tags.map(tag =>
<li>
{
tag === selectedTag
? <a href="/blog">
<NotchedBox color="gray" fillNotches={"left"}>
{tag}
</NotchedBox>
</a>
: <a href={`/blog/tag/${tag}`}>
<NotchedBox color="gray" fillNotches={"none"}>
{tag}
</NotchedBox>
</a>
}
</li>
)
}
</ul>
</section>
<section>
<ul class="posts">
{
posts.map((post) => (
<li>
<a href={`/blog/${post.id}/`}>
<NotchedBox fillNotches="left">
<div class="entry">
{post.data.heroImage && (
<Image width={720} height={360} src={post.data.heroImage} alt="" />
)}
<h4 class="title">{post.data.title}</h4>
<p class="date">
<FormattedDate date={post.data.pubDate} />
</p>
{ post.data.description &&
<p class="description">
{post.data.description}
</p>
}
</div>
</NotchedBox>
</a>
</li>
))
}
</ul>
</section>
</RootLayout>

View File

@@ -1,85 +1,5 @@
--- ---
import NotchedBox from '../../components/NotchedBox.astro'; import BlogList from '../../layouts/BlogList.astro';
import RootLayout from '../../layouts/RootLayout.astro';
import { getCollection, type CollectionEntry } from 'astro:content';
import FormattedDate from '../../components/FormattedDate.astro';
import { Image } from 'astro:assets';
function publishedOnly(p: CollectionEntry<'blog'>): p is (CollectionEntry<'blog'> & { data: { pubDate: Date }}) {
return p.data.pubDate !== undefined;
}
const posts = (await getCollection('blog', publishedOnly))
.sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
--- ---
<RootLayout> <BlogList/>
<style>
ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 16px;
align-items: stretch;
li {
/* Required since flex won't render list-elements correctly. */
display: block;
}
a {
text-decoration: none;
.title, .description {
color: var(--color-light-text);
}
.date {
color: var(--color-gray);
}
.entry {
padding: 0.5em;
}
p {
margin: 0;
}
}
a:hover .title {
color: var(--color-accent);
}
}
</style>
<section>
<ul>
{
posts.map((post) => (
<li>
<a href={`/blog/${post.id}/`}>
<NotchedBox fillNotches="left">
<div class="entry">
{post.data.heroImage && (
<Image width={720} height={360} src={post.data.heroImage} alt="" />
)}
<h4 class="title">{post.data.title}</h4>
<p class="date">
<FormattedDate date={post.data.pubDate} />
</p>
{ post.data.description &&
<p class="description">
{post.data.description}
</p>
}
</div>
</NotchedBox>
</a>
</li>
))
}
</ul>
</section>
</RootLayout>

View File

@@ -0,0 +1,20 @@
---
import { type CollectionEntry, getCollection } from 'astro:content';
import BlogList from '../../../layouts/BlogList.astro';
export async function getStaticPaths() {
const posts = await getCollection('blog');
const tags = posts.flatMap(p => p.data.tags);
return tags.map((tag) => ({
params: { tag: tag },
props: { tag: tag },
}));
}
type Props = { tag: string }
const tag = Astro.props.tag;
---
<BlogList selectedTag={tag} />