Rebuilding My Site with Narrative CMS

Rebuilding My Site with Narrative CMS

Twenty years ago, I built a blogging platform called Narrative. It was an ASP.NET-based CMS with advanced features like automatic page rebuilding, a sophisticated tagging system, and comment spam prevention. I used it to power this site from 2003 until 2008, when I abandoned it in favor of WordPress, saying "I am much more interested in blogging than the building of blogging software."

That code sat shelved for nearly two decades. Then, in 2024, I discovered Claude Code and realized something profound: with AI assistance, I could finally bring Narrative back to life—not as a compromise, but as exactly the system I'd always envisioned. This post tells that story.


The Original Narrative (2003-2008)

The first iteration of Narrative was born out of necessity. In the early 2000s, there wasn't a good blogging platform for ASP.NET. So I built one.

By June 2005, Narrative had some sophisticated features:

  • Smart Rebuilding: Instead of dynamically generating pages on every request, Narrative automatically rebuilt pages only when content or templates changed
  • Tagging Assemblies: A plugin system where code libraries could recognize template tags and replace them with dynamic content—without using ASP.NET
  • Comment Spam Prevention: A custom CAPTCHA system to combat the thousands of spam comments hitting the site
  • XHTML Compliance: Proper DOCTYPE handling for search engine indexing

I was proud of what I'd built. But by 2008, I'd moved from Windows to Mac, from .NET to LAMP stacks, and WordPress had matured into an excellent platform. Maintaining my own CMS no longer made sense. I walked away.

The Long Hibernation

For seventeen years, the Narrative codebase gathered digital dust. Occasionally, I'd think about it — about the clean architecture, the template system, the satisfaction of building something that worked exactly as I wanted. But the prospect of rebuilding it from scratch seemed daunting.

I tried Jekyll. I tried Hugo. I tried Gatsby and Next.js and a dozen other static site generators. Each had strengths, but I kept running into the same friction points:

  • Limited Markdown control: I wanted fine-grained control over parsing and rendering
  • Template limitations: Most systems only gave you rendered HTML, not structured content
  • Deployment complexity: I wanted seamless AWS S3 and CloudFront integration
  • Performance bottlenecks: Large sites needed intelligent caching and incremental builds

I knew what I wanted. I just didn't have the time or energy to build it.

Enter Claude Code

In late 2024, I started experimenting with Claude Code for software development projects. What I discovered was transformative.

AI-assisted development isn't about having the AI write all your code while you sit back. It's about iteration, refinement, and conversation. It's about explaining what you want, seeing an implementation, testing it, finding the edge cases, and iterating until it's right.

With Claude Code, I could finally resurrect Narrative—but better. Not as an ASP.NET application, but as a modern Python static site generator with all the features I'd dreamed about.

Building with AI: The Development Process

The development of the new Narrative was unlike any project I'd worked on before. Here's what that process looked like:

Iterative Architecture Design

I started by describing the core architecture I wanted:

"I need a Markdown parser that maintains document structure—not just converting to HTML, but preserving the hierarchy of headings, associating paragraphs with their parent sections, and extracting metadata like images and links."

Claude Code generated an initial implementation. We tested it. Found edge cases with nested lists. Refined it. Added support for blockquotes. Handled inline formatting. Each iteration built on the last, with me providing domain knowledge and Claude providing implementation expertise.

The result is a parser that goes far beyond simple Markdown-to-HTML conversion. It builds a complete document object model that templates can interrogate and manipulate.

Feature Development Through Conversation

Every feature in Narrative came through this iterative dialogue:

Me: "The breadcrumb navigation should show 'Blog' for recent posts but 'Archive' for posts older than one year. And it should hide the year directory in breadcrumbs for recent posts to reduce clutter."

Claude: Generates breadcrumb logic with date calculations and Jinja2 template code

Me: "It's not working. The year still shows for recent posts."

Claude: Analyzes the template, identifies that Jinja2's variable scoping was the issue, implements a namespace-based solution

