Single Page Application (SPA)
Deploy any client-side Single Page Application (SPA) and static site generator (SSG) on AWS S3 and CloudFront.
Thunder provides a secure and battle-tested pattern for deploying any SPA/SSG on AWS infrastructure using AWS CDK. This pattern leverages the @thunderso/cdk-spa package, which implements best practices for static site hosting with CloudFront distribution, S3 origin, and Lambda@Edge functions for advanced routing capabilities.
Supported Frameworks
- Astro (SSG mode)
- Next.js (static output export)
- Vite
- Gatsby (static)
- React Router (client-side and static prerendering)
- Any static site generator (SSG) framework
Hosting Architecture
The hosting architecture provides a globally distributed, secure, and performant infrastructure for serving static web applications.
Route 53 handles DNS resolution, directing users to the nearest CloudFront edge location. CloudFront serves as a global CDN, caching static assets at edge locations worldwide for low-latency delivery. S3 stores the application files as the origin, providing durable and scalable object storage.
CI/CD Pipeline Architecture
The pipeline architecture automates the build and deployment process, ensuring consistent and reliable deployments from source code to production.
GitHub triggers the pipeline on code changes. CodePipeline orchestrates the deployment workflow, while CodeBuild executes the build process in a managed environment. Built assets are uploaded to S3 and CloudFront cache is invalidated to serve the latest version.
Quick Start
Get your static site deployed to AWS in minutes with the CDK-SPA package. This guide walks through installation, configuration, and deployment of a basic static site.
Installation
bun add -D @thunderso/cdk-spaBasic Setup
mkdir stack && touch stack/index.tsConfiguration
import { Cdk, SPAStack, type SPAProps } from "@thunderso/cdk-spa";
const stackProps: SPAProps = { env: { account: 'your-account-id', region: 'us-east-1' }, application: 'my-app', service: 'frontend', environment: 'production', rootDir: '', // supports monorepos, e.g. frontend/ outputDir: 'dist/',};
new SPAStack( new Cdk.App(), `${stackProps.application}-${stackProps.service}-${stackProps.environment}-stack`, stackProps);Deploy
bunx cdk deploy --all --app="bunx tsx stack/index.ts"Custom Domain Setup
Connect your own domain to your static site using Route 53 and ACM certificates. Learn more about domain configuration.
const stackProps: SPAProps = { // ... other props domain: 'app.example.com', hostedZoneId: 'Z1D633PJN98FT9', globalCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/abcd1234-abcd-1234-abcd-1234abcd1234',};Advanced Features
URL Redirects and Rewrites
Configure URL redirects and rewrites using Lambda@Edge functions that run at CloudFront edge locations. Redirects return HTTP 301/302 responses to the client, while rewrites transparently serve different content without changing the URL. Perfect for handling SPA routing, legacy URL migrations, and A/B testing.
Learn more about redirects and rewrites configuration.
const stackProps: SPAProps = { // ... other props redirects: [ { source: '/home', destination: '/' }, { source: '/blog/:slug', destination: '/posts/:slug' } ], rewrites: [ { source: '/app/*', destination: '/index.html' } ],};Custom Headers
Add custom HTTP response headers using Lambda@Edge to control caching behavior. Headers are applied at the edge for optimal performance and can be configured per path pattern.
Learn more about response headers configuration.
const stackProps: SPAProps = { // ... other props headers: [ { path: '/*', name: 'Cache-Control', value: 'public, max-age=31536000' } ],};AWS CodePipeline Integration
Automate your deployment workflow with AWS CodePipeline and CodeBuild. Configure your GitHub repository as the source, define build commands, and let AWS handle the rest. Every push to your specified branch triggers a new build and deployment.
Learn more about build configuration.
const stackProps: SPAProps = { // ... other props githubAccessTokenArn: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:github-token-XXXXXX', sourceProps: { owner: 'your-username', repo: 'your-repo', branchOrRef: 'main', }, buildProps: { runtime: 'nodejs', runtime_version: '20', installcmd: 'bun install', buildcmd: 'bun run build', },};