Choosing Simplicity Over Stack Overload
Modern web development often feels like an arms race of abstraction. Frameworks pile on top of frameworks, bundlers wrap around transpilers, and before you know it, your “simple blog” has a webpack config longer than your actual content.
So I decided to do the unthinkable: build a blog using Ghost and no front-end frameworks. No React, no Vue, no Tailwind, no Bootstrap. Just raw HTML, CSS, and a pinch of JavaScript—when absolutely necessary.
This wasn’t about nostalgia. It was about focus.
Why Ghost?
Ghost is a clean, fast, and open-source platform purpose-built for publishing. It offers:
- A built-in admin interface
- Markdown-based content editing
- REST and Content APIs
- A theming system built around Handlebars
It’s also intentionally minimal. Which meant I could treat it as a foundation rather than a stack to customize out of existence.
Why No Frameworks?
The short answer: I wanted to understand everything that touched the user.
The longer answer: I’d grown tired of bloat. I wanted performance, full control, and a design that felt handcrafted. Frameworks are incredible tools—but they often encourage complexity under the guise of convention.
“Constraint is the source of elegance.” This project was a test of that philosophy.
What the Build Process Looked Like
Theme Development with Handlebars
Ghost themes use Handlebars templating. It’s logic-light and content-centric—perfect for a blog. I began with the official Starter Theme, stripped it down, and rebuilt with:
- Custom layouts for post, page, and home
- Semantic HTML structure
- Minimal helper logic to avoid overcomplicating the template flow
No virtual DOM. No hydration. Just static HTML rendered from dynamic content.
Each template corresponded directly to a part of the site, and each one was short enough to read in a single sitting.
Writing CSS from Scratch
I wrote pure CSS using custom properties and a basic typographic scale. No classes ending in -lg-900
, no utility-first clutter.
This gave me:
- Clean separation of design logic
- Total control over breakpoints
- A deeper understanding of how I actually wanted things to look
Performance-wise, the entire site CSS was under 30KB uncompressed.
JavaScript: Minimal by Design
A few sprinkles of JavaScript handled:
- Responsive navigation toggles
- Lazy-loading for images
- Smooth scrolling for internal links
Everything else was left to the browser’s native behavior. I wrote about 150 lines total, and that covered the entire site.
What I Learned from Avoiding Frameworks
You Have to Be Deliberate
Without frameworks, you can’t hide behind boilerplate. Every choice is intentional, which forces clarity:
- What needs to be dynamic?
- What actually improves UX?
- Where does performance begin to degrade?
The answers become obvious when you're not scaffolding abstractions to guess for you.
Fewer Tools, Better Understanding
Stripping down meant fewer dependencies, faster build times, and much deeper knowledge of how the system worked end to end. I understood how every part fit together, which made debugging—and extending—easier.
It's Okay to Build Small
The web is vast, and scale is seductive. But not every project needs to anticipate scale. Sometimes you just need a space to write—and for that, simplicity is not a limitation. It's a strength.
Challenges and Trade-offs I Faced
Simplicity isn’t free. Working without frameworks brings its own set of constraints—and not always the liberating kind.
Lack of Built-in Components
Without component libraries or a framework's ecosystem, everything had to be made from scratch:
- Modals
- Accordions
- Image galleries
- Accessibility considerations
This wasn’t bad, but it slowed things down. There were no drop-in solutions. Every feature required deliberate time and care to build and test manually.
No State Management
Most of the time, this was a feature, not a bug. But for certain dynamic elements—like theme toggles or interactive archives—I had to be creative. Without a framework's state system, I relied on:
localStorage
- Event delegation
- Vanilla JS data attributes
These worked, but they reminded me of how much ease we trade for control when we drop modern stacks.
Deployment and Maintenance Simplicity
This part was a joy. With no build tools, no npm dependencies, and no bundlers, deploying my theme was as simple as zipping a folder and uploading it to Ghost’s admin panel.
When updates are necessary, I just push changes to GitHub and pull down on the server. There's no dependency hell, no broken plugins, no version mismatches. This kind of maintenance peace is rare in today’s dev world.
What I’d Do Differently Next Time
Automate Without Abstracting
Though I avoided tooling, I now see value in light automation—like a CSS preprocessor or task runner. Not to reinvent the wheel, but to avoid tedious repetition. A Sass setup, for example, wouldn’t harm simplicity, and it’d save time.
Build a Tiny Component System
Even in raw HTML/CSS, you can build repeatable structures with partials and conventions. Next time, I’d define a more intentional component library—just enough to create reusable blocks without importing an entire framework.
Document My Design Decisions
Hand-built systems have one flaw: they're only in your head. I now maintain a small design README to track:
- Color palettes
- Type scales
- Layout principles
- Custom utilities
It’s low-effort and high-value, especially when you revisit the project months later.
Why This Still Feels Right
Despite the extra work, this approach still feels deeply satisfying. Not because it’s better in some objective way—but because it matches the scale and purpose of the project. The blog is personal. It's small. It doesn't need infinite scalability or enterprise architecture.
What it needs is:
- Fast load times
- Clear typography
- Full editorial control
- Minimal cognitive overhead
And that's exactly what it got.
Building this way reminded me of the early web—when simplicity wasn’t a statement, but a necessity. Reclaiming that spirit, even briefly, rewired how I think about code, content, and complexity.
Sometimes, no framework is the right framework.