Public Access
184 lines
4.5 KiB
Markdown
184 lines
4.5 KiB
Markdown
# VYTA
|
|
|
|
**VYTA** is a self-hosted health dashboard for Garmin data. It turns activity, sleep, recovery and training signals into a private daily overview with VYTA Age, pace of aging, training load, sleep insights, push notifications and local Garmin sync.
|
|
|
|
The project is built for people who want the feel of a polished health app without sending their personal health archive to a third-party dashboard.
|
|
|
|
## What It Does
|
|
|
|
- **VYTA Age**: a dynamic healthspan-style score based on VO2max, resting heart rate, HRV, sleep, steps and training signals.
|
|
- **Healthspan view**: weekly period display, animated orb, pace of aging and contributor breakdowns.
|
|
- **Today view**: Garmin-based recovery, strain, activity, sleep and energy summaries.
|
|
- **Sleep view**: sleep score, duration, sleep debt and sleep phase details.
|
|
- **Training view**: daily load, activity list, activity details and trend charts.
|
|
- **Notifications**: optional push alerts for recovery, HRV deviation, sleep, new activities, VYTA Age changes and more.
|
|
- **Garmin account setup in app**: each installation can connect its own Garmin account from settings.
|
|
- **Private local data**: runtime data, Garmin credentials and token stores are kept outside Git.
|
|
|
|
## Repository Layout
|
|
|
|
```text
|
|
app/vyta/ Next.js web app
|
|
sync/vyta-sync/ Python Garmin collector, normalizer and scheduler
|
|
```
|
|
|
|
Runtime data belongs outside the repository, normally in `/data` inside the containers and mounted from your server, for example:
|
|
|
|
```text
|
|
/mnt/tank/appdata/vyta/data
|
|
```
|
|
|
|
## Privacy Model
|
|
|
|
This repo intentionally does **not** include personal data or secrets.
|
|
|
|
Never commit:
|
|
|
|
```text
|
|
.env
|
|
.env.local
|
|
data/
|
|
private-data/
|
|
public/data/
|
|
garmin-credentials.json
|
|
.garmin_tokens/
|
|
vyta-garmin.json
|
|
vyta-data.json
|
|
settings.json
|
|
push-subscriptions.json
|
|
notification-state.json
|
|
```
|
|
|
|
Garmin credentials are saved by the app to:
|
|
|
|
```text
|
|
/data/garmin-credentials.json
|
|
```
|
|
|
|
Garmin session tokens are saved by the sync service to:
|
|
|
|
```text
|
|
/data/.garmin_tokens/
|
|
```
|
|
|
|
Both paths should be Docker volumes, not repository files.
|
|
|
|
## Configuration
|
|
|
|
The web container expects environment variables for authentication, public URL, push notifications and internal sync communication.
|
|
|
|
Common web variables:
|
|
|
|
```text
|
|
VYTA_PUBLIC_URL
|
|
VYTA_USERNAME
|
|
VYTA_PASSWORD_HASH
|
|
VYTA_SESSION_SECRET
|
|
VYTA_DATA_PATH=/data/vyta-data.json
|
|
VYTA_SETTINGS_PATH=/data/settings.json
|
|
VYTA_PUSH_SUBSCRIPTIONS_PATH=/data/push-subscriptions.json
|
|
VYTA_SYNC_STATUS_PATH=/data/sync-status.json
|
|
VYTA_SYNC_REQUEST_PATH=/data/sync-request.json
|
|
VYTA_INTERNAL_SYNC_SECRET
|
|
NEXT_PUBLIC_VAPID_PUBLIC_KEY
|
|
VAPID_PRIVATE_KEY
|
|
VAPID_SUBJECT
|
|
```
|
|
|
|
Common sync variables:
|
|
|
|
```text
|
|
VYTA_WEB_URL
|
|
VYTA_INTERNAL_SYNC_SECRET
|
|
VYTA_OUTPUT_PATH=/data/vyta-data.json
|
|
VYTA_SYNC_INTERVAL_SECONDS=300
|
|
VYTA_SYNC_POLL_SECONDS=2
|
|
VYTA_SYNC_STATUS_PATH=/data/sync-status.json
|
|
VYTA_SYNC_REQUEST_PATH=/data/sync-request.json
|
|
VYTA_GARMIN_CREDENTIALS_PATH=/data/garmin-credentials.json
|
|
VYTA_GARMIN_TOKENSTORE=/data/.garmin_tokens
|
|
TZ=Europe/Stockholm
|
|
```
|
|
|
|
## Build
|
|
|
|
Web app:
|
|
|
|
```bash
|
|
docker build -t vyta-web:latest app/vyta
|
|
```
|
|
|
|
Sync service:
|
|
|
|
```bash
|
|
docker build -t vyta-sync:latest sync/vyta-sync
|
|
```
|
|
|
|
## Run Example
|
|
|
|
Web:
|
|
|
|
```bash
|
|
docker run -d \
|
|
--name vyta \
|
|
--restart unless-stopped \
|
|
-p 3777:3000 \
|
|
-v /mnt/tank/appdata/vyta/data:/data \
|
|
--env-file /path/to/vyta.env \
|
|
vyta-web:latest
|
|
```
|
|
|
|
Sync:
|
|
|
|
```bash
|
|
docker run -d \
|
|
--name vyta-sync \
|
|
--restart unless-stopped \
|
|
-v /mnt/tank/appdata/vyta/data:/data \
|
|
--env-file /path/to/vyta-sync.env \
|
|
vyta-sync:latest
|
|
```
|
|
|
|
## Garmin Setup
|
|
|
|
1. Start the web app.
|
|
2. Sign in to VYTA.
|
|
3. Open **Inställningar**.
|
|
4. Connect Garmin under **Garmin-konto**.
|
|
5. The app stores credentials in `/data/garmin-credentials.json` and triggers sync.
|
|
6. The sync service uses `/data/.garmin_tokens/` after the first successful login.
|
|
|
|
Each clone or deployment can connect its own Garmin account without changing the code.
|
|
|
|
## Development
|
|
|
|
Web app:
|
|
|
|
```bash
|
|
cd app/vyta
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
Sync service:
|
|
|
|
```bash
|
|
cd sync/vyta-sync
|
|
python -m venv .venv
|
|
. .venv/bin/activate
|
|
pip install -r requirements.txt
|
|
python sync.py
|
|
```
|
|
|
|
## Roadmap
|
|
|
|
- Language selection in settings: Swedish and English UI.
|
|
- More install-friendly Docker Compose template.
|
|
- Better onboarding for first-time Garmin setup.
|
|
- Optional multi-user support.
|
|
- More Healthspan contributor tuning as more Garmin signals become available.
|
|
|
|
## Status
|
|
|
|
VYTA is a personal, self-hosted health app. It is not a medical device and does not provide clinical advice.
|