← Blog

From Ghost to first-class: blog on the main stack

Sep 5, 2026 · Harper Labs

We're moving blog content off Ghost onto MD/MDX in the main website repo. This post explains why that makes our security publish-gate actually work — and what still has to happen before Ghost goes offline (HLAI-239).

The Ghost problem

Ghost is a great CMS. But for our use case — security-reviewed blog posts — it had fatal gaps:

  1. No PR workflow — Publish is a button click, not a reviewable commit
  2. No draft gating — Posts are "scheduled" but still accessible via direct URL
  3. Separate stack — Different deploy, different auth, different everything

We needed blog posts to flow through the same security review as code changes.

Git-based authoring

Now posts live in content/blog/*.mdx with frontmatter:

---
title: "Post title"
description: "Meta description"
date: "2026-09-05"
author: "Harper Labs"
tags: ["ops", "reliability"]
draft: false
---

The workflow

  1. Write — Author creates new-post.mdx with draft: true
  2. Review — Open PR; team reviews content + security
  3. Publish — Set draft: false, merge PR, deploy
  4. Live — Post appears on index, tags, RSS, sitemap

Drafts are never public. No URL guessing. No preview leaks.

Why MDX

MDX lets us embed React components in posts:

<BlogCtaBand />

This means we can:

  • Inline interactive demos
  • Embed live API examples
  • Reuse site components (buttons, cards, forms)

Ghost's editor can't do this. Markdown alone can't do this. MDX is the bridge.

First-class blog = first-class design

With blog routes inside the main site, we get:

  • Shared chrome — Same nav, footer, fonts, tokens
  • Consistent SEO — Same metadata patterns, same sitemap
  • One deploy — No CMS sync, no CORS, no second stack

The blog isn't a separate property. It's part of the site.

The cutover plan

Right now:

  • Interim blog — blog.harperlabs.ai (Ghost on Dokploy) stays live for old links
  • New blog — harperlabs.ai/blog (this stack) is the destination once cutover is proven

Cutover steps:

  1. Smoke test new blog
  2. Redirect blog.harperlabs.ai → main site /blog (DevOps)
  3. Kill Ghost (HLAI-239 ticket)

Zero downtime. Zero broken links.

What we learned

  1. CMS flexibility vs. workflow control — Ghost is powerful, but we needed PR review more than we needed a web editor
  2. MDX > Markdown — Component embedding is a force multiplier
  3. One stack scales — Fewer moving parts = faster iteration

Running your own blog or docs site? This pattern works for any content that needs security review before publish.

Get a free audit if you're shipping content or code to production and want eyes on your workflow.

Agents already in production? Get a free Reliability Audit.

Get Free Audit