// Case study
Professional Portfolio & Blog Platform
The site you are reading — a content-driven Next.js 16 platform with exactly one backend route, an evidence policy enforced in code, and a technical audience able to check every claim against the live URL.

Table of Contents
Most case studies ask you to take the author's word for things. This one cannot: it describes the site you are reading, so every claim is checkable against a live URL, a response header, or view-source. I built fiqshal.dev alone and I run it deliberately over-engineered — not because a portfolio needs a hardened CSP and a dual deployment target, but because this is the one production system where I can show my working instead of describing it. Treat the page as a small audit where the subject and the evidence are the same artifact.
The brief
The site has three jobs, in priority order:
- A consulting funnel. A prospective client should land, understand what I do, see proof, and reach the contact form in under a minute — without meeting a single line of copy I cannot stand behind.
- A writing platform. Long-form technical essays in MDX, with what a reading audience expects: RSS, syntax highlighting, readable measure, dark mode.
- Proof of craft. For a senior engineer the portfolio is the first work sample a technical reader inspects. The site has to survive that inspection — payload sizes, headers, semantics, all of it.
All of it maintained by one person, in the hours around client work.
Constraints
- Solo maintenance. No database to migrate, no CMS server to patch, no queue to babysit. Anything that can be a build artifact is a build artifact.
- Content as data. Page copy lives in typed constant files; essays and case studies live as MDX in git. A content change is a commit — reviewable, revertable, greppable.
- Static-first, one real backend. Every public page is statically generated.
Exactly one route runs user-driven logic at request time:
POST /api/contact. - An honesty architecture. Site metrics carry a
verifiedflag in the data layer, and the homepage renders only those not marked unverified. A 99.9% uptime figure exists in the codebase today, flaggedverified: false— and is therefore invisible — until I can actually evidence it. The same policy governs this page. - Two exits. The identical build must run as a self-hosted Docker container and on Vercel-class hosts. Both targets are supported on purpose: one buys cost and control, the other convenience, and I decline to architect either option away.
Approach & decisions
The architecture is a static-generation pipeline with a single runtime appendix. MDX files and typed constants feed a Turbopack build that emits the static routes plus the machine-facing surface — feeds, sitemap, structured data, social images. The result is served from a container or an edge host, and one API route handles the only thing that genuinely needs a server: sending email.
- Server-first React. Components are React Server Components by default;
'use client'appears only where interactivity demands it (theme, search, the contact form, animation islands). Content reads —fsplusgray-matter, rendered throughnext-mdx-remote— never leave the server, and detail pages are emitted viagenerateStaticParams(). - Constants as content. Hero copy, the career timeline, testimonials and navigation are typed TypeScript constants. The compiler catches a missing field in copy the same way it would in code.
- An editing layer without a CMS to operate. Keystatic provides a git-backed admin UI, and middleware returns a 404 for the entire admin surface in production unless GitHub-mode auth is configured. No always-on editor, no second system to secure.
- Security as a posture, not a feature. Input sanitization in the contact route and the Content-Security-Policy are two halves of the same XSS defense. The contact route also rate-limits per IP in memory — an honest caveat: that limiter resets on restart and is per-instance, which is a documented trade-off, not an oversight.
- Motion discipline. Framer Motion everywhere it earns its keep, behind a
layered reduced-motion system: a
MotionConfigboundary plus a CSS kill-switch forprefers-reduced-motion, so no variant can opt out. - No machine learning where set intersection will do. Related posts are matched by shared tags. I label it that way, because calling tag overlap "AI-powered" is the kind of claim this site exists to avoid.
Two alternatives were considered and rejected. A hosted, database-backed CMS would have added an operational surface, a bill, and a second authentication system to a site one person maintains — for content that changes a few times a month. A client-heavy SPA would have shipped the entire rendering burden to the reader of what is, overwhelmingly, text.
Evidence
Dated where it decays, mechanical where it can be checked. Figures are as of 2026-06-12 and verifiable against the live site.
- 30+ statically generated routes. The production build pre-renders the full public surface — pages, posts, case studies, social cards — so serving is file delivery, not computation.
- First Load JS ≤ ~250 kB (gzip) on public routes. Held there by
optimizePackageImportsfor the two heaviest libraries (Framer Motion, lucide-react) and by lazynext/dynamicvariants for below-the-fold animation components. - Per-route Open Graph images. Every route generates its own social card, rendered with fonts vendored in the repository — no third-party screenshot service in the loop.
- A code-generated machine surface. RSS 2.0, sitemap, robots, a PWA manifest with icons, and JSON-LD (Person, Organization, Article) all derive from one site-config module, so they cannot drift apart.
pnpm audit --prod: 0 known vulnerabilities, as of 2026-06-12. The date is the point — this claim decays, so it ships with one.- A full security-header set, including a Content-Security-Policy with no
unsafe-evaland HSTS in production. In the interest of the same candor:script-srcstill carriesunsafe-inlinefor first-party inline bootstraps (JSON-LD, the theme anti-flash script); a nonce-based CSP is the planned upgrade. You can read all of this in the response headers. - Accessibility as mechanism, not score. A global
:focus-visiblesystem and the two-layer reduced-motion guard described above. WCAG 2.1 AA is the target I build against; the site has not been independently audited, so I do not claim conformance. - Server-rendered content, precisely stated. Posts and case studies arrive as server-rendered HTML and are readable as such. The theme toggle, search, and the contact form are client islands and require JavaScript — so no, the site does not simply "work without JavaScript", and I will not claim it does.
- Deterministic generative covers. Content without artwork receives cover art derived deterministically from its slug — the same input always draws the same image, and no binary assets enter git.
- Dual deployment, honestly. A multi-stage Dockerfile produces a non-root, standalone-output image for self-hosting; the same codebase deploys unchanged to Vercel-class hosts. Both are first-class targets, not a contradiction.
What this page does not claim: uptime (unmeasured), Lighthouse scores (unstable lab numbers), or any conformance certificate. An earlier version of this very page claimed "99.99% uptime" and "100% WCAG AA". Neither was measured, so both are gone — that deletion is the evidence policy doing its job.
Stack notes
Next.js 16 (App Router) · React 19 · TypeScript in strict mode · Tailwind CSS v4
· Turbopack for dev and production builds · MDX via next-mdx-remote with
sugar-high highlighting · Framer Motion · shadcn/ui · Resend for transactional
email · pnpm. Fonts are self-hosted; nothing on the critical path phones a third
party.