Files
bztmon-site/src/content.config.ts
T
jwright 354475a453
build-and-deploy / build (push) Failing after 11m14s
blog: hero images + publish secret-zero
Add an optional hero field to the blog schema; render it on the post page and
as the index card thumbnail. Ship 4 verified Nano Banana hero images (shipping/
init-gating/authentik/workload) as optimized webp (64-134KB). Publish the
secret-zero post. (outbound hero pending — its file was a dup of shipping;
secret-zero hero pending generation.)
2026-06-29 17:37:40 +10:00

43 lines
1.4 KiB
TypeScript

import { defineCollection } from "astro:content";
import { z } from "astro:schema";
import { glob } from "astro/loaders";
// Case studies. Adding a project = one .md file in src/content/projects/.
const projects = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./src/content/projects" }),
schema: z.object({
title: z.string(),
// The one-line "so what" — shown on cards and the case-study header.
outcome: z.string(),
summary: z.string(),
role: z.string(),
period: z.string(),
stack: z.array(z.string()),
featured: z.boolean().default(false),
// Lower sorts first on the index + homepage.
order: z.number().default(50),
// Optional diagram key → rendered by the Diagram component (M3).
diagram: z.string().optional(),
links: z
.array(z.object({ label: z.string(), href: z.string().url() }))
.optional(),
}),
});
// Blog — write-only, schema-validated, pipeline-publishable.
const blog = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
schema: z.object({
title: z.string(),
date: z.coerce.date(),
summary: z.string(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
// Optional hero image — a /blog/<slug>.webp in public/. Rendered on the post + as the card thumbnail.
hero: z.string().optional(),
heroAlt: z.string().optional(),
}),
});
export const collections = { projects, blog };