354475a453
build-and-deploy / build (push) Failing after 11m14s
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.)
43 lines
1.4 KiB
TypeScript
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 };
|