Skip to main content
The backend self-hosting guide gets the Flexprice API and its infrastructure running. This guide covers the other half: running the Flexprice dashboard (flexprice-front) yourself and pointing it at that backend.
Complete the backend self-hosting guide first. The frontend is a static single-page app that talks to the API over HTTP; it has no database or infrastructure of its own.

Self-hosting options

Docker Compose

Run the dashboard in a container alongside your self-hosted backend. Best for a single server.

Manual build

Build static files with npm run build and serve them with nginx or any static host.

Vercel

Deploy the same repo to Vercel using the bundled vercel.json.

Self-hosted environment configuration

Before you build or deploy anything, set these. They’re the three variables that actually change how the app behaves in a self-hosted setup, and getting them wrong is the single most common way this deployment breaks:
VariableSelf-hosted valueWhy
VITE_APP_ENVself-hostedSwitches the dashboard’s auth flow to call your backend’s own /auth/login and /auth/signup endpoints directly, and stores the session token in the browser instead of using Supabase. Without this, the app expects a Supabase project to exist.
VITE_AUTH_PROVIDERflexpriceConfirms the dashboard is using Flexprice’s own auth rather than Supabase, and hides Supabase-only UI (Google sign-in, cloud announcement banners) that don’t apply to a self-hosted instance.
VITE_API_URLhttp://<your-backend-host>:8080/v1Points the dashboard at your self-hosted API. See Connecting to the backend for what “reachable” means here.
The .env.example file defaults VITE_AUTH_PROVIDER to supabase and leaves VITE_APP_ENV unset (which falls back to local). If you skip setting these two values, login and signup will silently try to reach Supabase instead of your backend.
With VITE_APP_ENV=self-hosted set, you do not need to fill in VITE_SUPABASE_URL or VITE_SUPABASE_ANON_KEY — leave them blank.
Vite bakes every VITE_* variable into the static bundle at build time, not at container start. Whenever you change .env, you must rebuild (docker compose up -d --build, or npm run build again) before the change takes effect. This trips people up more than anything else in this guide, see Troubleshooting.

Full environment variable reference

VariableSelf-hosted valueNotes
VITE_APP_ENVself-hostedSee above. Also accepts local, development, production for other setups.
VITE_API_URLYour backend’s API URL, e.g. http://localhost:8080/v1Must be reachable from the browser, not just the server.
VITE_AUTH_ENABLEDtrueSet this regardless; the dashboard always requires login. Kept for forward compatibility.
VITE_AUTH_PROVIDERflexpriceUse Flexprice’s built-in auth instead of Supabase.
VariableSelf-hosted valueNotes
VITE_SUPABASE_URLLeave blankOnly used when VITE_AUTH_PROVIDER=supabase.
VITE_SUPABASE_ANON_KEYLeave blankSame as above.
VariableRecommended for self-hostedNotes
VITE_SENTRY_ENABLEDfalse unless you run your own SentrySet VITE_SENTRY_DSN if enabled.
VITE_POSTHOG_ENABLEDfalse unless you run your own PostHogSet VITE_POSTHOG_KEY / VITE_POSTHOG_HOST if enabled.
VITE_REO_ENABLEDfalseCloud session-replay integration; not relevant for self-hosted.
VariableSelf-hosted valueNotes
VITE_PADDLE_ENABLEDfalsePaddle checkout is used by Flexprice Cloud billing, not applicable when you self-host.
VITE_INTERCOM_ENABLEDfalseFlexprice Cloud support widget.
VariableSelf-hosted valueNotes
VITE_WEBHOOK_PROVIDERflexpriceUses the custom Flexprice webhook portal instead of hosted Svix. Set to svix only if you’re self-hosting Svix yourself.
VITE_SVIX_URLPublic origin of your self-hosted Svix API, or leave blankOnly needed if you run Svix yourself and set VITE_WEBHOOK_PROVIDER=svix.
VariableSelf-hosted valueNotes
VITE_DASHBOARD_URL_INDIA / VITE_DASHBOARD_URL_USLeave blankUsed to route between Flexprice Cloud regions; not applicable to a single self-hosted instance.
VITE_DATA_REGION_SELECTION_ENABLEDfalseSame as above.
VITE_RESTRICTED_ENVSLeave blankUsed by Flexprice Cloud to suspend tenant environments.
VITE_TENANT_FEATURE_ALLOWLISTLeave blankGates cloud-only UI for specific tenants; irrelevant when you’re the only tenant.
VariableNotes
VITE_GOOGLE_SHEETS_WEB_APP_URLOnly needed if you use the Google Sheets export integration.
VITE_FONT_CONFIGOptional JSON override for dashboard typography, e.g. {"primary":"Inter","fallback":"ui-sans-serif, system-ui, sans-serif"}. Omit to use the default font.

First login: create your account

A self-hosted instance starts with no dashboard users. There’s no default username or password: every account, including your first one, is created through Sign Up against your own backend:
1

Open the dashboard

