Case Study
How I Built This Portfolio
Most portfolios are static pages with hardcoded data. This one is a production system — database-driven, SEO-first, and automated. Here's exactly how it's engineered.
The Problem with Static Portfolios
Standard portfolios hard-code project data in a TypeScript file. Adding a new project requires editing code, committing, and re-deploying. That's not how production systems work.
I wanted a portfolio where I could add a project from a README file in under 2 minutes — with full SEO, dynamic routing, and case-study pages generated automatically.
System Architecture
The portfolio is a hybrid static/dynamic Next.js 15 App Router application deployed on Netlify. Key architectural decisions:
- ▸Server Components for all data-fetching — zero client bundle cost for project data
- ▸Static project data in TypeScript — type-safe, no external DB dependency
- ▸ISR (revalidate: 3600) on project pages, daily on homepage
- ▸generateStaticParams() pre-renders all project slugs at build time
// app/projects/[slug]/page.tsx
export const revalidate = 3600;
export async function generateStaticParams() {
const slugs = await getProjectSlugs(); // static project data
return slugs.map((slug) => ({ slug })); // pre-rendered at build time
}
export async function generateMetadata({ params }) {
const project = await getProjectBySlug(params.slug);
return {
title: project.title,
description: project.description,
openGraph: { type: "article", ... },
};
}Project Data Architecture
The projects data schema was designed for two consumers: the UI and search engines.
// projects data schema (src/lib/appwrite/queries.ts)
{
title: string // required
slug: string // unique — used as URL path
description: string // 160 chars max — used as meta description
content: string // full case study text
techStack: string[] // e.g. ["Next.js", "MongoDB"]
features: string[] // bullet list for SEO + UI
category: enum // saas | ai | ecommerce | fullstack | other
status: enum // production | building | archived
featured: boolean // controls homepage section
problemStatement: string // for case study UX
githubUrl: url // optional
liveUrl: url // optional
createdAt: datetime // ISO — used in sitemap lastModified
}The queries layer wraps all data access with typed functions — making it easy to swap data sources without touching UI code.
SEO Strategy
Three layers of SEO — each one independently valuable:
- ▸Per-page generateMetadata() — title, description, canonical URL, OG image from project data
- ▸JSON-LD structured data — Person schema on homepage, SoftwareSourceCode schema on project pages
- ▸Dynamic sitemap.ts — includes all /projects/[slug] routes generated at build time
- ▸robots.ts — programmatic robots file allowing all pages, disallowing /api/
Why Static Data Over a Database
For a portfolio site, static data in TypeScript gives the best tradeoffs:
// Benefits of static project data: // 1. Zero cold starts — no DB connection needed // 2. Type-safe — TypeScript catches errors at build time // 3. No external dependency — site never goes down // 4. Instant builds — no network calls during SSG // 5. Easy to update — just edit the array and deploy
Adding a new project means adding an object to the array and pushing to Git — Netlify auto-deploys in under 60 seconds.
Performance Decisions
- ▸System font stack — no Google Fonts network request, no layout shift
- ▸All data fetching in Server Components — zero client-side waterfall
- ▸ProjectFilter is the only client component — minimal JS hydration
- ▸next/image with explicit width/height everywhere — no CLS
- ▸RevealOnScroll uses Framer Motion useInView — no scroll event listeners
- ▸GitHub stats API cached at 1-hour revalidate — never blocks page render
- ▸Static fallback means the site works instantly with zero external dependencies
What This Demonstrates
This isn't about the tech choices. It's about the thinking:
- ▸System design before coding — schema decisions made for both UI and SEO needs
- ▸Resilient architecture — the system degrades gracefully, never breaks
- ▸Automation mindset — removing manual steps from repetitive workflows
- ▸Performance as a constraint — Lighthouse scores treated as requirements
- ▸SEO as engineering — structured data and canonical URLs are code, not configuration
Available Now
Looking for a Full Stack or Backend role
I'm actively looking for roles where I can build scalable systems, design clean APIs, and contribute to production applications. Open to full-time and contract work.
© 2026 Chirag Bhoi. Built with Next.js & Tailwind.