Personal Project — Agentic GW2 Companion (Planning & Optimization)
Working language for this project: English. This document is the single source of truth. We deep-dive section by section and keep it updated with decisions and open questions.
Context
I'm a lead frontend (React) engineer. I want a personal project to:
- Priority #1 — master an AI-assisted, spec-driven development workflow (the "agentic mindset"). Not to become an AI specialist, but to build much faster by orchestrating AI agents (Claude Code) through a disciplined workflow (Spec-Driven Development): specs as source of truth, plan-before-code, review instead of type, guardrails (tests/types) that let me trust the agent. See Working method below.
- Practice a modern full-stack: React (frontend) + NestJS (backend).
- Explore backend performance (concurrency, real-time, throughput, data pipelines).
- Stand up a real DevOps pipeline (CI/CD, observability, scalability).
- On a theme that motivates me: Guild Wars 2.
Note: "agentic" here means how I build (AI-orchestrated, spec-driven), not stuffing LLM agents into the product. The GW2 tool is the vehicle for practising the workflow. Any LLM feature in the product itself is a secondary nice-to-have, not the core.
Hard requirement learned the hard way: it must be a project I actually use and won't abandon. That means a real tool that helps me play, not an abstract tech demo.
The idea (crystallized)
Build an agentic companion service (FE + BE) that helps me play Guild Wars 2 better, focused on planning & optimization. I connect my account (GW2 API key), give it a goal, and a team of agents turns it into an optimized, personalized, tracked plan — using my real account state, the GW2 API, Trading Post prices, and the GW2 Wiki.
Why this fits the goals
- Agentic-first by nature: helping-with-a-game is intrinsically tool-use + orchestration + memory heavy.
- Tool use: GW2 API (account, materials, wallet, unlocks, crafting levels, TP prices), GW2 Wiki API (knowledge/RAG), recipe/ingredient graph.
- Planning as the core mechanic: goals (a legendary, a collection) are dependency trees → decompose → resolve prerequisites → optimize acquisition (buy vs craft vs farm) → sequence into steps.
- Heuristic vs LLM with a real payoff: graph/cost optimization = pure computation (cheap, exact); understanding fuzzy goals and reasoning over wiki knowledge = LLM. The comparison is built in.
- Persistent memory: the tool knows my account and progress, and re-plans as I advance or as prices move.
- Sticky: I'll use it every session because it solves my own problem.
Flagship MVP — Legendary crafting planner
First vertical (deliberately just one — it's already large and complex):
I name a legendary (e.g. The Bifrost). The agent reads my account, expands the full crafting dependency tree, checks what I already own, computes the cheapest buy-vs-craft path against live TP prices, estimates gold + time, produces a step-by-step plan, and tracks me toward it across sessions.
Two personas (both matter; the second is mine)
- Craft-for-self: "I want The Bifrost for myself" → cheapest acquisition path, actionable plan, progress tracking.
- Craft-for-profit (my actual use case): "Which legendaries are the most profitable to craft and sell right now?" → rank sellable legendaries by margin, show the optimal production path, factor in the time-gated inputs I can supply, tell me what's worth crafting.
Differentiator
Static calculators exist (e.g. gw2efficiency). Our edge is the agentic, conversational, goal-driven, self-updating layer on top: understand a fuzzy goal, reason over account + wiki + prices, produce and maintain a living plan.
Domain & data model (verified against the official GW2 API wiki)
GW2 API v2 surface (endpoints we'll use)
- Account state (needs API key):
/v2/account/materials(material storage),/v2/account/wallet(currencies),/v2/account/bank,/v2/account/inventory,/v2/characters/:id/inventory,/v2/characters/:id/crafting(disciplines + level/rating, max 500),/v2/account/recipes(unlocked recipes). - Item/recipe data (no auth):
/v2/items(fields incl.flags[]for binding —AccountBound,SoulbindOnAcquire…),/v2/recipes+/v2/recipes/search?input=|output=(station recipes only). - Trading Post (no auth):
/v2/commerce/prices(bestbuys.unit_price/sells.unit_price),/v2/commerce/listings(full order-book depth — use when buying/selling large quantities across price levels). - Auth & scopes:
Authorization: Bearer <key>; scopes needed =account, inventories, wallet, characters, unlocks(+tradingpostonly for the player's own orders/history). - Rate limit: per-IP token bucket — 300 burst, refill 5/sec (300/min),
429on overflow. Batch up to 200 ids per?ids=call.
The critical data-sourcing fact
Mystic Forge recipes are NOT in the API. /v2/recipes only covers the 9 crafting disciplines/stations; the Mystic Forge is not a discipline. So every legendary combine step — precursor forging, Gift of Fortune / Mastery / Magic / Might, Mystic Clovers, the weapon-specific gift, and the final 4-item assembly — is absent from the API. Every existing tool supplies these from the wiki / a curated dataset.
→ Data source = hybrid (decision):
- Official API for station-crafted leaves + live prices + account state.
- A curated Mystic Forge recipe table (from the GW2 Wiki) for the Forge nodes. This curated table is the project's key maintenance point (game patches drift the numbers).
- Resolve every leaf item id → price via
/v2/commerce/prices.
Legendary structure (Gen 1, example: The Bifrost)
Built in the Mystic Forge from 4 items: Precursor (The Legend) + Gift of Fortune + Gift of Mastery + Gift of The Bifrost.
- Gift of Fortune = Gift of Magic + Gift of Might + 77 Mystic Clovers + 250 Globs of Ectoplasm.
- Gift of Mastery = Bloodstone Shard + 250 Obsidian Shards + Gift of Exploration + Gift of Battle.
- Gift of <weapon> = weapon-specific (runestones, gold, discipline-crafted gift…).
Buyable vs account-bound (drives the profit model)
- Buyable on TP: precursors, Globs of Ectoplasm, Mystic Coins, T6 fine mats, Icy Runestones, and station-crafted ingredients.
- Account-bound / earned (NOT on TP): Gift of Exploration (100% world completion), Gift of Battle (WvW reward track), Bloodstone Shard (spirit shards), Obsidian Shards (karma), Mystic Clovers (RNG forge). These are a time cost, not a gold cost.
- Classify each leaf programmatically via item
flags[].
Profit model (confirmed)
profit = net_sell_price(legendary) − Σ cost(buyable leaf mats), where:
net_sell_price= TP price of the finished Gen 1 legendary minus the fixed 15% TP tax (5% listing + 10% exchange — hardcode it, not an API field).- account-bound/time-gated inputs are treated as player-supplied (cost 0, or an assigned opportunity cost).
- optionally subtract already-owned mats (from account endpoints) to get my personal cost.
- Optimization question: given the gated inputs (Gifts of Exploration/Battle, Clovers) I can produce, which Gen 1 legendaries maximize total profit / profit-per-gated-input?
- Prices are volatile → recompute against live TP data and re-check over time.
Verticals backlog (after the flagship)
- Weekly time optimizer: "given my goals + playtime, what should I do this session/week" (dailies, weeklies, resets).
- Achievement / goal roadmap: turn any long-term goal (mount, title, mastery) into a tracked step-by-step roadmap.
- Gearing & builds: optimize stat combos, ascended/legendary gear, build templates for a role/mode.
Working method — Spec-Driven Development (the core skill to master)
The spec is the durable source of truth; code is cheap to (re)generate. Invest in specs and review; the agent does the typing. Per-feature loop:
- Spec — short markdown in the repo (
specs/<feature>.md): problem, user story, in/out of scope, acceptance criteria, constraints. - Plan — feed the spec to Claude Code, use plan mode, review/refine the implementation plan before any code.
- Tasks — break the plan into small, independently verifiable steps.
- Implement — agent writes each task; I review the diff, not author it.
- Verify — tests + types + running the app are the guardrails that make agent output trustworthy; derive acceptance tests from the spec's criteria.
- Capture — record conventions/decisions in
CLAUDE.md(the project's constitution); turn repeatable steps into slash commands / subagents.
Mindset: I'm the architect + reviewer, not the typist. Small increments + strong guardrails = trust + speed. Reference: GitHub Spec Kit formalises this spec→plan→tasks→implement loop; Claude Code plan mode, CLAUDE.md, and subagents are the built-in primitives.
Why GW2 suits this: clean verifiable slices (the profit calc has a right answer; the recipe graph is well-defined; the API is documented) → strong guardrails → ideal conditions to practise trusting + reviewing an agent.
Architecture (to affine section by section)
Planning engine (mostly deterministic; LLM optional)
- Core is a deterministic engine, not a swarm of agents: recipe-graph resolver → buy-vs-craft/profit optimizer → account-state diff → live price fetch. This has right answers → easy to test → great SDD guardrails.
- Optional thin LLM layer only where judgment helps: parsing a fuzzy goal ("something profitable under ~500g upfront") into structured constraints, and light wiki reasoning. Deferred; not required for the MVP.
- If/when an LLM tool-use loop is added, build it on the official
@anthropic-ai/sdk(Tool Runner) — but it's a secondary feature, not the point of the project.
Backend (NestJS) — DECIDED: lean MVP, Postgres + in-memory cache
Module structure:
Gw2ApiModule— typed GW2 API client; owns auth (user API key), rate-limit budgeting (300/min per-IP token bucket), 200-id batching.StaticDataModule— items + station recipes (immutable) synced once & cached hard; holds the curated Mystic Forge table (wiki-sourced; the API can't provide it).RecipeGraphModule— merges API recipes + curated Forge table → full dependency graph; memoized tree expansion.PricingModule— live TP prices, short-TTL in-memory cache; buy-vs-craft cost resolution.PlanningModule— the optimizer: expand tree → classify leaves buyable/account-bound viaflags[]→profit = net_sell − Σ buyable_cost→ rank Gen 1 legendaries.AccountModule— reads user materials/wallet/crafting to personalise (subtract owned mats).Auth/UserModule— accounts + encrypted GW2 API-key storage.
The optimizer is a clean recursive computation (cost = min(buy_price, Σ children craft cost)) with right answers → ideal for unit tests = the SDD guardrail.
Perf posture (decided: "just enough"): honest framing — this is I/O-bound API orchestration, not a concurrency/throughput system. Perf = sensible caching + batching + rate-limit budgeting (good hygiene), not an elaborate pipeline. backend performance is downgraded from a headline goal to good practice here.
Infra (decided): Postgres (users, cached static data, curated Forge table) + in-memory cache for the MVP. Redis is a later add if/when the caching story is worth showcasing.
Real-time: deferred. Recompute margins on demand / on refresh for the MVP; WebSocket live-updating rankings is a stretch goal, not MVP.
Frontend (React) — DECIDED
- MVP centerpiece (decided): plan / tree view for ONE legendary — pick a legendary → full dependency tree + step plan + own-vs-need + buy-vs-craft per node. This is the thinnest end-to-end slice; the profit ranking view is the immediate next layer (same engine run across all Gen 1 legendaries, sorted).
- Tree visualization (decided): nested collapsible list — indented expandable rows with cost roll-ups and gated-input flags. Simplest MVP baseline; can upgrade to React Flow / d3 later for visual polish.
- Surfaces beyond MVP: profit ranking (persona money-shot), account dashboard, (stretch) fuzzy goal input.
- Honest note on FE perf: the original "render huge real-time datasets (virtualization/Web Workers)" challenge isn't naturally present (tree ≈ few hundred nodes, ranking ≈ 19 items). The FE strength here is dataviz quality + clean UX, not rendering-perf. Don't bend the product to manufacture a virtualization flex.
DevOps — DECIDED: right-sized, workflow-first
- CI/CD (GitHub Actions): lint + typecheck + test + build on PR, deploy on merge. Pairs with SDD — acceptance tests become the guardrail CI enforces ("trust the agent" → "CI proves it"). Do it early.
- Containerization: Dockerfile for the NestJS API + Docker Compose for local (API + Postgres).
- Deployment (decided): managed PaaS — Fly.io / Railway. Push-to-deploy, managed Postgres, free tiers. Fast to a live public URL; fits "workflow not infra" focus.
- Observability (decided: lean): structured logs (pino) + Sentry (error tracking) + health checks & a few request metrics.
- Dropped from the original scope (were tied to the abandoned swarm): ❌ Kubernetes, ❌ chaos engineering, ❌ heavy load testing (k6/Locust), ❌ agent/LLM cost tracing. Keeps the MVP lean.
- Honest framing: a complete, right-sized DevOps story (CI/CD + containers + real deploy + error tracking), not a "scale to millions" story — the correct call given priority = workflow, not infra.
Deep-dive plan (order of sections)
- Concept & MVP scope — lock flagship, define the thinnest end-to-end slice. (mostly done)
- Domain & data modeling — GW2 API surface, recipe/dependency graph, wiki RAG, account state, caching, the profit model. (done — verified)
- Working method (SDD) setup — repo skeleton,
CLAUDE.mdconstitution,specs/layout, first feature spec + acceptance criteria, plan-mode workflow. (the priority-#1 skill) - Planning engine — deterministic recipe-graph + buy-vs-craft/profit optimizer; test strategy (the guardrails).
- Backend (NestJS) — services, engine wiring, API sync/caching, real-time, perf.
- Frontend (React) — plan viz, goal input, dashboard.
- DevOps & observability — CI/CD, deploy, metrics/tracing.
- Portfolio framing — tell the story (the SDD workflow itself is part of the story).
Open questions / decisions to make
Resolved:
Recipe-graph data source→ hybrid (API + curated Mystic Forge table).Infra/perf→ lean; Postgres + in-memory cache; I/O-bound, no heavy pipeline.Deploy/observability→ managed PaaS (Fly/Railway) + logs/Sentry/health.Orchestration / LLM-in-product→ deterministic engine core; LLM optional & deferred.API sync/cache→ static data cached hard (immutable), prices short-TTL, respect 300/min + 200-id batching.
Still open (implementation-time):
- How to build & maintain the curated Mystic Forge dataset (scrape wiki once vs hand-curate; keeping it patch-current).
- How to price/value account-bound gated inputs (cost 0 vs opportunity cost vs "profit per gift of exploration").
- Exact test strategy for the optimizer (fixtures, golden values) — the SDD guardrail.
- LLM provider/model + cost control — only if/when the optional fuzzy-goal feature is built (default to latest Claude via
@anthropic-ai/sdk).
Final goal
A rich portfolio project that demonstrates:
- Mastery of an AI-assisted, spec-driven development workflow — shipping fast by orchestrating agents, with specs as source of truth and guardrails I trust (the priority-#1 skill).
- Strong full-stack React/NestJS with real backend performance work.
- A complete, professional DevOps chain.
- And — most importantly — a tool I actually use to plan and profit from legendary crafting in GW2.