- TypeScript 64.8%
- CSS 26.8%
- JavaScript 5.4%
- Nix 2.5%
- HTML 0.5%
- Add ExerciseStatus type (active/mastered/future/outdated) and ExerciseConfig - Persist user status overrides via /api/exercise-config endpoint + exercise-config.json - Add useExerciseConfig hook with resolvedStatus() merge logic - Add seated-heel-raise exercise (strengthening, active by default) - Set default statuses: seated-foot-flat→mastered, heel-raises/single-leg/eccentric→future - Library page: flat list with 4 toggle filter buttons, natural order - ExerciseCard: status badge in header, status picker in expanded body - Today page: show active+mastered as 'Current exercises / Exercices du moment' - Only future/outdated cards are dimmed in library view |
||
|---|---|---|
| deploy | ||
| public | ||
| src | ||
| .env.example | ||
| .gitignore | ||
| CLAUDE.md | ||
| eslint.config.js | ||
| exercise-config.json | ||
| flake.lock | ||
| flake.nix | ||
| index.html | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| server.mjs | ||
| tsconfig.app.json | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| vite.config.ts | ||
regait
A play on "regain" and "gait"
A personal recovery log built during rehabilitation from a Grade 2 calf strain. The app tracks daily exercises and habits, visualizes progress over time, and provides guided exercise instructions to support a structured recovery routine.
Disclaimer: This project is vibe-coded by someone with no prior React knowledge, assisted by AI. It is intended for personal use only — there is no authentication, no multi-user support, and no production hardening.
Features
- Log daily exercises and recovery habits
- Dashboard with progress visualization (habit compliance, exercise history)
- Exercise library with instructions and motion cues
- Daily standing instructions (e.g. avoid prolonged static posture)
Dev
Prerequisites
The development environment is managed with Nix flakes. No manual Node installation needed.
nix develop
This drops you into a shell with Node.js 22 available.
Running the app
The app has two processes running concurrently: the Vite dev server (frontend) and a local JSON-backed data server (backend).
npm install # first time only
npm run dev
- Frontend:
http://localhost:5173 - Data server:
http://localhost:3001(default)
Note on nix: If running commands from outside the nix shell, prefix with:
nix develop --command bash -c "<command>"
Environment variables
Create a .env file at the project root to override defaults:
SERVER_PORT=3001 # port for the data server
DATA_FILE=./regait-data.json # path to the local JSON data store
regait-data.json is the only persistence layer — it lives locally on disk and is not committed to the repository.
Tech stack
| Layer | Technology |
|---|---|
| Frontend framework | React 19 + TypeScript |
| Build tool | Vite |
| Charts | Recharts |
| Backend | Node.js HTTP server (no framework) |
| Data store | Local JSON file |
| Dev environment | Nix flakes (Node.js 22) |
| Linting | ESLint + typescript-eslint |
Deployment
The app ships as a single reproducible OCI image built by Nix (amd64 /
x86_64-linux), run under rootless podman via quadlet units. In production a
single Node process serves both the built frontend and the /api/logs endpoint
on one port.
Caution
Authentication and TLS are out of scope for this repo. The container publishes no host port; it joins a shared (internal) podman network and a reverse proxy (behind Authelia) on that same network forwards authenticated traffic to
http://regait:3001. The server binds to all interfaces, so it also works with host port publishing if you prefer that topology.
1. Build the image
The image contains only Node 22 + the built dist/ + server.mjs (no
node_modules — the backend uses Node built-ins only).
nix build .#image && ./result | podman load # → localhost/regait:latest
.#image is a streamLayeredImage builder: nix build produces a script
(./result) that streams the image tarball to stdout, which podman load reads.
To build elsewhere and ship the tarball to the VPS:
nix build .#image && ./result > regait.tar
scp regait.tar vps: # then on the VPS:
podman load < regait.tar
Note
If
package-lock.jsonchanges, setnpmDepsHashinflake.nixtopkgs.lib.fakeHash, runnix build .#regait, and copy the correct hash from the mismatch error.
2. Install the quadlet units (rootless)
Sample quadlet units are provided in the deploy directory. If you know quadlet, this is straightforward, if you do not, there is no interest then write a docker-compose.yml