<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matt.G</title>
    <description>The latest articles on DEV Community by Matt.G (@0xmattg).</description>
    <link>https://dev.to/0xmattg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3931573%2F3f951c98-c584-41b5-ace6-4d939dbcc44f.jpg</url>
      <title>DEV Community: Matt.G</title>
      <link>https://dev.to/0xmattg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/0xmattg"/>
    <language>en</language>
    <item>
      <title>Building a Go-native CMS engine with themes, plugins, admin CRUD, SEO, and caching</title>
      <dc:creator>Matt.G</dc:creator>
      <pubDate>Thu, 14 May 2026 15:59:28 +0000</pubDate>
      <link>https://dev.to/0xmattg/building-a-go-native-cms-engine-with-themes-plugins-admin-crud-seo-and-caching-351i</link>
      <guid>https://dev.to/0xmattg/building-a-go-native-cms-engine-with-themes-plugins-admin-crud-seo-and-caching-351i</guid>
      <description>&lt;p&gt;Hi everyone,&lt;br&gt;
I’m the author of GoPress, an open-source CMS framework and CMS engine written in Go.&lt;br&gt;
GitHub: &lt;a href="https://github.com/0xmattg/go-press" rel="noopener noreferrer"&gt;https://github.com/0xmattg/go-press&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GoPress started from a very practical question I kept running into:&lt;br&gt;
What if I want the authoring workflow and extension model of a traditional CMS, but I also want the deployment model, type safety, concurrency, and long-term maintainability of Go?&lt;/p&gt;

&lt;p&gt;I have used WordPress for real websites, and I still think the core product idea behind WordPress is extremely strong: content models, themes, plugins, admin workflows, media handling, permalinks, SEO, and a broad extension surface. That abstraction has survived for a reason.&lt;/p&gt;

&lt;p&gt;But for some self-hosted company websites, product sites, documentation hubs, editorial websites, and custom content systems, I often wanted something closer to a Go application: a compiled service, a clearer codebase, explicit interfaces, built-in caching paths, API-first content access, and a deployment model that feels more natural to backend engineers. That is why I built GoPress.&lt;/p&gt;

&lt;p&gt;GoPress is not a line-by-line rewrite of WordPress, and it is not an argument against PHP. It is a Go-native attempt to preserve the useful CMS shape — content, themes, plugins, admin, SEO, media, APIs — while rebuilding the engine around Go’s runtime and engineering style. The project describes this directly in its README: it focuses on keeping the editorial experience and CMS extension model while gaining Go’s deployment, concurrency, observability, and maintenance advantages.&lt;/p&gt;

&lt;h2&gt;
  
  
  What GoPress is
&lt;/h2&gt;

&lt;p&gt;GoPress is a composable CMS codebase for self-hosted websites and content applications.&lt;br&gt;
It currently includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A unified content model&lt;/li&gt;
&lt;li&gt;Theme-declared custom content types&lt;/li&gt;
&lt;li&gt;Data-driven admin CRUD&lt;/li&gt;
&lt;li&gt;A theme rendering engine&lt;/li&gt;
&lt;li&gt;Hook and filter extension points&lt;/li&gt;
&lt;li&gt;Plugin registration and deactivation&lt;/li&gt;
&lt;li&gt;REST APIs and Swagger / OpenAPI documentation&lt;/li&gt;
&lt;li&gt;SEO primitives&lt;/li&gt;
&lt;li&gt;Sitemap and redirect support&lt;/li&gt;
&lt;li&gt;Multi-level caching&lt;/li&gt;
&lt;li&gt;Media upload and responsive image variants&lt;/li&gt;
&lt;li&gt;Multi-site / instance-level configuration&lt;/li&gt;
&lt;li&gt;Bundled themes and bundled plugins
The intended use cases are things like company websites, editorial sites, product showcases, documentation hubs, and custom systems that want to keep a CMS authoring workflow inside a Go deployment model.
The current stack is intentionally familiar to Go backend developers: Gin, GORM, PostgreSQL, Redis, golang-jwt, Viper + TOML, slog, go-i18n, Quill 2.0, and swaggo/swag.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;Most CMS systems are either very mature but operationally heavy, or very flexible but not really designed around backend engineering constraints.&lt;br&gt;
I wanted a CMS engine where:&lt;/p&gt;

