← All projects

Previous portfolio

Data Analyst Portfolio Website

Schema-validated React portfolio SPA for data-analysis case studies.

  • React
  • TypeScript
  • Vite
  • Bun
  • +10 more

An earlier personal portfolio built to present data analysis case studies as structured, searchable content — static frontend, validated data pipeline, and one serverless route for geo IP checks.

Problem

I needed a portfolio for presenting data analysis work and project visualizations without running a CMS or database. Content stays in validated JSON, deploys as a static SPA, and only uses backend code where a server-side secret is required.

Frontend work
  • React 19 + TypeScript + Vite SPA with lazy-loaded routes
  • Theme UI design system with light/dark mode
  • Searchable and filterable project grid
  • Project detail pages with case-study structure and plot carousel
  • Static content pipeline using JSON, Zod schemas, and Vite asset resolution
  • Contact page with React Hook Form, Getform submission, clipboard copy, and resume download
  • SEO metadata with react-helmet-async, sitemap, robots, and Vercel Speed Insights
  • Accessibility details including skip link, reduced-motion styles, and ARIA feedback states
Backend & system work
  • Minimal Vercel serverless handler for GET /api/geo-block
  • Abstract API IP geolocation used server-side so the API key stays private
  • Vercel routing that sends /api/* to the serverless handler and the rest to the static frontend
  • Client-side Getform submission for contact messages
Key decisions
  • Used JSON + Zod instead of a CMS/database to keep content git-reviewable and statically deployable
  • Kept backend scope intentionally minimal — only serverless code where secrets must remain server-side
  • Used Zustand as a lightweight access layer over validated static content
  • Lazy-loaded routes and heavier UI pieces to keep the SPA structure cleaner
  • Used Vercel to deploy a static frontend and one serverless route from the same repo
Challenges
  • Keeping content integrity without a CMS
  • Resolving local asset references into Vite build output
  • Coordinating static frontend routing with a minimal serverless backend
  • Keeping Theme UI and React Bootstrap components visually consistent
  • Making geo-blocking fail open so the site still renders when the external API is unavailable
Tech stack
Frontend
  • React 19
  • TypeScript
  • Vite
  • React Router
  • Theme UI
  • React Bootstrap
  • Framer Motion
  • Zustand
  • Zod
  • React Hook Form
  • react-helmet-async
Backend
  • Vercel serverless Node handler
Data
  • Local JSON content files
Infrastructure
  • Vercel
  • Vercel Speed Insights
Tooling
  • Bun
  • TypeScript
  • Vite
Browser APIs
  • Clipboard API
  • fetch