docs(blog): add blog with halation/FFmpeg post#119
Conversation
Starlight site gets a /blog index and a per-post page driven by an Astro content collection (Markdown frontmatter, JSON-LD Article + optional FAQPage, per-post OG image via the Base layout). First published post: halation in FFmpeg vs one Hance flag. Real sunflower before/after images for both pipelines, the exact filter_complex, and the equivalent CLI flags. Dehancer/FilmConvert comparison post is included but flagged draft:true so it stays unlisted until it ships.
RichardBray
left a comment
There was a problem hiding this comment.
Blog infra is clean. Content collection + JSON-LD + per-post OG image is exactly the right shape. Posts are well-written and honest (the Dehancer post credits competitors on fidelity). One nit on heroImage validation below, otherwise good to merge.
The split from #118 was clean - no docs file references anything in the dither code, and the dither code doesn't touch anything in packages/docs/.
| pubDate: z.coerce.date(), | ||
| author: z.string().default("Richard Oliver Bray"), | ||
| // Header image: public path (e.g. "/blog/foo.png"). Also used as the | ||
| // per-post OG/Twitter card. Kept a string (not an Astro asset) so a |
There was a problem hiding this comment.
Minor: the comment says heroImage is kept as a plain string so "a not-yet-created file doesn't fail the build." That's convenient for drafting, but it means a published post with a typo'd heroImage will silently render a broken <img> in production - both on the post page ([...slug].astro:43) and on the index (index.astro:46), plus a broken OG card.
Two options:
-
Validate non-draft posts at build time. Add a ref-style check that fails the build when
!data.draft && !existsSync('public/' + data.heroImage). Drafts stay loose, published posts are guaranteed to have the asset. -
Keep it loose but warn. Log a build-time warning when the file is missing. Less safe but zero friction.
Option 1 is more aligned with how the rest of the site handles slugs - astro.config.mjs already fails the build on a missing slug, so a missing hero image failing too is consistent.
There was a problem hiding this comment.
Good catch - went with option 1. Added a .refine on the blog schema in content.config.ts that fails the build when a non-draft post's heroImage is missing from public/. Drafts stay loose so they can point at a not-yet-created asset. Mirrors the slug-validation behaviour you mentioned. Fixed in f847dc7.
- Click in-article blog images to open fullscreen, click again to zoom 2.5x with cursor-follow pan, X/Esc/backdrop to close (native <dialog>) - Explain the magenta cast and reword the FFmpeg crudeness paragraphs
Mirrors how a bad slug already fails the build. Drafts stay loose so they can reference a not-yet-created asset; non-draft posts must have the file in public/ or the build errors instead of shipping a broken <img> and OG card. Addresses PR #119 review feedback.
Mirrors how a bad slug already fails the build. Drafts stay loose so they can reference a not-yet-created asset; non-draft posts must have the file in public/ or the build errors instead of shipping a broken <img> and OG card. Addresses PR #119 review feedback.
What
Starlight site gets a
/blogindex and a per-post page driven by an Astro content collection (Markdown frontmatter, JSON-LD Article + optional FAQPage, per-post OG image via the Base layout).First published post
Halation in FFmpeg vs one Hance flag. Real sunflower before/after images for both pipelines, the exact
filter_complex, and the equivalent CLI flags.Also includes
draft: true, stays unlisted until it ships)/blogBase.astroaccepts a per-page OG image prop (falls back to/og-card.png)Test
bun run buildfrompackages/docs. The draft post is filtered from the index and fromgetStaticPaths, so it isn't routed or listed.Split out of #118 so the dither fix and the blog can ship independently.