- Rust/Axum backend skeleton with all crates, multi-stage Dockerfile - SvelteKit + TypeScript frontend with Tailwind CSS v4, adapter-node, Dockerfile - docker-compose.yml: db (postgres:16) → app → frontend → caddy with healthcheck and named volumes - Caddyfile: TLS via Let's Encrypt, cache headers, API/media routing to backend - .env.example: all environment variables documented with defaults - README.md: project overview, features, stack, deploy guide, roadmap - .gitignore: excludes secrets, build artifacts, node_modules, media uploads Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
27 lines
908 B
Caddyfile
27 lines
908 B
Caddyfile
{$DOMAIN} {
|
|
encode zstd gzip
|
|
|
|
# SvelteKit frontend — static assets with long-lived cache (content-hashed filenames)
|
|
@hashed_assets path_regexp hashed /_app/immutable/.*\.[a-f0-9]{8,}\.(js|css|woff2)$
|
|
header @hashed_assets Cache-Control "public, max-age=31536000, immutable"
|
|
|
|
# Media previews and thumbnails
|
|
@previews path /media/previews/* /media/thumbnails/*
|
|
header @previews Cache-Control "public, max-age=3600"
|
|
|
|
# Original media files (private — only host can download)
|
|
@originals path /media/originals/*
|
|
header @originals Cache-Control "private, max-age=86400"
|
|
|
|
# API — never cache
|
|
@api path /api/*
|
|
header @api Cache-Control "no-store"
|
|
|
|
# Route API and media requests to the Rust backend
|
|
reverse_proxy /api/* app:3000
|
|
reverse_proxy /media/* app:3000
|
|
|
|
# Everything else goes to SvelteKit frontend
|
|
reverse_proxy frontend:3001
|
|
}
|