This kind of back-and-forth debugging happened dozens of times. Claude Code could spot issues I missed, suggest alternative approaches, and implement solutions faster than I could type them.

Solving Problems I Couldn't Solve Alone

Some features required expertise I didn't have. SCSS compilation, for example. I knew I wanted to compile SCSS to CSS during builds, but I'd never worked with libsass in Python.

I described what I needed. Claude Code showed me how to:

  • Set up include paths for @import statements
  • Handle compilation errors gracefully
  • Ensure the CSS output directory existed before writing
  • Integrate it into the build process

Within an hour, I had working SCSS compilation—something that would have taken me days of documentation reading and trial-and-error.

The AI as Pair Programmer

The best analogy I have is pair programming, but with a partner who:

  • Never gets tired
  • Has instant recall of Python standard library functions
  • Can generate regex patterns on demand
  • Writes comprehensive docstrings
  • Follows PEP 8 style guidelines automatically
  • Can refactor code while maintaining functionality

When I needed to add CloudFront invalidation after S3 uploads, I just described the workflow. Claude Code generated boto3 client setup, error handling, logging, and the full integration—all following the existing code patterns.

What I Contributed

This wasn't autopilot development. My role was critical:

  • Domain expertise: What features a static site generator needs
  • Architecture decisions: When to use caching, how to structure pages
  • Testing: Trying edge cases, finding bugs, verifying behavior
  • Direction: Knowing when to iterate vs. when to move on
  • Integration: Ensuring components worked together coherently

I wrote requirements. Claude Code wrote implementations. I tested. We refined. It was collaborative in a way I'd never experienced before.

Why This Succeeded Where the Original Failed

The original Narrative died because maintaining it became a burden. This version thrives because:

  1. AI handles the tedious parts: Boilerplate, error handling, edge cases
  2. Documentation comes naturally: Claude Code writes docstrings as it codes
  3. Iteration is cheap: Want to refactor? Describe the change, review the diff, done
  4. Best practices emerge: The AI suggests patterns I hadn't considered
  5. I focus on features, not implementation: I think about what I want; Claude handles how

Most importantly: it's fun again. Every session feels productive. Every feature request becomes reality within minutes or hours, not days or weeks.

The Result: A Modern Narrative

Narrative is built around a clean, modular architecture with several key components:

Markdown Processing

At its heart is a sophisticated Markdown parser that goes beyond simple HTML conversion. The parser:

  • Maintains a hierarchical document structure with headings and associated paragraphs
  • Supports advanced features like nested lists, blockquotes, and code blocks
  • Extracts metadata like images, alt text, and titles
  • Provides structured access to content for templates
  • Uses pre-compiled regex patterns for optimal performance

Template System

The template system uses Jinja2 but with a twist—templates have access to the full document structure, not just rendered HTML. This means you can:

  • Generate table of contents from heading hierarchies
  • Access individual paragraphs and apply custom styling
  • Process images with metadata-aware rendering
  • Create sophisticated layouts based on content structure

Intelligent Caching

Narrative includes a Redis-backed caching system that:

  • Tracks dependencies between pages (like posts and tag indexes)
  • Enables incremental builds that only regenerate changed content
  • Monitors template modifications and rebuilds affected pages
  • Maintains page hashes to detect content changes

Features That Matter

Intelligent Rebuilding

One feature I'm particularly proud of is the intelligent rebuilding system. Like the original Narrative from 2003, the modern version knows exactly what needs to be regenerated when something changes. But it's far smarter now.

The system tracks dependencies between pages—when a blog post is updated, it knows to rebuild not just that post, but also the blog index, relevant tag pages, and RSS feeds. When you modify a template, it rebuilds only the pages that use that template. And when SCSS files change, it performs a CSS-only rebuild without touching any HTML pages.

This dependency tracking is backed by Redis caching with page hashes. The system maintains checksums of every page and template, detecting changes at a granular level. During development, this means instant feedback—save a file and see changes immediately. For production deployments, it means blazing-fast builds that only regenerate what's actually changed.

