Dev setup (all three)¶
The three apps share a stack, so this page covers all of them. Where the setup diverges (backend port, native scraper, DuckDB), it is called out per app.
Prerequisites¶
-
Node 20 (the Docker base image is
node:20-alpinefor CookTrace and LiftTrace,node:20-slimfor NutriTrace). Older Node majors will occasionally build but are not tested. nvm is the easy path: -
Git, plus a GitHub account if you plan to open a PR.
- Python 3 on your host if you want CookTrace's recipe-scrapers tier to run outside Docker. Not required for LiftTrace or NutriTrace.
- JDK 17 + Android Studio only if you plan to build the Android app. Not needed for backend or PWA work.
Clone the app you want to work on¶
Each app lives in its own repo under TraceApps on GitHub. Clone the one you want, then check out the dev branch (everything lands on dev first; main is squash-merged release commits only).
Ports¶
| App | Vite dev server | Backend Express |
|---|---|---|
| CookTrace | :5175 |
:3001 |
| LiftTrace | :5173 |
:3003 |
| NutriTrace | :5173 |
:3001 |
Vite falls forward if a port is already taken (:5174, :5175), so if you run two apps side by side, check the terminal for the real URL.
Two dev flows¶
Both flows work for all three apps. Pick based on what you are changing.
Path A: Vite dev server with API proxy¶
Fast HMR, but the frontend runs on a separate origin (:5173 or :5175) from the backend (:3001 or :3003). Vite proxies /api and /uploads through to the backend. Handy for iterating on markup and Svelte components.
Open the Vite URL that the second terminal prints.
Path B: Single-origin build¶
Build the frontend, drop it into server/dist, and let Express serve the built bundle. This matches exactly what the production Docker image does, so it is the reliable path when you want to verify a branch end to end.
Open http://localhost:3001 (or :3003 on LiftTrace). Re-run all three lines after any frontend change; the server templates dist/index.html at startup, so a rebuild needs a server restart to be picked up. Backend-only changes just need the server restarted.
Blank page in Path A
A stale PWA service worker will keep serving the previous shell even though your new build is on disk. Open DevTools, unregister the service worker, clear site data, hard-reload. If that does not fix it, switch to Path B; single-origin sidesteps the whole class of problem.
Per-app quirks¶
CookTrace has a Python tier for recipe scraping (recipe-scrapers, 300+ site-specific extractors). The Docker image bakes python3 and the library in. Locally, set PYTHON_BIN=python3 (or the full path to a venv) and install the library yourself: pip install recipe-scrapers. Without it, imports fall back to schema.org JSON-LD only.
LiftTrace builds pre-rendered rest-cue audio tones on first Android build via npm run build:rest-tones. It runs automatically as part of npm run android, android:run, and android:debug. If you only run vite build, the tones will be missing from the APK; use one of the android:* scripts instead.
NutriTrace uses node:20-slim (Debian) rather than Alpine because DuckDB (Open Food Facts local mirror) needs glibc. Local dev on Alpine or musl-libc distros will hit Error loading shared library ld-linux-x86-64.so.2 when the OFF mirror layer tries to load. On glibc-based Linux, macOS, and Windows this is a non-issue.
Android debug builds¶
Every app has an android:debug (LiftTrace) or android:apk:debug (CookTrace, NutriTrace) script that produces an unsigned APK at android/app/build/outputs/apk/debug/app-debug.apk.
Wireless ADB is the smoothest handset workflow. Enable Developer options > Wireless debugging on the phone, pair it once (the rotating port shows in the phone's Wireless debugging panel), then:
adb connect <phone-lan-ip>:<port>
adb -s <phone-lan-ip>:<port> install -r android/app/build/outputs/apk/debug/app-debug.apk
Debug builds are exempt from Android's cleartext-traffic ban, so they can talk to a plain http:// server on your LAN. Release builds cannot; see HTTPS on the LAN for the fix.
Commit and PR conventions¶
- Short one-line commit messages. Body only for architectural notes.
- Do not add
Fixes #NNorCloses #NNtrailers without asking; the maintainer prefers to close issues by hand after a release lands. - No DCO, no CLA. Just open the PR against
dev. - If your change touches user-facing strings, add them to
src/i18n/en.jsonin the same commit. See Translations (i18n). - If your change adds a Settings-panel field, add matching keywords to
SECTION_KEYWORDSinsrc/routes/Settings.svelteso the in-Settings search finds it.