table-craft
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Open-source board & card game engine: write the rules in one JS file, get a 3D multiplayer table with physics dice, bots, a referee and a balance lab.
Tablecraft
Write the rules. Get the table.
A server-authoritative 3D tabletop engine: describe any board or card game in one JavaScript module and get a
physics-based table with multiplayer rooms, bots and an automated referee.
Live demo · Playground · Examples · Getting started · Documentation
Why Tablecraft
Prototyping a tabletop game online usually means choosing between a spreadsheet-like UI that nobody enjoys and months
of game-engine work. Tablecraft sits in between: you write the rules, it builds the table.
- One file per game.
setup(),moves,view(),endIf(). State is plain JSON; randomness is seeded and replayable. - A real table. Cards arc, tilt and flip; dice are thrown with physics and land on the server's result; tokens toss and stack.
- Fair by construction. Moves run on the host in a sandbox. Each player's
view()contains only what they may see. - Bots and a referee for free. Export
actions()and bots can play; the referee plays hundreds of games and reports rule bugs. - Mechanics in the box. Drafting, auctions, worker placement, majorities, trick-taking, set collection, deck-building,
decision stacks, square and hex grids — 40+ mechanics as small, deterministic helpers onT. - Balance you can measure. The balance lab reports first-player advantage, game length, forced decisions, comebacks and dominant strategies — and sweeps a card count or point value to show what a change would do.
- Followable. The Spotlight puts every card another player reveals or plays on stage; the game log keeps the whole story.
- Play anywhere. In the browser against bots (no server), or on your own socket.io room server for real multiplayer.
- Typed. Hand-written TypeScript declarations: autocomplete for the module contract, the scene and
T— even in plain JS. - AI-ready.
npx @table-craft/table-craft mcpgives Claude (or any MCP client) tools to write, referee, audit and step through games.
60-second start
npm create tablecraft@latest my-game # templates: dice (default), cards, multiplayer
cd my-game && npm install && npm run dev
Or try it without installing anything in the playground:
edit a game on the left, play it on the right, run the referee and the balance lab, share a link.
Add it to an existing app
npm install @table-craft/table-craft react react-dom three cannon-es
import { createLocalMatch } from '@table-craft/table-craft';
import { TablecraftGame } from '@table-craft/table-craft/react';
import '@table-craft/table-craft/style.css';
import source from './treasure-road.js?raw'; // any game module, as text
const match = createLocalMatch({ source, players: ['Ada', 'bot', 'bot'] });
export default function App() {
return <TablecraftGame client={match} style={{ height: '100vh' }} />;
}
Copy examples/treasure-road/game.js next to it and you are playing a 3D card-and-dice
race against two bots. When you want friends at the table, swap one line:
import { io } from 'socket.io-client';
import { connectRoom } from '@table-craft/table-craft';
const match = connectRoom({ io, url: 'https://your-server', room: 'AB12CD', name: 'Ada' });
…and run a room server (full example):
import { createRoomServer } from '@table-craft/table-craft/server';
const rooms = createRoomServer(io.of('/tablecraft'));
const code = rooms.createRoom({ source: fs.readFileSync('game.js', 'utf8') });
What a game looks like
module.exports = {
meta: { name: 'Treasure Road', minPlayers: 1, maxPlayers: 4 },
setup({ players, random }) {
return { players: players.map((p) => ({ ...p, pos: 0 })), turn: 0, log: [] };
},
moves: {
roll(s, ctx) {
if (s.players[s.turn].id !== ctx.playerId) return { error: 'Not your turn' };
const r = ctx.roll(6, { id: 'die', by: ctx.playerId }); // 3D die lands on r
s.players[s.turn].pos += r.face;
s.turn = T.nextIndex(s.players.length, s.turn); // T = the rules kit
return s;
},
},
view(s, { playerId }) {
return {
type: 'tabletop',
scene: {
zones: [{ id: 'track', layout: 'track', cells: 16, at: [-30, 0], to: [60, 0] }],
objects: [
{ id: 'die', kind: 'die', at: [0, 10], click: { name: 'roll' } },
...s.players.map((p) => ({ id: p.id, kind: 'token', shape: 'pawn', zone: 'track', order: p.pos })),
],
},
hud: { title: 'Treasure Road', log: s.log },
};
},
endIf: (s) => (s.players.some((p) => p.pos >= 15) ? { reason: 'Someone found the treasure' } : null),
actions: (s, { playerId }) => (s.players[s.turn].id === playerId ? [{ name: 'roll' }] : []),
};
Most games are built from the same mechanics, so the kit has them — a trick-taking hand is a few lines:
const legal = T.tricks.legal(me.hand, s.trick, { trump: s.trump }); // follow suit if you can
s.leader = T.tricks.winner(s.trick, { trump: s.trump }).id; // highest trump, else highest of the suit led
// ...and at the end: a ranking with tie-breakers, ready for endIf
return T.score.result(s.players, { keys: ['score', '-penalties'] });
Packages in the box
| Import | What it is |
|---|---|
@table-craft/table-craft |
Isomorphic core: createLocalMatch, connectRoom, Match, the rules kit T, referee, seeded RNG |
@table-craft/table-craft/react |
<TablecraftGame> (lobby + table + end screen), <Tabletop>, useMatch() |
@table-craft/table-craft/embed |
mountGame(element, props) for pages without React code |
@table-craft/table-craft/engine |
The framework-free three.js table (TabletopWorld) for custom UIs |
@table-craft/table-craft/server |
Node: node:vm runtime, createRoomServer, referee (simulate, validate), balance lab (analyzeBalance, sweepParameter), view audit, worker-thread variants (simulateAsync, analyzeBalanceAsync) |
@table-craft/table-craft/style.css |
HUD styles (themeable with --tc-* custom properties) |
@table-craft/table-craft/game |
Types only: /// <reference types="@table-craft/table-craft/game" /> in a game file gives autocomplete for T, ctx and the scene |
@table-craft/table-craft/mcp · npx @table-craft/table-craft mcp |
MCP server for AI assistants; npx tablecraft validate / simulate / audit from the terminal |
Documentation
| Getting started | Your first game, locally, in ten minutes |
| Concepts | Host, views, intents, fx — the mental model |
| Game module | meta, setup, moves, view, endIf, actions, bot, invariants, ctx |
| Scene | Zones, layouts, cards, decks, dice, tokens, boards, timers, faces and art |
| HUD | Players, prompts, panels, log and 2D UI nodes |
| Effects | Dice, banners, toasts, sounds, tosses, highlights, reveals |
Rules kit T |
Decks, turn order, resources, sand timers, graphs, hex grids |
| Mechanics | A catalog of 40+ board-game mechanics and the helpers that implement them |
| Following the game | Spotlight, game log, pacing — and how to write games that read well |
| Client | React, embed, engine, theming, locales, keyboard |
| Server | Room server, wire protocol, hosting, security |
| Bots & referee | actions(), bot(), invariants(), simulate() in CI |
| Balance lab | Is it fair? First-player advantage, length, forced decisions, comebacks, dominant strategies, sweeps |
| AI assistants (MCP) | Connect Claude Code / Claude Desktop; tools, resources, prompts |
Examples
| Game | Players | Shows |
|---|---|---|
| Coin Flip Duel | 2 | the 40-line game from Getting started |
| Treasure Road | 1–4 | hidden hands, deck and discard, physical die, sand timer |
| Supply Lines | 2–4 | hex map, routes between corners, path finding |
| Spice Bazaar | 2–5 | simultaneous drafting, set collection, majorities |
| Harbor Workers | 2–4 | worker placement, phases, sliding market, decision stack |
| Auction House | 3–5 | open, once-around, sealed and Dutch auctions, hidden money |
| Drop Four | 2 | square grid, n-in-a-row (T.grid.lineRuns), a bot that wins and blocks |
| Liar's Dice | 2–5 | private dice rolls, bluffing, bots that bid with exact odds |
| Lantern Tricks | 3–4 | trick-taking with trumps and exact bids (T.tricks, T.flow) |
Every example passes npx tablecraft simulate and audit in CI. Play them all in the gallery. |
How it compares
| Tablecraft | boardgame.io | Tabletop Simulator | |
|---|---|---|---|
| Rules enforced by the server | ✅ | ✅ | ❌ (sandbox, optional Lua) |
| 3D table with physics dice and cards | ✅ built in | ❌ bring your own UI | ✅ |
| Hidden information per player | ✅ view() |
✅ playerView |
manual (hidden zones) |
| Bots from your rules | ✅ actions() + heuristics |
✅ MCTS | ❌ |
| Automated referee and balance metrics | ✅ | ❌ | ❌ |
| Board-game mechanics library | ✅ T |
❌ | ❌ |
| AI assistant tools (MCP) | ✅ | ❌ | ❌ |
| Price / license | free, MIT | free, MIT | paid, closed |
Pick boardgame.io if you want full control over a 2D React UI; pick Tabletop Simulator to play existing games freely
with friends. Tablecraft is for designers who want a rules-enforcing, playable, testable table from one file.
Develop
npm install
npm test # runtime, mechanics, referee, match, scaffolder and an end-to-end socket.io room
npm run lint # ESLint
npm run typecheck # the TypeScript declarations in types/
npm run site:dev # landing page + playground at http://localhost:5173
npm run example:server
npm run build # dist/ for npm
Node ≥ 22.12 (the server entry is ESM and also loads with require()). Browsers: anything with WebGL 2.
Docker
docker build --target site -t tablecraft-site . # landing + playground, static on nginx :80
docker build --target rooms -t tablecraft-rooms . # room server :5180 (GAME=examples/coin-flip-duel/game.js)
docker run -p 5180:5180 tablecraft-rooms # → http://localhost:5180/?room=<code from the log>
Origin
Tablecraft was extracted from the 3D playtest table of an AI board-game studio, where hundreds of machine-written
prototypes needed a table that was fair, readable and fun to watch.
Community
- Questions, ideas and games you made: Discussions
- Bugs and feature requests: Issues
- How to contribute: CONTRIBUTING · where we are going: ROADMAP
- Security reports: SECURITY · be kind: Code of conduct
License
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found