🏰 Inspiration

Our Castle: it takes a village to build one.

A family goal is never one person's project. There are several people, different budgets, and plans that change the week the car needs a repair. Most savings tools show one number to one person.

We wanted a goal the whole family can see, argue about and enjoy. In Our Castle, a family plans together, each adult offers what they can, and their progress builds a living pixel kingdom. Neighbors can join in too: lend a tent, give something useful, or chip in to a shared project.

▢️ Try it in one command, with no keys and no account: npm run demo -- --family-trip (or run the same demo in Docker).

βš”οΈ What it does

Everything lives in one parchment journal (House, Plan, Contribute, Ledger) beside an explorable medieval realm.

  1. πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ Plan as a family. Set a goal and a date. Each adult makes their own weekly offer; children can explore and state a preference, but cannot approve money. Try an unexpected expense and see what it does to the schedule before anything is saved.

  2. πŸŽ’ Compare complete kits. Type a list or photograph one. Mark what you already own, add product listings, and compare whole kits by cost, weight or number of shops. When an expense grows, the planner finds the smallest change that keeps what the family already agreed on. If nothing fits, it says how much you are short.

  3. πŸ’Έ Hold first, then decide. An adult approves an exact amount through PayPal checkout. A contribution can be paid at once, or held first, then released in steps or returned. Nothing counts toward the goal until an adult releases it and PayPal confirms the capture.

  4. 🏘️ Help the neighbors. The Village Exchange handles loans and gifts of real items, with explicit acceptance and handover. A village fund lets several families build one shared project, while each family's private goal stays private.

  5. πŸ—ΊοΈ Explore the realm. Nine districts, six rivers and nine bridges open as the goal fills. There are unlock cards, a family campsite that gets built in stages, a gold fountain, a tavern, farm animals, a wizard, a hidden sword, and snow, rain and night. Moss, the castle keeper, offers a guided tour.

  6. πŸ“œ Keep an honest record. The Treasury shows every record, what is still on hold and for how long. A read-only steward answers questions about it. It can read; it can never pay.

πŸ› οΈ How we built it

JavaScript, Node.js, SQLite, Rust and Three.js, with separate boundaries for planning, permissions, payments and the world.

  • πŸ¦€ Rust solver. A native, bounded solver searches complete-kit combinations in exact integer cents and finds the smallest-change repair. An independent JavaScript reference runs where Rust is not installed, and the two are checked against each other on hundreds of cases.

  • πŸ’™ PayPal. JavaScript SDK v6 opens checkout. The official Server SDK drives Orders v2 and Payments v2: authorize, capture in up to three steps, void and reauthorize. The server records the adult's decision first, checks amount, currency and order identity, and credits once. The PayPal Agent Toolkit gives the steward scoped, read-only tools.

  • 🧩 APIMatic. The PayPal Server SDK is APIMatic-generated, and APIMatic's SDK context skills guided the integration and its capture-recovery fixes.

  • πŸ“Š AG Grid and AG Studio. The Treasury is built on them: a custom parchment widget, three typed live tables totalled by Studio's data engine (including open PayPal holds with a guarantee timeline), and the Studio Agent Framework running the read-only steward.

  • πŸ›’ Channel3. Product search, price refreshes and cheaper alternatives in Market Town, feeding the kit planner. One press drafts a listing for every item that has none. Searching never buys anything.

  • πŸ€– Claude (Anthropic). Proposes weekly schedules; the server keeps one only if it matches its own arithmetic.

  • πŸ“· OpenAI. Reads a photographed list into an editable draft that an adult reviews.

  • 🧭 Cohere (optional). Orders kits that already qualify by a stated preference. The budget rules stay deterministic.

  • πŸ” WebAuthn and MCP. Passkeys, invitations and adult/child permissions for shared families. A local MCP adapter gives an assistant three read-only tools for one fund, through access an adult can revoke.

  • 🎨 The world. A Three.js scene drawn through a pixel renderer with a fixed 90-colour palette, a cloud shader, six retro soundtrack recordings (always starting muted), keyboard access, reduced-motion support and a 390 px phone layout. It builds on earlier Tiny Castle artwork and its renderer, with their notices preserved.

πŸ§ͺ How we know it works

  • βœ… 800+ unit tests on three Node versions, the Rust solver's own tests, and a 430-test browser suite on desktop and phone, across ten hosted jobs on every change, plus CodeQL and a container build.
  • 🎲 260 seeded random histories on every run: holds, stepped releases, returns, lost answers and repeated deliveries. After each step the ledger must equal what the (fake) PayPal actually took, and no family may see another's private amounts. They found two real gaps, both fixed.
  • πŸ“ Nine money rules, each with the test that fails if you break it.
  • πŸ’³ One real PayPal sandbox journey through the app's own controls: $25 authorized β†’ $15 captured β†’ $10 returned. The $10 was released from the authorization, not refunded, and a follow-up check against the same PayPal order matched the ledger.
  • 🌐 Live Channel3 search, Claude planning and OpenAI photo reading, and a four-person family journey with separate adult offers and child payment restrictions, all recorded.

πŸ›‘οΈ Challenges we faced

Keeping promises separate from payments. A weekly offer, an approved hold and a completed capture are three different things. We modelled them separately, so progress only ever shows what happened.

Uncertain payment outcomes. A delayed answer or a repeated request must never credit twice. That took idempotency, explicit payment states and reconciliation against the same PayPal order.

Changing a plan without undoing a family's decisions. The solver has to respect quantities, funds, the date and the items the family chose to keep, even when a new expense changes what fits.

A detailed world that still loads fast. Profiling showed one river function taking eight of the ten seconds the map needed to open. Rewriting it, with a test proving identical results, brought that under a second.

πŸŽ† What we're proud of

  • A real hold, partial release and return through PayPal, matched against PayPal's own record.
  • AI with bounded jobs: models read a list or propose a schedule; deterministic rules enforce the money, and adults decide.
  • A demo anyone can run in one command, where every invented price and simulated payment is labelled as such.
  • A world a family would want to come back to.

πŸ“œ What we learned

Money shared between people needs clear lines between what someone offered, what an adult approved and what the provider confirmed. And a visual world earns its place when it makes progress easier to understand without hiding the record underneath.

🌱 What's next

  • Family playtests, and passkeys on physical devices.
  • Fix the steward's explanation of partial captures: one model answer confused the original hold with the amount credited, although the ledger and the server check were correct.
  • Finish separate-recipient PayPal and PYUSD devnet checks before claiming those paths work end to end.
  • Connect an external assistant to the MCP adapter.
  • Hosting, and the provider approvals needed for wider use.

Demo scope: PayPal transactions use sandbox test money. Keyless examples use invented families, listings and simulated payments. Recorded passkey sign-ins use virtual authenticators, and the MCP footage shows protocol responses, not a conversation with an assistant. Our Castle tracks goal progress, not a bank balance.

Source code and demo instructions Β· Architecture Β· Verification notes

Built With

  • ag-grid
  • ag-studio
  • anthropic-claude
  • apimatic
  • channel3
  • claude-code
  • cohere-rerank
  • css3
  • github-actions
  • html5
  • javascript
  • model-context-protocol
  • node.js
  • openai
  • paypal-agent-toolkit
  • paypal-javascript-sdk
  • paypal-server-sdk
  • playwright
  • pyusd
  • rust
  • solana-devnet
  • sqlite
  • three.js
  • webauthn
Share this project:

Updates

Submission history