Static site engine · git-backed CMS

Write in Markdown.
Ship a fleet.

Narrative renders two dozen production sites from Markdown and Jinja2 — then deploys them through a cloud pipeline where git is the source of truth, every deploy is verified before it counts, and rollback is one revert away.

Incremental builds · verified deploys · promote & rollback · MCP + CLI + API

___PRESERVE_BLOCK_8___
Production sites rendered
0
Collection pages in under 2s
0
Tests in the suite
0
Seconds for an incremental build
~1.5

Cloud pipeline

Git is the source of truth.

Content, templates, and configuration live in each site's repository. The service is a deterministic build-and-deploy machine attached to it — no laptop in the loop.

  1. Push

    A commit lands on the staging branch — from an editor, the CLI, an MCP call, or the web UI. Every path is a git commit with the acting user as author.

  2. Build

    The HMAC-verified webhook queues a build. Per-site locks serialize same-site builds; different sites render in parallel.

  3. Verify

    HTTP checks, content markers, noindex correctness, and a preview-token leak scan. A failed verification fails the build — not the 3am pager.

  4. Live

    Promote merges staging into production and deploys. Rollback is a revert, never a force-push, so history stays append-only.

One pipeline, four doorways

A git push, a CLI command, an MCP call, and a UI button all invoke the same server-side pipeline. Only the recorded trigger differs.

Verified deploys

The manual curl ritual, codified: status checks, expected-content markers, staging noindex, and a production scan for leaked preview tokens.

Promote & rollback

Promote is a merge with full history; rollback is a revert that is itself undoable. Force-push does not exist here.

Scheduled publishing

Set publish_at in frontmatter and walk away. An EventBridge tick sweeps every site each minute and publishes what is due.

Cross-account publishing

Sites in other AWS accounts deploy through a per-account role assumed with an ExternalId. The service never touches SSO.

Gated previews, verified

VelvetRope™ locks staging behind an access key — and the verifier authenticates through the gate, so a healthy gated deploy verifies as one.

Content engine

Markdown in. Websites out.

A nine-layer build pipeline that turns frontmattered Markdown and Jinja2 templates into complete, optimized, SEO-ready sites.

Markdown + Jinja2 + YAML

Frontmatter drives everything — nineteen date formats parsed, drafts filtered per stage, tags and topics organized automatically.

Data sources & collections

Generate a page per item from JSON files or a REST API at build time. 720+ items become 747 pages in under two seconds.

Shortcodes & plugins

An extensible plugin architecture with nested shortcode support — and Mermaid diagrams rendered at build time, no client JS.

Multi-site, one engine

Every site is an independent directory with its own config, content, templates, and deploy stages. SITE_NAME selects; nothing leaks between sites.

SharedContent overlay

Eight AccelaStudy sites share one header, footer, feature pages, and CSS bundle through a build-time overlay — local files always win.

Canonical values

A [[canon:key]] placeholder resolves from a single source-of-truth YAML at build time, so a number is never stale on one site and fresh on another.

{{< toc >}}{{< callout >}}{{< code_tabs >}}{{< mermaid >}}{{< highlight >}}{{< youtube >}}{{< vimeo >}}{{< article_link >}}{{< current_year >}}{{< leverage_disclaimer >}}

Build intelligence

Rebuild what changed. Skip everything else.

Dependency tracking in Valkey knows which pages depend on which posts, templates, tags, and pagination groups — so edits rebuild in about a second and a half.

Incremental build times by scenario
You changeNarrative rebuildsTime
A single postThe post, its index, tag pages, pagination~1.5s
An imageJust that image — optimize + WebP<1s
A stylesheetCSS only<1s
A template partialEvery page using that templateproportional
Everything (450 pages)Everything~50s

Image pipeline

Hash-cached optimization, WebP conversion, and <picture> output. Add one image; only that image processes.

SCSS compilation

Stylesheets compile with @import resolution — no Node toolchain in sight.

Minification & upload

Per-stage HTML/JS minification, hash-based incremental S3 uploads, and CloudFront invalidations targeted to what actually changed.

Bundled effects library

You're looking at them.

Five vanilla-JS effects ship with the engine — drop-in replacements for the Framer Motion patterns marketing sites actually use, with zero React and zero build step. Every one of them is running on this page.

particles

The ambient canvas drifting behind the hero, with mouse-tracking glow and tiered connections. One element, five data attributes.

reveal

Every section heading on this page faded in and slid up as you scrolled to it — IntersectionObserver with a fast-scroll safety net.

stagger

These cards cascaded in one after another. Configurable delay and initial offset, honoring prefers-reduced-motion.

magnetic

Spring-physics buttons that lean toward the cursor. Try one:

A magnetic button

countup

Numbers that count to their target when scrolled into view — like this one: 0 tests.

Opt in per site

Five lines of site.yml. Narrative copies the modules into dist/effects/ at build time and exposes the list to templates.

Quality · search · SEO

Shipped is not the same as done.

Narrative checks the content before it publishes, links it after it renders, and makes every page legible to crawlers and screen readers alike.

AI content detection

Every article gets a provenance score via the Sapling API, written back into its frontmatter. Checked files skip until they change.

Link checker

Crawls the rendered HTML for broken internal links — and optionally external ones — before anyone else finds them.

Semantic search

Voyage AI embeddings over chunked content power a Lambda search endpoint with rate limiting built in.

Automatic related reading

Article-level embeddings and cosine similarity inject a “Related Reading” section into every article. Idempotent, threshold-filtered.

SEO on every page

Canonical URLs, Open Graph, Twitter Cards, JSON-LD, sitemap.xml, RSS/Atom feeds — generated, not remembered. Staging is always noindex.

WCAG 2.1 AA

Keyboard navigation, skip links, visible focus, AA contrast in both themes, 44px touch targets, and prefers-reduced-motion respected everywhere.

The CMS

A real control plane on top.

Sites, builds, and content in one place — every edit a git commit, every build in the history with its trigger, SHA, duration, and verification report.

The Narrative dashboard listing registered sites with their domains and deploy stagesThe Narrative dashboard listing registered sites with their domains and deploy stages
Build history with stage, trigger, status, and duration for each buildBuild history with stage, trigger, status, and duration for each build
The content list for a site showing articles with drafts and publish stateThe content list for a site showing articles with drafts and publish state
The content editor with Markdown source and frontmatter fieldsThe content editor with Markdown source and frontmatter fields

Both themes, of course. The screenshots switch with this page's toggle.

Integrations

Every doorway is first-class.

Humans get a UI and a CLI. Agents get MCP. Systems get a REST API. They all end up in the same pipeline, with the same audit trail.

MCP server

Full tool parity for LLM agents: site management, content CRUD, builds, deploys, and publishing over the Model Context Protocol.

CLI

narrative deploy / promote / rollback / status / doctor. pipx-installable, stdlib + httpx only.

REST API

A FastAPI backend with versioned routes, OIDC + service-token auth, and webhooks for GitHub push events.

React export

Articles as clean JSON — title, date, tags, excerpt, rendered HTML — for any SPA that wants them.

Pulse analytics

Per-stage analytics injection: staging and production report to separate Pulse sites, and local previews are never tracked.

Infrastructure provisioning

S3, ACM, CloudFront, and Route53 for a new site provisioned from code, with a dry-run mode.

One engine. A fleet of sites.

Narrative already renders, verifies, and ships the entire Renkara and AccelaStudy web estate — including the page you are reading.