Building a Portfolio with Production-Grade Discipline
How I applied the same performance budgets, deployment pipelines, and architectural thinking to a personal project that I'd use on a system serving 24 million customers.
Most developer portfolios are built in a weekend and forgotten. They start as a Vercel template, get a coat of paint, and sit there collecting dust. That approach is fine if the portfolio is just a formality — a link to drop into a job application.
Mine needed to do more than that. I'm positioning for remote senior engineering roles where the portfolio isn't a formality — it's the interview before the interview. Hiring managers spending 60 seconds on my site need to leave thinking: this person builds things properly.
So I built it the way I'd build a production system. Here's what that looks like in practice.
Start with the Constraint, Not the Stack
When I build channel services at work, the first question is never “which framework?” It's “what are the constraints?” A kiosk in a branch 1,000km away has different constraints to a mobile app on a user's phone. The technology choices follow from the constraints, not the other way around.
For this portfolio, the constraints were clear: static content that needs to load fast globally, zero ongoing server costs, a deployment pipeline that catches regressions before they ship, and an architecture that can evolve from a static portfolio into a platform with blog content and eventually digital product sales — without a rewrite.
That constraint set pointed directly at Next.js with static generation, hosted on Vercel. Not because it's trendy, but because static generation means zero server compute per request (cost: free), Vercel's CDN handles global distribution, and Next.js API routes give me a backend when I need one later. The migration from “static site” to “product platform” is incremental, not architectural.
Performance Budgets Are Not Optional
At work, performance isn't aspirational — it's contractual. A self-service terminal that takes 4 seconds to respond to a screen tap will have customers walking away. We set timeout budgets per service call, and we enforce them.
I applied the same discipline here. Before writing a single component, I defined performance budgets:
| LCP | < 1.5 seconds |
| CLS | < 0.05 |
| Page weight | < 200KB initial load |
| JS bundle | < 80KB gzipped |
| Font payload | < 60KB total |
These aren't aspirational. They're assertions in the CI pipeline. Lighthouse CI runs on every pull request. If a change pushes LCP past 1.5 seconds, the build fails. The same way a service call that exceeds its timeout budget gets killed, a deployment that exceeds its performance budget gets blocked.
The impact: the hero section loads in under a second on a fast connection. The code rain animation, gradient orbs, and grid overlay — all CSS-only. No JavaScript framework needed for the visual effects. The animated entrance sequence uses CSS keyframes with staggered delays, not a motion library.
If you wouldn't ship a production API without latency budgets, why would you ship a website without performance budgets?
Design as a System, Not a Collection of Pages
The visual design follows the same token-based approach I'd use for a component library at work. Every colour, spacing value, font weight, and animation timing is defined once and referenced everywhere. No magic numbers, no inline overrides.
Two decisions drove the design system:
First, a mixed dark/light theme. Hero sections and the navigation use a dark palette (establishing technical credibility), while content sections use light backgrounds (optimising readability for dense case study text). The wave dividers between sections are SVG paths that create a smooth visual transition rather than a hard cut.
Second, a deliberate typography split. Outfit (sans-serif) for headings and body text — it's clean and professional without being generic. JetBrains Mono for labels, tags, stats, and code — signalling “this is an engineer's site” in the typography itself. Every instance of monospace type is a deliberate marker of technical content: case study numbers, tech tags, stat values, navigation labels.
The Deployment Pipeline
Every push to a feature branch triggers a preview deployment on Vercel. The preview runs Lighthouse CI (performance, accessibility, best practices, SEO) and Playwright for visual regression tests against screenshot baselines at three breakpoints: mobile (375px), tablet (768px), and desktop (1440px).
Merging to main triggers production deployment with CDN cache invalidation. Rollback is instant via Vercel's deployment history — no downtime, no manual intervention.
This is the same deployment confidence model I use at work. The question isn't “does this look right on my machine?” It's “have the automated checks confirmed this looks right at every breakpoint, loads within budget, and passes accessibility requirements?”
Accessibility Is Architecture, Not Afterthought
This was non-negotiable. At work, the self-service terminals serve customers across every demographic in South Africa. Accessibility isn't a nice-to-have — it's a legal and ethical requirement.
The portfolio targets WCAG 2.1 AA compliance. That means body text (#2D2D48 on #F7F7F9) achieves 8.2:1 contrast ratio. Every interactive element is keyboard-focusable with visible focus rings. Page transitions move focus to the new page heading. A prefers-reduced-motion media query disables all animations for users who've set that preference.
The automated accessibility audit runs axe-core through Playwright on every page. If a heading hierarchy is broken, or an interactive element lacks an accessible name, the build fails.
Architecture for Evolution
The most important architectural decision was designing for what the site will become, not just what it is today. Phase 1 is a static portfolio. Phase 2 adds a blog (MDX files in the repo, processed at build time). Phase 3 adds digital product sales (Stripe Checkout via API routes, Supabase for authentication).
Critically, none of these phases require an architectural change. The same Next.js App Router structure that serves static portfolio pages will serve dynamic blog listings and product pages. The same deployment pipeline that validates portfolio performance will validate blog post rendering and checkout flow reliability.
What This Proves
The portfolio itself isn't the point. Every engineer has a portfolio. What matters is whether the portfolio demonstrates the engineering discipline you'd bring to a team.
Performance budgets enforced in CI. Automated accessibility audits. A deployment pipeline with preview environments and instant rollback. A design system built on tokens rather than ad-hoc values. An architecture designed for evolution rather than just today's requirements.
These are the same patterns I apply to systems serving millions of customers. The scale is different. The discipline is identical.
This site is built with Next.js, Tailwind CSS, and deployed on Vercel. The source code is available on GitHub. If you're working on similar problems — channel services, service orchestration, resilience engineering — I'd enjoy the conversation.