Code-first CMS

The CMS this site runs on

UI-FIRST
devgon is a code-first CMS I designed and built: developers build the UI freely in Next.js, then expose any section to admin editing - no backend changes, no schema migrations. Every word and image on this website is served through it.
1Universal content entity
MultipleEditable sections live
0Migrations to add a field
Development flow

From static markup to editable content

Traditional CMSes make you design the database first and bend the UI to fit. devgon inverts it - the admin panel becomes a structured mirror of whatever UI you already built.
  1. Build the UI freely

    No templates, no theme system, no constraints. Next.js, Tailwind and whatever the design needs.

  2. Declare what is editable

    Wrap a section in ContentCardManager, name the fields and their limits. That is the entire integration.

  3. The backend just stores it

    One universal Content entity absorbs every section site-wide. New field, new section - no migration.

  4. Fetch via GraphQL with ISR

    Pages are statically generated and cached by tag, with JSON fallbacks so the site renders even if the backend is down.

  5. Edit live, revalidate instantly

    Saving in the panel triggers on-demand revalidation of exactly the pages that use that content key.

What is actually in the box

Everything below is built from scratch - no headless CMS SDK, no admin panel generator.
  • Universal content layer

    A single Content entity - title, subtitle, description, customData, media, key, order - backs every section of every page. Adding a section means picking a new key, not writing a model, an API and an admin form.

    TypeORMPostgreSQLGraphQL
  • customData as the escape hatch

    A JSONB column holds anything a section needs: CTA buttons, tag lists, stat rows, nested objects, feature flags. Extending a block never requires a schema migration.

    JSONBSchema-freeValidated
  • Rich text and JSON editing

    Tiptap for description fields with a sanitizing paste pipeline, plus a validating JSON editor for customData - so structured content stays structured even when edited by hand.

    TiptapSanitizerInline editing
  • Media pipeline

    Uploads land in MinIO with rollback on failure, drag-and-drop reordering on desktop and directional buttons on mobile, and permanent public URLs that browsers can cache.

    MinIOS3 APIDrag & drop
  • Auth and access control

    Google OAuth2, dual JWT with access and refresh tokens in HttpOnly cookies, refresh-token rotation in the database, and role-based guards - editing is gated behind the admin role.

    OAuth2JWTRBAC
  • ISR and on-demand revalidation

    Content is fetched with Next.js cache tags, so saving a block revalidates only the pages that consume that key. Static performance, live editing, no rebuild.

    Next.js ISRCache tagsSWR

The admin panel

A structured mirror of the real UI - each card maps to one section of one page, with exactly the fields that section renders.
  • devgon admin panel menu tabs
  • Content card in the devgon admin panel
  • Content cards in the devgon admin panel
  • Tiptap editor with multiple media
  • Google OAuth2 Sign in

The decisions behind it

Four choices that shaped the architecture - and what each one bought me.
  • UI-first instead of schema-first

    Traditional CMSes force the design to fit the data model. Here the model absorbs whatever the design needs, so a new section is a key and a JSON fallback - not a migration, a resolver and an admin form.

  • Fallbacks that keep the site alive

    Every section ships with a JSON fallback compiled into the bundle. If the backend or database is unreachable, pages still render fully - the CMS degrades to a static site instead of a 500.

  • One entity instead of N models

    Multiple live sections across three pages share a single table. Adding a fourth page costs no backend work at all - the content engine already handles it.

  • Tested where it actually breaks

    Unit tests cover content and media services including MinIO rollback paths; Playwright drives the real admin panel through create, edit, delete, reorder and upload against a live database.

Let's talk

Open to remote roles. Happy to walk you through any of the projects above.

Phone / WhatsApp

Notice period: 1 month. Available for B2B or an employment contract. I read every message and usually reply within 24 hours - my full CV is available on request.