How this site was built.
The site you are reading is itself a portfolio piece. Written in collaboration with Claude Code, deployed in days, intentionally over-engineered in the places that matter and intentionally simple everywhere else.
Stack
- Next.js 15 (App Router): static rendering for every page, zero client-side data fetching.
- React 19 + TypeScript, strict mode on.
- Tailwind CSS: design tokens defined in
tailwind.config.ts, customink+accentpalettes. - MDX via
next-mdx-remote: case studies are content files, not React components. Edit a paragraph, redeploy in 30 seconds. - Gray-matter for front-matter (metrics, stack, ordering, featured flag).
- Vercel for hosting and preview deploys.
- Headless Chrome for the résumé PDF pipeline (
resume/build.mjs, zero dependencies).
On the MCP server
There are now official marketing-stack MCP servers, including one from HubSpot. I built my own hubspot-mcp before that, to learn the protocol from the ground up and to demonstrate the architecture I would build inside a marketing organization.
The build partner: Claude Code
Claude Code is Anthropic's CLI for Claude: agentic, file-system-aware, runs tools, takes a brief and ships code. I drafted the spec for this site (positioning, sections, content), Claude turned that into a working Next.js app, I reviewed, asked for changes, repeated. The same pattern I use professionally for marketing automation: human owns judgment, model owns mechanics.
The case study MDX system, the résumé HTML to PDF pipeline, the SEO and OG image setup, and the Lighthouse-passing performance tuning were all collaborative: fast iterations, explicit decisions, full version history.
Architecture decisions, briefly
Static everything
Most of the codebase avoids "use client". Pages are server-rendered at build time. The result: first contentful paint under a second on a cold cache, JS bundle close to zero. Hiring managers on a slow mobile connection see content immediately.
Content as front-matter
Case studies live in content/work/*.mdx with structured front-matter for the metrics, stack, and ordering. The home page and the work index both call getAllWork() from lib/work.ts. Add a new case study, push, deploy. It shows up everywhere with no manual wiring. The same pattern I use for client content pipelines at HAZE.
Résumé pipeline as a separate concern
The résumé is generated by a small Node script that prints an HTML template to PDF with headless Chrome. Every bullet is tagged by variant, so two résumés (AI Marketing and AI Engineer) ship from one content file with npm run resume. Adding a variant is one more tag.
Dark mode, one accent
Technical hiring audiences read dark mode more comfortably, and it avoids the standard agency-portfolio look. One accent color (a desaturated warm cream) used sparingly, applied to the primary CTA and case-study links, keeps the page from looking generic.
What I'd build next
- An MDX component library for inline metric callouts inside case studies.
- Per-case-study OG images generated from front-matter (next/og dynamic OG).
- A small writing section once I have 2–3 essays worth shipping.
Why this page exists
Claiming "I ship with AI tooling" is easy. Demonstrating it is the harder part. If you are hiring for a role where the candidate needs to understand both the marketing and the systems behind it, this page is the evidence. Let’s talk if that is the role.