&lt;p&gt;Content models are explicit.&lt;br&gt;
Themes are separated from the engine.&lt;br&gt;
Plugins extend through interfaces and hooks.&lt;br&gt;
Admin pages can be generated from registered content definitions.&lt;br&gt;
Caching is part of the core path, not an afterthought.&lt;br&gt;
SEO is handled at the framework layer.&lt;br&gt;
REST APIs are available for registered content types.&lt;br&gt;
A production deployment can be a compiled Go binary plus PostgreSQL, with Redis optional.&lt;br&gt;
That last part matters to me. A lot of smaller self-hosted websites do not need a complicated distributed architecture. But they still deserve good internal structure, clean deployment, and a predictable extension model.&lt;br&gt;
GoPress is my attempt to make that middle ground practical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some technical design details
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Unified content model&lt;/strong&gt;&lt;br&gt;
The core content model is based around Content, ContentMeta, and a ContentType registry.&lt;br&gt;
The framework keeps core types such as post and contact_message, while themes can declare custom content types through theme.toml. These theme-declared models can drive admin navigation, CRUD screens, REST API exposure, rewrite rules, template mapping, and menu icons.&lt;br&gt;
For example, a theme can define content types like product, service, showcase, case study, or any domain-specific entity without requiring the engine to hard-code those concepts.&lt;br&gt;
The goal is to keep the engine generic while allowing each site or theme to express its own content structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Config-driven routing and templates&lt;/strong&gt;&lt;br&gt;
GoPress uses theme.toml to define things like rewrite slugs and optional archive / single templates. These settings are used to drive archive URLs, detail URLs, sitemap entries, admin permalinks, and dynamic template resolution.&lt;br&gt;
This is one area where I intentionally borrowed the “CMS mental model” from WordPress, but moved the implementation into a more explicit configuration-driven Go structure.&lt;br&gt;
Themes render output, but the engine owns routing, querying, SEO, media behavior, admin behavior, and shared infrastructure. That separation is one of the main design principles of the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Hook and filter system&lt;/strong&gt;&lt;br&gt;
GoPress includes a hook event bus with actions and filters:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AddAction / DoAction&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;AddFilter / ApplyFilter&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The hook system returns removable handles, which allows plugins to deactivate cleanly without leaving hidden runtime coupling behind.&lt;br&gt;
This is important because plugin systems can easily become messy. My goal is to provide extension points that feel familiar to CMS developers, while still keeping the integration boundary explicit and maintainable for Go developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Admin CMS generated from content definitions&lt;/strong&gt;&lt;br&gt;
The admin CMS is data-driven.&lt;br&gt;
Registered ContentType definitions can generate list and edit screens. The admin supports role-based access control with roles such as admin, editor, author, and subscriber, plus rich text editing, media picking, and drag-and-drop ordering.&lt;br&gt;
This matters because I do not want every new content type to require a custom admin module from scratch. A Go-based CMS should still provide a practical authoring experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Built-in SEO layer&lt;/strong&gt;&lt;br&gt;
SEO is part of the core framework.&lt;br&gt;
GoPress includes site metadata, canonical links, meta descriptions, Open Graph tags, JSON-LD output, sitemap support, multilingual sitemap transformation, redirects, and per-content SEO overrides through the bundled seo-extras plugin.&lt;br&gt;
A lot of CMS projects treat SEO as something to bolt on later. I wanted it to be part of the engine from the beginning, because real company websites and editorial sites need SEO infrastructure by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Multi-level caching&lt;/strong&gt;&lt;br&gt;
GoPress has a built-in cache path with L1 memory cache, optional L2 Redis cache, graceful fallback when Redis is unavailable, and page-cache middleware.&lt;br&gt;
The current README lists performance targets such as sub-millisecond page-cache hits, under-50ms first render without cache, 50,000+ concurrent connections, and 100,000+ QPS with cache hits. These are stated as architecture targets, and the project still needs reproducible benchmark scripts and public benchmark reports before a stable release.&lt;br&gt;
I want to be very clear here: GoPress is still beta. I am not presenting those numbers as proven production benchmark claims yet. They are design targets for the architecture, and benchmark work is one of the areas I want to improve next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Theme and plugin separation&lt;/strong&gt;&lt;br&gt;
GoPress has a BaseTheme runtime that gives themes config-driven URL resolution, archive and detail rendering, fallback hierarchy, and automatic SEO integration. It also provides a shared template function map with helpers such as buildURL, archiveURL, contentURL, seoHeadFor, menuByLocation, translation helpers, hook rendering, and responsive image helpers.&lt;br&gt;
Plugins are designed to extend through the core boundary rather than directly depending on specific themes. Bundled plugins currently include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multilang — WPML-style translation, menu translation, language-prefixed routing, and language-aware redirects&lt;/li&gt;
&lt;li&gt;seo-extras — Yoast-style per-content SEO fields&lt;/li&gt;
&lt;li&gt;code-snippets — site-level injection for head, body open, and body end slots
The idea is simple: themes should own presentation, plugins should own extensions, and the core should be the integration boundary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some UI Preview&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpjsh8a2efpez3n5toki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpjsh8a2efpez3n5toki.png" alt=" " width="800" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9joq07vaarq3wmy9embq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9joq07vaarq3wmy9embq.png" alt=" " width="800" height="809"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Current status
&lt;/h2&gt;

