Skip to main content
Resources / Product Concepts / Reader Publications
Product concept · Reference implementation

A serial longform publication where editorial discipline is the architecture — not a CMS afterthought.

Long-form publications break when the editorial layer is a UI on top of a database. Reader Publications inverts the stack: schema-validated frontmatter, a cross-entry invariant checker, and design tokens as code — so the manuscript and the build refuse to diverge. The live showcase is Outchurched, a 34-day greenfield build that hit production on day 28.

Live in production at outchurched.websiteAstro · MDX · Zod · JSON Schema · OKLCH tokens · nginx · Traefik
34days
first-commit to v0.3.0 production launch
122
merged PRs across 610 commits, single-contributor
6min
median PR time-from-creation-to-merge
9
reusable editorial design moves applied across the reader shell
01 — The problem

Generic CMSes leak. Hand-rolled publication sites rot.

Generic CMS · WordPress, Ghost, Contentful, Notion-as-CMS

Editorial integrity is an opt-in plugin, not a contract

The schema is whatever the editor happened to type. Cross-references break silently. Required fields aren't required. Translation, taxonomy, and version pinning are bolted-on add-ons whose contracts drift from the manuscript. A typo in one entry can publish a broken page hours later, and the build will not stop you.

Bespoke publication sites · hand-rolled Next/Astro/Hugo

Schema discipline starts strong and decays

Day-one frontmatter is clean. By chapter forty, optional fields have crept in, two contributors disagree about field names, the cross-reference convention shifted, and the design tokens are scattered across half a dozen CSS files. Nothing automated tells you the manuscript and the build have diverged — until a release breaks the reader experience.

Reader Publications closes the gap

The manuscript and the website are coupled by a checked contract. Frontmatter validates against generated Zod schemas, a cross-entry invariant checker runs before every build, and design tokens emit from a single source — so a broken manuscript cannot produce a deployed site, and the editorial system cannot quietly drift from the design system.

02 — What it is

A two-repo split with a checked contract at the seam.

The website repo owns Astro, build, and tooling. The content submodule owns the manuscript, the JSON Schemas, and the editorial specs. The seam between them is enforced by codegen, schema validation, and a cross-entry invariant checker — every build, every PR, every release.

1

Two-repo split with submodule pinning

The website repo never duplicates manuscript content; the content repo never holds Astro tooling. They link via a Git submodule pinned to an explicit SHA per release — make sync-content advances the pin, releases bake the SHA into the deploy. The build is reproducible from git alone, with no --remote drift at deploy time.

2

JSON Schema → Zod codegen, validated at build

Four JSON Schema files (book, episode, chapter, threads) are the upstream source of truth for frontmatter shape. make gen-schemas emits src/generated/content-schemas.ts as named Zod exports; Astro's Content Layer validates every MDX file against them. A frontmatter typo is a build failure, not a 404 in production.

3

Cross-entry invariant checker as the final build gate

scripts/check-invariants.mjs runs as the last step of pnpm prebuild before every astro build — including inside the Docker builder stage. It enforces seven rules JSON Schema cannot express: unique IDs per collection, chapter.episode resolves to a real episode, every crossReferences[] entry resolves to a real chapter, outline coverage, and per-(episode, part) personal-voice presence. A broken content tree cannot produce a deployed site.

outchurched.website — 34-day greenfield to production launch
First commit on 2026-04-18; v0.3.0-launch tagged on 2026-05-16 at 575 commits[1]. Across the project: 122 merged PRs, 213 commits carrying explicit WBS task identifiers, a 6-minute median PR turnaround[2], and a single in-flight revert epic structured as four reviewable steps rather than one squashed commit[3]. The contract held: when CI gates finally turned on for master, the first failure was a 5-line absolute-path test bug — caught before it shipped[4].
Two repos, one submodule pin, reproducible from git alone4 JSON Schemas → generated Zod → validated at every build7 invariants checked before any astro build succeeds9 editorial design moves applied across the reader shell
03 — Why it wins

Editorial discipline is structural, not a layer you bolt on.

A competitor can spin up an MDX blog in an afternoon. Holding a long-form publication to a schema-validated frontmatter contract, a cross-entry invariant checker, and a token-driven editorial design language across a hundred-plus chapters is a different exercise — and it is the entire bet.

Schema-validated frontmatter, generated from JSON Schema

Four JSON Schema files compile to named Zod exports via <code>make gen-schemas</code>. Astro's Content Layer validates every MDX file at build. A frontmatter typo fails the build, not the reader.

Cross-entry invariants checked before every build

Seven rules JSON Schema cannot express — unique IDs, cross-reference resolution, outline coverage, per-(episode, part) personal-voice presence — enforced by a Node ESM checker that runs in the Docker builder stage.

Two-repo split, pinned per release

Manuscript and tooling live in different repositories joined by an explicit-SHA submodule pin. The website never copies manuscript content; the content repo never holds Astro tooling. Releases are reproducible from git alone.

Design tokens as code, not as CSS sprawl

An OKLCH token system in <code>src/lib/tokens.ts</code> emits the entire palette, surface, text, border, and spacing scale to <code>src/styles/tokens.css</code>. A nine-move editorial design language reuses these tokens across the reader shell — masthead, title-page hero, pull-quote, lede band, contents-as-frontmatter, descent spine — with WCAG AA contrast verified by unit test.

Six author-facing MDX components, contract-locked

<code>KeyPassage</code>, <code>WordStudy</code>, <code>DiscoveryMoment</code>, <code>Application</code>, <code>PersonalVoice</code>, <code>Callout</code> — importable from <code>@/components/book</code> with a documented prop surface. Authors compose with these; the editorial system stays narrow, the manuscript stays portable.

