- Solo developer project; scope and maintenance burden should stay realistic for one person.
- Communicates in Indonesian sometimes; wants English copy for gate/OverTheWire-style puzzles and related developer-facing UI.
- Landing and gate UI: English default with i18n toggle (reuse existing i18n), not Indonesian-first for those surfaces.
- Do not discard the terminal experience; prefer dual entry (standard landing + gated terminal) over a full UI rewrite.
- Create git commits and pull requests only when explicitly asked.
- Gate stays enabled in development; bypass only via
GATE_BYPASS_SECRET, not an automatic dev-off flag. - User fills API keys and other random secrets in
.env.developmentlocally (copy from.env.example); production via.envon GCP or Vercel platform env. Local.env.developmentAPI URLs should targetlocalhost:8080, not production Cloud Run. - Gate puzzles should be NATAS-style web challenges (login, hidden paths, Referer), not SSH/Bandit/Behemoth simulations.
- First time deploying to GCP; prefers clear, beginner-friendly infrastructure documentation and bootstrap guides.
- Portfolio-frontend chats must proactively use Cursor SDK + Team Kit skills/MCP (
.cursor/rules/cursor-sdk-team-kit.mdc, alwaysApply). - Roadmap.sh proxy auth: email/password only via
POST https://roadmap.sh/api/v1-login; reject GitHub OAuth and manual bearer-token flows. - Backend SLA target: all API routes P95 < 50ms (not health-only
responseTime).
- Multi-repo portfolio:
portfolio-backend(Rust/Axum, SQLx/PostgreSQL) andportfolio-frontend(Next.js 16, React 19, terminal-interactive portfolio). - Planned public routing: standard landing at
/, terminal at/terminal, three-level gate at/gate(and/gate/[level]). - Blog, social share, RSS, and other content routes stay shared/public; do not duplicate them across standard and terminal UIs.
- Gate puzzles (backend-validated, no answers in frontend bundle): L1 static login
yourblooo0/yourblooo0; L2 requires L1 completion before/s3cr3t/users.txtreveals loginyourblooo1+ env password; L3 backend validatesReferer: {SITE_URL}/terminalincomplete_level_3; gate JWT pinned to HS256 withiss/aud. Terminal routenoindex; terminal SSR verifies JWT via/api/gate/status. Gate/terminal is UX puzzle layer, not API auth perimeter (admin JWT separate).GATE_BYPASS_SECRETvia Next.jsproxy.ts(X-Gate-Bypass), not Rust handlers. Legacy envGATE_L2_STUB_MD5,GATE_L3_SHELLCODE_HASH,GATE_L3_OFFSETunused (archived shellcode design); onlyGATE_L1_ANSWER,GATE_L2_ANSWER,GATE_TOKEN_SECRETrequired. Rebuild/restart local Docker backend after gate answer or gate code changes — stale image keeps old L1 credentials. - Backend API default port 8080; frontend align
NEXT_PUBLIC_API_URL/BACKEND_URLwith 8080 locally. Production (Vercel): both must be the HTTPS Cloud Run service base URL (no trailing slash);NEXT_PUBLIC_*changes require a Vercel redeploy; a wrong*.run.appURL yields a Google-edge 404 with zero Cloud Run requests. Most prod API traffic is Vercel SSR server-side, with silent empty fallbacks if the backend is unreachable.ROADMAP_EMAIL/ROADMAP_PASSWORDare Cloud Run/GCP secrets only — not Vercel env. Local dev: backendload_env_file()reads.env.developmentwhenENVIRONMENT != production; frontendbun run devuses--env-file=.env.development; Docker Compose viascripts/compose-dev.shor--env-file .env.development. CORS auto-merges localhost origins (ports 3000–3002) whenENVIRONMENT != production; gate vars documented in.env.example. - Feature status SSOT:
portfolio-frontend/FEATURE_PLANNING.md(+docs/dual-ui-gate.mdfor gate ops);ROADMAP.mdremoved May 2026 after performance backlog moved to Feature #33. - PWA is site-wide (
public/manifest.json,public/sw.js, scope/, offline page); install prompt only after terminal onboarding tour completes. - Observability stack (Loki, Grafana, Prometheus) runs on a GCE ops VM in production via
docker-compose.gcp-ops.yml; same stack in localdocker-compose.ymlfor dev. Redis on ops VM (6379) backs distributed rate limiting and WebSocket presence whenREDIS_URLis set; falls back to in-memorytower_governor+ local presence counts when unset or unreachable. OptionalMETRICS_BEARER_TOKENprotects/metrics; Prometheus prod scrape uses bearer auth. - GCP production: backend on Cloud Run (asia-southeast2/Jakarta) with
max_instances=1for in-memory gate sessions (Redis not used for gate yet), publicallUsersrun.invoker(Vercel frontend + public API; admin auth app-level), frontend on Vercel;DATABASE_URLmust be the ops VM internal IP over Serverless VPC Access (not a subnet-CIDR host, notlocalhost);REDIS_URL=redis://<ops_vm_internal_ip>:6379from Terraform; ops VM may use default VPC addressing or Terraform ops ranges—firewall must allow TCP 5432 and 6379 from the VPC connector CIDR to the VM; unreachable Postgres at startup panics before the revision listens on 8080. Serverless VPC Access connector (10.10.1.0/28, not Direct VPC egress); Terraform egressPRIVATE_RANGES_ONLY—ALL_TRAFFICthrough VPC without Cloud NAT breaks outbound APIs (roadmap.sh, GitHub, Resend, Gemini); container command/args empty (image CMD/app/portfolio-backend, port 8080); Terraform (network, iam, artifact_registry, secrets, compute_ops, cloud_run); ops VM (e2-medium, no public IP, IAP SSH) hosts Postgres 16 + observability at/mnt/data;REDIS_URLoptional on Cloud Run (health probe only, not in prod compose stack). CI viadeploy-gcp.ymlWorkload Identity Federation. - Next.js 16 edge handler is
src/proxy.ts(export function proxy()), not legacymiddleware.ts. - Frontend performance:
cacheComponents: true(PPR) with Feature #33 docs atdocs/features/FEATURE_33_PERFORMANCE.md;/roadmapuses request-time fetch viaawait headers()under PPR; dual RUM (pino/Loki + Vercel Speed Insights). Production CSP must not usestrict-dynamic/nonce without wiring nonce into Next.js scripts ('unsafe-inline'used); Vercel builds disable file logging (LOG_TO_FILE,NEXT_PHASE=phase-production-build— nologs/servermkdir); client logs POST plain JSON to/api/logs(in-memory crypto session fails across Vercel serverless instances). Pre-completion verification: backendcargo fmt/check/clippy/test; frontendbun run lint+type-check. Known Vitest hang:background-manager.test.tsx(~16 min). - Backend performance & integrations: all API routes P95 <50ms SLO (
docs/performance/API_SLA.md,config/slo-rules.yml, Grafana 50ms alerts,scripts/latency-smoke.shin CI); roadmap/github in-memory cache with stale-while-revalidate; roadmap auth viaROADMAP_EMAIL/ROADMAP_PASSWORD→POST …/v1-login(Terraform secretsroadmap-email/roadmap-password;ROADMAP_AUTH_TOKENremoved); Swagger UI disabled in production.