Vite + React single-page portfolio with AI chat. Target deployment is AWS S3 + CloudFront for the static site and a tiny Gemini proxy behind API Gateway/Lambda to keep the API key server-side.
- Cyber/tech visual theme, scroll-spy navigation, AI chat assistant
- Projects/skills/experience pulled from
constants.ts
npm install
# copy env template
cp .env.example .env.local
# set VITE_GEMINI_PROXY_URL to your dev proxy endpoint (e.g. http://localhost:8787/gemini)
npm run dev| Name | Scope | Description |
|---|---|---|
VITE_GEMINI_PROXY_URL |
frontend | URL of the server-side Gemini proxy (API Gateway/Lambda, etc.). No keys go to the browser. |
GEMINI_API_KEY |
server | Stored only on the proxy/Lambda (e.g. AWS SSM/Secrets Manager). |
GEMINI_MODEL |
server (optional) | Override model name (defaults gemini-2.5-flash). |
- Sample handler:
api/gemini-proxy.ts(Node 18, API Gateway + Lambda style). ReadsGEMINI_API_KEY, calls Gemini, returns{ text }. - Deploy any equivalent edge/Lambda/Container service, then set
VITE_GEMINI_PROXY_URLto that endpoint.
npm run buildOutput goes to dist/.
-
Build:
npm run build -
Sync to S3:
aws s3 sync dist/ s3://<bucket> --delete -
CloudFront:
- Origin: S3 bucket
- SPA fallback: custom error responses for 403/404 ->
/index.html(200) - Caching: long cache for hashed assets; short for HTML
- Security headers: HSTS, X-Content-Type-Options=nosniff, Referrer-Policy=strict-origin-when-cross-origin, CSP allowing your domains (and fonts.googleapis.com/gstatic if you keep Google Fonts)
Helpers (in
aws/):aws/cloudfront-errors.json— example 403/404 ->/index.htmlrulesaws/cloudfront-headers.json— example response-headers policy with HSTS, CSP, etc. (updateconnect-src/domains as needed)
- Images are lazy-loaded; consider replacing PNG/JPEG with WebP/AVIF for further weight savings.
- Animations respect
prefers-reduced-motion.
- No secrets ship to the browser; the Gemini key must live in the proxy.