diff --git a/docs/e2e/feature-matrix.md b/docs/e2e/feature-matrix.md index 545466ede..151140759 100644 --- a/docs/e2e/feature-matrix.md +++ b/docs/e2e/feature-matrix.md @@ -97,7 +97,7 @@ DASH-001 note: `dashboard.e2e.ts` verifies the default owner dashboard route, Ov DASH-002 note: `dashboard.e2e.ts` verifies customize mode, the Block library, adding the built-in AI usage widget, server-backed `dashboard-layout` preference persistence, reload restoration, grid drag move, right-edge resize, drag-to-library removal, final reload absence, and 390px customize/library containment. DEF-20260623-DASH002-01 fixed invalid nested buttons in Block library live previews by rendering preview widget chrome in edit mode. -DASH-003 note: `dashboard.e2e.ts` runs in a dedicated post-setup, pre-persona project and verifies onboarding progress from genuinely clean E2E state (1/5: identity complete; framework in progress; first page, plugin, and team not started), all five step labels/actions, the Settings modal action, workspace routes for New page/Browse plugins/Add members, 390px mobile containment, and server-backed dismiss persistence through `dashboard-layout`. +DASH-003 note: `dashboard.e2e.ts` runs in a dedicated post-setup, pre-persona project and verifies onboarding progress from genuinely clean E2E state (1/5: identity complete; framework and first page in progress; plugin and team not started), all five step labels/actions, the Settings modal action, workspace routes for New page/Browse plugins/Add members, 390px mobile containment, and server-backed dismiss persistence through `dashboard-layout`. ## Capabilities And Access Control diff --git a/docs/features/dashboard.md b/docs/features/dashboard.md index 029e3bf3f..f8acb4b51 100644 --- a/docs/features/dashboard.md +++ b/docs/features/dashboard.md @@ -265,11 +265,11 @@ Each CMS hook fetches on mount through `useAsyncResource` + `apiRequest`, valida - [ ] Set site identity - [ ] Choose Core Framework import -- [ ] Create your first page +- [ ] Add a page of your own - [ ] Install a plugin - [ ] Invite your team -State lives in `useOnboardingState(...)`. It reads the current site, installed plugins, and users concurrently. The seed Home page does not satisfy "Create your first page"; that step flips done when the site has at least two pages. Framework import defaults to `active` until the user picks a framework mode. +State lives in `useOnboardingState(...)`. It reads the current site, installed plugins, and users concurrently. The seeded Home page does not satisfy "Add a page of your own"; that step flips done when the site has at least two pages, and reads `active` while only the seed exists so the checklist never reports "Not started" for a site that already has a live page. Framework import defaults to `active` until the user picks a framework mode. The panel is dismissible per-user and persisted with the dashboard layout preference (`dashboard-layout`). `useDashboardLayout.restoreOnboarding()` flips the same preference flag back to visible. diff --git a/src/admin/pages/dashboard/components/OnboardingPanel.tsx b/src/admin/pages/dashboard/components/OnboardingPanel.tsx index 709f18988..ac6d527fb 100644 --- a/src/admin/pages/dashboard/components/OnboardingPanel.tsx +++ b/src/admin/pages/dashboard/components/OnboardingPanel.tsx @@ -83,9 +83,9 @@ const STEPS: readonly StepDef[] = [ }, { id: 'firstPage', - title: 'Create your first page', + title: 'Add a page of your own', desc: - 'Start from a blank canvas, a starter layout, or import HTML and we will scaffold a tree.', + 'Beyond the starter Home page — begin from a blank canvas, a starter layout, or import HTML and we will scaffold a tree.', cta: 'New page', icon: FileTextSolidIcon, action: { kind: 'navigate', to: '/admin/site' }, diff --git a/src/admin/pages/dashboard/hooks/useOnboardingState.ts b/src/admin/pages/dashboard/hooks/useOnboardingState.ts index 166545067..56182b928 100644 --- a/src/admin/pages/dashboard/hooks/useOnboardingState.ts +++ b/src/admin/pages/dashboard/hooks/useOnboardingState.ts @@ -7,8 +7,10 @@ * • Framework import — derived from `site.settings.framework` being * populated. Defaults to `'active'` so the user is nudged to make a * deliberate decision; once they pick a mode the step flips to done. - * • First page — done when ≥ 2 pages exist (the seed Home page - * doesn't count). + * • First page — done when ≥ 2 pages exist (the seeded Home page + * doesn't count). While only the seed exists the step reads + * 'active', not 'todo': the site already has a page, so "Not + * started" would contradict the Pages widget's published count. * • First plugin — done when any plugin is installed. * • Team — done when more than the owner is in the users table. * @@ -71,7 +73,7 @@ export function useOnboardingState(): OnboardingStateResult { loading: false, identity: hasIdentity || hasFavicon ? 'done' : 'active', framework: hasFramework ? 'done' : 'active', - firstPage: pageCount >= 2 ? 'done' : 'todo', + firstPage: pageCount >= 2 ? 'done' : pageCount >= 1 ? 'active' : 'todo', plugin: plugins.length > 0 ? 'done' : 'todo', team: users.length > 1 ? 'done' : 'todo', } diff --git a/tests/e2e/dashboard.e2e.ts b/tests/e2e/dashboard.e2e.ts index 1f98bfae7..15c0fe1ea 100644 --- a/tests/e2e/dashboard.e2e.ts +++ b/tests/e2e/dashboard.e2e.ts @@ -212,7 +212,7 @@ test.describe('dashboard', () => { await expectOnboardingStep(panel, 'Set site identity', 'Completed', 'Open settings') await expectOnboardingStep(panel, 'Choose Core Framework import', 'In progress', 'Import') - await expectOnboardingStep(panel, 'Create your first page', 'Not started', 'New page') + await expectOnboardingStep(panel, 'Add a page of your own', 'In progress', 'New page') await expectOnboardingStep(panel, 'Install a plugin', 'Not started', 'Browse plugins') await expectOnboardingStep(panel, 'Invite your team', 'Not started', 'Add members')