Skip to content

v0.1.0

2026-02-08 243eb5

For some reason, I didn't have a CHANGELOG.md file before, so we'll start here.

Brief summary of the 236 commits that led to this version:

  • Platform
    • Created a multi-package repository with shared code and separate packages for the client and server.
    • Platform Philosophy: instances of this app should always run on the user's own hardware.
      • The simplest approach is to run sqlite, server-core, LLMs, the Library, and a server hosting the frontend all on one machine. This could be the user's personal computer (likely requiring NAT or a VPN for multiplayer), or a cloud VM that they rent (which would be publicly accessible, but they have to pay for it; we can still help them provision it, in their name).
      • The full cloud-hosted approach separates the server-core, LLM core, postgres db, and frontend assets into various ECS, S3, and RDS instances, all under the user's own cloud account, which we could help them set up. This is more expensive and complex, but offers better performance and accessibility.
      • The current "production" implementation is a more traditional shared hosting approach, where we host the server and database on our own infrastructure, and users connect to it with their clients. This is the easiest to set up and maintain for us, but it has some limitations in terms of performance and scalability, and it also raises some privacy concerns since we're hosting user data on our servers. This is intended as a temporary solution until we can implement the more user-controlled hosting options. (TODO: make TODOs for provisioning a customer environment)
  • Database
    • Data abstraction layer, with two adapters built so far: sqlite and postgres.
    • Also, external APIs for game systems like D&D 5e are accessed, processed, and cached by the server, but live in the external API's data source.
  • Server
    • Express server with REST API and WebSocket support.
    • User authentication and session management (mostly offloaded to Clerk).
    • CRUD for entities like systems, campaigns, characters, and tokens.
    • On-server LLMs for things like Character Sheet parsing. Also uses APIs for LLMs-as-a-service, but the on-server ones are preferred for small, quick jobs.
    • Background process that can iterate through a filesystem, scanning files which might be VTT assets, and process them into the DB. Uses local LLM to identify asset type (map, token, object, character sheet, etc) and add tags (this map is a city, this token is a goblin, etc).
  • Map
    • WebGL (using Three.js) map rendering, with a foundation layer (textured, such as "grass"), a grid layer, and 2 or more token layers.
    • Tokens can be snapped-to-grid (PCs and monsters) or resizable rectangles (objects and pre-rendered maps).
    • Tokens can have properties (e.g. HP) and actions (e.g. attack, cast spell) which can be triggered by the GM or players.
      • Token Properties are defined for each campaign, optionally inherited from a system. For instance, 5e D&D campaigns would likely populate HP, Str, AC, etc, and an individual campaign would inherit these, allowing the GM to extend or override them. Token Properties have a name and a data type, with the ability to define custom data types, also on a per-campaign level.
      • Token Actions are functions (actual JavaScript) which take in the token's properties and emit a string, which is piped to the Chat window. Typically, this is used to trigger attacks, spellcasting, or other actions which have variable output. For instance, an Attack With Sword macro might read the token's Strength, roll a d20, add the appropriate modifiers, and emit a string like "Goblin attacks with sword: rolls 15 + 2 (Str) = 17, hits for 5 slashing damage!".
  • Typical VTT map features:
    • Fog of War (toggleable, revealable by the GM manually painting visible areas onto the map, or through integration with the Vision system (see below))
    • Dynamic lighting:
      • When enabled, map is either in outdoor mode with a chosen time of day, or indoor mode where no light sources exist by default.
      • Light sources can be added directly to the map, or attached to tokens (e.g. a torch or a PC with a lantern). Light sources have properties like radius, brightness, color, and flicker. The list of light sources is a property of the Campaign (inherited from System), and extensible by the GM.
      • The DM can draw a Vision-Blocking-Layer on the map, in the form of rectangles, circles, or polygons. When vision is enabled, this geometry is used to calculate what areas of the map are visible from each token, based on the token's position and light sources.
      • When a token shouldn't be visible based on the vision system, it is literally not visible (if you're a PC; GMs can always see everything, but vision-blocked tokens are partially transparent; also, there's a "view as PC" option to see using PC logic).
      • With vision enabled, the Fog of War system is integrated such that token owners can manually or automatically reveal the fog of war as their tokens explore the map, but only in areas visible to their tokens.
      • Feature in development, intended for Beta: VBL can be attached to a token, rather than the map itself. The likeliest use of VBL is to indicate which areas of a pre-rendered map are vision-blocking. Painstakingly drawing this geometry onto the map, only to have it all break if the token is ever moved or resized, is a non-starter. Attaching the VBL to the token itself allows it to move and resize with the token, making it much easier to set up and maintain.
      • Feature intended for GA: VBL on a token (i.e. a map) can be auto-generated using an LLM, which analyzes the map image and identifies vision-blocking features (e.g. walls, trees, hills, etc) and draws the VBL geometry accordingly.
    • Chat system, with support for text and dice rolls. Dice rolls can be triggered by token actions, special 'die roller' buttons (which throw a 3d dice onto the tabletop which uses a physics engine to determine the result), or by typing directly into the chat (e.g. "I rolled 1d20" => "I rolled 7 (on 1d20)").
      • This system uses WebSockets to broadcast messages to all connected clients in real-time, and also stores chat history in the database.
  • Character Sheet
    • Character entities are a superset of Tokens. Tokens can do a lot with properties and actions, but the Map feature doesn't exactly help a PC build their character. The Character Sheet app understands various systems, and provides a UI for building out a character, which then syncs to a Token on the map.
      • Systems supported with Beta: D&D 5e 2014/2024 (using SRD), System 8 (homebrew, similar to 5e).
      • Systems planned for GA: the entire modern d20 tree: 3e, 3.5e, Pathfinder 1e and 2e, Starfinder, and more. - Later releases possible: non-d20 systems like World of Darkness, Shadowrun, etc.
    • Characters can be inserted as a token onto a map from the Character Sheet, or imported while in the map itself.
  • Character/Token Art
    • Characters and tokens can have one or more pieces of artwork associated with them.
    • Token art is stored either on the filesystem of the server, or on a third-party service like S3 (more options may be added in GA or later).
    • Upon upload, token art is processed into:
      • Full-res, high-quality webp
      • Low-res, medium-quality webp preview image
      • For particularly large images (e.g. maps), various LOD images are generated at different resolutions, which can be swapped in and out based on the client's zoom level.
    • For a token, art can be "tokenized", meaning:
      • Cropped to a circle
      • Circle has a customizable border (color, thickness, pattern)
      • Background can be made transparent, or filled with a solid color or pattern.
      • Original art image can be panned/zoomed within the cropping circle
      • In-browser open-source LLM can automatically detect face and select a good pan and zoom for the token, which works like 98% of the time in just a second or two.
      • Token art is rendered as a WebGL material on the map, with the cropping/etc performed by WebGL. In other words, the "tokenized" image is not rasterized to a separate image file.
      • Token art source formats supported with Beta: png, jpeg, webp, and mp4. Video art does work, looping through a video to offer an animated token.
        • Features considered the future: progressive tokens, with multiple images which can be stepped through in sequence (like a progressively sinking ship or burning building). This isn't too hard to do manually, so it may be too much fluff to automate it.
    • Sourcing an image offers several options:
      • Upload via browser
      • Google image search integration (type "orc", pick one of 10 suggestions)
      • Choose from Library (see Library feature below)
      • Others planned for GA:
        • Paste a URL to an image
        • Paste a complete image from the clipboard (not just the URL, but the actual image data)
        • Pinterest integration (similar to Google image search, but I don't know if Pinterest even has this kind of API available to third parties, so it may not be possible)
        • Possibly even a Chrome extension to borrow images from other tabs (as permitted by the user). For example: they've got their favorite genAI open in another tab, and we offer a single-button (or even automated) feature to grab the most recent high-res image loaded in that tab. (Also works for Pinterest!)
      • Others considered for the future:
        • GenAI: easy to implement, contraversial in practice, even with open-source models. Most uses envisioned for this VTT are personal and non-commercial, but still, many users have strong feelings about AI-generated art, so this may be best left out. It isn't hard for them to use the genAI of their choice and copy manually.
    • Token art can be easily swapped between multiple Artwork instances on the same token, allowing for quick changes (e.g. a PC taking damage might have their token art swapped to a more battered version).
    • Token art not currently used on the token itself can be shown in the Token's tooltip. A rectangular portrait image usually looks better in this context, compared to just showing the tokenized image, but bigger.
  • Library
    • A repository of user-uploaded assets, including character sheets, map art, tokens, and more.
    • User provides a starting folder (for now, the server's local filesystem, but in the future, this could be a third-party service like Google Drive or Dropbox), and the server's background process scans this folder and all subfolders for new files, processes them (e.g. token art processing, character sheet parsing, map analysis, etc), and adds them to the database with tags for easy searching.
    • Library has its own UI for browsing and searching assets, and any asset can be inserted into a Map from here by clicking a button.
    • When on the map, tokens and objects can be added from the Library, and when in the Character Sheet, characters can be added from the Library. In both cases, the asset is copied from the Library into the current campaign, allowing for modifications without affecting the original asset in the Library.
  • Systems
    • Considering the legal ramifications of D&D SRD, the platform "supports" D&D 5e in a notional sense only. We will not be hosting any non-OGC owned by Wizards of the Coast on any servers we own. Perhaps we may be able to enter a legal agreement with WotC, but unless they have some sort of easy rubber-stamp process, this is presumably a post-GA, post-funding feature.
    • That said, we have several different approaches to amelioriate this issue.
      • System 8: a homebrew system which is easy to grasp for 5e veterans, but 100% original. Well, more like 98%, because there are still abilities like Uncanny Dodge, but no wording and few mechanics are copied verbatim.
      • System 5: a complete implementation of D&D 5e, hand-written with no copying from WotC material, and some spell/monster/etc names changed to avoid copyright issues. This system is meant to be 99% compatible with 5e. It will require constant updating as new material is added, and needs to support both 2014/2024, possibly hybrid modes which may be popular.
      • Upload your own system: most VTTs have some sort of module system which allows users to import a 3rd party system. It is assumed at this point that none of these modules are portable to other VTTs, either technically or at least legally (TODO: research this), and that creating a module like this would be a herculean effort for the average user. We could make such a module, but that would violate our "host nothing belonging to WotC" policy. If someone were to build this module, we could import it into a customer's self-hosted environment without violating our hosting policy, but we couldn't build it ourselves, because then we'd have to host the module somewhere.
      • Upload your own system...with AI: possible next-gen approach: user provides PDFs or other documents of a system (any system, really). LLMs process the data, and create the System data structure, hosted on their environment. This sounds like a lot of LLM processing, with a lot of room for error, so at best it's a convenience on top of "upload your own system", and in many ways, this is just us duplicating Claude Code or something. So probably not.
      • Build your own system: distinct from 'upload your own system', in that most VTT system modules (as far as I know...TODO: research this) are built like code: hand-writing data files (perhaps json or yml), packaging it in some sort of folder structure, maintaining some sort of manifest, etc. But this could easily be a nice, user-friendly UI. Our app already supports adding ad-hoc traits like custom feats, and we plan to extend that to almost all aspects of a character (equipment, attributes, even custom ability scores). With such a feature, we've basically already implemented a UI for the System entities that already exist. This is 'upload your own system' with UI lubrication. And we could legally import either 5e SRD as a starting point, saving the user a lot of work. And we could still let them package it, host it on their hardware, and share, so only one user would have to use this feature to make a 5e module.