Building this site
This portfolio renders from a single resume.json. The goal: a new resume is parsed, validated with zod and lands as a reviewed pull request before Cloud Build deploys it to Cloud Run. Validation and rendering work today; the pull request and deploy stages are in progress.
- Status
- In progress
- Dates
- Tags
- Next.js
- TypeScript
- zod
- MDX
- Cloud Run
Problem
Keeping a portfolio in sync with a resume by hand drifts. This site renders all career content from one validated file, so the resume is the source of truth.
TODO(saketh): in your words, why you built this and who it is for.
My role
TODO(saketh): your role (e.g. sole designer and engineer) and how you used Claude Code with guardrails.
Architecture
- resume.pdfinbox
- Parsezod
- resume.jsonvalidated
- PR reviewhuman gate
- Cloud Rundeploy
- Drawn
- SK
- Rev
- A
- Status
- In progress
Content is data: content/resume.json and content/projects/*.mdx are
validated with zod at build time, and an invalid file fails the build. Project
frontmatter uses a strict schema:
export const projectFrontmatterSchema = z.strictObject({
slug: z.string().regex(/^[a-z0-9]+(-[a-z0-9]+)*$/),
title: text,
summary: text,
featured: z.boolean().optional(),
tags: z.array(text),
status: z.enum(["in-progress", "shipped", "archived"]),
diagram: diagramSchema,
});
Key decisions and trade-offs
- Cloud Run over Vercel. TODO(saketh): the reason in your words (PROGRESS.md records it as "for the infra talking point").
- Strict zod objects as the PII guard: unknown keys such as
phonefail validation, so a resume parse that carries them over cannot be published. - WCAG 2.2 AA as a test gate: a contrast matrix over the design tokens in both themes, plus axe-core on every route.
- MDX is evaluated at build time only; no MDX runtime ships to the browser.
Outcome
TODO(saketh): the outcome. No metrics until real ones exist.
What I'd change
TODO(saketh): what you would do differently.