Skip to content

Configuration

All Glint configuration lives in Cloudflare KV and is managed through the web UI or environment variables. There is no .env file — the init wizard writes values directly into KV on first run, and subsequent changes go through the Settings page.


App Config

Configured during the initialization wizard or in Settings → App Config (owner only after setup).

KeyDescription
prism_base_urlBase URL of your Prism instance, e.g. https://id.example.com. No trailing slash.
prism_client_idOAuth Client ID from your Prism app registration.
prism_client_secretOAuth client secret. Only required for confidential clients. Leave empty when using PKCE.
prism_redirect_uriThe callback URL registered in your Prism app, e.g. https://glint.example.com/callback. Must match exactly.
use_pkcetrue for public (PKCE) clients; false for confidential (secret-based) clients.
allowed_team_idRestrict sign-in to members of a specific Prism team. Leave empty to allow any authenticated Prism user.
action_bar_defaultsArray of action keys shown in the per-todo quick-action bar for all users by default. See Action Bar below.

All values are stored under the KV key config:app as a JSON object.

WARNING

prism_client_secret is stored in KV, not as an environment variable. Make sure your KV namespace is not publicly readable. In Cloudflare's security model, KV bindings are only accessible to your Worker — they are never exposed via any public API.

PKCE vs Confidential Client

PKCE (Public)Confidential
use_pkcetruefalse
prism_client_secretemptyrequired
Token exchangeCode + PKCE verifierCode + client secret
Security modelVerifier stays in WorkerSecret stays in Worker, never in browser
Best forMost deploymentsHigh-security private deployments

Both modes are equally secure when deployed on Cloudflare Workers — the PKCE verifier and the client secret are both handled server-side and never exposed to the browser.

allowed_team_id

When set, Glint enforces team membership at login time only. Users not in the specified team(s) cannot sign in and see a "Not Authorized" page.

⚠️ Important: This is an authentication boundary, not a visibility filter. Once a user successfully signs in, they can access all teams they are a member of using the workspace switcher in the sidebar — not just the allowed team. allowed_team_id only controls who can enter the system.

Multiple team IDs can be specified, separated by commas, semicolons, or spaces:

team_a, team_b, team_c

TIP

allowed_team_id set via the ALLOWED_TEAM_ID environment variable (in wrangler.jsonc or the Cloudflare dashboard) takes precedence over the KV-stored value and cannot be modified from the UI. The Settings page shows a "locked" indicator when the env var is active.


Team Settings

Per-team branding and behaviour, configurable in Settings → Branding (owner or users with manage_settings).

KeyDescription
site_nameDisplay name shown in the sidebar header, browser tab title, and login page.
site_logo_urlURL to a logo image. When set, replaces the text title in the sidebar. Must be publicly accessible.
accent_colorCSS color value (hex, rgb(), etc.) applied as the primary theme color. Leave empty for default.
welcome_messageShort message shown below the app name on the login page. Optional.
default_set_nameName given to the auto-created set when a team is first accessed. Default: "Not Grouped".

Team settings are stored under the KV key team_settings:{teamId}.


Action Bar Defaults

The action_bar_defaults field in App Config sets which quick-action buttons appear on each todo row for all users by default. It is configurable in Settings → App Config (owner only).

Valid action keys:

KeyAction
add_beforeInsert a new todo above this one
add_afterInsert a new todo below this one
add_subtodoAdd a nested sub-todo
editEdit the todo title
completeToggle completion
claimClaim / unclaim the todo
commentOpen the comments panel
deleteDelete the todo

Built-in site default (used when not configured): ["add_after", "edit", "complete", "delete"].

Users can override the site default with their own preference (stored in localStorage). Workspace owners can set a workspace-level default that applies to all team members. The priority chain is: user preference → workspace default → site default.


Cloudflare Bindings

Your wrangler.jsonc must declare three bindings:

D1 Database (DB)

Stores all persistent data: todos, sets, comments, and permission overrides.

jsonc
{
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "glint-db",
      "database_id": "YOUR_DATABASE_ID"
    }
  ]
}

The schema is managed via numbered migration files in migrations/. Run them with:

bash
# Local
wrangler d1 migrations apply glint-db --local

# Production
wrangler d1 migrations apply glint-db

Migrations use CREATE TABLE IF NOT EXISTS and are idempotent — re-running is safe.

KV Namespace (KV)

Used for sessions, configuration, team settings, and user-teams caching.

jsonc
{
  "kv_namespaces": [
    {
      "binding": "KV",
      "id": "YOUR_KV_ID",
      "preview_id": "YOUR_KV_PREVIEW_ID"
    }
  ]
}

preview_id is required for wrangler dev (local development). Create one with:

bash
wrangler kv namespace create KV --preview

Durable Object (TODO_SYNC)

Powers realtime WebSocket sync. No manual creation is needed — Cloudflare provisions the namespace automatically on first deploy.

jsonc
{
  "durable_objects": {
    "bindings": [
      { "name": "TODO_SYNC", "class_name": "TodoSync" }
    ]
  },
  "migrations": [
    { "tag": "v1", "new_classes": ["TodoSync"] }
  ]
}

The migrations array registers the class with Cloudflare's migration system. This only needs to be present once; subsequent deploys detect that the class is already registered and skip re-provisioning.

TIP

Durable Objects require a Workers Paid plan. On the free tier the binding will fail to resolve and realtime sync will be unavailable. All other functionality is unaffected.

See Realtime Sync for full details on how the WebSocket layer works.


KV Key Reference

Key patternContentsTTL
init:configured"1" once setup is completeNone (permanent)
config:appJSON object with all app config fieldsNone (permanent)
team_settings:{teamId}JSON object with branding/settingsNone (permanent)
session:{sessionId}JSON session data including access tokenSet to token expiry
user-teams:{userId}JSON array of TeamInfo objects10 minutes

The user-teams cache is populated at login and used by cross-app middleware to resolve team membership without a live Prism API call. It expires after 10 minutes; if absent, the middleware falls back to a live lookup.


Environment Variables

Only one optional environment variable exists:

VariablePurpose
ALLOWED_TEAM_IDOverrides config:app.allowed_team_id. Cannot be changed from the UI when set.

Set it in wrangler.jsonc:

jsonc
{
  "vars": {
    "ALLOWED_TEAM_ID": "your-prism-team-uuid"
  }
}

Or in the Cloudflare dashboard under Workers → Your Worker → Settings → Variables.


Resetting Configuration

To wipe the init state and re-run the wizard (local development):

bash
wrangler kv key delete --local --binding KV "init:configured"

This lets you re-run POST /api/init/setup. Tables are recreated with IF NOT EXISTS, so existing data is preserved.

To reset on production, delete init:configured from your production KV namespace:

bash
wrangler kv key delete --binding KV "init:configured"

WARNING

Re-initializing in production does not wipe your database. It only allows the config to be overwritten. Todos, sets, and comments remain intact.