Imported from sasler/questgen (
AGENTS.md). Install upstream withnpx skills add sasler/questgen. Copyright stays with the author.
This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ before writing any code. Heed deprecation notices.
On this Next.js version, middleware.ts is deprecated and proxy.ts is the correct file convention. Never add both entrypoints at once; keep a single src/proxy.ts file and read the relevant node_modules/next/dist/docs/ proxy docs before changing file conventions.
QuestGen Agent Workflow
Task Breakdown + TDD Workflow (mandatory for all tasks)
Before touching code, break the work into smaller logical tasks. Complete those tasks one at a time; do not batch unrelated implementation together.
For each logical task:
- Check git state first — before starting the task, run
git fetch --all --pruneandgit status -sbto confirm the working tree is in the expected state and the current branch is not behind its upstream. If it is behind, pull/rebase and resolve that before writing code. - Write failing tests first — but only tests that meaningfully verify functionality. Do not add filler tests.
- Implement the task — make the failing tests pass.
- Run tests and smoke tests — run the relevant task tests, then run the repo smoke checks:
npx vitest run,npm run typecheck,npx next build, andnpx playwright test e2e/game-creation-smoke.spec.ts. If anything fails, fix it and rerun until all pass. - Code review — use a subagent with a different AI model than the one used to generate the code.
- Address review findings carefully — evaluate each suggestion, fix the valid ones, then go back to step 2 and keep iterating until the review is satisfied and the code is reverified.
- Update docs when behavior changes — if the task adds or changes commands, workflows, features, or other user/admin-visible behavior, update the relevant docs in the same task before moving on.
- Move to the next task only when the current one is clean — do not advance until tests, smoke tests, docs, and code review are all green for the current task.
- Repeat until all tasks are complete — only finish the overall job after every task has gone through the same loop and the final state is verified.
Code review models
If the GPT family of models was used to writhe the code, use Sonnet 4.6. For everything else, use GPT 5.4 for code reviews.
Commands
npm test # Run all tests (vitest)
npm run test:watch # Watch mode
npm run typecheck # TypeScript strict check
npm run format # Prettier
npm run dev # Dev server (localhost:3000)
npx next build # Production build
npx playwright test # E2E tests (requires dev server running)
AutoPilot / Fleet Execution
- When asked to implement in AutoPilot or fleet mode, still follow the same logical-task workflow above.
- Parallelism is for independent tasks or investigations, not for skipping the per-task test -> implement -> smoke test -> review loop.
- Invoke the
pr-workflowskill only after every logical task is complete and reverified.
Repo-local skills
This repository has local agent skills under .github/skills. At the start of any task, check this directory and read the relevant SKILL.md before planning or editing. Current skills include:
pr-workflow— use after all implementation, tests, docs, and review are complete to create the branch/commit/PR, push it, wait for Copilot review, triage comments, and address valid feedback.playwright-cli— use when browser automation, interactive web testing, screenshots, tracing, request mocking, or Playwright-driven inspection would help.frontend-design— use for frontend UI, page, component, layout, styling, or visual polish tasks.
Architecture Principles
- AI is NOT the game engine — deterministic code validates all state changes
- World topology is deterministic and seeded per game — room graphs, blockers, and the win path come from code, not free-form AI output
- Connections are single bidirectional edges — one
Connectionalready includesdirectionandreverseDirection; do not add mirrored reverse duplicates - Room interactables are explicit authoritative entities — use persistent interactable records with stable IDs, aliases, and state instead of ad-hoc room prose targets
- Movement and direct interactions stay deterministic — turn parsing may assist, but final room traversal and interactable targeting must resolve in engine code against the current authoritative world state
- Local context only — only current room + neighbors sent to AI per turn
- Settings in localStorage — BYOK keys never sent to server-side storage
- BYOK is first-class — free-provider presets live in
src/lib/byok-providers.ts; settings should load models after key entry and route BYOK model discovery throughPOST /api/modelswithx-byok-api-key, never query-string keys. - BYOK discovery must not become SSRF — unauthenticated model discovery may only fetch known preset model endpoints. Custom OpenAI-compatible endpoints can be saved for runtime use, but do not server-fetch arbitrary custom URLs from
/api/models. - Guest BYOK saves use browser identity — unauthenticated BYOK players are owned by
guest:<uuid>fromx-questgen-guest-id; authenticated sessions may also carry this guest owner so signing in does not strand guest saves. - Split Redis keys — world, player, history, settings, metadata stored separately
- Deployer vs player UX — regular players can use BYOK without GitHub sign-in or connect GitHub Copilot; when deployment auth is missing, the landing page should still provide an actionable path to
/setup - Unified settings — all client settings flow through
src/lib/settings.ts(single source of truth) - Copilot status checks stay lightweight — do not boot the Copilot SDK or call
listModels()from simple status endpoints; only actual model-loading paths should start the CLI/runtime - Deployment auth env compatibility — accept both
GITHUB_ID/GITHUB_SECRETandGITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET; docs should prefer theGITHUB_CLIENT_*names, andNEXTAUTH_URLmust point at the QuestGen app URL, not Upstash - Deployment storage envs must be explicit — Vercel must have both
UPSTASH_REDIS_REST_URLandUPSTASH_REDIS_REST_TOKEN; if either is missing, fail with a clear config error instead of letting Upstash surface a vague/pipelineURL parse failure - Vercel Copilot runtime stays binary-first — preserve the
next.config.tsserverExternalPackagesandoutputFileTracingIncludesentries that trace@github/copilot-sdkplus the platform@github/copilot-<platform>-<arch>executable; falling back to the JS launcher can fail in serverless runtimes and bloat function size - Hidden tester commands stay hidden in the UI —
/showfullmapand/showentitytablesare repo-documented debug tools, not player-facing affordances - Player hints stay actionable but spoiler-bounded —
/hintshould point to the next useful step in tone, not dump the whole solution - All room surfaces use authoritative interactable state —
RoomInfoPanel, visible hints, and/showentitytablesshould describe the same deterministic interactables; richer debug output must stay consistent without becoming a visible UI affordance - Copilot SDK text streaming uses delta events — enable session streaming and forward
assistant.message_deltachunks immediately; do not buffer them until the end
Key Directories
src/types/— TypeScript interfaces and Zod schemassrc/engine/— Deterministic game engine, world validator, context buildersrc/providers/— AI provider abstraction (Copilot SDK + BYOK)src/lib/— Storage, auth, settings, utilitiessrc/prompts/— System prompts and prompt builderssrc/components/— React UI componentssrc/app/— Next.js App Router pages and API routese2e/— Playwright E2E tests
Key Pages
/— Landing page (auth-aware)/setup— Owner-only deployment setup/settings— AI provider config, BYOK presets, model selection, connection status/guide— AI provider guide covering GitHub Copilot and BYOK/new-game— New game creation wizard/game/[id]— Main gameplay page/dashboard— Saved games list
Game Creation API (SSE)
POST /api/game/new returns a Server-Sent Events stream (Content-Type: text/event-stream):
event: progress—{ stage: string, message: string }— live status updatesevent: complete—{ gameId: string, warnings?: string[] }— generation finishedevent: error—{ message: string }— unrecoverable generation failure
Auth/validation errors (401/400) return JSON before the stream opens. Only the generation phase uses SSE. The Vercel maxDuration for this route is 300 s (Pro plan). Each AI call has a 90 s SDK timeout; worst-case 3 calls = 270 s.