Overview
This website strategically combines three different frameworks to optimize for performance, developer experience, and specific use cases:- Astro: Server-side rendering and zero-JS static pages
- React: Image optimization component
- Solid.js: Interactive UI components
Framework Configuration
The multi-framework setup is configured inastro.config.mjs:
astro.config.mjs
React is intentionally limited to specific files using the
include pattern, preventing it from processing all components.Astro: The Foundation
When to Use Astro
Static Pages
Home, about, blog posts, project pages - any content-focused page
Layouts
Page templates, navigation, footer, SEO components
Data Fetching
Build-time Notion API calls, static data loading
Server Components
Components that don’t require client-side JavaScript
Astro Component Example
src/layouts/Layout.astro
Why Astro for this?
Why Astro for this?
- Zero JavaScript: This layout generates pure HTML with no runtime JS
- Fast builds: Astro’s compiler is optimized for static sites
- SEO-friendly: Server-rendered HTML is immediately indexable
Build-Time Data Fetching
Astro components can fetch data at build time:src/pages/index.astro
The
await in the frontmatter runs once at build time, not on every request. This is what makes Astro so fast.React: Image Optimization Only
When to Use React
Astro Image Component
React is used exclusively for Astro’s
<Image /> component, which provides automatic image optimization.Image Component in MDX
When Notion content is synced, images are converted to Astro Image components:src/lib/notion-parse.ts:222-236
Benefits of Astro Image
Automatic Optimization
Automatic Optimization
- Converts to WebP/AVIF formats
- Generates responsive image sizes
- Lazy loads images by default
Build-Time Processing
Build-Time Processing
- Images processed during
astro build - Uses Sharp for fast, high-quality optimization
- No runtime performance cost
Type Safety
Type Safety
- TypeScript validation for image imports
- Compile-time errors for missing images
Solid.js: Interactive Components
When to Use Solid.js
Client Interactivity
Maps, navigation menus, toggles - anything requiring JavaScript
Better Performance
Solid.js has smaller bundle sizes than React (~7KB vs ~40KB)
Fine-Grained Reactivity
More efficient updates than React’s virtual DOM
Solid.js Component Example
src/components/Map.tsx
Hydration Directive
Solid components require theclient:only directive to hydrate on the client:
src/pages/places.astro
Why client:only?
Why client:only?
client:only="solid-js" tells Astro to:- Skip server-side rendering for this component
- Load Solid.js runtime on the client
- Hydrate the component after page load
Solid.js Component Gallery
- Map.tsx
- Icon.tsx
Interactive Leaflet map with custom markers and zoom controls.Bundle size: ~35KB (Solid + Leaflet)Features:
- Dynamic marker placement from JSON data
- Zoom-based marker visibility
- Custom tile provider (Stadia Maps)
Framework Decision Matrix
Use this guide to choose the right framework:| Requirement | Framework | Reason |
|---|---|---|
| Static content page | Astro | Zero JS, fastest load time |
| Blog post layout | Astro | No interactivity needed |
| Image display | React | Astro Image optimization |
| Interactive map | Solid.js | Requires client JS, smaller bundle |
| Navigation menu (mobile) | Solid.js | Toggle state, animations |
| SEO metadata | Astro | Server-rendered <head> |
| Data fetching | Astro | Build-time API calls |
| Form validation | Solid.js | Client-side interactivity |
Bundle Size Comparison
Here’s how each framework impacts bundle size:Astro Pages
~0-5KBStatic HTML with optional CSS
React (Image Only)
+0KBCompiled away at build time
Solid.js Page
~7KB + componentSolid runtime + component code
Actual Bundle Sizes
From production builds:Performance Implications
Page Load Speed
Astro Pages (0KB JS)
- TTFB: Less than 50ms
- FCP: Less than 200ms
- LCP: Less than 500ms
- TTI: Same as FCP (no hydration)
Why Not Use React Everywhere?
Comparing React vs. Solid.js for interactive components:| Metric | React | Solid.js | Winner |
|---|---|---|---|
| Runtime size | 40KB | 7KB | 🏆 Solid.js |
| Rendering speed | Virtual DOM | Direct DOM | 🏆 Solid.js |
| Re-render cost | Diff entire tree | Update changed signals | 🏆 Solid.js |
| Ecosystem | Massive | Growing | React |
| Learning curve | Familiar | Similar | Tie |
For this project’s needs (maps, navigation), Solid.js provides better performance with minimal trade-offs.
Islands Architecture
Astro uses the Islands architecture pattern:Benefits of Islands
Benefits of Islands
- Partial hydration: Only interactive components load JS
- Faster TTI: Less JavaScript to parse and execute
- Better SEO: Static HTML is immediately visible to crawlers
- Progressive enhancement: Site works without JS, enhanced with JS
Development Experience
TypeScript Support
All three frameworks have excellent TypeScript support:Hot Module Replacement
During development (pnpm dev):
- Astro: Instant HMR for content changes
- Solid.js: Fast refresh preserves component state
- React: Standard Fast Refresh (used minimally)
Build Times
Incremental sync reduces subsequent builds to ~10-20s total.
Migration Guidelines
When to Convert Astro → Solid.js
Convert a component from Astro to Solid.js if:- It needs client-side state management
- It has event handlers (click, scroll, etc.)
- It uses browser APIs (localStorage, geolocation)
- It requires animations/transitions
Conversion Example
Testing Strategy
Astro Components
Tested through integration tests:Solid.js Components
Tested with Vitest and Solid Testing Library:Best Practices
Minimize Client JavaScript
Minimize Client JavaScript
Default to Astro components. Only use Solid.js when interactivity is truly needed.
Lazy Load Heavy Components
Lazy Load Heavy Components
Use
client:visible for below-the-fold components:Share Types Between Frameworks
Share Types Between Frameworks
Optimize Images at Build Time
Optimize Images at Build Time
Always use Astro’s
<Image> component for static images, never raw <img> tags.Next Steps
Architecture Overview
Return to the high-level architecture guide
Content Sync Process
Learn how content flows from Notion to Astro