Features
The blog: posts, guides and comparisons
MDX files in site/content/blog/, one per post, rendered at /blog/<slug>.
The model post is writing-your-first-post.mdx (a draft, so it never ships);
/add-blog-post writes new ones in the same shape.
What the site does with a post
| Surface | What it shows |
|---|---|
/blog/<slug> | the answer first, then the body, sources, tags, related posts |
/blog/<slug>/opengraph-image | a share card with the title and answer |
/blog, /blog/tag/<tag> | lists; noindex until MIN_INDEXABLE_ITEMS (3) posts |
/authors/<id> | the author, their profiles, their posts (site/lib/authors.ts) |
| JSON-LD | BlogPosting (or TechArticle for guides) with the answer as abstract, plus breadcrumbs |
/sitemap.xml | every post; the index and tags once they pass the threshold |
/feed.xml | posts and releases, newest first |
/llms.txt, /llms-full.txt | each post by its answer; the full text with sources |
| footer | a Blog link, once there is a published post |
Drafts (draft: true) render under pnpm dev only: never in a build, the
sitemap or the feed.
The rules, and why
site/lib/blog/index.ts holds them, and a post that breaks one fails the
build with the file and the reason:
- Answer first (
answer, one or two sentences). Search results and answer engines lift the first direct answer. A post that makes them read five paragraphs of scene-setting gets someone else quoted. - Title at most 60 characters, description at most 155, no price in the description. These are the lengths search results show, and prices live in one file.
- Hand-written dates.
updatedmoves when the prose changes. It feeds the byline, the JSON-LDdateModifiedand the sitemaplastModified, so it can never be a clock. - Sources with
https://links for every claim a reader might check. They're printed under the post and inllms-full.txt. - Comparisons also need
checked:(the date the facts about other products were verified) and at least one source. No verdicts: facts, a source for each, the date, and the reader decides. - The plain-text mirror (
llms-full.txt, search snippets) is generated from the MDX. The test fails a post whose mirror is empty or still carries markup.
Getting found
- IndexNow. Set
INDEXNOW_KEY(8 to 128 letters, digits or hyphens) and deploy. The site then serves/indexnow-key.txt, and after each deploy that publishes or changes posts, runcd site && pnpm indexnow(the whole sitemap) orpnpm indexnow /blog/<slug>. Bing, and through it ChatGPT search, picks the pages up within hours. - AI crawlers are allowed (
site/app/robots.tslists them by name). Blocking them is one edit there, with the reasons written beside it. - Authors are real people. Fill in
site/lib/authors.ts, with profiles that prove the person exists. Engines weigh attributable writing.
This page is docs/blog.md in the repository, copied 2026-09-25.