Skip to content

Admin

A private CMS for Portfolio and Blog, with shared validation contracts, live capability checks, and Drizzle writes.

By End-to-end case study
  • Next.js Server Components
  • Supabase SSR and RLS
  • Typed CMS contracts
  • RBAC and revalidation
Editorial operations are separated from public presentation, so the portfolio can evolve without code edits or duplicated content while authorization remains server-enforced.
01 / Problem

The product tension

Editorial changes should not require editing application source, but hiding an editor route is not enough to protect a CMS. Admin needed to write the same records Portfolio reads while checking the caller at each privileged operation.

02 / Solution

What I built

Admin provides section-owned editing workspaces for Portfolio and Blog. Forms and API handlers share typed content contracts with the public reader. Work visibility and case-study publication remain explicit controls; Blog records have their own publication state.

The editor validates a write, checks the live caller capability, and updates the canonical content through Drizzle. Auth owns interactive entry and account security; Admin owns whether that identity can perform an editorial or access-management operation.

03 / Architecture

How the system fits together

The request proxy handles admission and MFA step-up where required. API handlers still authorize their specific operation. Product data modules run validated CMS and IAM commands through the restricted Admin database boundary. Supabase platform administration remains server-side and capability-gated.

Shared packages contain identity, session mechanics, and content contracts. Admin and Portfolio do not import each other’s screens. See the CMS walkthrough for the editorial flow.

04 / Decisions

The calls that shaped the build

  1. 01

    Share the record contract

    The form, write API, and public reader agree on fields and publication rules instead of maintaining three interpretations of the same content.

  2. 02

    Authorize the operation, not just the page

    Admission to Admin does not grant every write. Live capabilities distinguish read-only access from content and access-management mutations.

  3. 03

    Reduce latency across the request path

    The applications now run in Vercel’s Mumbai region near the database. Repeated auth work and database reads were reduced alongside the Drizzle migration; no isolated ORM speedup is claimed.

05 / Security

Trust boundaries

The app is private. MFA step-up applies when a factor exists. Service-role and Vercel tokens never ship to the browser. Public Portfolio queries never receive unpublished rows or privileged credentials.

06 / Tradeoffs

What I chose—and accepted

A separate editor adds deployment and session coordination. Explicit capabilities and shared contracts require maintenance, but make the difference between reading a draft and publishing it visible in the implementation.

07 / Outcome

Why the work matters

Content updates reach the same CMS records used by the public site without a code change for each edit. Read-only and editing access remain distinct, and database transport changes stay behind the existing APIs.

08 / Next

What I would improve next

Add preview and revision comparison before publishing, keeping publication an explicit choice rather than an autosave side effect.