Environment (.env)
Environment variables (.env)
Section titled “Environment variables (.env)”The server reads .env from the repository root with its own small loader (server/config/env.js). A variable that is already set in the process environment (for example by Docker or systemd) wins over the same line in .env. The loader understands plain KEY=VALUE lines and strips one pair of surrounding quotes; it does not expand variables, accept an export prefix or strip inline comments, so CLAUDE_MODEL=claude-sonnet-5 # note makes the comment part of the value.
Boolean flags share one vocabulary: 1, true, yes and on mean on, 0, false, no and off mean off (any case). Anything else, including a typo, keeps the flag’s default. Numeric settings fall back to their default when the value is not a number or out of range. The full annotated list lives in .env.example in the repository.
Core server
Section titled “Core server”- PORT: HTTP port (default
4177) - HOST: bind address (default
127.0.0.1; set0.0.0.0inside a container) - APP_URL: public base URL of the instance (e.g.
https://slides.yourcompany.com). Used for absolute links such as share URLs, social cards and emails. Falls back tohttps://{DOMAIN}if not set; with neither set the server warns at boot and those links end up empty or relative. - DOMAIN: public hostname, used as the
APP_URLfallback and by the Caddy reverse proxy - TRUST_PROXY:
truebehind a reverse proxy you control, so the client IP is read fromX-Forwarded-For/X-Real-IP. The per-IP login throttle keys on that IP. Leave it off on a directly exposed server. TRUSTED_PROXY_COUNT sets how many proxies sit in front (default1). - DATA_DIR, UPLOADS_DIR: data and local-media directories, absolute or relative to the repository root (defaults
server/dataandserver/uploads)
Database settings (DATABASE_URL, DATABASE_*) are on Database.
Auth (recommended in production)
Section titled “Auth (recommended in production)”Auth is on by default. Users are managed in the database; there is no user list in the environment.
- AUTH_SECRET: required. Session tokens are signed with it, so it must be at least 32 characters (generate one with
openssl rand -base64 48). The server refuses to start when it is missing, unless auth is explicitly switched off withAUTH_ENABLED=falseor the instance runs in demo or sandbox mode. It also refuses a secret shorter than 32 characters. - AUTH_ENABLED: default on. Only an explicit off value (
false,0,no,off) disables auth; a typo leaves it on. With auth off, every visitor is an anonymous admin. - AUTH_ADMIN_EMAIL: the user with this email always gets the admin role
- AUTH_ALLOW_WEAK_SECRET:
truelets the server boot with a secret shorter than 32 characters (not recommended; rotate to a strong secret instead) - SECURE_COOKIES:
trueforces theSecureflag on cookies. Requests that arrive over HTTPS (directly or withX-Forwarded-Proto: https) get it regardless. - COOKIE_DOMAIN: optional cookie domain, e.g.
.yourdomain.comto share the session across subdomains - CSRF_ALLOWED_ORIGINS: comma-separated extra origins allowed to send cookie-authenticated state-changing requests. By default only the app’s own origin (
Host,APP_URLorDOMAIN) is accepted. - AUTH_DEV_BYPASS:
trueenables a “bypass login” button on/loginthat signs you in as admin without a password. It only takes effect withNODE_ENV=development; withNODE_ENV=productionthe server refuses to start while it is set.
Single sign-on with one OIDC provider is configured with SSO_ENABLED, SSO_PROVIDER (oidc), OIDC_ISSUER_URL, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET and OIDC_REDIRECT_URI, plus the optional OIDC_ALLOWED_DOMAINS, OIDC_AUTO_PROVISION, OIDC_DEFAULT_ROLE, OIDC_ADMIN_GROUPS and SSO_ENFORCE (hide password and magic-link login). The server refuses to start when SSO_ENABLED=true but the OIDC settings are incomplete.
See Authentication.
Feature flags / demo mode
Section titled “Feature flags / demo mode”- DEMO_MODE:
truemakes a read-mostly showcase install: AI, direct uploads and the Notion compose features are off, and the server boots withoutAUTH_SECRET(default off) - AI_ENABLED:
falseswitches AI features off even when vendor keys are configured (default on). Demo mode and sandbox mode also switch AI off. Not everything checks it: the editor’s AI Analysis (and its endpoint), the public API’s/api/v1/ai/*endpoints and the MCP server’s AI tools still run while a vendor key is configured. Remove the vendor keys to rule out every model call. See Getting started with AI. - UPLOADS_ENABLED:
falseswitches direct file uploads off (default on). Demo mode, sandbox mode andIMAGEKIT_ONLYalso switch them off. - IMAGE_LIBRARY_ENABLED:
falseswitches the local image library off (default on;IMAGEKIT_ONLYalso switches it off) - MULTI_ORG_ENABLED:
truelets one instance hold several workspaces that users can create and switch between (default off) - COLLAB_ENABLED:
trueenables real-time collaborator presence in the editor (default off); COLLAB_LIVE_EDITS adds experimental live document editing on top of it. See Real-time collaboration. - LIVE_DATA_ENABLED:
truelets slides connect to external data sources (default off) - RSS_FEED_ENABLED:
falseis an instance-wide kill switch for the RSS/Atom/JSON feeds of published presentations (default on; each organization still switches its feeds on itself)
The older disable-form spellings DISABLE_AI, DISABLE_UPLOADS and DISABLE_IMAGE_LIBRARY still work but print a boot warning, and are removed in the first release after 1 November 2026. Replace DISABLE_AI=true with AI_ENABLED=false, and likewise for the other two. When both spellings are set, the *_ENABLED variable wins.
Sandbox mode (public demo instance)
Section titled “Sandbox mode (public demo instance)”- SANDBOX_MODE:
trueenables sandbox behavior (anonymous guest sessions, automatic cleanup after the TTL, watermarked exports; AI, direct uploads and publishing off) - SANDBOX_TTL_HOURS: deck TTL in hours (default
24) - SANDBOX_DEFAULT_THEME: default theme id (default
editorial) - SANDBOX_WATERMARK: watermark text on exports (default
Sandbox export • Created by an anonymous user)
Guest quotas, cookie lifetime and separate data directories have their own variables; see Sandbox mode.
Data retention (optional)
Section titled “Data retention (optional)”A daily cleanup trims data that would otherwise grow without bound. It runs once when the server starts and then every 24 hours.
- TRASH_RETENTION_DAYS: days a trashed presentation stays recoverable before the cleanup deletes it for good, thumbnails included (default
30). The trash page states this number. A whole number of at least1;0or an invalid value falls back to30, so there is no way to switch the cleanup off. See Trash & Recovery. - ACTIVITY_RETENTION_DAYS: days an activity event is kept in the organization feed (default
180). Events carry the actor’s email address.
Upgrading from a version before 1.36.0: the first start deletes every presentation that has already been in the trash longer than TRASH_RETENTION_DAYS. Raise the number before you deploy if you want to keep that backlog. See the 1.36.0 release notes.
AI vendors (optional)
Section titled “AI vendors (optional)”A vendor counts as configured when its key is set; openai-compat needs an endpoint and a model instead.
- LLM_VENDOR: default vendor when several are configured:
openai,claude,mistral,deepseekoropenai-compat. Unset (or an unknown value): the first configured vendor in that order wins.
OpenAI:
- OPENAI_API
- OPENAI_MODEL (default
gpt-5.2)
Claude:
- CLAUDE_API
- CLAUDE_MODEL (default
claude-sonnet-5) - CLAUDE_MODEL_PLAN: model for the deck outline step (default
claude-opus-4-8, orCLAUDE_MODELwhen that is set)
Mistral:
- MISTRAL_API
- MISTRAL_MODEL (default
mistral-large-latest)
DeepSeek:
- DEEPSEEK_API
- DEEPSEEK_MODEL (default
deepseek-chat)
OpenAI-compatible endpoint (Ollama, vLLM, Together AI, Fireworks and similar):
- OPENAI_COMPAT_ENDPOINT: full chat-completions URL, e.g.
http://localhost:11434/v1/chat/completions - OPENAI_COMPAT_MODEL: model name (required)
- OPENAI_COMPAT_API: API key (optional; not needed for Ollama)
- OPENAI_COMPAT_LABEL: display name in the UI (optional)
Other:
- AI_VALIDATION_LOGGING:
falsestops writing AI validation events (unknown fields, schema issues) toserver/logs/ai-validation(default on)
Notion (optional)
Section titled “Notion (optional)”- NOTION_SECRET: Notion integration secret; enables Notion fetch, import and publish
- NOTION_FEATURE:
trueadditionally enables the Notion subjects, compose and suggestion endpoints (default off; ignored in demo mode)
See Notion.
Analytics (optional)
Section titled “Analytics (optional)”The server can inject third-party analytics tags into the app’s <head>. Only the app itself gets them: published decks and embeds never load third-party analytics. Matomo, Plausible, Umami and GA4 can also be configured in Settings > Analytics; a provider enabled there wins, and the variables below are the fallback. See Analytics for setup.
Common toggles:
- DISABLE_ANALYTICS:
trueremoves every provider tag - ANALYTICS_ALLOW_IN_SANDBOX:
trueallows provider tags even when sandbox mode is enabled
Providers:
- GTM_CONTAINER_ID (environment only)
- MATOMO_URL, MATOMO_SITE_ID (both required), optional MATOMO_DISABLE_COOKIES (default on), MATOMO_REQUIRE_CONSENT (default off), MATOMO_TRACK_LINKS (default on)
- PLAUSIBLE_DOMAIN, optional PLAUSIBLE_URL (when self-hosting Plausible)
- UMAMI_WEBSITE_ID, optional UMAMI_URL (when self-hosting Umami)
- GA4_MEASUREMENT_ID
Escape hatch (environment only):
- ANALYTICS_HEAD_HTML: raw HTML injected into
<head> - ANALYTICS_HEAD_HTML_B64: base64 version (recommended to avoid quoting issues; wins when both are set)