Demo mode
Every SeqDesk installation can host disposable demo workspaces — fully isolated, token-keyed copies of a researcher (or facility-admin) experience that anyone can spin up, poke at, and walk away from. The data lives in the same database as the rest of the install but is partitioned per token, so a demo session can’t see or affect real facility data. After a configurable expiry the workspace is deleted by a cleanup job.
This is what the seqdesk.com/demo URL points at, but the same surface is available in any install — handy for training, screencasts, or letting a prospective researcher click around before they sign up.
URLs
| Path | Audience | What it shows |
|---|---|---|
/demo | Public researcher demo | Standalone researcher dashboard with seeded orders/studies |
/demo/admin | Public facility-admin demo | Same install seen as a facility admin (form builders, modules, ENA settings) |
/demo/embed | Embeddable researcher demo | Stripped-down chrome for use inside an iframe (e.g., on the marketing site) |
All three flows share the same backend. The difference is just which
demoExperience is requested at bootstrap and how the page chrome renders.
Lifecycle
The flow is bootstrap → use → reset (optional) → expire → cleanup.
1. Bootstrap
When a user first hits /demo, the page calls POST /api/demo/bootstrap. The
server either reuses an existing workspace (matched by a token cookie) or
creates a new one:
| What gets created | Detail |
|---|---|
DemoWorkspace row | New id, fresh random token, hashed and stored as tokenHash, expiresAt set in the future |
| Demo user | Either a researcher or facility-admin user, marked isDemo: true |
| Seed data | A small set of demo orders, samples, studies, and form fields — enough that the dashboard isn’t empty |
| Site-settings overrides | Display name set to “SeqDesk Demo”, help text set to a “this is a disposable session” reminder |
| Modules config | Reset to defaults |
| Auth cookie | A session token cookie scoped to the demo user, expiring at expiresAt |
The bootstrap response includes:
{
"created": true,
"workspaceId": "ckxx...",
"expiresAt": "2026-05-12T12:00:00.000Z",
"demoExperience": "researcher"
}2. Use
From this point on, every API request the demo session makes carries the
session cookie. Server-side, isDemoSession() checks the user.isDemo flag
and disables a small number of features that don’t make sense in a sandbox
(see Restrictions).
3. Reset
A logged-in demo user can call POST /api/demo/reset to wipe their workspace
and re-seed. The same workspaceId is kept; the auth session token is
re-issued. Useful when a demo gets “messy” mid-walkthrough.
4. Expire
Each DemoWorkspace.expiresAt is set at bootstrap. Once that time passes the
session cookie no longer authenticates and the workspace becomes a candidate
for deletion.
5. Cleanup
GET /api/demo/cleanup deletes every DemoWorkspace whose expiresAt is in
the past. The endpoint is gated behind a Bearer token check so it can be
wired to a cron job (Vercel Cron, GitHub Actions, systemd timer) without
exposing the cleanup ability to anonymous traffic. A typical setup runs it
every 15 minutes.
Embed mode
/demo/embed renders the same researcher demo with chrome simplified for
iframe embedding:
- Top navigation collapsed
- Branded SeqDesk header hidden
- Sidebar minimized
The marketing site at seqdesk.com embeds this view to give visitors a working
demo without leaving the page. The bootstrap, reset, and expiry flows are
identical to the standalone /demo route — only the layout differs.
Restrictions
In a demo session the following are deliberately disabled:
- File downloads —
/api/files/downloadreturns 403 forisDemousers. - Assembly downloads — the Assemblies viewer hides the download column and shows a banner.
- Real ENA submissions — submission attempts fall through to test mode regardless of the configured ENA settings.
- Pipeline execution — pipelines can be inspected but not actually launched.
Outbound side effects (sending mail, calling external APIs) are also gated. Everything else — clicking through orders, editing forms, browsing studies — behaves exactly like the real app.
DemoWorkspace fields
Defined at prisma/schema.prisma:
| Field | Type | Purpose |
|---|---|---|
id | cuid | Workspace identifier |
tokenHash | unique string | SHA-256 of the bootstrap token; the raw token only lives in the browser cookie |
userId | unique string | Researcher User row owned by this workspace |
adminUserId | optional string | Facility-admin User row, populated for admin demos |
seedVersion | int | Bumped when the seeder schema changes, used for migrations |
lastSeenAt | datetime | Updated on each request — useful for “active demos” telemetry |
expiresAt | datetime, indexed | Cleanup query target |
createdAt / updatedAt | datetime | Standard timestamps |
Operating a public demo
A typical configuration for a public-facing demo:
# Run the cleanup endpoint every 15 minutes
*/15 * * * * curl -fsS -H "Authorization: Bearer $DEMO_CLEANUP_TOKEN" \
https://your-host/api/demo/cleanupSet the cleanup token in your environment so the demo install can verify it. Workspace expiry is configured server-side; rebuild the install to change the default.
When to use it
- Onboarding — give new researchers a working sandbox before exposing them to production.
- Marketing — embed
/demo/embedon a landing page; visitors can interact with a fully functional SeqDesk without account creation. - Training & screencasts — record against
/demoso the URL reset flow gives you a clean state between takes. - Bug repro — file uploads and pipeline launches are gated, but everything else (form configuration, MIxS validation, study workflows) reproduces faithfully.