Skip to Content

Dashboard

The Pug dashboard — the React UI where you explore analytics and manage projects — is a separate repo from the backend: pug-sh/app (“Pug UI”). It’s a static single-page app (React + Vite, ConnectRPC, Tailwind) that talks to your pug server over Connect RPC. There’s no server runtime to operate: you build it to a folder of static files and serve them from any web server or CDN.

git clone [email protected]:pug-sh/app.git cd app

1. Configure (build time)

The dashboard’s configuration is baked in at build time via VITE_* environment variables — they’re compiled into the JavaScript bundle, not read at runtime. Copy .env.example to .env.production (Vite loads it for production builds) and set the values, or export them in your CI before bun run build.

VariableRequired?DefaultDescription
VITE_API_BASE_URLYeshttp://localhost:3000Your pug server’s public URL. This is the one that makes it your instance — point it at the backend you deployed (e.g. https://api.example.com).
VITE_GOOGLE_CLIENT_IDNo(empty)Google OAuth client ID for “Sign in with Google”. Leave empty to hide the button. Must match the backend’s PUG_OAUTH_GOOGLE_CLIENT_ID.
VITE_MAP_ASSETS_URLNohttps://maps.pug.shBase URL for the dashboard’s self-hosted map assets (basemap tiles, fonts, boundary data). Defaults to Pug’s public CDN — see Map assets.
VITE_DEMO_ENABLEDNo(empty)Cosmetic — set to true to advertise an “Explore the live demo” link on the sign-in page. The real demo switch is the backend’s PUG_DEMO_ENABLED.

Because these are compiled in, changing a value means rebuilding (or re-templating the built assets at deploy). If you serve the same build to multiple environments, build once per environment.

2. Build

bun install bun run build

bun run build type-checks and produces a static bundle in dist/ — plain HTML, JS, and CSS with no server component. That folder is your entire deployable.

3. Serve

Serve the contents of dist/ from any static host — Cloudflare Pages, Netlify, S3 + CloudFront, nginx, Caddy. Two requirements:

  • SPA fallback (history mode). The dashboard uses client-side routing, so the host must serve index.html for any unmatched path (e.g. Cloudflare Pages does this automatically; for nginx use try_files $uri /index.html). Without it, deep links and refreshes 404.
  • HTTPS. The dashboard sends a JWT to the backend; serve it over TLS.

4. Wire it to the backend

The dashboard and backend are separate origins (e.g. https://app.example.com and https://api.example.com), so two backend settings must know about the dashboard — set these in the backend configuration:

Backend variableSet it toWhy
PUG_CORS_ORIGINSyour dashboard originThe browser blocks the dashboard’s API calls otherwise. Don’t use * — it disables the credentialed requests sign-in needs.
PUG_DASHBOARD_BASE_URLyour dashboard originSo magic-link and invite emails link back to your dashboard.

If you enabled Google sign-in, the same client ID goes in both places: VITE_GOOGLE_CLIENT_ID (dashboard) and PUG_OAUTH_GOOGLE_CLIENT_ID (backend).

Dashboard → APIVITE_API_BASE_URL points at your pug server
API → Dashboard (CORS)PUG_CORS_ORIGINS includes your dashboard origin
API → Dashboard (emails)PUG_DASHBOARD_BASE_URL is your dashboard origin
Google sign-in (optional)VITE_GOOGLE_CLIENT_ID == PUG_OAUTH_GOOGLE_CLIENT_ID

Map assets

The dashboard renders maps from a set of static assets — a basemap tile archive, label fonts, and boundary data — rather than a third-party tile server. VITE_MAP_ASSETS_URL points at where those assets are hosted and defaults to Pug’s public CDN (https://maps.pug.sh), which works out of the box; leave it as-is for most self-hosts.

If you can’t reach that CDN (air-gapped, or by policy), mirror the assets to your own object store or CDN — it must allow CORS and honor HTTP Range requests — and point VITE_MAP_ASSETS_URL there. Either way, the dashboard works without reachable map assets: only the map visualizations are affected, everything else renders normally.

Local development

Run the dashboard against your local backend with Vite’s dev server:

bun install bun run dev # http://localhost:5173

The default VITE_API_BASE_URL (http://localhost:3000) already matches a local pug dev backend, so the two line up with no extra config. Full local walkthrough: Development.

Further reading

Last updated on