Skip to content

prodmodfour/rotom-table

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

713 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rotom Table

CI Nuxt 3 TypeScript Vitest License Local-first Fan project

Rotom Table is a long-running hobby/passion project: a local-first Nuxt 3 tabletop companion for Pokémon Tabletop United campaigns. It brings an isometric map table, editable Pokémon and trainer sheets, encounter-table tooling, a searchable Pokédex, and PTU reference pages into one browser app backed by inspectable JSON files.

The project is intentionally product-shaped rather than tutorial-sized. It demonstrates TypeScript/Nuxt application structure, complex Vue UI, Three.js scene management, domain modelling for tabletop rules, filesystem-backed persistence, data-management workflows, and long-term ownership of a feature-rich tool.

Rotom Table is a fan-made tabletop utility, not an official or commercial Pokémon product. It uses a trust-based GM / Player role picker for local campaign use; it is not hardened public authentication and should not be exposed as a public multi-user service without replacing those assumptions.

Quick start

npm install
npm run dev

Nuxt will print the local URL, usually http://localhost:3000. Open it in a browser and choose GM Login for editing/encounter tools or Player Login for the shared player-facing view.

Recommended verification commands:

npm run typecheck
npm test
npm run build

Reviewer starting points

Features

  • Isometric map table — create map folders, edit maps, build voxel terrain, place hazards, manage field effects, spawn Pokémon and trainer tokens, move/turn tokens, track initiative, and use move/ability automation.
  • Sheet library — create, organise, rename, edit, and autosave Pokémon and trainer sheets from the browser.
  • Pokédex browser — search and filter Pokémon entries, view sprites and detail panes, and jump directly to Pokémon-specific pages.
  • Reference library — browse moves, maneuvers, abilities, capabilities, conditions, rules, items, features, and edges.
  • Encounter tools — manage JSON encounter tables, roll previews, and generate wild Pokémon sheets into the sheet library.
  • GM/player access modes — GM-only routes and controls are hidden from player sessions and checked on server routes.
  • Filesystem-backed data — maps, sheets, trainers, and encounter tables are stored as JSON in the repository tree for easy inspection, backup, and diffing.

Suggested review path

5-minute reviewer path

  1. Read the project positioning above and the fan/auth caveats.
  2. Skim docs/review-guide.md.
  3. Inspect the route list in this README, then open /maps, /sheets, /pokedex, and /generate locally as GM.
  4. Look at src/pages/, src/components/map/, src/utils/isometric/, server/useCases/, and tests/ to see the product surface area.

15-minute reviewer path

  1. Run npm run typecheck, npm test, and npm run build.
  2. Review docs/architecture.md and docs/data-model.md.
  3. Trace one local-first workflow end-to-end: edit a sheet, place it on a map, save the map JSON, and inspect the corresponding data/ file.
  4. Trace one encounter workflow: inspect encounter_tables/, open /encounter-tables, then use /generate or just encounter ... preview.
  5. Browse a few tests under tests/server, tests/composables, and tests/utils to see behaviour coverage around persistence, routing, and domain helpers.

What the project demonstrates

  • Product thinking around a real tabletop workflow instead of a thin demo.
  • Frontend complexity: searchable libraries, editors, autosave, role-aware navigation, and dense control panels.
  • Domain modelling for maps, sheets, trainers, move data, encounter tables, and app-owned PTU reference content.
  • Local-first persistence with human-readable JSON and .gitignore boundaries for personal campaign data.
  • Long-term ownership: broad test coverage, refactoring-oriented structure, and supporting documentation.

Intentionally out of scope

  • Hardened public authentication, accounts, permissions, or multi-tenant hosting.
  • Cloud persistence or collaborative database infrastructure.
  • Claiming official status, commercial distribution, or ownership of Pokémon/PTU names, images, or concepts.
  • A generic virtual tabletop; this is specifically shaped around one PTU campaign workflow.

Screenshots

No screenshot files are committed in this presentation pass. See docs/screenshots.md for the capture checklist to add later without inventing or linking missing images.

Tech stack

  • Nuxt 3 and Vue 3
  • TypeScript
  • Vitest
  • Three.js
  • npm
  • Optional Python/just helper scripts for PTU reference lookup and encounter generation

Architecture at a glance

  • src/ contains the Nuxt app: pages, components, composables, assets, and browser-side utilities.
  • server/ contains Nitro API routes, use cases, and filesystem persistence helpers.
  • shared/ contains auth, path, realtime, sheet, and encounter helpers shared by app and server code.
  • data/ and encounter_tables/ hold app-owned JSON/TypeScript data consumed at runtime; ptu-data/ is documentary upstream/source material and parser tooling.
  • tests/ contains Vitest coverage across server use cases, composables, shared helpers, and domain utilities.

See docs/architecture.md for more detail.

Common routes

