Typical Project Setup
A Health Universe React app is an ordinary Node project — there's nothing special about the layout beyond installing the SDK and wiring a few build-time settings so it serves correctly behind a path prefix. The react-starter repo is a complete worked example; clone it as a starting point.
Step 1: Create a GitHub Repository
Push your app to a GitHub repository. As with the other runtimes, the repo must be reachable by Health Universe to deploy it.
Step 2: Repo layout
A typical Vite-based React app looks like:
my-clinical-app/
├── package.json # dependencies + build/start scripts (drives runtime detection)
├── vite.config.js # base path + optional dev proxy
├── index.html
└── src/
├── main.tsx # mounts <HUProvider> + your app
├── HUProvider.tsx # wraps HealthUniverseProvider (see "Your First App")
└── … # your components, using the SDK hookspackage.json is the file the platform inspects to identify the runtime. A React (Vite) SPA only needs a build script — the platform serves the build output for you, so no start script is required:
{
"name": "my-clinical-app",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"@health-universe/react": "^0.1.0",
"@tanstack/react-query": "^5.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
}A Next.js or Node app instead needs a
startscript that listens on the port the platform provides (PORT, set to8501) — e.g."start": "next start -p $PORT".
Step 3: Build & run — static SPA vs Node server
How your app runs on Health Universe depends on the framework, and the platform picks the right mode automatically:
React (e.g. Vite) — built as a static SPA. Health Universe runs your
buildstep, then serves the static output (dist/orbuild/) with a single-page-app fallback. There is no long-running server process, and astartscript, if present, is ignored.Next.js / Node — run as a Node server. After the build, Health Universe runs
npm run start, so yourpackage.jsonmust expose astartscript that listens onPORT(8501). Next.js apps also needbasePathconfigured (see Step 5).
Step 4: Runtime auto-detection
When you deploy, Health Universe inspects your repository and auto-detects the runtime from package.json (the deploy "main file" is package.json; in a monorepo it's <your-app-folder>/package.json). You don't choose React/Next.js/Node from a dropdown — the dependencies decide:
a
nextdependency → Next.js (Node server),otherwise a
react/react-domdependency → React (static SPA),otherwise → a plain Node server.
This determines whether the app is served as static assets or run as a Node server.
Step 5: Base-path handling
Deployed apps are served under a path prefix, e.g. https://apps.healthuniverse.com/<slug>/, not a dedicated subdomain. For assets and client-side routing to resolve correctly, your build must know that prefix.
The platform injects the prefix at build time under several names so each framework can read it — VITE_BASE_PATH (Vite), NEXT_PUBLIC_BASE_PATH (Next.js basePath), PUBLIC_URL (CRA), and a bare HU_BASE_PATH. Wire the right one into your build. For Vite:
Client-side routing: strip the trailing slash
If you use a client-side router (React Router, etc.), point its basename at the same prefix — but strip the trailing slash first. Vite's base keeps the trailing slash (/<slug>/) because that's correct for asset URLs, but React Router treats a basename of /<slug>/ as not matching the no-trailing-slash landing URL /<slug> — so the app mounts to a blank page even though every asset loaded fine. Strip it so /<slug>, /<slug>/, and /<slug>/... all match:
This is the most common blank-page-after-deploy cause once you add routing: assets resolve (correct
base), but no route matches the landing URL. Don't useimport.meta.env.BASE_URLfor the basename directly — it carries the same trailing slash. Any in-app URLs you build by hand should still use the un-strippedBASE_URLso asset paths stay correct.
When deployed, Health Universe also injects the API origin and account settings (e.g.
VITE_HU_API_URL,VITE_CLERK_PUBLISHABLE_KEY) at build time, so the SDK is configured for you and the signed-in user is already authenticated — no secrets to manage in your repo for the default deployed setup.
Step 6: Local development against a remote API
To develop against a remote API (staging or a preview) without running a local backend — and without CORS headaches — proxy /api through your dev server and point the SDK at the same origin. With Vite:
Then set VITE_HU_API_URL= (empty → same-origin) and VITE_HU_API_PROXY=https://<staging-host>, and sign in with the matching Clerk development instance (pk_test_…).
If you reinstall the SDK and an import looks stale (
does not provide an export named …), clear the Vite optimize cache (rm -rf node_modules/.vite) and restart the dev server.
Step 7: Commit and deploy
Commit your code, push to GitHub, then deploy via Create → Source Code. See Deploying to Health Universe for the step-by-step deploy flow.
Last updated
Was this helpful?