{"id":26460306,"url":"https://github.com/ryleu/simple-vtt","last_synced_at":"2025-03-19T02:49:30.208Z","repository":{"id":37265500,"uuid":"458382368","full_name":"ryleu/simple-vtt","owner":"ryleu","description":"A simple, fast, system-less VTT.","archived":false,"fork":false,"pushed_at":"2022-10-03T15:11:23.000Z","size":116,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-03-04T16:03:36.942Z","etag":null,"topics":["dungeons-and-dragons","ttrpg","virtual-tabletop"],"latest_commit_sha":null,"homepage":"https://vtt.ryleu.me","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ryleu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":"ryleu","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2022-02-12T00:40:31.000Z","updated_at":"2023-01-15T18:59:59.000Z","dependencies_parsed_at":"2023-01-19T01:05:14.503Z","dependency_job_id":null,"html_url":"https://github.com/ryleu/simple-vtt","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryleu%2Fsimple-vtt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryleu%2Fsimple-vtt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryleu%2Fsimple-vtt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryleu%2Fsimple-vtt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ryleu","download_url":"https://codeload.github.com/ryleu/simple-vtt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244345078,"owners_count":20438241,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dungeons-and-dragons","ttrpg","virtual-tabletop"],"created_at":"2025-03-19T02:49:29.673Z","updated_at":"2025-03-19T02:49:30.201Z","avatar_url":"https://github.com/ryleu.png","language":"TypeScript","funding_links":["https://ko-fi.com/ryleu"],"categories":[],"sub_categories":[],"readme":"# SimpleVTT\nA simple, fast, system-less Virtual Table Top.\n\nIf you want to use it **right now**, you can use this handy button here to\nlaunch it on Heroku:\n\n[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/ryleu/simple-vtt/tree/main)\n\nA free demo (that may be laggy and should not be used for actual games) can be\nfound at \u003chttps://vtt.ryleu.me\u003e.\n\n**Table of Contents**\n - [Configuration](#configuration)\n - [Running](#running)\n - [Protocol](#protocol)\n - [Roadmap](#roadmap)\n - [Attribution](#attribution)\n\n## Configuration\n\nThe port is set through the `$PORT` environment variable.\n\n## Running\n\nInstall Node.JS and NPM and then run `npm i` in the project root.\n\nUse `npm start` to start the server.\n\n## Protocol\nS-VTT uses a simplistic spec for websocket communication:\n\n|      Action       |                   Request                    |                         Response                          | Description                                                                                                                                     |\n|:-----------------:|:--------------------------------------------:|:---------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------|\n|    Add a piece    |          `\u0026S;\u003cname\u003e;\u003cx\u003e,\u003cy\u003e;\u003cicon\u003e`          |              `\u0026S;\u003cid\u003e;\u003cname\u003e;\u003cx\u003e,\u003cy\u003e;\u003cicon\u003e`              | `id`: Unique identifier \u003cbr /\u003e `name`: Base 64 encoded piece name \u003cbr /\u003e `x,y`: Integer coordinate pair \u003cbr /\u003e `icon`: Base 64 encoded icon URL |\n|   Move a piece    |              `\u0026M;\u003cid\u003e;\u003cx\u003e,\u003cy\u003e`               |                     `\u0026M;\u003cid\u003e;\u003cx\u003e,\u003cy\u003e`                     | `id`: Unique identifier \u003cbr /\u003e `x,y`: Integer coordinate pair                                                                                   |\n|  Delete a piece   |                  `\u0026D;\u003cid\u003e`                   |                         `\u0026D;\u003cid\u003e`                         | `id`: Unique identifier                                                                                                                         |\n|   Create a line   | `\u0026L;\u003cx1\u003e,\u003cy1\u003e;\u003cx2\u003e,\u003cy2\u003e;\u003cthickness\u003e;\u003ccolor\u003e` | `\u0026L;\u003cx1\u003e_\u003cy1\u003e__\u003cx2\u003e_\u003cy2\u003e;\u003cx1\u003e,\u003cy1\u003e;\u003cx2\u003e,\u003cy2\u003e;\u003cthickness\u003e` | `x1,y1`: Initial coordinate pair \u003cbr /\u003e `x2,y2`: End coordinate pair \u003cbr /\u003e `thickness`: Thickness of the line \u003cbr /\u003e Hex color code            |\n|   Remove a line   |          `\u0026R;\u003cx1\u003e_\u003cy1\u003e__\u003cx2\u003e_\u003cy2\u003e`           |                 `\u0026R;\u003cx1\u003e_\u003cy1\u003e__\u003cx2\u003e_\u003cy2\u003e`                 | `x1,y1`: Initial integer coordinate pair \u003cbr /\u003e `x2,y2`: End integer coordinate pair                                                            |\n|    Fill a tile    |         `\u0026F;\u003cx\u003e,\u003cy\u003e;\u003ccolor\u003e;\u003cstyle\u003e`         |               `\u0026F;\u003cx\u003e,\u003cy\u003e;\u003ccolor\u003e;\u003cstyle\u003e`                | `x,y`: Tile coordinate pair \u003cbr /\u003e `color:` Hex color code \u003cbr /\u003e `style:` Style of fill. Options: solid. Default: solid.                       |\n| Re-size the board |                 `\u0026B;\u003cx\u003e,\u003cy\u003e`                 |                       `\u0026B;\u003cx\u003e,\u003cy\u003e`                        | `x,y` Integer length / width pair                                                                                                               |\n|  Clear the board  |                     `\u0026C`                     |                        `\u0026B;30,15`                         | None                                                                                                                                            |\n|    Join a room    |                `\u0026A;\u003cinvite\u003e`                 |                   `\u0026A;\u003cinvite\u003e;\u003csuccess\u003e`                 | `invite`: Invite code \u003cbr /\u003e `success`: true if the session exists, false if it does not                                                        |\n| Set the background|             `\u0026G;\u003cimage\u003e;\u003cwidth\u003e`             |                    `\u0026G;\u003cimage\u003e;\u003cwidth\u003e`                   | `image`: Base64-encoded image URL \u003cbr /\u003e `width`: integer width of the background image measured in tiles                                       |\n\nThere are also an HTTP API at `/api/`:\n\n|         Endpoint          | Description                                                                |\n|:-------------------------:|:---------------------------------------------------------------------------|\n| `/api/board/?id=\u003cinvite\u003e` | GET to get the board for \u003cinvite\u003e or PUT to load in a new one for \u003cinvite\u003e |\n|        `/api/new/`        | POST to generate a new blank board, responds with `{\"invite\": \"\u003cinvite\u003e\"}` |\n\nAny other path is sourced from `site/`.\n\n## Roadmap\n\n - [x] Basic HTTPS communication\n - [x] Rendering\n - [x] Lines\n - [x] Pieces\n - [x] Saving and loading\n - [x] Heroku deploy support\n - [x] Tile fills\n - [x] Chromium / Webkit support\n - [x] Rewrite in TypeScript\n - [x] Reactive design for mobile\n - [ ] Default pieces\n - [ ] Custom saved pieces\n - [ ] ~~Game master~~ This will never be implemented in v1.x.x.\n\n## Attribution\nIcons are from the [Papirus Icon Theme](https://github.com/PapirusDevelopmentTeam/papirus-icon-theme).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryleu%2Fsimple-vtt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryleu%2Fsimple-vtt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryleu%2Fsimple-vtt/lists"}