Route Purpose
/ Redirects to the map library.
/login Choose GM or Player session mode.
/maps Map library and folders.
/maps/:slug Map editor/table view.
/sheets Pokémon and trainer sheet library.
/sheets/:slug Pokémon sheet editor.
/sheets/trainers/:slug Trainer sheet editor.
/pokedex Searchable Pokédex browser.
/pokedex/:pokemon_name Pokédex detail view for one Pokémon.
/generate GM encounter generation page.
/encounter-tables GM encounter-table library/editor.
/moves, /maneuvers, /abilities, /capabilities, /conditions, /rules, /items, /features, /edges PTU reference pages.

Data layout

Path What it contains
data/maps/ Saved map JSON and map-adjacent local files.
data/sheets/ Pokémon character-sheet JSON, including generated wild sheets.
data/trainers/ Trainer sheet JSON.
encounter_tables/ Encounter-table JSON, grouped by folder/region.
data/reference/ App-owned PTU reference JSON used by runtime pages, sheets, lookup helpers, and automation.
books/markdown/ Markdown source/reference content.
ptu-data/ Documentary upstream PTU parsing/source helpers; not the runtime source of truth.
public/ Public static assets.
trainer_sizes/sprites/ Trainer sprite assets served by Nitro at /trainer-sprites.
src/ Nuxt app source: pages, components, composables, assets, and utilities.
server/ Nitro API routes and filesystem persistence helpers.
shared/ Shared auth/path/sheet helpers used by both app and server.
tests/ Vitest coverage for shared logic, utilities, composables, and server helpers.

Saved sheets and maps are edited by the app itself. In development, Nuxt/Vite ignores changes under data/sheets, data/trainers, and data/maps so autosaves do not force a full page reload. .gitignore is configured to keep personal campaign data out of the repository while allowing curated examples to remain inspectable.

npm scripts

Command Description
npm run dev Start the Nuxt development server.
npm run build Build the Nuxt app.
npm run preview Preview the built app.
npm run typecheck Run Nuxt/Vue TypeScript checks.
npm test Run the Vitest test suite once.
npm run test:watch Run Vitest in watch mode.
npm run check:move-automation Check move automation coverage.
npm run sync:item-sprites Sync item sprite assets.
npm run refactor:loop Run the refactor loop helper script.

Optional just commands

The justfile includes convenience commands for PTU reference lookups, encounter rolls, and generated sheets.

just                         # show available commands
just pokemon "Pikachu"       # lookup a Pokémon
just move "Thunderbolt"      # lookup a move
just ability "Static"        # lookup an ability
just encounter               # list available encounter regions
just encounter <region>      # list tables in a region
just encounter <region> <table> <count>

Generated encounters are written under data/sheets/wild/<table>_<count>/ by default, which makes them appear automatically in the /sheets page.

Preview without writing files:

just encounter <region> <table> <count> preview

Clear generated encounter output:

just encounter --clear

Working with encounter tables

Encounter tables live in encounter_tables/ and are exposed through the GM-only /encounter-tables route. A table has a name, level range, and weighted entries with species/level data. The app can create, rename, move, delete, and save encounter tables during local development.

The /generate page rolls from those tables and can either preview generated sheets or write them into the sheet data tree.

Auth and access model

Rotom Table currently uses a trust-based role picker, not password authentication:

  • GM — full map, sheet, encounter, and control-panel access.
  • Player — shared player view with player-visible maps and sheets.
  • Guest — redirected to /login.

Server routes also check the session role for protected actions. Treat this as a local/campaign-table workflow, not a hardened public authentication system.

Production notes

This project is strongest as a local development/table tool because many workflows persist JSON directly into the repository tree. Several mutating API routes are guarded against production mode, so use npm run dev when you need browser-based editing, autosave, encounter generation, or filesystem-backed management.

For a hosted deployment, decide which data should be static, which data should be persisted elsewhere, and whether to replace the trust-based role picker with real authentication.

Portfolio framing

Rotom Table complements backend/platform repositories by showing a different set of engineering strengths: frontend/product complexity, UI state management, interactive graphics, typed domain modelling, data stewardship, and the maintenance habits required for a long-lived personal tool.

Troubleshooting

I am redirected to login.
Choose GM or Player on /login. The chosen role is stored in the rotom-role cookie.

Browser edits are not visible immediately.
Most app pages update through local state and realtime events. If you generated or edited files outside the browser, refresh the page or restart the dev server.

Write actions fail in production.
Run the app with npm run dev. Production mode intentionally disables several filesystem-mutating endpoints.

Generated wild sheets do not show up.
Check that generated JSON files landed under data/sheets/, usually data/sheets/wild/..., and refresh the /sheets page.

Contributing, security, and notices

License

Original Rotom Table application code, project-specific documentation, and original tooling are available under the MIT License. See LICENSE.

That license does not grant rights to Pokémon-related or PTU-related names, images, rules terms, concepts, sprites, reference text, or other third-party materials.

Fan project notice

Rotom Table is a fan-made tabletop utility. Pokémon-related and PTU-related names, images, and concepts belong to their respective owners. This repository does not claim official affiliation, endorsement, or ownership of those materials.

About

Local-first Nuxt/TypeScript tabletop companion for Pokémon Tabletop United campaigns, with maps, sheets, encounter tools, Pokédex/reference pages, and filesystem-backed campaign data.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors