Technical Stack: Site Architecture
This site is built with Astro in SSR mode, deployed to Cloudflare Pages, and uses Flox for development environment management. This post documents the technical stack and implementation decisions.
Framework: Astro SSR
Astro with Server-Side Rendering provides the foundation. Key implementation details:
- Islands architecture minimizes JavaScript bundle size
- Content Collections with TypeScript validation for type-safe content
- MDX integration for interactive blog components
- Built-in optimizations: image optimization, HTML minification
- SSR mode enables dynamic content generation at the edge
SSR was chosen over static generation to support dynamic features while leveraging Cloudflare’s edge computing for performance. The home page is pre-rendered for optimal loading speed, while blog pages and API routes use SSR for request-time functionality like category filtering.
Environment Management: Flox
Flox provides reproducible development environments across machines and platforms. Having experienced the transformative impact of uv for Python dependency management, I was drawn to Flox for bringing similar fast, reliable tooling to JavaScript projects.
flox install nodejs # Install Node.js in one command
flox activate # Sets up Node.js, installs dependencies
flox services start # Runs development server
Configuration in .flox/env/manifest.toml:
- Node.js runtime
- Automatic npm install on activation
- Wrangler service for local Cloudflare Pages testing
- Cross-platform support (macOS, Linux x86/ARM)
Eliminates environment inconsistencies and simplifies contributor onboarding.
Content & Styling
Content Collections: TypeScript-validated content collections in src/content/config.ts
Blog: MDX posts with frontmatter validation
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
heroImage: z.string().optional(),
draft: z.boolean().optional().default(false),
categories: z.array(z.string()).optional()
})
Images: Gallery configurations supporting multiple image sources:
- R2 buckets: Private image storage served via
/image/[...path].jsendpoint with responsive sizing - External URLs: Direct URL references for external images
- Local assets: Bundled images processed through Astro’s optimization pipeline
Work: Timeline data with automatic period string generation
Styling: Tailwind CSS with utility-first approach for rapid development and maintainable components.
Why Tailwind: Chosen for its utility-first methodology that eliminates context switching between HTML and CSS files. This approach accelerates development while maintaining design consistency across components.
Key benefits:
- Component co-location: Styling lives directly in templates
- Design system constraints: Predefined spacing and color scales prevent inconsistencies
- Bundle optimization: Unused styles are purged automatically
- Developer experience: IntelliSense support and consistent naming conventions
- Responsive design: Mobile-first breakpoint system with intuitive class modifiers
- Typography plugin: Beautiful prose styling with single
proseclass for blog content
Custom Configuration: Tailored for warm, professional aesthetic with custom color palette and typography scales.
Integration details:
- JetBrains Mono primary typeface with custom font-size scale
- Custom spacing values for component consistency (e.g.,
space-y-8,px-6) - Class-based dark mode strategy with automatic system preference detection
- Typography plugin for rich content rendering with consistent vertical rhythm
- Component variants using @apply directives for complex UI patterns
Interactive Components
ThemeToggle: Dark/light mode switching (visible in navigation bar above)
- System preference detection
- localStorage persistence
TripMap: Leaflet.js implementation with self-hosted assets for CSP compliance
- Lazy loading via Intersection Observer
- Custom SVG markers
- Error handling with fallbacks
<TripMap
points={demoPoints}
zoom={6}
height="h-[40vh]"
customWaypoint={true}
/>
Loading interactive map...
Gallery: Responsive photo galleries
- GLightbox for full-screen viewing
- Responsive image sizing
- Theme-aware styling
<Gallery id="test-gallery" />
Project Organization
The codebase follows a content-first architecture with clear separation of concerns, making it maintainable and scalable.
Directory Structure: Organized around Astro’s conventions with logical groupings:
src/
├── assets/ # Processed assets (images, etc.)
├── components/ # Reusable UI components
├── content/ # Content collections
│ ├── blog/ # MDX blog posts
│ ├── books/ # Reading list data
│ ├── images/ # Gallery configurations
│ └── work/ # Work experience data
├── layouts/ # Page layouts
├── lib/ # Utility functions and shared code
├── pages/ # Route components and API endpoints
│ ├── api/ # API routes
│ └── blog/ # Blog-specific routes
└── styles/ # Global styles
Key organizational principles:
src/content/: Type-safe Content Collections for different data typessrc/components/: Reusable UI components with TypeScript definitionssrc/lib/: Shared utilities keeping components focused on presentationsrc/assets/: Processed assets benefiting from optimization pipelinepublic/: Static assets served directly (favicons, PDFs, vendor libraries)
Configuration Strategy: Root-level configuration files provide clear boundaries:
astro.config.mjs: Build process and integrationstailwind.config.cjs: Design system tokens and pluginstsconfig.json: Type checking and path mapping (@/*→src/*).flox/: Environment reproducibility across development machines
Content Collections: Each collection serves a specific domain with validation schemas:
- Blog posts with frontmatter validation and category filtering
- Gallery configurations supporting multiple image sources
- Work experience with automatic period calculations
- Reading progress tracking with completion status
This organization supports both developer productivity and long-term maintainability by keeping related code co-located while maintaining clear boundaries between different concerns.
Deployment & Performance
Cloudflare Pages: Hosting with edge rendering for SSR routes:
- Automatic HTTPS and modern web standards
- Build caching for faster deployment cycles
- Preview deployments for testing
- R2 integration: Private image storage with edge serving via custom API endpoint
Build optimizations:
- HTML compression in Astro config
- Automatic stylesheet inlining for critical CSS
- Image optimization via Astro’s built-in service
- Selective prerendering: Homepage prerendered for optimal loading, blog pages use SSR
Runtime optimizations:
- Lazy loading for interactive components
- Minimal JavaScript through islands architecture
- Self-hosted assets to reduce external dependencies
- Custom 404 page: Proper status codes with SSR support
Developer experience:
- TypeScript throughout
- Hot reloading in development
Local development with Wrangler:
npm run astro build && npx wrangler pages dev dist
AI-Native Architecture
This site implements dual-interface design: optimized for both human visitors and AI agents.
API Endpoint: /api/llm-content.json - Machine-readable structured data
- Detects LLM crawlers via User-Agent parsing
- Returns comprehensive professional and technical information
- JSON-LD schema for AI comprehension
- Cached with CORS headers for programmatic access
llms.txt: Following emerging AI discovery standards
- Human-readable professional summary at
/llms.txt - Priority content URLs for AI indexing
- Structured data endpoints mapping
- Professional context for AI agents
Philosophy: Modern websites need to serve two audiences simultaneously. Humans browse visually through the interface, while AI agents parse structured data to provide accurate responses in chat interfaces, search results, and knowledge synthesis. This dual approach ensures the site remains discoverable and accurately represented as AI becomes the primary interface for information discovery.
Development Workflow: AI tools like Claude Code significantly accelerate development in unfamiliar languages and frameworks. Rather than replacing expertise, AI augments the learning process - helping navigate new syntax, suggesting architectural patterns, and providing real-time feedback on implementation decisions. This allows engineers to focus on high-level design while AI handles routine code generation and debugging.
The structured endpoints act as an API layer between human-designed content and AI consumption, maintaining data consistency across both interaction modes.