A simple yet complete portfolio website built with React, TypeScript, and Tailwind CSS.
npm install
npm run devsrc/
├── components/
│ ├── ui/ # Design system primitives
│ │ ├── Button.tsx # Variants: primary, secondary, ghost
│ │ ├── Input.tsx # Accessible form input with error states
│ │ └── Card.tsx # Compound component for content containers
│ └── layout/ # Page structure components
│ ├── Container.tsx
│ ├── Header.tsx
│ ├── Footer.tsx
│ └── PageLayout.tsx
├── pages/
│ ├── Home.tsx # Landing page with positioning
│ ├── CaseStudies.tsx # Case study overview
│ ├── CaseStudyDetail.tsx # Individual case study template
│ ├── HowIWork.tsx # Approach and philosophy
│ ├── Components.tsx # Design system documentation
│ └── About.tsx # Personal background
├── data/
│ └── caseStudies.ts # Case study content
├── types/
│ └── index.ts # Shared type definitions
├── App.tsx # Routing and layout
├── main.tsx # Entry point
└── index.css # Tailwind imports and custom styles
- No UI library: Components are simple enough that a library adds more complexity than value
- CSS-in-Tailwind: Utility classes for most styling, custom CSS only for prose content
- Route-based code splitting: Pages load on demand for smaller initial bundle
- Typed data files: Case studies as TypeScript objects provide type safety without CMS complexity
- Compound components (Card.Header, Card.Body): Composition over configuration
- forwardRef on form elements: Compatibility with form libraries
- useId for accessibility: Automatic unique ID generation for label/input pairs
- No global state management (not needed for a portfolio)
- No form library (controlled inputs are sufficient)
- No animation library (CSS transitions handle hover states)
- No image optimization (native loading="lazy" is enough)
npm run dev— Start development servernpm run build— Build for productionnpm run preview— Preview production buildnpm run lint— Run ESLint
Edit src/data/caseStudies.ts and add a new CaseStudyDetail object. The type system will enforce the required structure.
Edit tailwind.config.js to modify:
- Colors in
theme.extend.colors - Fonts in
theme.extend.fontFamily - Spacing and other design tokens
New UI components go in src/components/ui/. Follow the existing patterns:
- Accept
classNamefor styling overrides - Use
forwardReffor interactive elements - Document design decisions in comments