Skip to main content
getbased loads native ES modules during local development. Production deployments run a Rolldown build that creates a hashed startup bundle and keeps feature-level lazy chunks separate. The resulting runtime is still mostly static HTML, CSS, and JavaScript, plus optional API routes for hosted features.

Quick start

1

Clone the repository

2

Start a local server

Open http://localhost:8000/app in your browser. The dashboard runs immediately.
Use node dev-server.js for wearable OAuth and other features that depend on /api/proxy. A static server such as python3 -m http.server 8000 is sufficient only for browser-local features; it cannot load deployment OAuth settings or exchange confidential OAuth tokens, so Google Health remains unavailable there.
The quick local server loads source modules directly, so this path needs no npm install or compile step. Production deployments install dependencies and run node scripts/build-production.mjs; Vercel does this through the repository’s existing build command. The app is installable as a PWA and works fully offline for browser-local features — labs, charts, custom markers, already-imported wearable data, and local encryption are available without a network connection after the first load. OAuth connection, token refresh, and live wearable sync still require the provider network and the deployment’s server routes.

Wearable OAuth apps

The OAuth client_id values baked into the app belong to the maintainer’s registered apps, which are authorized for *.getbased.health redirect URIs only. If you self-host under a different domain, the provider returns invalid_client when the bundled credentials are paired with your redirect URI. To run wearable OAuth on your own host, register your own OAuth app with each provider you want to support and supply the credentials via environment variables.

Register your OAuth apps

When registering, add both your local dev redirect URI (http://localhost:8000/app) and your production hostname (e.g. https://your-host.example/app) to the allowed redirect URI list in each provider’s portal — the URIs must match character-for-character. For a custom hostname that is not already listed, add the same URI to that provider’s oauth.redirectUris entry in js/wearable-adapters.js in your fork.

Environment variables

Create a .env.local file in the repo root (copy .env.local.example as a starting point):
Apple Health is file-import only — no OAuth, no credentials, no portal registration. It works identically on every self-hosted install.
At startup, the browser fetches active public client_id values and provider availability flags from /api/proxy. Google Health, WHOOP, and Ultrahuman are fail-closed: each is available only when its *_ENABLED value is exactly true and its client ID and secret are all present. Only the public client ID and availability flag reach the browser; each client secret stays on the server and is injected during token exchange and refresh. WHOOP and Ultrahuman are experimental self-host integrations. They are hidden on hosted deployments that have not enabled them. On localhost, their disabled setup rows remain visible so an operator can find the required configuration; Connect appears only after the server reports a complete, enabled setup.
Google Health uses restricted, read-only OAuth scopes. The owner of each self-hosted Google Cloud project is responsible for the OAuth consent screen, verification, testing-user limits, and any Cloud App Security Assessment that Google requires. Do not reuse the official getbased OAuth project. See Google Health setup for current requirements.
The integration requests only these scopes:
  • https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly
  • https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly
  • https://www.googleapis.com/auth/googlehealth.sleep.readonly
A copy-ready explanation for Google’s How will the scopes be used? field is kept under 1,000 characters in google-health-scope-justification.md.
Google currently caps a new unverified OAuth client at 100 users. Testing mode requires each tester to be added explicitly, and its refresh tokens expire after seven days. Supporting more than 100 users requires a third-party security review. Check Google’s setup page before launch because these requirements can change.

Deploying to Vercel

A vercel.json is already present in the repo root — no extra configuration is needed.
1

Import the repository on Vercel

In the Vercel dashboard, click Add New → Project and import your fork of get-based. Vercel detects vercel.json automatically.
2

Set environment variables

Go to Project → Settings → Environment Variables and add your wearable credentials. Mark each *_CLIENT_SECRET value as Sensitive. Google Health, WHOOP, and Ultrahuman each require their enable flag, client ID, and secret.
3

Deploy

Vercel builds and deploys on every push to your default branch. The app runs at your Vercel project URL immediately after the first deploy.
For a basic self-hosted install, no additional build configuration is needed — the app runs out of the box with the example supplement catalog included in the repo.

Running your own sync relay

Cross-device sync uses a relay — a blind store-and-forward server that holds encrypted blobs. The relay never sees your plaintext data. By default, getbased connects to wss://sync.getbased.health. You can run your own.
1

Clone the relay

getbased-relay wraps Evolu’s sync protocol with configurable quotas, health checks, metrics, and owner-signed storage recovery.
Review docker-compose.yml before starting it. In particular, set QUOTA_PER_OWNER_MB to the encrypted-history allowance you want each Sync identity to have.
2

Start the relay

The default compose file starts the WebSocket relay on port 4000, the loopback-only owner self-service API on port 4003, and persists the SQLite database in a Docker volume.
3

Add TLS with Caddy

Install Caddy and create /etc/caddy/Caddyfile:
The versions h1 directive is required — WebSocket upgrades need HTTP/1.1. Restart Caddy:
Caddy provisions a TLS certificate via Let’s Encrypt automatically.
4

Point DNS

Add an A record for sync.yourdomain.com pointing to your server’s IP address.
5

Point getbased at your relay

In getbased, open Settings → Data → Cross-device sync → Advanced, enter wss://sync.yourdomain.com, and click Save. Use Sync status & storage to verify both relay connectivity and the configured quota.
A small Linux VPS with 1 CPU, 1 GB RAM, Docker, persistent storage, and a domain with TLS is sufficient for a personal relay. Monitor disk usage and keep regular backups of the relay volume.
Do not expose the admin port or SQLite database volume publicly. Route /self/* through the same TLS hostname as the WebSocket relay; those endpoints verify owner signatures and let the app report or rebuild only the caller’s own encrypted history.

Local AI with a self-hosted instance

getbased supports Ollama, LM Studio, Jan, llama.cpp, and other OpenAI-compatible servers through Settings → AI → Local AI. Enter the server’s base URL and getbased sends AI calls directly from the browser to that endpoint. Privacy depends on the address and model you choose. A loopback endpoint with a downloaded model keeps inference on the browser device. A LAN server moves requests to another machine, while a remote endpoint or Ollama :cloud model sends them off your network. getbased shows the detected execution location in the provider panel.
The page and model-server schemes must satisfy browser mixed-content rules. An HTTPS getbased page can use an HTTP loopback endpoint, but the browser blocks plain HTTP LAN and remote endpoints. Put the model server behind HTTPS or an encrypted local tunnel. A getbased instance served over plain HTTP can call an HTTP LAN server when CORS allows the page origin, but the traffic itself is unencrypted unless a VPN or tunnel protects it.
Allow the exact getbased origin in your model server’s CORS configuration. For example, a self-hosted page at http://192.168.1.20:8000 should use that origin instead of * in OLLAMA_ORIGINS. LM Studio users should enable CORS and API authentication. See Connect an AI provider for backend detection, context and VRAM behavior, and model-testing links.

Tor access

A .onion address is available for getbased. When you access the app via Tor Browser, the sync relay automatically switches to the .onion address (ws:// — no TLS needed over Tor’s end-to-end encryption). No additional configuration is required.