Once your container or dev server is running, visit it in a browser (e.g. http://localhost:3000).
2

Use Sign Up, not Login

On the auth screen, switch to the Sign Up tab and enter an email and password (6+ characters).
3

You're in immediately

In self-hosted mode, sign-up skips email verification entirely: the app posts straight to your backend’s /auth/signup endpoint and logs you in right away using the returned session token. There’s no confirmation email to wait for.
If Sign Up fails with a network or CORS error instead of a validation error, that’s almost always VITE_API_URL or backend CORS, not the auth flow itself. See Troubleshooting.

Docker Compose

Prerequisites

Node.js 20+ and npm (only needed for a manual build; skip if you’re using Docker exclusively)
A running Flexprice backend, reachable over HTTP from wherever the frontend runs. See the backend self-hosting guide.

Quick start

# Clone the frontend repository
git clone https://github.com/flexprice/flexprice-front
cd flexprice-front

# Copy the environment template
cp .env.example .env
Edit .env with at least the three variables from self-hosted environment configuration above, then build and start the container:
docker compose up -d --build
Use --build here, and every time you change .env afterward. docker compose up -d alone reuses a cached image if one already exists, which silently keeps your old environment variables since Vite bakes them in at build time.
The docker-compose.yml in the repo builds the image from the included Dockerfile (a multi-stage Node 20 build) and exposes the dashboard on port 3000 with a built-in healthcheck.
# View logs
docker compose logs -f app

# Stop
docker compose down
Visit http://localhost:3000 once the container reports healthy, then follow First login to create your account.

Manual build and serve

If you’d rather not use Docker, build static files and serve them yourself.
git clone https://github.com/flexprice/flexprice-front
cd flexprice-front
npm install

cp .env.example .env
# Edit .env: VITE_APP_ENV=self-hosted, VITE_AUTH_PROVIDER=flexprice,
# VITE_API_URL=http://<your-backend-host>:8080/v1

npm run build
This produces a static dist/ folder. Serve it with any of the following:
Copy the repo’s nginx.conf (SPA fallback already configured) and point it at dist/:
cp nginx.conf /etc/nginx/conf.d/flexprice.conf
nginx -s reload
Whatever you use to serve the built files, it must fall back to index.html for unknown paths (a single-page app client-side router). The bundled nginx.conf handles this with try_files $uri $uri/ /index.html;. If you configure your own web server, replicate this rule or client-side routes like /customers/123 will 404 on a hard refresh.

Deploying on Vercel

The repo includes a vercel.json with the SPA rewrite already configured (/(.*) → /), so you can deploy directly:
  1. Import the flexprice-front repository into Vercel.
  2. Set the environment variables from the reference above in the Vercel project settings (VITE_APP_ENV=self-hosted, VITE_AUTH_PROVIDER=flexprice, VITE_API_URL, and any optional ones you need).
  3. Deploy. Vercel runs npm run build automatically and serves the dist/ output.
Your backend must be reachable from the public internet (or accessible to wherever your Vercel deployment resolves VITE_API_URL) since Vercel doesn’t proxy to a private network by default.

Connecting to the backend

  • VITE_API_URL is baked into the JavaScript bundle and fetched by the end user’s browser, not by the Docker container or server that built it. Use an address the browser can actually reach: the host machine’s real IP or domain, not a Docker-internal hostname. http://localhost:8080/v1 only works if the person opening the dashboard is on the same machine as the backend.
  • CORS: the Flexprice API needs to allow requests from the origin the dashboard is served on. If you’re serving the frontend from a different domain or port than the API expects, configure the backend’s CORS allow-list accordingly (see the backend self-hosting guide and configuration reference).
  • Login and signup (/auth/login, /auth/signup) are public endpoints: they don’t require an API key. After you log in, the dashboard authenticates every other request with the session token from that login, not with a Flexprice API key. You only need an API key (e.g. for testing with curl) if you’re calling the API directly, outside the dashboard.

Troubleshooting

VITE_APP_ENV is not set to self-hosted, or VITE_AUTH_PROVIDER is still supabase (the .env.example default). Set both explicitly and rebuild, since Vite environment variables are baked in at build time, not read at container start.
Confirm VITE_APP_ENV=self-hosted was set at build time. If it wasn’t, sign-up falls back to the Supabase flow and waits for an email confirmation that will never arrive on a self-hosted instance with no email provider configured.
The web server isn’t falling back to index.html for unknown paths. Use the bundled nginx.conf, or add an equivalent SPA fallback rule to your own server config.
  1. Confirm VITE_API_URL is reachable from your browser, not just from the container network:
curl <your-VITE_API_URL>/health
  1. Check the browser console for a CORS error. If present, add the frontend’s origin to the backend’s CORS configuration.
  2. Remember Vite bakes VITE_* variables in at build time. Changing .env after npm run build requires rebuilding.
Vite environment variables are compiled into the static bundle at build time, they aren’t read at runtime. Rebuild the image (docker compose up -d --build) or rerun npm run build, then restart the container or server.
docker compose logs -f app
docker compose ps
The bundled healthcheck curls http://localhost:3000 inside the container; a non-2xx response usually means the build failed or the app crashed on start. Check the logs above for the actual error.

Need help?

Additional resources

Backend Self-Hosting Guide

Run the Flexprice API and infrastructure

Configuration Reference

Complete list of Flexprice environment variables

Contribution Guidelines

Learn how to contribute to the frontend

Flexprice Website

Visit our official website