From website-deployment
Sets up a Vite + React frontend with S3 and CloudFront hosting. Use when setting up frontend hosting, CDN, static file serving, or creating the React app.
npx claudepluginhub schuettc/website-deployment-plugin --plugin website-deploymentThis skill uses the workspace's default tool permissions.
You are creating a Vite + React frontend and setting up S3 + CloudFront hosting. This replaces Express's `express.static()` with a build pipeline and CDN hosting.
Deploys and configures static sites on Render's global CDN with build commands, publish paths, SPA fallback routing, redirects, custom headers, and PR previews for React, Vue, Hugo, Gatsby frontends.
Guides step-by-step deployment of static sites, React/Vue/Next.js/Nuxt frontends, Python (Flask/FastAPI/Django) or Node.js (Express/Nest) backends to Vercel, Netlify, Cloudflare Pages, Railway, Render. Prepares build configs, env vars, gitignore.
Scaffolds and deploys Cloudflare Workers with Hono routing, Vite dev server, static assets, and D1/R2/KV bindings. Troubleshoots export errors, API conflicts, HMR, and deployments.
Share bugs, ideas, or general feedback.
You are creating a Vite + React frontend and setting up S3 + CloudFront hosting. This replaces Express's express.static() with a build pipeline and CDN hosting.
Present the plan to the user, explaining each concept:
/api/..., CloudFront routes that to API Gateway. This means no cross-origin issues."d1234abcd.cloudfront.net. If you want a custom domain like myapp.com, we'd need to set up Route53 (AWS's DNS service, ~$0.50/month per domain) and an SSL certificate (free). Want to set that up now, or use the default URL? You can always add a custom domain later."npm create vite@latest frontend -- --template react-ts
cd frontend && npm install
Project structure:
frontend/
├── index.html
├── public/
│ └── favicon.ico
├── src/
│ ├── main.tsx
│ ├── App.tsx
│ ├── components/
│ ├── pages/
│ ├── hooks/
│ │ └── useApi.ts
│ ├── lib/
│ │ └── api.ts
│ ├── App.css
│ └── index.css
├── vite.config.ts
├── tsconfig.json
└── package.json
Update frontend/vite.config.ts:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/api': 'http://localhost:3000', // Proxy API calls to Express during development
},
},
build: {
outDir: 'dist',
sourcemap: true,
},
});
Create frontend/src/lib/api.ts:
const API_BASE = import.meta.env.VITE_API_URL || '';
export async function apiFetch(path: string, options?: RequestInit) {
const response = await fetch(`${API_BASE}${path}`, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
});
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
return response.json();
}
Note: VITE_API_URL is empty in production (same-origin). Vite injects VITE_-prefixed env vars at build time.
src/pages/src/index.csspublic/fetch() calls with the apiFetch helpercd frontend && npm install react-router-dom
Create infrastructure/lib/frontend-stack.ts:
S3 Bucket:
Origin Access Control (OAC):
CloudFront Distribution:
/api/* -> API Gateway originindex.html/dashboard and visits it directly, S3 doesn't have a file called /dashboard — it would return a 404. We tell CloudFront to serve index.html instead, and React figures out which page to show. This is standard for all React apps."S3 Deployment:
BucketDeployment to upload frontend/dist/assets/* (hashed filenames): cached forever — "Vite adds a unique hash to each file name (like app-a1b2c3.js). When your code changes, the hash changes, so the browser knows to download the new version. This means assets can be cached indefinitely."index.html: never cached — "This is the entry point that references your assets. It needs to always be fresh so it points to the latest asset hashes."Outputs: CloudFront URL, distribution ID, S3 bucket name
Update the CDK stack or add a build step that:
cd frontend && npm run build before deployingVITE_API_URL if needed (empty string for same-origin)frontend/dist/ to S3cd frontend && npm run dev
cd frontend && npm run build to verify the Vite build succeedscd infrastructure && npx cdk synth to verify CDK compilation.migration/plan.md to mark setup-frontend as completeContent-Security-PolicyX-Frame-Options: DENYX-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originimport.meta.env.VITE_* for environment variables (not process.env)npm run build locally before deploying to catch build errors earlynpm run dev — Vite dev server with HMRnpm run build — Production bundle to dist/npm run preview — Preview production build locally