M2: content collections — case studies, blog, RSS, tags, sitemap

Projects + blog as schema-validated content collections; structured case
studies (problem/design/outcome), blog with tag pages, reading time, RSS
feed (drafts excluded), sitemap, and Shiki dual-theme code highlighting.
This commit is contained in:
2026-06-17 16:56:46 +10:00
parent 720d579386
commit 22f482d89a
26 changed files with 1139 additions and 105 deletions
+9 -5
View File
@@ -2,24 +2,28 @@
import Layout from "../../layouts/Layout.astro";
import Section from "../../components/Section.astro";
import ProjectCard from "../../components/ProjectCard.astro";
import { projects } from "../../data/projects";
import { getCollection } from "astro:content";
const projects = (await getCollection("projects")).sort(
(a, b) => a.data.order - b.data.order,
);
---
<Layout title="Projects" path="/projects" description="Selected platform & infrastructure projects by Jonathon Wright.">
<Section id="all-projects" eyebrow="Projects" index="*" title="Everything I've built worth writing about.">
<p class="lead projects__intro" data-reveal>
Edge Kubernetes, GPU inference, self-hosted AI, and the automation that ties
it together. Full case studies are on the way.
Edge Kubernetes, GPU inference, self-hosted AI, and the automation that ties it
together — each with the problem, the design, and the outcome.
</p>
<div class="grid">
{projects.map((project) => <ProjectCard project={project} />)}
{projects.map((entry) => <ProjectCard entry={entry} />)}
</div>
</Section>
</Layout>
<style>
.projects__intro {
max-width: 50ch;
max-width: 52ch;
margin-bottom: var(--space-6);
}
.grid {