deploy static-app
Deploy static websites (React, Vue, Angular, Docusaurus) to S3 with optional CloudFront distribution.
Overview
carlin deploy static-app
This command:
- Finds your built static files (
build/,out/,storybook-static/,dist/) - Creates S3 bucket for hosting
- Optionally creates CloudFront distribution
- Uploads files to S3
- Configures caching and CDN
Quick Start
Build and deploy a Vite app:
# Build your app
pnpm build
# Deploy to S3 only
carlin deploy static-app
# Deploy to S3 + CloudFront
carlin deploy static-app --cloudfront
Deploy with custom domain:
carlin deploy static-app \
--cloudfront \
--aliases app.example.com \
--acm arn:aws:acm:us-east-1:123456789012:certificate/abc123 \
--hosted-zone-name example.com
Options
--build-folder
Specify build output folder.
carlin deploy static-app --build-folder dist
Default: Auto-detects build/, out/, storybook-static/, or dist/
--cloudfront
Create CloudFront distribution.
carlin deploy static-app --cloudfront
Benefits:
- Global CDN (faster load times)
- HTTPS support
- Custom domains
- Caching
Default: false (S3 only)
--aliases
CloudFront custom domain names (CNAMEs).
carlin deploy static-app --cloudfront --aliases app.example.com www.app.example.com
Requires: --acm (SSL certificate)
Related: CloudFront Alternate Domain Names
--acm
SSL certificate ARN or exported CloudFormation value name.
# Direct ARN
carlin deploy static-app --acm arn:aws:acm:us-east-1:123456789012:certificate/abc123
# CloudFormation export
carlin deploy static-app --acm MyCertificateArn
Requires: Certificate in us-east-1 region for CloudFront
Related: AWS Certificate Manager
--hosted-zone-name
Route 53 hosted zone for automatic DNS configuration.
carlin deploy static-app \
--hosted-zone-name example.com \
--aliases app.example.com
carlin automatically creates DNS records pointing aliases to CloudFront distribution.
Example: For hosted zone example.com and alias app.example.com, carlin creates A record app.example.com → CloudFront.
--append-index-html
Append index.html to request URIs (for Docusaurus, VitePress, static site generators).
carlin deploy static-app --append-index-html
Behavior:
- Request:
/docs/guide→ Serves:/docs/guide/index.html - Request:
/about→ Serves:/about/index.html
Use case: Clean URLs without .html extension
--spa
Enable Single Page Application (SPA) mode.
carlin deploy static-app --spa
Behavior: All 404 errors serve index.html (for client-side routing)
Use case: React Router, Vue Router, Angular Router
--skip-upload
Update CloudFormation without uploading files.
carlin deploy static-app --skip-upload
Use case: Update CloudFront configuration without re-uploading files
--upload-source-maps
Upload source map (.map) files to S3.
carlin deploy static-app --upload-source-maps
Default: false — source maps are excluded from the upload.
The bucket this command publishes to is public, and a source map embeds your
application's original source, so publishing one discloses that source to
anyone who requests it. carlin therefore never uploads .map files unless you
ask for it explicitly.
Before enabling this, consider uploading your source maps to your error tracking provider instead. That gives you readable stack traces without serving the source publicly.
carlin only decides which files are uploaded — it does not modify file
contents. If your bundler emits sourceMappingURL comments and you leave this
option off, those comments will point at files that return 404. Strip them at
build time (most source-map upload tools do this for you) if that matters to
you.
--region
Static app deployments always use us-east-1 (CloudFront requirement). This option is ignored.
Examples
Vite/React App
# Build
pnpm build
# Deploy with CloudFront and custom domain
carlin deploy static-app \
--cloudfront \
--spa \
--aliases app.example.com \
--acm arn:aws:acm:us-east-1:123456789012:certificate/abc123 \
--hosted-zone-name example.com
Docusaurus Documentation
# Build
pnpm build
# Deploy with clean URLs
carlin deploy static-app \
--cloudfront \
--append-index-html \
--aliases docs.example.com \
--acm arn:aws:acm:us-east-1:123456789012:certificate/abc123
Next.js Static Export
# Build static export
pnpm build
# Deploy
carlin deploy static-app \
--build-folder out \
--cloudfront \
--spa
Multi-Environment Deployment
# Staging
carlin deploy static-app \
--environment staging \
--cloudfront \
--aliases staging.app.example.com
# Production
carlin deploy static-app \
--environment production \
--cloudfront \
--aliases app.example.com www.app.example.com
Architecture
S3 Only
Pros: Simple, low cost Cons: No CDN, no HTTPS, slower for global users
S3 + CloudFront
Pros: Fast globally, HTTPS, custom domains, caching Cons: Slightly higher cost
Deployment Flow
SSL Certificate Setup
Create SSL certificate in AWS Certificate Manager (must be in us-east-1):
# Request certificate
aws acm request-certificate \
--domain-name app.example.com \
--subject-alternative-names www.app.example.com \
--validation-method DNS \
--region us-east-1
# Note the certificate ARN
# arn:aws:acm:us-east-1:123456789012:certificate/abc123
Validate certificate via DNS or email, then use ARN in deployment:
carlin deploy static-app \
--acm arn:aws:acm:us-east-1:123456789012:certificate/abc123 \
--aliases app.example.com
Caching Strategy
CloudFront caches files based on file type:
- HTML files: No cache (always fetch latest)
- JS/CSS/Images: Long cache (1 year) with content hash in filename
Recommended build setup (Vite example):
// vite.config.ts
export default {
build: {
rollupOptions: {
output: {
entryFileNames: 'assets/[name].[hash].js',
chunkFileNames: 'assets/[name].[hash].js',
assetFileNames: 'assets/[name].[hash].[ext]',
},
},
},
};
Updating Deployments
Update files:
pnpm build
carlin deploy static-app
carlin uploads changed files and invalidates CloudFront cache automatically.
Update CloudFront configuration only:
carlin deploy static-app --skip-upload
Cost Considerations
See AWS S3 Pricing and CloudFront Pricing for current rates.
Troubleshooting
Build Folder Not Found
Error: Build folder not found
Solution: Build your app first or specify folder:
pnpm build
carlin deploy static-app --build-folder dist
Certificate Not in us-east-1
Error: Certificate must be in us-east-1 region
Solution: Create certificate in us-east-1:
aws acm request-certificate --region us-east-1 --domain-name app.example.com
CloudFront Propagation Delay
Problem: Changes take 15-30 minutes to appear globally
Solution: This is normal CloudFront behavior. Wait for distribution deployment to complete.
Check status:
aws cloudfront list-distributions
Source Maps Return 404
Problem: .map files that used to be served now return 404
Cause: source maps are excluded from the upload by default. This changed in carlin v2 — earlier versions published everything in the build folder, including source maps.
Solution: if you intend to serve them publicly, opt back in:
carlin deploy static-app --upload-source-maps
SPA Routes Return 404
Problem: Client-side routes (e.g., /about, /contact) return 404
Solution: Use --spa flag:
carlin deploy static-app --spa
Related Topics
- Base Stack - CloudFront function for
--append-index-html - Environments - Multi-environment deployments