Blog
MDX blog with citations, JSON-LD schema, AI-Summarize bar, glossary linking, and a category index. No CMS, no database, just files.
What's enforced
The blog reads MDX files from content/blog/ at build time via next-mdx-remote and gray-matter. No CMS, no database. Posts are static-rendered, citations are typed, FAQ data renders as both visible DOM and FAQPage JSON-LD, and the renderer emits Article + BreadcrumbList JSON-LD on every post.
The same renderer is the surface the SecureStartKit content corpus runs on. Everything you see at /blog is the same template you ship.
Creating a post
Create content/blog/your-post-slug.mdx:
---
title: "Your Post Title"
description: "A short description for SEO and link previews."
date: 2026-05-25
modified: 2026-05-25
author: "Your Name"
category: "Guide"
tags: ["nextjs", "supabase"]
published: true
citations:
- url: "https://example.com/source"
title: "Source Article Title"
source: "example.com"
faq:
- question: "A question your readers actually ask?"
answer: "A complete, self-contained answer."
---
Your content here. Markdown plus React components.
Frontmatter fields
| Field | Required | Purpose |
|---|---|---|
title | Yes | Post title (use front-loaded keywords for SERP CTR) |
description | Yes | SEO description and link preview text (keep under 155 characters) |
date | Yes | Original publish date (ISO YYYY-MM-DD) |
modified | No | Last substantive update; activates the visible "Last updated" line + dateModified in Article schema |
author | No | Author name (used in visible byline + Person schema) |
authorCredential | No | One-line credential shown next to the byline |
category | No | Single category string; categories get their own index page at /blog/category/[category] |
tags | No | Array of tag strings |
image | No | Cover image URL |
published | No | Defaults to true. Set false to hide |
citations | No | Typed source list; rendered as a numbered references section + inline [1] markers in body |
faq | No | Typed FAQ array; rendered as visible DOM AND emitted as FAQPage JSON-LD (single source of truth) |
The modified field is the one nuance that matters: only update it when you make substantive content changes. Bumping modified on a date-only edit signals fake freshness to Google's quality classifiers and risks demotion.
Categories and the index
Categories are extracted automatically from the published posts and rendered at:
/blog(the main index, paginated)/blog/category/[category](per-category index)
The sitemap auto-includes both the index and per-category pages.
RSS feed
The RSS feed at /feed.xml is generated from the published posts. Subscribers get every new post automatically.
AI-Summarize bar
Every post includes a "Summarize with AI" bar above the article body. It copies the canonical post URL to clipboard and opens ChatGPT, Claude, or Perplexity with a pre-filled prompt. This is the one user-visible component that explicitly courts AI-engine traffic; the rest of the GEO work (atomic answers, citable passages, schema) is in the content itself.
To customize the prompt text or AI engines, edit components/shared/summarize-with-ai.tsx.
Glossary first-mention linking
Many blog posts reference defined security terms (RLS, Server Actions, AAL, PKCE). The convention is to link the FIRST mention of a glossary term in body text to /glossary/[slug]. Subsequent mentions stay unlinked to avoid over-linking. Terms that ARE the post's primary topic do not link to the glossary (avoids cannibalization).
The glossary data file is lib/glossary.ts. Adding new terms there makes them link-target candidates for future posts.
Writing posts with the /write-blog skill
If you have Claude Code installed, /write-blog automates the full research-to-publish flow: keyword research, primary-source verification, brand-frame compliance, citation insertion, internal-linking, and topical-map updates. See Claude Code skills for the four bundled skills.