LJ Next LJ Next

Lädt...

0%

Back to blog
6 min read LJ Next

Why We Built Our Own CMS Architecture Instead of Using WordPress

How choosing Nuxt Content over WordPress gave us full control, better performance, and a developer experience that actually scales.

architecturenuxtcmsperformance

Why We Built Our Own CMS Architecture Instead of Using WordPress

When we started building the new LJ Next site, the first question everyone asked was: "Why not just use WordPress?" It powers over 40% of the web, has thousands of plugins, and every hosting provider supports it out of the box. Fair question.

Here is why we went a different route — and what we gained from it.

The problem with WordPress for our use case

WordPress is a fantastic tool for many projects. But for a performance-focused web studio building custom client work, it introduced friction at every level:

  • Plugin dependency hell. Need a contact form? Plugin. SEO? Plugin. Caching? Plugin. Each one adds weight, potential conflicts, and security surface area.
  • Opaque rendering pipeline. PHP templating with layers of hooks and filters makes it hard to reason about what actually gets sent to the browser.
  • Database overhead. Every page load hits MySQL, even for content that rarely changes. You end up needing caching layers on top of caching layers.
  • Hosting constraints. WordPress needs PHP and MySQL, which means either shared hosting (slow) or managed WordPress hosting (expensive for what you get).

We wanted something leaner, something where the architecture itself solves the problems that WordPress solves with plugins.

What we chose instead

Our stack is straightforward:

  • Nuxt 3 as the application framework
  • Nuxt Content as the file-based CMS
  • Cloudflare Pages for hosting and edge delivery
  • Tailwind CSS for styling
  • TypeScript everywhere

The key piece is Nuxt Content. It turns Markdown files into a queryable content layer with zero database overhead. Content lives in the repository, gets version-controlled with Git, and renders at build time into static HTML.

// content.config.ts — defining our blog collection
export default defineContentConfig({
    collections: {
        blog: defineCollection({
            type: "page",
            source: "blog/*.md",
            schema: z.object({
                title: z.string(),
                description: z.string().optional(),
                date: z.string(),
                tags: z.array(z.string()).optional(),
                author: z.string().optional(),
            }),
        }),
    },
});

That is the entire CMS configuration. No admin panel to maintain, no database to back up, no plugin updates to worry about.

Performance: not even close

WordPress with a caching plugin and CDN can get decent Lighthouse scores. But it takes effort and ongoing tuning. Our approach is fast by default:

  • Static generation means every page is pre-rendered HTML. Time to first byte is the time it takes Cloudflare's edge to serve a file — typically under 20ms.
  • No runtime PHP. The server does not execute code on each request. It serves files.
  • Minimal JavaScript. Nuxt's hybrid rendering only hydrates what needs interactivity. Blog posts ship almost zero client-side JS.
  • Asset optimization is handled at build time, not by a plugin that runs on every request.

A typical blog post on our site loads in under 500ms on a 3G connection. Try that with a stock WordPress install.

Developer experience matters

This is where the gap is widest. Working on our site feels like working on a modern application, not fighting a legacy system:

  • Type safety. Every content field is validated by Zod schemas. If a blog post is missing a required field, the build fails with a clear error.
  • Component-driven. Blog cards, headers, filters — they are all Vue components. Reusable, testable, easy to reason about.
  • Git-based workflow. Content changes go through pull requests. We can review, diff, and roll back any change.
  • Local development is instant. nuxt dev starts in seconds, hot-reloads everything, and the content preview updates in real time.
<!-- Querying blog posts is just a function call -->
<script setup lang="ts">
const { data: posts } = await useAsyncData("blog", () =>
    queryCollection("blog").order("date", "DESC").all(),
);
</script>

Compare that to writing a WP_Query with meta queries and custom taxonomies. The cognitive overhead is not comparable.

What about non-technical editors?

This is the one area where WordPress genuinely shines. Its admin panel is approachable for non-developers. We solved this differently:

  • For our own content, Markdown in VS Code is faster than any WYSIWYG editor.
  • For client projects that need a visual editor, we use Nuxt Studio — a hosted editing layer that connects to the Git repository and provides a visual interface without changing the architecture.
  • The content format (Markdown) is portable. If we ever want to switch tools, the content moves with us.

The cost comparison

WordPress is "free" until you count the real costs:

WordPressOur Stack
Hosting$20–50/mo (managed)$0 (Cloudflare free tier)
SSLIncluded or pluginIncluded
CDNPlugin + configBuilt-in (edge network)
BackupsPlugin or host featureGit history
Security updatesConstantNone needed (static)
Build timeN/A (runtime)~30s per deploy

For a studio building multiple sites, the savings compound quickly.

When WordPress is still the right choice

We are not anti-WordPress. It is the right tool when:

  • The client's team is non-technical and needs a familiar admin interface
  • The project needs e-commerce with WooCommerce
  • There is an existing WordPress ecosystem the project must integrate with
  • Time-to-launch matters more than long-term architecture

For everything else — especially performance-critical marketing sites, blogs, and landing pages — a modern static-first architecture wins.

What we learned

Building our own CMS layer taught us a few things:

  1. Simpler systems are easier to maintain. Fewer moving parts means fewer things break.
  2. Performance should be a default, not an optimization. If your architecture is fast by design, you spend zero time tuning it.
  3. Developer experience drives quality. When the tooling is good, you ship better work, faster.
  4. Content and presentation should be separate. Markdown files do not care how they are rendered. We can redesign the entire site without touching a single blog post.

Next up

In upcoming posts, we will dig into the specifics: how we structured our Nuxt Content collections, the component architecture behind our blog, and how we handle i18n for content that needs to work in both German and English.

If you are considering a similar move away from traditional CMS platforms, reach out. We are happy to share what we have learned.