9 min read Dillon Browne

How I Built This Website: Edge-First Architecture with Cloudflare & Astro

A deep dive into the technical architecture, design decisions, and performance optimizations behind this modern portfolio site built with Astro 6, React 19, and Cloudflare's edge network.

Astro Cloudflare React Edge Computing Web Performance AI DevOps
How I Built This Website: Edge-First Architecture with Cloudflare & Astro
On this page

As a staff cloud architect, I’ve spent years building infrastructure for others. When it came time to create my own portfolio, I wanted to demonstrate my expertise through implementation, not just description.

The result is a modern, edge-first website deployed across Cloudflare’s global network with sub-100ms response times worldwide. It features an AI-powered chat assistant, loads in under 1 second, and achieves a 98/100 PageSpeed score.

In this post, I’ll walk you through the key technical decisions and lessons learned.

The Stack

I chose Astro 6 for its islands architecture—it ships zero JavaScript by default and only hydrates interactive components when needed. This reduced my bundle size by 70% compared to a traditional React SPA.

For hosting, the site ships as a single Cloudflare Worker (with the static-assets binding) deployed to 300+ edge locations globally. The API endpoints are Astro endpoints under src/pages/api/* compiled into that same Worker, creating a truly distributed application where static assets, APIs, and AI inference all run at the edge.

Interactive features use React 19 with selective hydration:

  • AI chat assistant with streaming responses
  • Build info modal showing git metadata
  • Animated counters triggered by scroll
  • Infinite logo carousel

Tailwind CSS v4 handles styling with JIT compilation, keeping the CSS bundle under 47KB.

The AI Chat Assistant

The most interesting technical challenge was building an AI chat into a static site. The solution streams responses from Workers AI—the chat model is GLM-5.2 (env.CHAT_MODEL)—routed through Cloudflare’s AI Gateway.

Here’s how it works:

  1. User message hits /api/copilot (an Astro endpoint in the Worker, at the edge)
  2. The endpoint checks rate limits in KV storage (6/min burst, 30/hour per IP, 300/day site-wide)
  3. Request goes through AI Gateway for analytics and caching
  4. The model responds with a streamed response—tokens appear in real-time

The AI has context about my experience through RAG (Retrieval-Augmented Generation). During build, a Node script compiles all markdown files from /knowledge-base/ into a TypeScript constant that gets bundled with the Worker. This means the AI always has current information without runtime file access.

Rate limiting uses KV storage—lightweight, globally replicated, perfect for this use case. No database needed.

Performance Optimizations

I obsessed over performance to hit sub-1-second page loads globally:

Bundle reduction — Astro’s client:idle directive delays React hydration until the browser is idle. Combined with per-page code splitting, this reduced initial JavaScript from 350KB (typical SPA) to 220KB total, only 59KB gzipped.

Font loading — I use a clever trick to load fonts without blocking render:

<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800"
      media="print"
      onload="this.media='all'" />

By setting media="print", the browser loads fonts with low priority. Once loaded, onload makes them apply to screen. Zero render-blocking, virtually no layout shift.

Caching strategy — JavaScript and CSS get cached for 1 year (max-age=31536000, immutable). HTML gets max-age=0, must-revalidate to stay fresh. Second page loads are instant.

Deployment

The workflow is beautifully simple: push to main, and GitLab CI handles the rest.

Commits trigger a pipeline that runs Astro, generates the AI knowledge base, compiles the Worker, and deploys via wrangler deploy to 300+ edge locations.

During build, I inject git metadata (commit SHA, timestamp) using Vite’s define option:

define: {
  // commit comes from `git rev-parse HEAD` at build time
  'import.meta.env.GIT_COMMIT': JSON.stringify(commit),
  'import.meta.env.BUILD_TIME': JSON.stringify(new Date().toISOString()),
}

This powers the “Build Info” modal, giving visitors transparency about which version they’re viewing.

Key Lessons

Astro’s islands architecture is perfect for content sites with selective interactivity. The performance benefits are immediate—70% less JavaScript without sacrificing React where it matters.

Edge computing changes everything for global performance. Sub-100ms response times worldwide aren’t just nice to have—they fundamentally improve user experience.

Streaming AI responses feel magical. Real-time tokens appearing beat a 3-second loading spinner every time. SSE isn’t hard to implement, but the UX impact is massive.

Static-first doesn’t mean static-only. Combining static generation with serverless Functions gives you instant page loads plus dynamic capabilities where needed.

Trade-offs

No architecture is perfect. Here are the compromises I made:

Platform Lock-in

I accepted Cloudflare platform lock-in for the integration and performance benefits. The tight coupling with Workers, KV, and Workers AI means migrating would require significant refactoring. But the performance gains and developer experience make it worth it.

Static-First Limitations

Static-first limits user-specific server-side rendering, but that’s fine for a portfolio. If this were a SaaS application requiring personalization, I’d need a different approach.

Technical Challenges

Several interesting problems emerged during development:

  • SSE buffering logic — Implementing proper handling for partial JSON chunks across multiple Server-Sent Events
  • Astro scoped CSS — Working around limitations with Tailwind’s group-hover utilities for complex interactions
  • Cumulative layout shift — Eliminating CLS entirely with the media="print" font loading trick

The Results

After all the optimization work, here’s what I achieved:

Performance Metrics

PageSpeed
98/100
First Paint
0.6s
LCP
1.1s
CLS
0.01

Bundle Size

JavaScript
59KB gzipped
CSS
47KB

These aren’t just vanity metrics—they translate to a site that loads instantly, responds immediately, and works beautifully even on slow connections.

Since Then

This post keeps pace with the site. Since it first went live, the stack has moved to Astro 6, and a few additions have earned their place: a Vitest 4 test suite with workerd integration tests and a Playwright smoke, build-time satori-generated OG share cards, a ⌘K terminal-style command palette, and native cross-document View Transitions. The figures above are from the original measured audit and still hold.

What’s Next

Future enhancements include:

  • Service Worker for offline support
  • Blog pagination as content grows
  • Image optimization pipeline (WebP/AVIF conversion)
  • Real-time analytics via Cloudflare Analytics Engine

Final Thoughts

This website demonstrates what modern web development can achieve when you prioritize performance and user experience. By choosing edge-first architecture, AI integration, and static-first with selective interactivity, I’ve created a platform that loads in under a second globally while showcasing my skills through implementation, not just claims.

The web is moving toward the edge, toward AI-enhanced experiences, and toward leaner architectures. This site embraces that future.


Tech Stack: Astro 6 • React 19 • Tailwind v4 • TypeScript • Cloudflare Workers (static-assets binding) • Workers AI (GLM-5.2 chat) • KV Storage • AI Gateway • Turnstile

Want to learn more? The AI chat assistant can answer questions about the architecture, or check the Build Info modal to see the exact commit powering this site.

Found this helpful? Share it:

Related