Bump to v0.4, document self-hosted backend in README

The rework-backend merge added an optional self-hosted Express/ws/SQLite
backend (npm workspaces, single-container Docker deployment) alongside
the existing Firebase default. Bump APP_VERSION and refresh README to
cover both storage modes and the new repo layout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 19:59:46 -04:00
parent c54fd88c32
commit ec578eeef5
2 changed files with 65 additions and 13 deletions
+64 -12
View File
@@ -1,4 +1,4 @@
# TTRPG Initiative Tracker (v0.2.5) # TTRPG Initiative Tracker (v0.4)
![Here it is in use](images/in_use.png) ![Here it is in use](images/in_use.png)
@@ -12,6 +12,8 @@ A web-based application designed to help Dungeon Masters (DMs) manage and displa
Have you tried it? Got feedback or questions? Discuss here: [https://discourse.draft13.com/c/ttrpg-initiative-tracker/16](https://discourse.draft13.com/c/ttrpg-initiative-tracker/16) Have you tried it? Got feedback or questions? Discuss here: [https://discourse.draft13.com/c/ttrpg-initiative-tracker/16](https://discourse.draft13.com/c/ttrpg-initiative-tracker/16)
As of v0.4, the app can optionally run against a self-hosted backend (Node/Express/ws/SQLite, shipped as a single Docker container) instead of Firebase — useful if you'd rather not depend on a Google account. Firebase remains the default; see [Self-Hosted Backend (Optional)](#self-hosted-backend-optional) below.
## Features ## Features
![DM View.](images/dm_view.png) ![DM View.](images/dm_view.png)
@@ -59,7 +61,7 @@ Have you tried it? Got feedback or questions? Discuss here: [https://discourse.d
* A **fullscreen button** (top-right corner) toggles the browser into fullscreen mode — ideal for a dedicated second monitor. * A **fullscreen button** (top-right corner) toggles the browser into fullscreen mode — ideal for a dedicated second monitor.
* A **prevent sleep toggle** (moon/coffee icon, top-right corner) uses the browser Wake Lock API to keep the screen on while active. * A **prevent sleep toggle** (moon/coffee icon, top-right corner) uses the browser Wake Lock API to keep the screen on while active.
* **Combat Action Log:** A running log of combat events (HP changes, condition changes, turn advances, participant additions/removals, encounter starts/ends, etc.) is available at `/logs`. Entries are timestamped and tagged with the encounter name. Most entries include an **↩ Undo** button that rolls back the action in Firestore (restoring HP, conditions, turn order, etc.). Rolled-back entries are greyed out with a strikethrough. The log can be cleared in bulk from that page. * **Combat Action Log:** A running log of combat events (HP changes, condition changes, turn advances, participant additions/removals, encounter starts/ends, etc.) is available at `/logs`. Entries are timestamped and tagged with the encounter name. Most entries include an **↩ Undo** button that rolls back the action in Firestore (restoring HP, conditions, turn order, etc.). Rolled-back entries are greyed out with a strikethrough. The log can be cleared in bulk from that page.
* **Real-time Updates:** Uses Firebase Firestore for real-time synchronization between DM actions and the player display. * **Real-time Updates:** Uses Firebase Firestore for real-time synchronization between DM actions and the player display (or a self-hosted WebSocket backend, see below).
* **Initiative Tie-Breaking:** DMs can drag-and-drop participants with tied initiative scores (before an encounter starts or while paused) to set a manual order. * **Initiative Tie-Breaking:** DMs can drag-and-drop participants with tied initiative scores (before an encounter starts or while paused) to set a manual order.
* **Responsive Design:** Styled with Tailwind CSS. * **Responsive Design:** Styled with Tailwind CSS.
* **Confirmation Modals:** Used for destructive actions like deleting campaigns, characters, encounters, or ending combat. * **Confirmation Modals:** Used for destructive actions like deleting campaigns, characters, encounters, or ending combat.
@@ -68,8 +70,9 @@ Have you tried it? Got feedback or questions? Discuss here: [https://discourse.d
* **Frontend:** React * **Frontend:** React
* **Styling:** Tailwind CSS * **Styling:** Tailwind CSS
* **Backend/Database:** Firebase Firestore (for real-time data) * **Backend/Database:** Firebase Firestore (default), or a self-hosted Node/Express + `ws` + SQLite (`better-sqlite3`) backend behind Caddy (optional, see [Self-Hosted Backend](#self-hosted-backend-optional))
* **Authentication:** Firebase Anonymous Authentication * **Authentication:** Firebase Anonymous Authentication (Firebase mode only; the self-hosted backend has no auth layer — intended for trusted/local networks)
* **Shared logic:** Turn-order state machine (`shared/`) is framework-agnostic and used by both the frontend and the self-hosted backend, covered by a Jest test suite
## App Usage Overview ## App Usage Overview
@@ -128,11 +131,13 @@ This flow allows the DM to prepare and run encounters efficiently while providin
### Prerequisites ### Prerequisites
* **Node.js and npm:** Ensure you have Node.js (which includes npm) installed. You can download it from [nodejs.org](https://nodejs.org/). * **Node.js and npm:** Ensure you have Node.js (which includes npm) installed. You can download it from [nodejs.org](https://nodejs.org/).
* **Firebase Project:** You'll need a Firebase project with: * **Firebase Project** (only if using the default Firebase storage mode): You'll need a Firebase project with:
* Firestore Database created and initialized. * Firestore Database created and initialized.
* Anonymous Authentication enabled in the "Authentication" > "Sign-in method" tab. * Anonymous Authentication enabled in the "Authentication" > "Sign-in method" tab.
* **Git:** For cloning the repository. * **Git:** For cloning the repository.
The project is an npm workspaces monorepo (`server/`, `shared/`, plus the CRA frontend at the root) — a single `npm install` at the repo root installs everything.
### Local Development Setup (using npm) ### Local Development Setup (using npm)
1. **Clone the Repository:** 1. **Clone the Repository:**
@@ -190,7 +195,14 @@ This flow allows the DM to prepare and run encounters efficiently while providin
### Deployment with Docker ### Deployment with Docker
This project includes a `Dockerfile` to containerize the application for deployment. It uses a multi-stage build: There are two Docker paths, depending on which storage mode you want:
* **Firebase mode (default):** the root `Dockerfile` builds a static frontend-only image, described below.
* **Self-hosted mode:** the `docker/` directory builds a single container running the Node backend + SQLite + the frontend behind Caddy, with no Firebase dependency. See [Self-Hosted Backend (Optional)](#self-hosted-backend-optional).
#### Firebase-mode image (root `Dockerfile`)
This project includes a `Dockerfile` to containerize the Firebase-backed application for deployment. It uses a multi-stage build:
* **Stage 1 (build):** Installs dependencies, copies your `.env.local` (for local testing builds), and builds the static React application using `npm run build`. * **Stage 1 (build):** Installs dependencies, copies your `.env.local` (for local testing builds), and builds the static React application using `npm run build`.
* **Stage 2 (nginx):** Uses an Nginx server to serve the static files produced in the build stage. * **Stage 2 (nginx):** Uses an Nginx server to serve the static files produced in the build stage.
@@ -225,6 +237,30 @@ This project includes a `Dockerfile` to containerize the application for deploym
* If your CI/CD pipeline builds the Docker image, ensure these environment variables are securely provided to the build environment. * If your CI/CD pipeline builds the Docker image, ensure these environment variables are securely provided to the build environment.
* **Implement strict Firebase Security Rules** appropriate for a production application to protect your data. * **Implement strict Firebase Security Rules** appropriate for a production application to protect your data.
### Self-Hosted Backend (Optional)
If you'd rather not depend on Firebase/Google, the app can run entirely self-hosted: a Node/Express + `ws` backend backed by SQLite, with the frontend talking to it instead of Firestore. Intended for trusted/local networks (no auth layer yet).
**Quickest path — Docker Compose (single container: Caddy + Node + SQLite):**
```bash
docker compose -f docker/docker-compose.yml up --build
```
This serves the app at `http://localhost:8080` (override with `PORT`), proxies `/api` and `/ws` to the backend, and persists the SQLite database in a named Docker volume. Override the Firestore-style app-id namespace with `TRACKER_APP_ID` if needed.
**Local dev (backend + frontend separately):**
```bash
npm install # installs root, server/, and shared/ workspaces
npm run server:dev # starts backend on :4001 (SQLite at server/data/tracker.sqlite)
# in another terminal:
REACT_APP_STORAGE=ws \
REACT_APP_BACKEND_URL=http://127.0.0.1:4001 \
REACT_APP_BACKEND_WS=ws://127.0.0.1:4001/ws \
npm start
```
See `docs/DEVELOPMENT.md` for the full architecture (generic KV doc store, storage adapter interface, test layers) and `docs/REWORK_PLAN.md` for the design rationale.
## Project Structure ## Project Structure
<pre> <pre>
@@ -233,21 +269,37 @@ ttrpg-initiative-tracker/
├── .env.example # Example environment variables ├── .env.example # Example environment variables
├── .env.local # Local environment variables (ignored by Git) ├── .env.local # Local environment variables (ignored by Git)
├── .gitignore # Specifies intentionally untracked files that Git should ignore ├── .gitignore # Specifies intentionally untracked files that Git should ignore
├── Dockerfile # Instructions to build the Docker image ├── Dockerfile # Firebase-mode image (frontend-only, served by nginx)
├── package.json # Workspaces root: frontend + server + shared
├── package-lock.json # Records exact versions of dependencies ├── package-lock.json # Records exact versions of dependencies
├── package.json # Project metadata and dependencies
├── postcss.config.js # PostCSS configuration (for Tailwind CSS) ├── postcss.config.js # PostCSS configuration (for Tailwind CSS)
├── tailwind.config.js # Tailwind CSS configuration ├── tailwind.config.js # Tailwind CSS configuration
├── docker/ # Self-hosted deployment: Dockerfile, docker-compose.yml, Caddyfile
├── docs/ # Rework plan, dev setup, testing, encounter-builder guide, glossary
├── scripts/ # Manual demo/ops tooling (e.g. replay-combat.js)
├── tests/ # Exploratory audit tooling (not part of the automated suite)
├── public/ # Static assets ├── public/ # Static assets
│ ├── favicon.ico │ ├── favicon.ico
│ ├── index.html # Main HTML template │ ├── index.html # Main HTML template
│ └── manifest.json │ └── manifest.json
── src/ # React application source code ── src/ # React frontend (Create React App)
├── App.js # Main application component ├── App.js # Main application component
├── index.css # Global styles (including Tailwind directives) │ ├── storage/ # Storage adapter layer: firebase / ws / memory
── index.js # React entry point │ ├── index.css # Global styles (including Tailwind directives)
│ └── index.js # React entry point
├── server/ # Self-hosted backend: Express + ws + SQLite (better-sqlite3)
└── shared/ # Framework-agnostic turn-order logic, used by frontend + server
</pre> </pre>
## Further Reading
* `docs/DEVELOPMENT.md` — setup, running the backend, test suites
* `docs/REWORK_PLAN.md` — why/how the self-hosted backend was added
* `docs/TESTING.md` — test layers and how to run them
* `docs/ENCOUNTER_BUILDER.md` — entity model and storage paths behind the DM interface
* `docs/GLOSSARY.md` — domain terms (turn vs. round, etc.)
* `TODO.md` — known bugs and backlog
## Contributing ## Contributing
If you want to contribute, send me a message here: [https://discourse.draft13.com/c/ttrpg-initiative-tracker/16](https://discourse.draft13.com/c/ttrpg-initiative-tracker/16), and I can add to this Gitea instance and you can feel free to fork the repository and submit pull requests. For major changes, please pose a topic to the Discourse instance above linked above first to discuss what you would like to change. If you want to contribute, send me a message here: [https://discourse.draft13.com/c/ttrpg-initiative-tracker/16](https://discourse.draft13.com/c/ttrpg-initiative-tracker/16), and I can add to this Gitea instance and you can feel free to fork the repository and submit pull requests. For major changes, please pose a topic to the Discourse instance above linked above first to discuss what you would like to change.
+1 -1
View File
@@ -46,7 +46,7 @@ if (typeof document !== 'undefined') {
// CONSTANTS // CONSTANTS
// ============================================================================ // ============================================================================
const APP_VERSION = 'v0.3'; const APP_VERSION = 'v0.4';
const { DEFAULT_MAX_HP, DEFAULT_INIT_MOD, MONSTER_DEFAULT_INIT_MOD, generateId, rollD20, formatInitMod, sortParticipantsByInitiative, syncTurnOrder, computeTurnOrderAfterRemoval } = shared; const { DEFAULT_MAX_HP, DEFAULT_INIT_MOD, MONSTER_DEFAULT_INIT_MOD, generateId, rollD20, formatInitMod, sortParticipantsByInitiative, syncTurnOrder, computeTurnOrderAfterRemoval } = shared;
const ROLL_DISPLAY_DURATION = 5000; const ROLL_DISPLAY_DURATION = 5000;