Skip to content

feat(dashboard): onboarding checklist and a settings page (#958) - #1096

Merged
suleimansh merged 2 commits into
mainfrom
feat/958-onboarding
Jul 23, 2026
Merged

feat(dashboard): onboarding checklist and a settings page (#958)#1096
suleimansh merged 2 commits into
mainfrom
feat/958-onboarding

Conversation

@suleimansh

Copy link
Copy Markdown
Contributor

Closes #958.

Adds the ## Onboarding section to the Overview and the settings page it points at.

Onboarding checklist

Six steps, each with an explainer and an action:

Step Done when Action
Add a project a project is registered one-click Add {cwd} as project, or the existing add-directory dialog
Populate the queue of AI tasks TODO_AGENTS.md has open items explainer only
Populate tickets/ any project has a ticket Import tickets from GitHub (runs the import-tickets preset)
Add the Discord bot the daemon holds DISCORD_BOT_TOKEN explainer dialog
Add browser notifications permission granted and the toggle on requests permission on the click
Add Discord notifications the daemon holds DISCORD_WEBHOOK explainer

Every done-state is derived from a real fact, never from having clicked the row. So a step cannot be faked, and one completed outside the dashboard shows up completed. Dismissing hides it on the Overview only.

Settings page

New /settings, reachable from a header gear, collecting what was spread across the header menus: appearance + editor, agent / model / run-on, run options, eco, notifications, automation. The checklist lives here too and is not dismissible, which is what dismissing it on the Overview promises. Everything writes the global tier (the route has no project), so it sets defaults rather than one repo's override; per-project overrides stay in the launcher's gear.

The four gaps this had to build

  1. A non-project route. The router was {projectId, runId} with the first segment always a project id. settings is now reserved, which is safe because a generated project id is always <name>-<hash> and so can never be the bare word. Both directions are tested, including that /settings-a1b2 still routes to a project.
  2. A cross-project tickets signal. onTickets is per-project only. onDashboard's rollup now carries hasTickets, backed by a readdir-only hasTickets() rather than parsing every ticket, since it is asked for every project on every poll.
  3. A cwd suggestion. New onOnboarding read returns the server's working directory and whether it is already registered. Gated on the same addProject wiring as sendAddProject, so a public host (the relay) discloses nothing about where it runs.
  4. onboardingDismissed joins the preferences (interface and BOOLEAN_PREFERENCES, or the sanitizer drops it on save; the repo's own test caught this).

Discord is deliberately instructional

The dialog explains the bot and reports whether the daemon holds a token, but does not take one. Taking a token means the dashboard storing a secret, which needs its own decision. Filed as #1095.

Verification

  • pnpm build 12/12, pnpm typecheck 22/22
  • framework 1176 pass / 0 fail (+4 new), dashboard 386 pass (+3 new)
  • Driven in a real browser, not just unit tests: checklist states, gear to /settings, a toggle surviving a reload, the Discord dialog, dismiss-then-reload-then-still-on-settings, Back/Forward across the reserved segment, and dark mode.

Two things that live drive caught, both fixed here: a native <input type="checkbox"> on the settings page (the repo's Checkbox exists precisely because native ones draw a light box on the dark canvas), and an em-dash in the dismiss label where the issue uses a comma.

Latest main is merged in.

Add an Onboarding section to the Overview and a settings page at /settings.

Each onboarding step derives its done-state from a real fact (a registered
project, a non-empty queue, a ticket on disk, a granted browser permission,
credentials the daemon holds), so a step cannot be ticked by clicking it and one
completed outside the dashboard shows up completed.

Routing gains its first non-project view: `settings` is reserved as a first
segment, which is safe because a generated project id is always `<name>-<hash>`.

Backend support:
- onDashboard's per-project rollup carries `hasTickets`, backed by a readdir-only
  `hasTickets()` rather than parsing every ticket on each poll
- a new `onOnboarding` read offers the server's cwd as a one-click first project,
  gated on the same wiring as sendAddProject so a public host discloses nothing
- `onboardingDismissed` joins the preferences (interface + BOOLEAN_PREFERENCES,
  or the sanitizer would drop it on save)

The Discord step is instructional: it explains the bot and reports whether the
daemon holds a token, but does not take one. Configuring the credentials from the
dashboard is #1095, which needs a secret-storage decision of its own.
@suleimansh suleimansh self-assigned this Jul 23, 2026
@suleimansh
suleimansh marked this pull request as ready for review July 23, 2026 21:04
@suleimansh
suleimansh merged commit 85c5f73 into main Jul 23, 2026
1 check passed
@suleimansh
suleimansh deleted the feat/958-onboarding branch July 23, 2026 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Onboarding

1 participant