SovereignStrength is documented as a self-hosted local-first application with:
- static frontend files
- Flask API backend
- Python dependencies are installed from
app/backend/requirements.txt - The repository root
requirements.txtis only a wrapper to that authoritative backend file - local JSON storage
- Gunicorn
- systemd
- unix socket communication
/var/www/sovereign-strength/
Expected files:
index.htmlapp.jsstyles.css
/opt/sovereign-strength-api/
Expected entry point:
app.py
/var/www/sovereign-strength/data/
Runtime JSON data lives under:
/var/www/sovereign-strength/data/
This path is operationally sensitive.
It contains live application state such as:
- check-ins
- workouts
- session results
- user settings
- adaptation state
That means frontend deploy workflow must not treat the live web root as a disposable static-output directory.
Do not run a frontend deploy like this against the live root:
rsync -av --delete app/frontend/ /var/www/sovereign-strength/
Why this is dangerous:
app/frontend/is only the frontend source subtree/var/www/sovereign-strength/is not a frontend-only target- the live root may also coexist with runtime-sensitive paths and files
--deletecan therefore remove data or other live files that are not present in the frontend source tree
Deploy frontend files explicitly and without destructive delete semantics against the live root.
Documented safe path:
- use
scripts/deploy_frontend_safe.sh
This script intentionally:
- deploys only repo-managed frontend files
- avoids broad destructive sync against the live root
- checks that runtime-sensitive live directories such as
assets/anddata/still exist after deploy
Current managed frontend file list in the safe script:
index.htmlapp.jsi18n/da.jsoni18n/en.json
If additional frontend-managed files are added later, update the script in the same change.
Do not use broad --delete sync against /var/www/sovereign-strength/.
Backend deploy should update the live backend entry point directly:
- source:
app/backend/app.py - target:
/opt/sovereign-strength-api/app/backend/app.py
Then restart:
sovereign-strength-api.service
Runtime catalog files must stay aligned with seed files used by selector logic.
Primary operational sync path:
python3 scripts/init_catalog_from_seed.py
This script:
- copies
app/data/seed/programs.jsoninto/var/www/sovereign-strength/data/programs.json - copies
app/data/seed/exercises.jsoninto/var/www/sovereign-strength/data/exercises.json - creates timestamped backups of existing live catalog files before overwrite
- verifies that live
programs.jsoncontains required selector metadata for strength programs
Available admin alternative:
POST /api/admin/reset-catalog
Use the script for normal server-side maintenance and deploy recovery. Use the admin endpoint only when an authenticated operational reset through the running app is explicitly intended.
After deploy, verify at minimum:
- frontend files are present in the expected live locations
- i18n files are present under
/var/www/sovereign-strength/i18n/ - runtime data still exists under
/var/www/sovereign-strength/data/ - live
programs.jsoncontains selector metadata keys such assupported_weekly_sessionsandequipment_profiles - backend service is active
GET /api/healthreturns healthy- at least one core user flow still works
A bad frontend deploy can require runtime data restore.
A known restore source used in practice was:
/home/jakob/backups/sovereign-strength-deploy-20260320-055123/data/
The operational lesson is simple:
- static frontend deploy is not allowed to casually touch runtime data
- restore is recovery, not a normal deploy step
The documented backend runtime consists of:
- Flask application
- Gunicorn process manager
- systemd unit
- unix socket
Documented service name:
sovereign-strength-api.service
Documented socket path:
/home/jakob/nextcloud/nginx/html/strength-api.sock
The documented login endpoint is:
POST /auth/login
Session handling is cookie-based.
Authenticated users can:
- fetch plan data
- register workouts
- fetch progression data
The documented planning endpoint is:
GET /plan/today
Documented decision mode:
fatigue_primary_v1
Documented inputs include:
- readiness
- fatigue
- days since last strength session
- time budget
The current documented plan variants are:
short_20short_30light_strength
Example documented rule:
- if
fatigue_score >= 2, uselight_strength
A healthy deployment should allow the following:
- frontend loads correctly
- authenticated session works
GET /plan/todayresponds as expected- workout data can be written to JSON
- progression decisions are explainable
- no external APIs are required for core behavior
This file should describe actual deployment, not desired deployment.
If the socket path, service name, reverse proxy path, or file locations change, update this document in the same commit. Because future-you is not a mystical being with telepathic access to old server states.