The breadcrumb navigation demonstrates this intelligence too—it's context-aware, showing "Blog" for recent posts and "Archive" for older ones, and intelligently hides year directories in breadcrumbs for recent posts to reduce clutter. This kind of smart behavior permeates the entire system.

SCSS Compilation

Narrative automatically compiles SCSS to CSS during the build process, with support for:

  • @import statements for modular stylesheets
  • Compressed output for production
  • Source path resolution for clean organization
  • Error handling with helpful debugging information

I can organize my styles into \_colors.scss, _typography.scss, and other partials, then import them into a main style.scss file. It all just works.

Powerful Shortcode System

Narrative includes a flexible shortcode system that extends Markdown with dynamic functionality. Shortcodes are processed before the Markdown parser runs, allowing them to generate HTML that seamlessly integrates with your content.

The system comes with several built-in shortcodes that I use throughout this site:

  • article_link: Creates links to other posts or articles by name, automatically resolving the correct path. This post uses it to reference older Narrative posts without hardcoding URLs.
  • toc: Generates a table of contents from the document's heading hierarchy, with customizable depth and styling.
  • youtube: Embeds YouTube videos with proper responsive containers.

Creating custom shortcodes is straightforward—they're Python plugins that receive the shortcode context and return HTML. The architecture is similar to the original Narrative's "Tagging Assemblies" concept from 2003, but modernized with a clean plugin interface.

What makes this especially powerful is that shortcodes have access to the full site context, including all pages, configuration values, and the current page's metadata. This allows for sophisticated cross-referencing and dynamic content generation that would be impossible with static Markdown alone.

CloudFront Integration

Deployment is streamlined with built-in S3 upload and CloudFront integration. When I deploy to staging or production, Narrative:

  1. Uploads all files to the configured S3 bucket
  2. Sets appropriate MIME types for HTML, CSS, JavaScript, images, and other assets
  3. Automatically creates a CloudFront invalidation to clear the cache
  4. Logs the invalidation ID and status for verification

The entire process takes seconds, and visitors see the latest content immediately.

HTML and JavaScript Minification

Modern websites benefit from minification—removing unnecessary whitespace, comments, and formatting from HTML and JavaScript to reduce file sizes and improve load times. But most minification tools require heavyweight dependencies and can be fragile, breaking code if not configured carefully.

