Skip to content

Self Hosting

Ratomir Jovanovic edited this page Oct 25, 2026 · 1 revision

Self-Hosting

PandaPayLens can be hosted in two ways.

Static site (GitHub Pages or any static host)

apps/pages builds the analyzer as a static export with a base path. It needs no server and no configuration.

pnpm build:packages
pnpm build:pages     # output in apps/pages/out, verified after the build

The build checks every exported file and path. The repository deploys it to GitHub Pages automatically after each push to main, and a smoke and privacy test runs against the live site.

Full application (Vercel)

apps/web is a Next.js application with the same analyzer plus an optional admin control plane for maintainers. The public analyzer works without any configuration. The admin area is switched off (/admin returns 404) until every required variable is set.

Setup is described step by step in docs/deployment.md. In short:

  1. Import the repository in Vercel with root directory apps/web.
  2. Add a Neon Postgres database from the Vercel Marketplace.
  3. Migrations run automatically during the build using the owner connection.
  4. Create a restricted runtime role and set its connection as ADMIN_DATABASE_URL.
  5. Set the auth secret, the production URL, the email sender and the first superadmin email.

The admin area

The admin area is for maintainers of a deployment. It never sees imported payment data.

Area Purpose
Dashboard overview of the deployment
Users invitations and roles (admin, superadmin)
Providers provider visibility and notes
Catalog and rules rule drafts and their review
Releases release notes
Settings, System deployment settings and health
Audit logs append-only record of every privileged action

Security model:

  • sign-in by email magic link, plus a required passkey (WebAuthn) as the second factor;
  • short sessions with secure, HTTP-only, same-site cookies;
  • sensitive actions need a passkey check from the last few minutes;
  • authorization is checked on the server for every operation;
  • the audit log is append-only and protected by a database trigger, and the runtime database role cannot delete from it.

Clone this wiki locally