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.
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.
Build
The HMAC-verified webhook queues a build. Per-site locks serialize same-site builds; different sites render in parallel.
Verify
HTTP checks, content markers, noindex correctness, and a preview-token leak scan. A failed verification fails the build — not the 3am pager.
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.
| You change | Narrative rebuilds | Time |
|---|---|---|
| A single post | The post, its index, tag pages, pagination | ~1.5s |
| An image | Just that image — optimize + WebP | <1s |
| A stylesheet | CSS only | <1s |
| A template partial | Every page using that template | proportional |
| 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.
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.








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.