storypane.

Authentication and access

Storypane includes invitation-only email/password sign-in. Accounts and sessions live in your installation PostgreSQL database; you do not need Clerk or SMTP to get started. Clerk is an optional, explicitly selected provider.

Authentication identifies a person. Space memberships, roles, and content scopes determine what that person can do. Neither a successful sign-in nor an API token bypasses those permissions.

Choose a provider

Provider Required configuration Account management
Built-in, default AUTH_PROVIDER=local, BETTER_AUTH_SECRET, installation database, STORYPANE_APP_URL Bootstrap and recovery CLI; invitations and account controls in the editor.
Clerk, optional AUTH_PROVIDER=clerk, CLERK_SECRET_KEY, VITE_CLERK_PUBLISHABLE_KEY, installation database, STORYPANE_APP_URL Clerk handles sign-in; Storypane still controls installation privileges, space memberships, roles, and content scopes.

Local authentication uses Better Auth with password hashing, database-backed sessions, and persisted authentication rate limits. Public signup is disabled. Built-in MFA, SAML, and OIDC federation are not included in this RC. If you need those sign-in features, evaluate your Clerk configuration and its provider pricing; Storypane’s MIT license does not cover third-party service charges.

Set up local sign-in

Follow getting started to create configuration and start the services. node scripts/setup-env.mjs generates a private BETTER_AUTH_SECRET and the other installation keys without printing them. Keep these values on upgrades. The command refuses to overwrite an existing file.

For Docker, create your first installation administrator:

docker compose --env-file .env.production -f compose.node.yaml exec web \
  node --import tsx scripts/admin.ts bootstrap

For a source/server checkout with .env.production, use pnpm admin bootstrap. The command requires a terminal and asks for name, email, and a hidden password of 12–128 characters. It refuses to bootstrap a second installation admin. Open the configured application URL and sign in.

Set STORYPANE_APP_URL to the exact origin people use, such as https://cms.example.com, and configure HTTPS at your reverse proxy. Scheme, host, and port must agree with the browser. HTTPS enables secure session cookies; plain HTTP is intended for local development. Keep the database and bucket off the public internet wherever possible. Auth writes must originate from the configured editor origin; do not weaken that check to fix a proxy mismatch.

Invite your team

  1. Open the space’s Settings → Members & roles. Choose the invited email and the appropriate role, then create the invitation.
  2. Share its single-use URL privately. Invitations expire after seven days. Add SMTP_URL and MAIL_FROM if you want Storypane to attempt email delivery; otherwise share the link yourself. A link is still available if email fails.
  3. A new local user enters their name and password, then signs in. An existing user signs in with the matching invited account before accepting.
  4. Repeat for other spaces. Access to one space does not grant membership in production, a developer’s space, or another team’s space.

Invitation possession is not email verification. Local accounts are created unverified; the RC has no built-in email-verification flow. An invitation cannot reset an existing account’s password or replace its existing membership role. Revoke and recreate a lost invitation rather than reusing a leaked URL.

An installation administrator provisions databases and manages installation connections. Space roles and content scopes govern content access separately; installation administration is not a blanket space-content permission. Use pnpm admin grant-admin <userId> only to deliberately grant installation control to an existing identity. Keep operator shell and database access restricted.

Password changes and recovery

Signed-in local users choose Account → Change password and supply their current password. Other sessions are revoked. Signing out revokes the current session. Resetting or recovering a password revokes the account’s existing sessions.

Set both optional variables and restart the app to enable emailed invitations and Forgot password?:

SMTP_URL=smtps://user:password@mail.example.com:465
MAIL_FROM=Storypane <cms@example.com>

Use your mail provider’s real settings in an ignored env file or secret manager. URL-encode special characters in SMTP credentials. Verify actual email delivery before relying on password resets; do not publish this example as credentials. Without SMTP, or if mail is unavailable, an operator can recover a local account:

docker compose --env-file .env.production -f compose.node.yaml exec web \
  node --import tsx scripts/admin.ts recover

The terminal asks for the account email and a new hidden password. In a server checkout, use pnpm admin recover. Never put passwords in command arguments, issue reports, screenshots, or an agent conversation. Account recovery is a privileged operator action, not an unauthenticated web endpoint.

Optional Clerk setup

For a new, empty installation, set AUTH_PROVIDER=clerk, the backend secret key and the matching publishable key before migrations and startup. Configure your exact editor origin in Clerk. The publishable key is public by design; the secret key stays server-side. The bundled Docker Compose passes both at runtime.

Sign in with a Clerk account whose primary email is verified. Storypane records that identity in its installation database. An operator then grants the first installation administrator with pnpm admin grant-admin <userId> using the installation identity ID. Do not run the local bootstrap command in Clerk mode. Invite users into spaces and assign roles in Storypane.

Clerk sessions, banned/locked status, local disabled-account status, and space permissions are checked during authenticated operations. Clerk adds an external authentication dependency; configure its production instance and test its own account recovery and session revocation. Enabling an upstream sign-up method does not itself grant a Storypane space membership.

Change providers on an existing installation

Take a restorable backup of the installation database and every space database. Stop the web process and jobs for the maintenance window. Preserve identity IDs; Storypane never merges accounts just because their email addresses match. Run operator commands with the currently recorded provider configured:

Changing only AUTH_PROVIDER is rejected. A provider switch does not delete old identities or migrate third-party MFA/recovery settings. Keep the maintenance window open until the checks pass; see backup and recovery.

API, agents, and preview credentials

Use credentials for their intended boundary:

Credential Purpose Handling
Editor session Interactive editing and authenticated collaboration Browser session; do not copy its cookie into CI or an agent.
Management token Management API, CLI, and MCP Space-scoped with explicit capabilities, constrained by the issuer’s current access. Store privately on the server/agent host; revoke when finished.
Published delivery token Website reads of published snapshots Keep server-side; it does not grant editor access. Cache published output deliberately in your frontend.
Preview token or short-lived preview grant Authorized draft preview Follow the SDK’s server-token/preview-bridge guidance; never expose a management token in the preview page.

An agent does not need your administrator password. Create a narrowly scoped management token under Settings → API & preview → Management API and configure it privately. See management API, CLI, and MCP for scopes and connection examples, and the SDK preview guide for origin-bound preview. Revocation, session expiry, and content filtering also apply to live connections; reconnecting must authenticate again.

Troubleshooting

Run the fresh-install checklist, including recovery and revoked-session checks, before relying on a new hosted installation.

View this guide on GitHub ↗