$

Plain-HTTP origin behind shared Traefik, no per-tenant TLS surface

Production is <code>nginx:alpine</code> serving static files on internal port 8080. A shared Traefik v3 edge terminates TLS, issues Let's Encrypt certs via TLS-ALPN-01, and forwards cleartext on the <code>web</code> Docker network. The container ships no certs, binds no host ports, and adds the publication as one more tenant — not one more operational footprint.

04 — How we engage

Four engagement tiers — from a one-week scope to an ongoing build.

Every engagement is fixed-price against a written scope. We start small on purpose: a Discovery week usually pays for itself in scope clarity before a line of editorial schema is written.

Discovery
$8k fixed
Authors, editors, publishers scoping a long-form site
  • 1–2 weeks of joint work with you and your editorial lead
  • Frontmatter schema sketch (book / episode / chapter or equivalent)
  • Invariant catalogue — the rules your manuscript must obey
  • Written architecture brief and price quote for the build
MVP Publication
$35k–$60k fixed
Teams shipping a first long-form serial publication
  • 6–10 week build against the Discovery spec
  • Two-repo split with submodule pinning
  • JSON Schema → Zod codegen + cross-entry invariant checker
  • Reader shell with masthead, title-page hero, chapter reader, TOC
  • OKLCH token system + four to six MDX editorial components
Retainer
From $6k /mo
Live publications under active authoring
  • Ongoing schema and invariant evolution as the manuscript grows
  • New MDX component development and editorial design moves
  • Submodule-pin release cadence and CI maintenance
  • Performance, accessibility, and SEO regression work
05 — How it's built

The canonical stack we ship — proven in the reference implementation.

Frontend Astro 5 with MDX, the Content Layer API, and Islands-style hydration. Newsreader display + Inter Variable webfont, self-hosted. Reading column max-width: 68ch, line-height 1.7, OKLCH-tuned text colours that pass WCAG 2.1 AA on every shipped surface.
Content & schema MDX for the manuscript; JSON Schema (draft 2020-12) as the upstream contract; Zod generated via json-schema-to-zod and committed to src/generated/. Six author-facing components — KeyPassage, WordStudy, DiscoveryMoment, Application, PersonalVoice, Callout — importable from @/components/book.
Build & invariants pnpm with a frozen lockfile; pnpm prebuild runs gen-schemas then check-invariants.mjs before every astro build. Seven cross-entry rules enforced; broken manuscript = failed build, not failed reader.
Container Multi-stage Dockernode:24-alpine builder with BuildKit cache mount for the pnpm store; nginx:alpine runtime that discards the Node toolchain entirely. Image is the single deployable artefact; make test-e2e exercises the same image that ships.
Origin & edge nginx serves static files on internal :8080; Traefik v3 on a shared VPS terminates TLS via Let's Encrypt (TLS-ALPN-01). HSTS, CSP, X-Content-Type-Options, and Referrer-Policy set by container nginx — Traefik is header-transparent. Three cache tiers: _astro/* immutable for a year, *.html always-revalidate, everything else one hour.
Release & deploy Tag-triggered deploy.yml: BuildKit build → GHCR push (semver + :latest) → SSH into the VPS → docker compose pull && up -dcurl /healthz smoke. The content submodule pins to an explicit SHA in the release commit; deploy is reproducible from git alone, with no --remote drift at build time.
The stack
Astro 5MDXZodJSON SchemaTypeScriptOKLCH tokenspnpmDocker / nginxTraefik v3GitHub Actions / GHCR

Single-host nginx:alpine origin on internal port :8080, fronted by shared Traefik v3 that terminates TLS and forwards cleartext on a shared Docker network. The container ships no certs, binds no host ports, and reads no runtime env vars — all configuration is baked in at build time via --build-arg. To change a value, rebuild the image and redeploy.

06 — Engagement phases

Three fixed phases from a scoping call to a production handoff.

Every build runs through the same gates. Earlier phases are de-risked by the Discovery week; the handoff is non-negotiable — you leave with both repositories, the schemas, the invariant checker, and the deploy pipeline.

Discover
Week 0–2
Proven

Joint scoping with your editorial lead. We leave Discovery with a frontmatter schema sketch, a written invariant catalogue, a reader-shell wireframe, and a fixed quote for the build.

Build
Week 2–10
Where we live

Two-repo split with submodule pinning, JSON Schema → Zod codegen, cross-entry invariant checker, reader shell, MDX editorial components, OKLCH token system, multi-stage Docker, tag-triggered deploy. The reference implementation reached production in 34 days through this loop.

07 — Where this pattern fits

Anywhere a serial publication needs to hold a contract over time.

Outchurched is one instance of a generalisable pattern. The same architecture — manuscript-as-MDX, schema-validated frontmatter, cross-entry invariants, design tokens as code — applies wherever editorial discipline has to outlast the team that started it.

📖 Technical books — multi-chapter manuals with cross-references and code samples📰 Longform journalism — multi-installment investigations with citation contracts🎓 Academic publications — open monographs, edited volumes, journal special issues🗂 Multi-author collections — essay anthologies, festschriften, conference proceedings📚 Serialised fiction & memoir — episodic publications with internal continuity
Built by Amysoft Digital Technologies

Need a publication where the manuscript and the build cannot drift?

We build serial longform publications for authors, editors, and publishers who need editorial discipline as a checked contract — fixed price, fixed timeline, two-repo handoff. Start with a Discovery week; leave with a schema sketch, an invariant catalogue, and a quote. If you build, you own both repos.