6.7 KiB
GamerComp.com - AI Game Arcade
Mobile-first game arcade where kids (8-16) play AI-generated HTML5 canvas games, create games via wizard, and earn XP.
Quick Reference
./deploy.sh # Build + restart + reload nginx
./deploy.sh --clear-cloudflare # Also purge CDN cache
pm2 logs gamercomp-api --lines 50
sudo -u postgres psql -d game_arcade
Tech Stack
| Layer | Tech |
|---|---|
| Frontend | React 18, Vite, React Router, PWA |
| Backend | Node.js, Express, PostgreSQL, Redis |
| Auth | JWT + FingerprintJS (guests) |
| AI (generation) | Claude Sonnet (claude-sonnet-4-20250514) — streaming |
| AI (lightweight) | Claude Haiku (claude-haiku-4-5-20251001) — tweaks, refinement, summaries |
| Push | Web Push (VAPID) via web-push |
| Infra | DigitalOcean, Nginx, PM2, Cloudflare |
Project Structure
frontend/src/
├── pages/
│ ├── Play.jsx # Game player + DevToolbar (P key)
│ ├── CreateWizard.jsx # 3-step wizard + SSE progress
│ ├── Dashboard.jsx # "My Games" - collections + created games only
│ ├── Profile.jsx # Stats, streaks, XP activity, achievements, history
│ ├── Arcade.jsx # Game browser with live previews
│ └── ...
├── components/
│ ├── Header.jsx # Sticky nav (static on /play/*), mobile menu
│ ├── DevToolbar.jsx # Tweak, refine, code editor (P key)
│ ├── TweakPanel.jsx # 3-step: preview → confirm → success
│ ├── GameCard.jsx # Live preview with audio mock
│ ├── OnboardingTutorial.jsx # First-time wizard (DB-persisted)
│ └── ...
├── context/AuthContext.jsx
└── api.js # 180s timeout, SSE streaming, push
backend/src/
├── routes/
│ ├── creation.js # Background generation + SSE streaming
│ ├── localai.js # Haiku tweaks: preview, classify, apply, review
│ ├── push.js # VAPID key, subscribe/unsubscribe
│ └── ...
└── utils/
├── claude.js # Sonnet: generateGameStream, regenerateGameStream
├── haiku.js # preprocessTweak, explainError, summarize*
├── localAI.js # refinePrompt, classifyTweak, applyTweak
└── pushNotify.js # Web push send/subscribe
AI Architecture
Haiku-first: All lightweight AI uses Claude Haiku directly.
| Task | Model | Location |
|---|---|---|
| Game generation/refinement | Sonnet (streaming) | claude.js |
| Tweak preview/apply | Haiku | localAI.js |
| Prompt refinement | Haiku | localAI.js |
| Code review | Haiku | localai.js route |
| Error explanation | Haiku | haiku.js |
| Summaries | Haiku | haiku.js |
Background Generation + SSE
POST /api/creation/:id/generatereturns immediately- Backend runs async, streams progress to
activeGenerationsMap (5min TTL) - Client connects
GET /api/creation/:id/stream?token=JWT - SSE replays buffered events, streams new ones
- On complete: DB save, in-app notification, email, push
SSE auth: JWT via ?token= query param.
Nginx: Requires proxy_buffering off for /api.
Key Pages
Dashboard → "My Games"
- Collections grid (4 max shown)
- Created games list with status badges
- Create button — no stats/XP (moved to Profile)
Profile (own)
- Avatar, XP bar, level icon
- Quick stats: Games Created, Played, Time, Total XP
- Streaks: Login (🔥), Creation (⚡) with milestones
- XP activity: Recent transactions
- Achievements grid (earned/locked toggle)
- Tabs: Created Games, Favorites, Play History
Play + DevToolbar
- Press P to open (creators only, draft/testing)
- Tweak tab: 3-step flow with Haiku preview → confirm → success
- Edit tab: Code editor with Haiku review before save
- Refine tab: Full Sonnet regeneration with SSE progress
- Prompt tab: View generation prompt
- Test 30s minimum before publishing
Header
- Sticky on all pages except
/play/*(static there) - Mobile hamburger menu
- Token display, notification bell, avatar+level badge
Onboarding
- 4-step welcome wizard for new users
- Persisted in DB (
onboarding_completecolumn) - Survives cache clear/reload
API Endpoints
# Public
GET /api/arcade/games|:id
GET /api/leaderboard/players|creators|games
GET /api/push/vapid-key
# Auth
POST /api/auth/register|login|guest-login
POST /api/auth/forgot-password|reset-password
# Authenticated
POST /api/play/start|finish|rate|favorite
POST /api/creation/start|:id/generate|refine|publish
GET /api/creation/:id/stream # SSE (?token=JWT)
POST /api/localai/refine-prompt|classify|tweak/:gameId
POST /api/localai/tweak/:gameId/preview # Haiku preview
POST /api/localai/review-code/:gameId # Haiku code review
POST /api/localai/save-code/:gameId # Save manual edits
POST /api/push/subscribe|unsubscribe
GET /api/users/me
Database Tables
Core: users, games, plays, ratings, high_scores Social: favorites, follows, notifications, collections Progress: achievements, user_achievements, xp_transactions Education: classrooms, classroom_students, assignments Push: push_subscriptions Reports: game_reports, bug_reports
Common Tasks
# Add page
1. frontend/src/pages/NewPage.jsx
2. Add route in App.jsx
3. Add to Header.jsx if needed
4. ./deploy.sh
# Add API endpoint
1. backend/src/routes/file.js
2. frontend/src/api.js method
3. Mount in app.js if new file
4. pm2 restart gamercomp-api
# Database change
sudo -u postgres psql -d game_arcade
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO gamearc;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO gamearc;
Troubleshooting
| Issue | Fix |
|---|---|
| UI not updating | /clear-cache.html or Ctrl+Shift+R |
| PM2 errors | pm2 flush && pm2 restart gamercomp-api |
| SSE not working | Check nginx proxy_buffering off |
| Generation timeout | Check 180s timeouts (nginx, api.js) |
| Iframe blank | Needs sandbox="allow-scripts" |
| Push not delivered | Check VAPID keys, subscriptions pruned on 410 |
| Mobile keyboard hiding | Use font-size: 16px on inputs |
Architecture Notes
Iframe Communication: Games export pauseGame(), resumeGame(), pauseMusic(), resumeMusic(), gameScore, setMusicEnabled(), setSfxEnabled() on window.
Content Safety: Multi-layer filtering (profanity, PII, violence). Gaming allowlist. Kid-friendly errors.
Audio Mocking: GameCard.jsx mocks AudioContext and Audio completely to prevent sounds in previews.
Mobile Touch: Play.jsx uses onTouchEnd with e.preventDefault() for buttons. Textareas need font-size: 16px to prevent iOS zoom and keyboard issues.