No description
  • TypeScript 64.8%
  • CSS 26.8%
  • JavaScript 5.4%
  • Nix 2.5%
  • HTML 0.5%
Find a file
muffie be5ab68e08 feat(exercises): add status system with filter, seated heel raise, and current exercises view
- 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
2026-05-24 11:02:10 +02:00
deploy build(deploy): flake+OCI building 2026-05-23 11:19:29 +02:00
public chore: init react+vite+ts scaffold with nix dev env 2026-05-21 17:48:16 +02:00
src feat(exercises): add status system with filter, seated heel raise, and current exercises view 2026-05-24 11:02:10 +02:00
.env.example feat(storage): replace localStorage with file-backed JSON server 2026-05-21 19:37:27 +02:00
.gitignore build(deploy): flake+OCI building 2026-05-23 11:19:29 +02:00
CLAUDE.md feat(i18n): add French/English language switch 2026-05-22 23:40:37 +02:00
eslint.config.js chore: init react+vite+ts scaffold with nix dev env 2026-05-21 17:48:16 +02:00
exercise-config.json feat(exercises): add status system with filter, seated heel raise, and current exercises view 2026-05-24 11:02:10 +02:00
flake.lock chore: init react+vite+ts scaffold with nix dev env 2026-05-21 17:48:16 +02:00
flake.nix build(deploy): flake+OCI building 2026-05-23 11:19:29 +02:00
index.html chore: init react+vite+ts scaffold with nix dev env 2026-05-21 17:48:16 +02:00
package-lock.json feat(i18n): add French/English language switch 2026-05-22 23:40:37 +02:00
package.json feat(i18n): add French/English language switch 2026-05-22 23:40:37 +02:00
README.md build(deploy): flake+OCI building 2026-05-23 11:19:29 +02:00
server.mjs feat(exercises): add status system with filter, seated heel raise, and current exercises view 2026-05-24 11:02:10 +02:00
tsconfig.app.json chore: init react+vite+ts scaffold with nix dev env 2026-05-21 17:48:16 +02:00
tsconfig.json chore: init react+vite+ts scaffold with nix dev env 2026-05-21 17:48:16 +02:00
tsconfig.node.json chore: init react+vite+ts scaffold with nix dev env 2026-05-21 17:48:16 +02:00
vite.config.ts feat(storage): replace localStorage with file-backed JSON server 2026-05-21 19:37:27 +02:00

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.json changes, set npmDepsHash in flake.nix to pkgs.lib.fakeHash, run nix 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