Narrative includes a custom-built minifier that's lightweight, dependency-free, and designed specifically for the HTML it generates. The minifier:

  • Removes all HTML comments while preserving the actual content
  • Compresses whitespace between tags without breaking layout
  • Minifies JavaScript inline within <script> tags:
    • Removes single-line (//) and multi-line (/* */) comments
    • Eliminates unnecessary whitespace and line breaks
    • Preserves string literals, regex patterns, and template strings
    • Compresses operators and punctuation
  • Protects critical content by preserving whitespace in <pre>, <textarea>, and <style> tags
  • Fails gracefully by returning the original HTML if minification encounters an error

What makes this especially elegant is the dual deployment approach. By default, minification happens at deployment time when uploading to S3—this means you develop and debug with readable, formatted HTML, then automatically optimize for production. But you can also test minified builds locally using the --minify flag, ensuring everything works correctly before deployment.

The minifier was built collaboratively with Claude Code, and it handles edge cases that would have taken weeks to debug manually—like distinguishing between // in comments versus // in URL strings, or properly preserving JavaScript regex literals while removing comment blocks. It's the kind of seemingly-simple-but-actually-complex feature that AI-assisted development makes practical.

Tag and Topic Organization

The system includes sophisticated content organization:

  • Tags for blog posts with automatic tag index generation
  • Topics for longer-form articles organized by subject
  • Tag and topic pages with proper pagination
  • Automatic generation of index pages

Real-Time Development

During development, Narrative watches the source directory and automatically:

  • Performs full rebuilds when content or templates change
  • Does CSS-only rebuilds when SCSS files are modified
  • Injects auto-reload scripts so the browser refreshes automatically
  • Adds cache-control headers to prevent stale content

The feedback loop is instant—I save a file and see changes immediately.

Technical Implementation

For those interested in the technical details:

Language and Stack

  • Python 3.9+ for the core engine
  • Jinja2 for templating
  • PyYAML for frontmatter parsing
  • libsass for SCSS compilation
  • Boto3 for AWS integration
  • Redis for caching (via Valkey)

Docker-Based Development

The entire system runs in Docker containers:

  • Backend CMS in Python
  • Valkey (Redis-compatible) for caching
  • Optional React frontend for build management
  • All orchestrated with Docker Compose

WebSocket Integration

The backend includes a Flask-SocketIO server that provides real-time communication:

  • Build status updates
  • File change notifications
  • SCSS rebuild events
  • Deployment progress

This powers the optional React frontend, but the system works perfectly fine with just API calls or command-line usage.

Performance

One of my key goals was performance, both in build times and runtime:

  • Fast builds: The hierarchical document structure is built once per page, then cached
  • Incremental rebuilds: Only changed content is regenerated
  • Pre-compiled patterns: All regex patterns are compiled once at startup
  • Efficient templates: Jinja2's template caching ensures fast rendering

On this site with 50+ posts and articles, a full build takes under 2 seconds. Incremental builds complete in milliseconds.

What's Next

The beauty of building with AI assistance is that adding features no longer feels daunting. I'm continually refining Narrative, and some items on the roadmap:

  • Image optimization and responsive image generation
  • Built-in search functionality
  • RSS/Atom feed enhancements
  • Multi-language support
  • Additional built-in shortcodes

Each of these would have taken weeks in the old development model. With Claude Code, they're weekend projects.

The Future of Development

This experience has fundamentally changed how I think about software development. Not because AI can "write code for you"—that's missing the point entirely.

The transformation is in the collaboration model. I can focus on:

  • Understanding what users need
  • Designing elegant solutions
  • Testing edge cases
  • Ensuring quality

While Claude Code focuses on:

  • Implementation details
  • Best practices
  • Error handling
  • Documentation
  • Code consistency

Together, we're far more productive than either could be alone.

Open Source?

Currently, Narrative is a private project powering my personal site and a few client sites. I'm considering open-sourcing it once the documentation is more complete and the API is more stable.

But here's what's interesting: if I do open source it, the development workflow would be unique. Contributors wouldn't just submit pull requests—they could describe features, iterate with AI assistance, and submit well-tested, documented code. The barrier to contribution drops dramatically.

A Personal Reflection

Twenty years ago, I built Narrative because I had to. I needed a blogging platform and none existed for my stack.

Today, I rebuilt Narrative because I could. Because AI assistance made it feasible to create exactly what I wanted without sacrificing months of my life to do it.

The original Narrative was abandoned because maintaining it wasn't worth the effort. This version is sustainable because the effort-to-value ratio has fundamentally changed. When you can add a feature in an afternoon instead of a week, when debugging is a conversation instead of hours of print statements, when refactoring is describing what you want instead of manually updating hundreds of lines—suddenly, building custom software makes sense again.

If you're interested in learning more or have questions about AI-assisted development, static site generation, or resurrecting twenty-year-old projects, feel free to reach out via Twitter or LinkedIn.


Conclusion

The site you're reading this on is powered by the rebirth of a project I started in 2003 and abandoned in 2008. It sat dormant for seventeen years until AI assistance made it possible—and practical—to bring it back.

Narrative CMS 2025 is everything the original aspired to be: fast, flexible, and exactly tailored to my needs. But more than that, it represents something larger: proof that AI-assisted development isn't about replacing programmers, it's about amplifying what we can build.

Every page on this site, every feature, every line of code was created through iteration between human intent and AI implementation. The code is mine. The architecture is mine. The vision is mine. But the speed, the completeness, the polish—that came from collaboration with Claude Code.

This isn't the future of development. It's the present. And it's extraordinary.