Portfolio Website
Value statement: High-performance developer portfolio showcasing data engineering projects and technical blog with perfect Lighthouse scores and modern web standards.
Overview
Built personal portfolio website using modern web technologies emphasizing performance, accessibility, and developer experience. Astro framework provides static-site generation with React islands for interactivity, Tailwind CSS for utility-first styling, and MDX for content authoring.
Achieved perfect 100/100 Lighthouse scores across all metrics (Performance, Accessibility, Best Practices, SEO). Features include dynamic project showcase, technical blog with syntax highlighting, dark mode, responsive design, and optimized image loading.
Goals
- Build fast, accessible personal portfolio and blog
- Achieve perfect Lighthouse scores (100/100)
- Support MDX for rich content authoring with React components
- Implement dark mode with persistent user preference
- Optimize Core Web Vitals (LCP, FID, CLS)
- Enable SEO with Open Graph and schema.org metadata
- Provide excellent developer experience with hot reload
- Deploy with CI/CD to Vercel/Netlify
Architecture
┌─────────────────────────────────────────────────────────────┐│ Astro Framework (SSG) ││ Static Site Generation | Partial Hydration │└──────────────────────────┬──────────────────────────────────┘ │ ┌──────────────────┼──────────────────┐ ▼ ▼ ▼┌──────────────┐ ┌──────────────┐ ┌──────────────┐│ Content │ │ React │ │ Styling ││ (MDX) │ │ Islands │ │ (Tailwind) ││ │ │ │ │ ││ - Blog posts │ │ - Theme │ │ - Utility ││ - Projects │ │ toggle │ │ classes ││ - Resume │ │ - Giscus │ │ - Dark mode ││ │ │ comments │ │ - Responsive ││ │ │ - Search │ │ │└──────────────┘ └──────────────┘ └──────────────┘ │ │ │ └──────────────────┼──────────────────┘ ▼┌─────────────────────────────────────────────────────────────┐│ Build Pipeline ││ TypeScript | Vite | Image Optimization | Minification │└──────────────────────────┬──────────────────────────────────┘ ▼┌─────────────────────────────────────────────────────────────┐│ Static Assets ││ HTML | CSS | JS | Images (WebP/AVIF) | Fonts │└──────────────────────────┬──────────────────────────────────┘ ▼┌─────────────────────────────────────────────────────────────┐│ Deployment (Vercel) ││ CDN | Edge Functions | Analytics | Auto-HTTPS │└─────────────────────────────────────────────────────────────┘Technology Stack
| Layer | Technologies |
|---|---|
| Framework | Astro 4.x, React 18 |
| Language | TypeScript (strict mode) |
| Styling | Tailwind CSS 3.x, CSS custom properties |
| Content | MDX, Markdown, Content Collections |
| Images | Astro Image, Sharp (WebP/AVIF) |
| Icons | Heroicons, Lucide React |
| Syntax Highlighting | Shiki (VS Code highlighting) |
| Comments | Giscus (GitHub Discussions) |
| Analytics | Vercel Analytics, Plausible |
| Deployment | Vercel (CDN + Edge Functions) |
| Version Control | Git, GitHub |
Implementation Details
Astro Framework for Performance: Astro’s partial hydration strategy delivers:
- Zero JS by default: Static HTML for non-interactive components
- Islands architecture: React components hydrate only when needed (
client:load,client:visible) - Build-time rendering: All pages pre-rendered at build time
- Automatic code splitting: Each island is separate bundle
- CSS scoping: Component styles don’t leak, only ship used CSS
React Islands for Interactivity: Strategic use of React for dynamic features:
- ThemeToggle: Dark/light mode with localStorage persistence
- Giscus comments: GitHub Discussions integration for blog
- Search: Full-text search across blog posts
- Gallery: Image lightbox with keyboard navigation
- All islands use
client:visiblefor lazy loading below fold
Tailwind CSS + Dark Mode: Utility-first styling with:
- Custom color palette for brand consistency
- Dark mode via
classstrategy (toggle persistence) - Responsive breakpoints (sm, md, lg, xl, 2xl)
- Custom utilities for animations and transitions
- JIT compiler for minimal CSS bundle (~15KB gzipped)
MDX Blog with Syntax Highlighting: Rich content authoring capabilities:
- Import React components directly in Markdown
- Shiki for VS Code-quality code highlighting
- Custom components: Alert, Gallery, YouTube embeds
- Reading time estimation
- Table of contents auto-generation
- Anchor links for headings
Image Optimization: Automatic image transformations:
- Convert to WebP/AVIF for modern browsers
- Generate responsive srcset (multiple sizes)
- Lazy loading with
loading="lazy" - Blur-up placeholders for LCP optimization
- Automatic width/height to prevent layout shift (CLS)
SEO Optimization: Comprehensive metadata strategy:
- Open Graph tags for social sharing
- Twitter Card meta tags
- Canonical URLs for duplicate content prevention
- XML sitemap auto-generation
- Robots.txt configuration
- Schema.org structured data (Person, BlogPosting)
- Semantic HTML (header, nav, article, aside)
Performance Metrics
Lighthouse Scores (Mobile):
| Metric | Score |
|---|---|
| Performance | 100/100 |
| Accessibility | 100/100 |
| Best Practices | 100/100 |
| SEO | 100/100 |
Core Web Vitals:
| Metric | Value | Target |
|---|---|---|
| LCP (Largest Contentful Paint) | 0.8s | <2.5s ✓ |
| FID (First Input Delay) | 8ms | <100ms ✓ |
| CLS (Cumulative Layout Shift) | 0.001 | <0.1 ✓ |
| TTFB (Time to First Byte) | 120ms | <600ms ✓ |
Bundle Sizes:
- Initial HTML: ~8KB (gzipped)
- CSS: ~15KB (gzipped)
- JavaScript: ~25KB (gzipped, only for islands)
- Total page weight: ~200KB (with images)
Features & Capabilities
Content Management:
- Type-safe content collections with Zod schemas
- Frontmatter validation (title, date, tags, draft status)
- Automatic RSS feed generation
- Tag-based filtering and navigation
- Pagination for blog post lists
User Experience:
- Dark/light theme with system preference detection
- Keyboard navigation support
- Screen reader friendly (ARIA labels)
- Print stylesheets for blog posts
- Copy code button for syntax blocks
- External link indicators
Developer Experience:
- Hot module replacement (HMR) in development
- TypeScript strict mode for type safety
- ESLint + Prettier for code consistency
- Pre-commit hooks with Husky
- GitHub Actions for CI/CD
- Preview deployments for pull requests
Lessons Learned
Astro vs Next.js: Initially considered Next.js but Astro’s content-first approach and zero-JS default made it perfect for portfolio/blog use case. Simpler mental model and better performance out of box.
Islands architecture: Over-hydrating with React everywhere hurts performance. Identifying truly interactive components and using client:visible reduced JS bundle by 60%.
Tailwind adoption curve: Initial resistance to utility classes but quickly appreciated speed of iteration and consistency. Dark mode implementation was trivial compared to traditional CSS.
MDX power: Ability to import React components into Markdown unlocked rich content possibilities (interactive demos, embedded visualizations) without complex CMS.
Image optimization matters: Switching from <img> to <Image> component with automatic WebP/AVIF conversion improved LCP from 1.8s to 0.8s.
Future Improvements
- Add full-text search with Pagefind or Algolia
- Implement view counts and popular posts tracking
- Add newsletter subscription with Buttondown/ConvertKit
- Build project showcase with live demos (CodeSandbox embeds)
- Add CSS-in-JS with Emotion for dynamic theming
- Implement internationalization (i18n) for multi-language support
- Add webmentions for cross-site comments
- Create automated screenshots with Playwright for project cards
- Add reading progress indicator for blog posts
- Implement related posts recommendation algorithm