&lt;p&gt;GoPress is currently in beta.&lt;br&gt;
The core content model, admin CMS, theme engine, plugin mechanism, SEO layer, cache path, media pipeline, and bundled example themes are usable. However, the project still needs more production validation, benchmark coverage, migration guides, and security review before I would call it stable.&lt;br&gt;
If you try it today, I would recommend starting with internal sites, company websites, documentation sites, or content-driven applications where you can validate your own traffic profile, editorial workflow, backup strategy, and deployment model.&lt;br&gt;
This is an early public release, and I would rather be transparent about that than over-market it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;p&gt;Requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go 1.25+&lt;/li&gt;
&lt;li&gt;PostgreSQL 14+&lt;/li&gt;
&lt;li&gt;Redis 7+ optional&lt;/li&gt;
&lt;li&gt;cwebp optional for WebP variants
The local build flow is:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/0xmattg/go-press.git
&lt;span class="nb"&gt;cd &lt;/span&gt;go-press

go mod download
make gopress

./build/gopress serve

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On first run, the web installer guides database setup, site bootstrap, and admin account creation. After startup, the public site is available at &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;, the admin CMS at /admin, Swagger docs at /swagger/index.html, and the REST API at /api/v1/content.&lt;br&gt;
GoPress also includes a small CLI named gopress. It scans themes/ and plugins/ at startup, regenerates the autoload package, and runs the server, so adding a theme or plugin does not require hand-editing imports.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would love feedback on
&lt;/h2&gt;

&lt;p&gt;I am especially interested in feedback from people who have built CMS systems, WordPress plugins/themes, Go web services, self-hosted publishing tools, or internal admin platforms.&lt;br&gt;
Some questions I am thinking about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the content model feel flexible enough without becoming too abstract?&lt;/li&gt;
&lt;li&gt;Are the theme and plugin boundaries clear?&lt;/li&gt;
&lt;li&gt;Is the hook/filter design idiomatic enough for Go developers?&lt;/li&gt;
&lt;li&gt;What would you expect from a production-ready Go CMS?&lt;/li&gt;
&lt;li&gt;Which migration path would matter most: WordPress import, Markdown import, static-site import, or custom database import?&lt;/li&gt;
&lt;li&gt;What benchmark scenarios would you consider meaningful?&lt;/li&gt;
&lt;li&gt;Would you use this more as a CMS, a website engine, or a content framework embedded into another Go application?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;GoPress is still early, but the direction is clear: I want to build a serious Go-native CMS engine for developers who like the CMS product model but prefer Go’s deployment and engineering characteristics.&lt;br&gt;
It is not trying to replace the entire WordPress ecosystem. That would be unrealistic. Instead, it is trying to serve a narrower group of developers and teams who want a self-hosted, extensible, Go-based content system with themes, plugins, admin workflows, APIs, SEO, media handling, and caching in one coherent codebase.&lt;br&gt;
If this sounds interesting, I would really appreciate stars, issues, pull requests, technical criticism, architecture feedback, or even just a quick “this part feels wrong” comment.&lt;br&gt;
GitHub: &lt;a href="https://github.com/0xmattg/go-press" rel="noopener noreferrer"&gt;https://github.com/0xmattg/go-press&lt;/a&gt;&lt;br&gt;
Site: &lt;a href="https://gopress.xyz" rel="noopener noreferrer"&gt;https://gopress.xyz&lt;/a&gt; (also powered by GoPress)&lt;br&gt;
Thanks for reading.&lt;/p&gt;

</description>
      <category>go</category>
      <category>wordpress</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
