
Building LightSite CMS: A Make-Based Approach to Multi-Protocol Publishing
When I set out to build my own content management system, I had a few specific requirements that existing solutions didn’t quite meet. I wanted something that could publish to both the modern web and the nostalgic gopher protocol, something lightweight that wouldn’t require a database or runtime server, and something that embraced the Unix philosophy of small, composable tools. What emerged was LightSite CMS - a Make-based system that’s proven surprisingly robust and enjoyable to work with.
The Genesis: Why Build Another CMS?
The decision to build LightSite came from a specific itch that needed scratching. I wanted to maintain both a modern website and a gopher site, but existing static site generators were either web-only or required significant gymnastics to output multiple formats. Jekyll and Hugo are fantastic for what they do, but they’re designed with the web in mind. Meanwhile, the gopher community tends to hand-roll everything, which is charming but doesn’t scale well when you’re maintaining more than a handful of files.
I also had a philosophical preference for tools that I could understand completely. Modern static site generators often feel like black boxes with hundreds of dependencies and magical behaviors. I wanted something where I could trace every step from source to output, something that wouldn’t mysteriously break when I came back to it six months later.
The breakthrough came when I realized that Make - yes, the venerable build tool - was actually perfect for this job. Content management is fundamentally a build problem: you have source files that need to be transformed into output files, with complex dependency relationships and incremental builds. Make has been solving exactly this problem for decades.
Architecture: Standing on the Shoulders of Unix
LightSite’s architecture embraces the Unix philosophy wholeheartedly. Rather than building a monolithic application, it orchestrates a collection of existing tools, each doing one thing well. The core components include:
Make serves as the orchestration layer, managing dependencies and ensuring that only changed content gets rebuilt. This gives us incremental builds for free - something that becomes important when you have dozens of articles and multiple output formats.
M4 handles templating, which might seem like an unusual choice in an era of Liquid and Handlebars, but it’s proven remarkably capable. M4 is designed for macro processing, which is exactly what templating is. It’s also rock-solid stable - M4 macros I wrote two years ago still work identically today.
Lowdown converts Markdown to HTML, but more importantly, it can also output groff format. This dual capability means I can write content once in Markdown and publish it to both web and gopher with different formatting appropriate to each medium.
AWK processes frontmatter and generates content lists. I initially considered using more modern tools, but AWK’s text processing capabilities and ubiquity made it the obvious choice. The frontmatter processor is about 100 lines of AWK and handles edge cases that would require significantly more code in other languages.
ImageMagick handles all image processing, creating thumbnails, banners, and applying the distinctive duotone effect that gives the site its visual character.
The beauty of this approach is that each tool is replaceable. Don’t like M4? Swap in another templating system. Want different image processing? Replace the ImageMagick calls. The Make-based architecture provides the scaffolding while keeping individual components loosely coupled.
Content Organization: Embracing Platform Differences
One of the more interesting challenges was handling content that should appear on one platform but not the other. The web and gopher have different strengths and audiences. Some content makes sense for both, while other content is platform-specific.
The solution emerged organically from the filesystem structure. Shared content lives in the top-level directories (site/articles/
and site/pages/
), while platform-specific content lives in subdirectories (site/articles/www/
and site/articles/gopher/
). The Make system automatically includes shared content on both platforms while respecting the platform-specific divisions.
This has led to some interesting content decisions. Technical articles tend to be shared across both platforms, but more personal or experimental content often ends up gopher-only. There’s something about gopher’s text-focused nature that encourages a different kind of writing - more stream-of-consciousness, less polished. The platform shapes the content in subtle ways.
Image Processing: Making Constraints Creative
The image processing pipeline deserves special mention because it’s where some of the system’s most distinctive features emerge. Rather than serving full-color images that would clash with the site’s minimalist aesthetic, all images get processed through a duotone filter that reduces them to just two colors: white and transparent.
This constraint initially came from technical limitations - I wanted images that would work well with the site’s blue background. But it’s become one of my favorite features. The duotone processing creates a cohesive visual language across all images, regardless of their source. Screenshots, photos, and diagrams all get unified into the same aesthetic.
The processing pipeline itself showcases the power of Make’s pattern rules. A single rule definition handles all image types and sizes, automatically generating thumbnails, banners, and full-size versions. The recent addition of intelligent cropping using ImageMagick’s attention algorithms means that thumbnails automatically focus on the most visually interesting parts of images.
One challenge we solved recently was thumbnail consistency. Initially, images would end up with different aspect ratios, creating visual chaos in article lists. The solution was a processing pipeline that gently crops images to a 5:4 or 4:5 ratio (depending on orientation) before padding to a perfect square. This preserves the important parts of images while ensuring consistent layout.
The Gopher Renaissance
Building LightSite introduced me to the gopher protocol, and it’s been one of the project’s most rewarding aspects. Gopher represents a different philosophy of information sharing - text-focused, lightweight, and deliberately minimal. There’s no JavaScript, no CSS, no tracking pixels. Just content and navigation.
The gophermap generation exemplifies this simplicity. While the web gets complex HTML with navigation, styling, and metadata, gopher gets a simple text file that lists articles with their titles and paths. The M4 template that generates the gophermap is under 20 lines, compared to the significantly more complex HTML templates.
Yet gopher’s constraints have proven creatively liberating. Without the option of rich formatting, writing becomes more focused on clarity and structure. The medium really does shape the message.
Lessons Learned: The Joy of Boring Technology
Building LightSite has reinforced my appreciation for “boring” technology. Make is approaching its 50th birthday, M4 is nearly as old, and AWK has been around since the late 1970s. These tools have survived because they solve fundamental problems well and don’t try to do too much.
This stability pays dividends in maintenance. I can revisit the LightSite codebase after months away and immediately understand what’s happening. The tools don’t change out from under me, dependencies don’t suddenly break, and there’s no framework churn to keep up with.
The error handling story is instructive too. Early versions would fail catastrophically if a single image couldn’t be processed. Now, image processing uses Make’s ignore-errors feature (-
prefix), allowing the build to continue even if individual files fail. This resilience comes from embracing Make’s philosophy rather than fighting it.
Perhaps most importantly, building LightSite taught me to question assumptions about what tools are “appropriate” for different jobs. Make isn’t typically thought of as a CMS foundation, but it’s proven ideal for this use case. Sometimes the best tool is the one that’s already there, waiting to be applied creatively.
Looking Forward: Incremental Improvements
LightSite continues evolving, but in measured increments rather than revolutionary changes. Recent additions include the platform-specific content directories, improved image processing, and better error handling. Future plans include automatic git commit generation and perhaps a simple web interface for content editing.
The key insight is that the system doesn’t need to be revolutionary to be effective. By combining proven tools in thoughtful ways, it’s possible to create something that’s both powerful and maintainable. LightSite handles everything I need from a CMS while remaining comprehensible and hackable.
In an era of increasingly complex web frameworks and build systems, there’s something deeply satisfying about a CMS that fits in a few hundred lines of Make and shell scripts. It’s a reminder that sometimes the best solution is the simplest one that works.
Building LightSite has been an exercise in constraint-driven design, Unix philosophy, and the creative potential of boring technology. It might not win any innovation awards, but it reliably transforms my scattered thoughts into organized, multi-protocol publications. For a personal CMS, that’s exactly what success looks like.