Portfolio

The public editorial product: CMS-backed Work and Writing, no static fallback catalog, and no service-role key in the public app.

Product engineering · Content systemsEnd-to-end case study
  • Next.js Server Components
  • Supabase and PostgreSQL CMS
  • Google Drive PDF export
  • Resend contact workflow
Founders, recruiters, and engineers get one evidence-led path from positioning to shipped systems, technical depth, current experience, and contact.2025—26 · Product engineering · Content systems
01 / Problem

The product tension

A personal site that lives in the repo is always a week behind the work. I needed a public product that founders and engineers can read without a deploy for every sentence, and without a second copy of the same facts in TypeScript.

The trap is a brochure: screenshots, a résumé dump, and no evidence. The other trap is a CMS that the public app cannot trust—so the site falls back to hardcoded pages and the two stories diverge. Portfolio had to be the live narrative of what I build, with Work as the proof, not a gallery.

02 / Solution

What I built

I built jayantgoyal.com as a Next.js editorial product that reads only from the portfolio schema. There is no static fallback catalog. If a Work row is not visible, or a case study is not published, the detail route is a 404.

Read path. Server Components load typed public columns through @jayantgoyal/portfolio-contracts. The loader maps CMS rows into the editorial view model and caches them under the portfolio-content tag with a one-minute ISR window. Person name is not CMS-editable; shared identity supplies Jayant so Admin cannot rebrand the public person.

Write path. Admin owns mutations. Portfolio never creates a service-role client. Contact mail, résumé PDF, GitHub stats, and aggregate analytics stay on the server. Request admission lives in src/proxy.ts.

Proof. A case study is a structured JSON document—problem, solution, architecture (including Mermaid), decisions, security, tradeoffs, outcome—not a markdown file in git. The public renderer and the Admin form share that shape.

Walk it. This is already a public note, not a second product: how a record moves from Admin edit to the public page, and why the family is four apps with one data model.

03 / Architecture

How the system fits together

The public site is an editorial shell, not the Studio/Admin application chrome. Shared packages stop at identity, URLs, SEO helpers, and contracts. Content ownership stays in Postgres.

Drawing architecture diagram…
04 / Decisions

The calls that shaped the build

  1. 01

    I refused a second copy of the work

    If the public page can render without the CMS row, the CMS is decoration. I made published case studies the only way a Work detail exists, and I keep visibility and publication as explicit columns.

  2. 02

    I kept privileged keys out of Portfolio

    Portfolio and Auth use the anonymous key and RLS. Service-role work belongs in Admin after a live capability check. That is slower to operate and the reason a public deploy cannot silently become a CMS.

  3. 03

    I split editorial UI from the product shell

    Studio, Admin, and Auth share an application chrome. Portfolio does not. Recruiters should not feel like they logged into a console. Identity and URLs still come from packages so hosts do not drift.

  4. 04

    I show four systems on home, not every experiment

    CodeSync, this site, Studio, and Admin share the home grid. Auth and Studio's internal tools stay in the catalog or the Work archive so a formatter does not compete with a production RCM loop.

05 / Security

Trust boundaries

Public selects are column-limited. Administrative writes never run in this app. Contact submissions are validated and throttled; I do not persist raw network identifiers as a lead database. Analytics on the public site are aggregate Cloudflare signals, not visitor dossiers.

06 / Tradeoffs

What I chose—and accepted

A CMS-backed site has cache and schema cost a static export does not. ISR can show a minute of stale copy after an Admin save. I accept that over dual-maintaining markdown and SQL. Four featured cards can look like a product list; I keep each one a full study so the grid is range, not filler.

07 / Outcome

Why the work matters

The live site is the same contract Admin edits. Work details fail closed without a published study. Home shows CodeSync, this publishing system, Studio, and Admin. Auth stays in the Work archive. The walkable demo is the CMS note, not another dashboard.

08 / Next

What I would improve next

I would add preview and a field-level diff in Admin before publication so a case-study save is reviewable, then keep the public cache tag. I will not add a fifth featured card to fill space.