Deploying¶
Where it runs¶
The hosted demo is one of the six apps in the navase-apps monorepo
(github.com/puneetmanku-tech/navase-apps), deployed as a free Render web
service at navase-universal-crm.onrender.com.
In that monorepo each app is one folder (universal-crm/) containing
backend/ and a pre-built frontend/dist/. A single FastAPI process
(backend/app/serve.py, added by the packaging step) serves the React build
and mounts the API under /api — that's why the production frontend uses
VITE_API_BASE_URL=/api.
Render service¶
| Setting | Value |
|---|---|
| Root directory | universal-crm/backend |
| Build | pip install -r requirements.txt |
| Start | uvicorn app.serve:root --host 0.0.0.0 --port $PORT |
| Health check | /api/health |
| Env | PYTHON_VERSION=3.12.6 |
Auth is dev-auth on the hosted demo (any email, no password) — Supabase env vars are not set. SQLite on the free tier's ephemeral disk, so the workspace re-seeds on every cold start / redeploy — expected for a demo.
Redeploying¶
There is no auto-deploy webhook on navase-apps. After pushing to the repo
you must trigger a deploy manually: Render dashboard → the service → Manual
Deploy → Deploy latest commit.
Building the frontend for the bundle¶
npm run build is tsc -b && vite build. If tsc -b fails on a pre-existing
type error, build with npx vite build directly (esbuild strips types
without checking) and commit frontend/dist/.
A real (non-demo) deployment¶
For an actual tenant you would:
- Set
DATABASE_URLto a managed Postgres (Neon / Supabase / Render Postgres). - Set
SUPABASE_URL+SUPABASE_JWT_SECRET(and the frontendVITE_SUPABASE_*) so auth is real JWT, not dev tokens. - Set the Stripe keys so billing is real.
- Set
CORS_ORIGINS/FRONTEND_URLto the real domain.
No schema migration tool is wired — Base.metadata.create_all() only creates
missing tables. Schema changes to a live Postgres DB must be applied by hand
(or add Alembic).