ProjectsCase Study

ZN CMS

The private content desk behind zohaibnawaz.dev—Share Studio, Hire Forms, leads, manager RBAC, and draft approvals on a shared Supabase database.

ZN CMS dashboard overview in light mode
Industry
Professional services · Portfolio operations
Category
Internal CMS · Ops console
Role
Full Stack Product Engineer — product, RBAC, content workflows, and monorepo architecture
Timeline
2026 — ongoing
Status
Private production companion to zohaibnawaz.dev
Stack
Next.js · Turborepo · TypeScript · Tailwind · Supabase · RLS · Server Actions · Realtime

Executive Overview

ZN CMS is the staff-facing half of the personal brand system. Public hire and share URLs live on zohaibnawaz.dev; editors manage the same records from a private Dashboard.

Access is invite-only. Managers get scoped presets; sensitive edits go into draft_data until Admin approval—so public content is never half-published by accident.

Active modules: Share pages, Hire forms and submissions, Team, Leads with a realtime inbox, Managers, Approvals, and Notifications. Projects and Media stay roadmap—not padded into this case study as finished product.

Business Problem

Existing workflow

Portfolio content, proposals, hire applications, and contact leads lived across the public site UI, Drive folders, and email—with no clean draft → review → publish path.

Pain points

  • Editing live portfolio content from the public site risks broken client-facing pages.
  • Collaborators need scoped access without becoming full owners.
  • Hire applications and contact leads arrive faster than a static inbox can handle.
  • A general multi-tenant SaaS shell is overkill for one brand site.

Why it matters

A personal practice that ships proposals and hiring flows needs clear roles, non-destructive review, and a live ops inbox—without opening a public CMS to the world.

Solution

ZN CMS keeps portfolio operations in one private desk that shares a database with the live site:

  • Shared Supabase backend

    CMS and zohaibnawaz.dev read/write the same hire, share, leads, and profile tables.

  • Manager RBAC

    Invite-only Managers with viewer/editor/publisher presets and per-module caps.

  • Draft → Admin approval

    Manager edits write draft_data; live blocks stay intact until Admin approve/reject.

  • Realtime ops

    Leads inbox and notification bell update over Supabase Realtime.

One private console for share/hire/leads ops, safer collaborator access, and a live portfolio that only shows Admin-approved content.

Core Features

Share & hire

Share pages

Client share pages with slug, blocks (pdf, link, note, pricing), visibility, and expiry.

NeedClients need one branded link—not a Drive folder dump.

ValueFaster reviews and stronger proposal presentation.

Draft → publish

Manager edits land in draft_data; Admin Approvals publish without overwriting live pages mid-edit.

NeedPublic /share/[slug] URLs must stay stable.

ValueSafe collaborator editing for client-facing links.

Hire → Team

Public apply on the portfolio; staff triage in CMS; approved applicants become team profiles.

NeedHiring needs structured intake without sharing one UI with candidates.

ValueShort path from application to internal roster.

Ops inbox

Leads

Contact-form leads with status pipeline, search, and filters.

NeedInquiries need triage, not an unread email pile.

ValueClear follow-up state for serious conversations.

Realtime + notifications

Leads and a per-user bell update live via Supabase Realtime.

NeedOps desks go stale if staff must refresh constantly.

ValueFaster response when a lead or review arrives.

Access

Managers & approvals

Admin invites Managers with presets; Approvals queue for pending drafts.

NeedCollaborators need scoped power; publish must stay intentional.

ValueSafe division of labor on a single brand site.

Invite-only auth

Public signup disabled; Admin-driven invites.

NeedThis is a private desk, not a self-serve SaaS.

ValueHard boundary against random account creation.

User Journey

Manager → Draft share page

  1. 01

    Admin invites Manager with Share editor access

  2. 02

    Manager creates or edits a share page

  3. 03

    Changes land in draft_data

  4. 04

    Admin reviews Approvals and publishes

  5. 05

    Public portfolio URL serves the live version

Visitor → Hire submission

  1. 01

    Candidate opens hire apply link on zohaibnawaz.dev

  2. 02

    Completes form and uploads documents

  3. 03

    Submission appears in CMS Hire inbox

  4. 04

    Staff review; optional approve into Team

Technical Highlights

SaaS kit, one workspace

Started from a Makerkit-style Turborepo, then deliberately collapsed multi-tenant org patterns to one Admin-owned workspace.

Business valueSerious ops ergonomics without shipping a public multi-tenant CMS.

One database, two surfaces

ZN CMS and zohaibnawaz.dev share the same Supabase tables for share pages, hire, leads, and notifications.

Business valuePublic URLs and the ops desk never drift out of sync.

Draft vs live publish

Manager edits write draft_data; live columns stay public until an Admin approves or rejects.

Business valueCollaborators can work without half-publishing a client-facing page.

Capability checks on every mutation

Presets × module flags × canDelete / requiresApproval, enforced in Server Actions through assertCapability—not only in the UI.

Business valuePermissions match real desk roles even if a route is wrong.

Challenges & Solutions

ChallengeSolution
Managers needed to edit share and hire content without overwriting what clients already see on live URLs.draft_data staging plus an Admin Approvals queue before anything becomes public.
A multi-tenant SaaS starter assumed orgs and self-serve signup; this desk is invite-only for one brand.Constrain the fork to a single workspace owner, block public signup, and invite Managers with scoped presets.
If portfolio and CMS used separate databases, hire and share records would need constant sync jobs.One Supabase project: portfolio serves public pages; CMS owns staff workflows on the same tables.
UI-only permission menus are not enough when Server Actions can still mutate modules a Manager should not touch.assertCapability on mutations, backed by RLS and CSRF on state-changing requests.

Tech Stack

Monorepo
Turborepo, pnpm workspaces, Makerkit-lite packages
Frontend
Next.js App Router, React, Tailwind, Shadcn/Radix (@kit/ui)
Backend
Server Components + Server Actions
Database
Supabase Postgres with Row Level Security
Auth
Supabase Auth — invite-only
Realtime
Supabase Realtime — leads inbox and notifications
Security
CSRF, JWT claims in middleware, service role server-only

Project Gallery

Recommended capture order for the case-study gallery.

  1. 01Dashboard home — module overview
  2. 02Share Studio — editor with blocks
  3. 03Approvals — pending Share draft review
  4. 04Hire — submission inbox
  5. 05Leads — realtime inbox
  6. 06Managers — invite and capability presets
  7. 07Notifications — bell feed

Key Learnings

Product

A personal-brand CMS should feel like a private companion desk—not a second public product you have to market.

Engineering

When content already has public URLs, draft vs live is the real unlock for safe collaborator editing.

Architecture

One shared database beats dual-write sync—only if capability checks and RLS stay strict on every write path.

Future Improvements

PriorityImprovementBusiness value
HighProjects module wired to portfolio case-study contentEdit work entries in CMS without touching the site repo for every change.
HighMedia library with Storage-backed assetsOne place to manage images used across the brand system.

Need a private ops desk behind a public brand site?

ZN CMS is a case study in invite-only RBAC, draft approval, and a shared Supabase backend with a live portfolio—not a multi-tenant CMS for everyone. If you want the same clarity for your product or practice, start a conversation.

Start a conversation
Role

Full Stack Product Engineer

Client

Personal brand ops / internal CMS

Date

2026

Collaborators

Solo build

Next Project

Zohaib Nawaz Dev

View next