Compare commits
3 Commits
rework-backend
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ec578eeef5 | |||
| c54fd88c32 | |||
| e31fe15382 |
+4
-1
@@ -7,8 +7,11 @@ LABEL stage="build-local-testing"
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy package.json and package-lock.json (or yarn.lock)
|
# Copy root package.json/lockfile plus workspace manifests so npm can
|
||||||
|
# resolve the @ttrpg/shared and server workspace links during install.
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
|
COPY shared/package.json ./shared/
|
||||||
|
COPY server/package.json ./server/
|
||||||
|
|
||||||
# Install dependencies using the lock file for consistency
|
# Install dependencies using the lock file for consistency
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# TTRPG Initiative Tracker (v0.2.5)
|
# TTRPG Initiative Tracker (v0.4)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||

|

|
||||||
@@ -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
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user