STAKR CMS

STAKR is a multi-tenant, headless CMS built to power a fleet of client websites from a single editor, using one API and one shared edge infrastructure.

Product
Headless CMS Platform
Role
Design & Development
Stack
React · Cloudflare Workers
admin.stakrcms.com
On the brief

Client sites kept needing the same things: editable pages, a media library, forms, navigation, SEO, and accessibility checks. Rather than rebuild them each time, I built one platform that every site plugs into. Editors get a familiar tool and each site keeps its own design without compromise.

The STAKR page builder showing the homepage sections listed on the left and the live preview scrolled to the gap between the hero and stats sections, with an Add Section button between them.
Page builder
The media library grid of property photos showing file sizes, unused badges, and missing alt text flags.
Media library
What editors get
  • Visual page builder Drag-to-reorder sections with a live preview that renders the site's own components and CSS.
  • Collections & articles Repeatable content types declared by each site, with scheduling, publishing, and SEO fields built in.
  • Media library Upload, crop, and tag images with alt text, served with on-the-fly transforms.
  • Accessibility scanning WCAG 2.1 AA checks, bulk alt-text fixing, and a conformance report inside the editor.
  • Messages, tasks & analytics Contact-form inbox, an internal task board, and traffic overview.
  • Roles & tenants Super-admin, tenant-admin, and editor roles with a tenant switcher for multi-site users.
Other Features
  • Scheduled publishing
  • Redirect manager
  • Nested navigation menus
  • Events calendar
  • Popup modals
  • Saved sections
  • Password-protected pages
  • Core Web Vitals
  • GEO audit
  • llms.txt generator
  • Dynamic sitemap & robots.txt
  • JSON-LD schema
  • Customizable dashboard
  • Google Maps regions
  • Commerce7 integration
  • Mailchimp forms
  • Instagram feed
  • Product feed
  • Notifications
  • PDF compression
  • User invitations
  • Cloudflare Turnstile
  • Rate limiting
  • Storage limits
  • Per-tenant branding
  • Light & dark themes
A property listings table with thumbnails, addresses, slugs, prices, and status tabs for active, draft, pending and sold.
Properties collection
The accessibility panel showing an automated check score and a list of open issues.
Accessibility checks
Under the hood

A Hono API on Cloudflare Workers backed by D1 and R2, a React 19 admin, and server-rendered client sites that cache at the edge and purge on publish. Sites teach the CMS their own section types through a JSON schema, so the admin never needs site-specific code.

A task board with To Do, In Progress and Done columns holding task cards with priorities, due dates, checklists and assignee avatars.
Task board
The image editor with the crop tool active, a 4:3 crop box over a coastal home photo and aspect ratio, flip and rotate controls in the side panel.
Image editing with crop
Sections

Every page is a stack of sections: a hero, a gallery, a form, a feed. A site defines the sections it has, and the CMS turns each definition into an editor, so a new section is one JSON entry and one component.

1 · Declare it — cms-schema/sections.json
{
  "type": "ProjectCapabilities",
  "label": "Project Capabilities List",
  "hasItems": true,
  "itemLabel": "Capability",
  "fields": [
    { "key": "eyebrow", "type": "text",
      "default": "What editors get —" }
  ],
  "itemFields": [
    { "key": "title", "type": "text" },
    { "key": "body",  "type": "textarea" }
  ]
}
2 · Register it — React component (simplified)
// sectionRegistry.js
export const SECTION_REGISTRY = {
  ProjectCapabilities: ProjectCapabilitiesSection,
}

// ProjectCapabilitiesSection.jsx
export default function ProjectCapabilitiesSection({ fields, items }) {
  return (
    <ul className="caps">
      {items.map((it) => (
        <li key={it.id}>
          <strong>{it.fields.title}</strong> {it.fields.body}
        </li>
      ))}
    </ul>
  )
}
How a section works
  • Declared, not hard-coded Each site lists its section types in a JSON file and pushes it with one command. The admin builds its editing forms from that, so it holds no code for any particular site.
  • Typed fields Text, rich text, numbers, links, selects, toggles, colors, images, galleries, tags and categories. A section declares which ones it needs.
  • Repeatable items A section can hold a list of sub-records, like the rows of a capabilities list or the slides in a gallery, each with its own fields.
  • One component, two jobs The React component that renders a section on the live site is the same one the builder previews, so what editors see is what ships.
  • Alt text managed once Image fields take their alt text from the media library: one string per asset, updated everywhere that image is used.
  • Traceable Every rendered section carries a hidden marker, so an accessibility finding points back to the exact section and field that caused it.

Let's make something.