A self-hosted livediagram is configured through environment variables, secrets and each Worker's wrangler.toml, not application code. A few wrangler.toml values ship with livediagram.app's own settings (the database and KV ids, the allowed AI origins, the MCP issuer and consent URL, and the guest-signing date), so a fork replaces those with its own. The most important thing to understand is that the optional features are genuinely optional: leave them unset and the editor still works perfectly, just in a simpler mode. This page covers how configuration is supplied and the main toggles you will care about.
How configuration is supplied
Secrets and settings never live in source code, since the repository is public. Instead, each Worker reads them at runtime.
- Local development uses a gitignored
.env.localfile per frontend app and a gitignored.dev.varsfile per Worker. - Workers receive secret values via
wrangler secret put, and non-secret settings as[vars]in the Worker'swrangler.toml. Set plain settings in the file rather than the Cloudflare dashboard: every deploy replaces them with what the file declares. - Static frontends only ever bundle values explicitly marked as publishable, prefixed
NEXT_PUBLIC_so it is obvious they are safe to ship to the browser, and baked in at build time. Server-only secrets stay on the Worker side and never reach client code.
Each app that needs configuration ships an example file documenting which variables it expects, so you can see at a glance what to set.
Optional sign-in
Authentication is provided by an optional integration with Clerk, and the app supports three modes depending on what you configure.
- Hybrid, the production setup: both the publishable key (
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, on the live and community builds; a repository secret when you deploy through GitHub Actions) and the API's verification URL (CLERK_JWKS_URL) are set, so guests and signed-in users coexist. - Guest-only, the typical self-host: leave the auth variables unset. The app runs without an account system, sign-in routes say sign-in isn't enabled and offer Continue as guest, and the editor is unchanged.
- A partial misconfiguration (frontend configured, API not) exists only for debugging and is not meant for production: people can sign in, but the API treats everyone as a guest.
With sign-in on, also set GUEST_ID_HMAC_SECRET so guest ids are signed and nobody can claim another guest's documents when they sign up. Accounts unlock the features that need one: teams, API tokens, and, if you set them up, email, the Google Drive mirror and the MCP server.
Guest-only is what lets a self-hoster run with zero outbound runtime traffic beyond their own hosting if they want to.
Guest-only fallback
The API identifies the owner of a request in one of two equivalent ways: a verified sign-in token, or a per-browser guest id sent as a header. When sign-in is not configured, every request simply uses the guest path, and the editor stays fully usable, with persistence, sharing, and real-time collaboration all working.
Other optional features
Every other optional feature follows the same pattern: unset means off, and the editor hides what it cannot use.
| Feature | Turn it on with |
|---|---|
| Image uploads, thumbnails | Create the livediagram-images R2 bucket the api wrangler.toml already binds (or delete that binding to leave uploads off). Optional per-owner caps: IMAGE_MAX_PER_OWNER, IMAGE_MAX_BYTES_PER_OWNER |
| AI assistant, photo import | One AI key on the api Worker: OPENAI_API_KEY, GOOGLE_AI_STUDIO_API_KEY, or AI_API_KEY with AI_BASE_URL and AI_MODEL. Also set AI_ALLOWED_ORIGINS to your own origin or remove it: it ships with livediagram.app's, and any other origin gets a 403 |
RESEND_API_KEY on the api Worker, plus RESEND_FROM on a domain verified in Resend and APP_BASE_URL set to your origin, since both default to livediagram.app (needs sign-in) | |
| Google Drive mirror | GOOGLE_CLIENT_ID on the api Worker and NEXT_PUBLIC_GOOGLE_CLIENT_ID on the live build; GOOGLE_CLIENT_SECRET and DRIVE_TOKEN_KEY keep it syncing (needs sign-in). See Google Drive and MCP |
| MCP server for AI tools | Deploy the mcp Worker with its own KV namespace and hostname, then point CONSENT_BASE_URL (mcp Worker) at your editor's origin, and NEXT_PUBLIC_MCP_ORIGIN (live build) and OAUTH_ISSUER (api Worker) at your MCP host (needs sign-in). See Google Drive and MCP |
| Telemetry | TELEMETRY_ENABLED on the api Worker and NEXT_PUBLIC_TELEMETRY_ENABLED on every frontend build |
| Workbenches | Nothing extra beyond sign-in, but set APP_BASE_URL on the api Worker to the origin that serves the app, or pairing and frame links point at livediagram.app (needs sign-in) |
| Continue with Google | NEXT_PUBLIC_GOOGLE_OAUTH_ENABLED on the live build, with Google enabled in Clerk. The bundled deploy workflow already sets it, so enable Google in Clerk or remove that line |
The NEXT_PUBLIC_* values above are baked in at build time. When you deploy through the bundled GitHub Actions workflow, add them to the workflow's build step (or set mcp_origin in deploy.yml); apart from the Clerk publishable key and the Google Picker key, they are not read from repository secrets.
The Community is the one feature that is on by default; set COMMUNITY_ENABLED to false on the api Worker to switch it off.
For every variable, where it lives and the steps around it (OAuth redirect URIs, KV namespaces,
the AI model knobs), follow the repository's docs/operations/self-hosting.md and each app's
.env.example file.
Was this article helpful?