Deployment
getbased is deployed on Vercel. The browser app is shipped as static files, and Vercel also runs small same-origin API routes fromapi/ for features that need hosted infrastructure. Vercel serves the app files directly, executes those API routes, and injects security headers.
Vercel configuration
vercel.json uses a deploy-time catalog fetch plus the legacy routes array (not rewrites or headers):
User documentation is not built from this repository anymore. It lives in the separate Mintlify docs project at
docs.getbased.health; this app keeps only compatibility redirects for old app.getbased.health/docs/* links.
API routes
Vercel functions live inapi/. They must stay same-origin, minimal, and avoid handling plaintext health data unless a feature explicitly requires it.
/api/share
api/share.js stores password-protected profile share links. The browser builds a single-profile export, encrypts it locally with AES-GCM using a key derived from the user-provided password, and uploads only the encrypted envelope. The password is never sent to the route and is not embedded in the link.
Production requires a Vercel Blob write token configured as a sensitive environment variable. The route uses a private Blob store namespace, caps payload size, rejects shares longer than 30 days, rejects weak PBKDF2 iteration counts, rate-limits anonymous share creation, and returns
no-store JSON responses. The route never has the password or plaintext profile JSON.
Local development mirrors the endpoint in dev-server.js with an in-memory store so the modal and deep-link flow can be smoke-tested without Blob credentials. That local store is process-local and disappears when the dev server restarts.
/api/proxy
api/proxy.js is the controlled same-origin proxy boundary. It exists for browser flows that cannot safely call a third-party endpoint directly from app.getbased.health.
Current responsibilities:
- wearable runtime configuration and OAuth helper calls where client IDs/secrets must not be hardcoded into docs;
- CAMS/light-data relay paths used by Sun & Light calculations;
- Custom API proxying with public-host and allowlist checks so it cannot become a general SSRF tunnel;
- CORS and method handling for the app’s own allowed origins.
/api/commit
api/commit.js returns the deployed app identity used by smoke checks, diagnostics, and “which build am I looking at?” debugging. Keep it cheap, no-store, and free of private deployment-provider details.
Domain layout
The app and landing page are deployed as two separate Vercel projects on the same domain:
DNS points the root, app, and www hostnames at the Vercel projects. Keep provider-specific DNS account details out of public docs.
The landing page is self-contained (all CSS/JS inline) and depends only on three icon files. CTA links point to
https://app.getbased.health. A small inline script rewrites these to /app on localhost for local development.
Local dev server
node dev-server.js mirrors the production layout. If the site repo is cloned as a sibling (../get-based-site), the server routes:
Without the sibling repo,
/ serves the app directly. Override the site path with SITE_DIR=/path/to/site node dev-server.js.
CSP headers
The Content-Security-Policy allows what the current app needs:'unsafe-inline' is required for scripts because index.html has inline bootstrapping and legacy window-exported action hooks. 'wasm-unsafe-eval' and blob: are needed for in-browser model/vector/worker paths such as local Knowledge Base and private transports.
Most JS libraries are bundled locally in vendor/, but the CSP currently permits https://cdn.jsdelivr.net for explicitly allowed browser-runtime dependencies. Run ./update-vendor.sh when bumping vendored assets, and update vercel.json whenever a provider or runtime dependency needs a new host.
localhost:* and 127.0.0.1:* in connect-src allow plain HTTP Local AI servers on the same machine. The general https: source permits HTTPS LAN and remote compatible endpoints. A plain HTTP LAN endpoint such as http://192.168.x.x is blocked from the hosted HTTPS app by browser mixed-content rules; this is separate from CORS and cannot be relaxed by changing the CSP alone. An encrypted tunnel or HTTPS reverse proxy is required.
If a new AI provider, wearable provider, private transport, worker runtime, or relay host is added, review connect-src, script-src, service-worker bypass rules, and api/proxy.js together.
vercel.json also sets Onion-Location for Tor discovery and Link service descriptors for /.well-known/mcp.json and /.well-known/agent-skills/index.json.
Service worker
The service worker (service-worker.js) manages PWA caching. The cache name includes a version number:
The API bypass is critical for streaming. If the service worker intercepts a streaming SSE response, the IPC pipe between the SW and the page buffers the chunks, breaking the streaming experience. The bypass (returning without calling
event.respondWith) routes requests directly to the network. Local/private hosts are bypassed only when they are cross-origin, so same-origin app-shell requests can still be cached. Normal localhost development unregisters the SW to avoid stale module caches; use /app?dev-sw=1 for an explicit local offline smoke test.
PWA manifest
manifest.json makes the app installable as a native app on desktop and mobile:
Vendor dependencies
Chart.js, pdf.js, and Google Fonts are bundled locally invendor/. To update:
- Edit the version pins at the top of
update-vendor.sh - Run
./update-vendor.sh - Bump
version.jsto bust the SW cache - Commit the updated
vendor/directory