Canviq Admin — Multi-Product Support (Issue #705)

Mockup
Scene 1 — All Projects (Default View)
When no project filter is active, the sidebar shows "All Projects" in the switcher and the dashboard shows aggregate metrics across all projects. The triage queue shows submissions from all projects, each tagged with a colored project indicator.

Admin Dashboard

Total Submissions
847
Open
124
Active Users
2,340
Votes This Week
562
Triage Queue
Open Push notification scheduling is unreliable
Revoir iOS 42 votes
Review Add relationship timeline export
Revoir iOS 38 votes
Open Dark mode on Android has contrast issues
Revoir Android 27 votes
Planned Employee satisfaction pulse surveys
Internal Tools 15 votes

Design Notes

1

All Projects default. No project is selected. Switcher shows muted dot + "All Projects" in muted text. Metrics are aggregated across all projects.

2

Project tags on items. Each triage item shows a small colored dot + project name so you can distinguish sources at a glance.

3

Nav links carry context. All sidebar links append ?project= when a project is active, preserving filter as you navigate between pages.

4

Settings pinned to bottom. API Keys + Settings separated by divider at the bottom of the sidebar for quick access.

Scene 2 — Single Project Selected
When the user selects "Revoir iOS" from the project switcher, the sidebar dot turns blue, the project name is shown, a context banner appears in the main content area confirming the filter, and all metrics/data are scoped to that project. A "View all" link clears the filter.

Admin Dashboard

Showing data for Revoir iOS
Total Submissions
512
Open
78
Active Users
1,450
Votes This Week
341
Triage Queue
Open Push notification scheduling is unreliable
42 votes
Review Add relationship timeline export
38 votes
Open Improve matching algorithm accuracy
31 votes

Design Notes

1

Colored dot in switcher. The project's assigned color (blue) replaces the muted dot. Name shown in full foreground color.

2

Context banner. A subtle banner confirms which project is active. Includes a "View all projects" link to clear the filter. Uses the project's color for the dot.

3

Scoped metrics. All numbers reflect only the selected project. Users see the subset of data, not the aggregate.

4

No project tags needed. When a project is selected, the triage items don't need project tags since everything is already filtered to one project.

Scene 3 — Project Switcher Dropdown
The project switcher dropdown uses the Command/Combobox pattern (like Vercel and Linear). It shows "All Projects" at the top, followed by the organization's projects grouped under the org name. Each project has a color dot, type icon, and name. Search appears when there are 5+ projects. A "Create Project" action sits at the bottom.

Admin Dashboard

Showing data for Revoir iOS
Total Submissions
512
Open
78
Active Users
1,450
Votes This Week
341

Design Notes

1

Command pattern. Search input at top (shown when 5+ projects). Uses shadcn/ui Command component with fuzzy matching on project names.

2

Org-grouped projects. Projects are grouped under the organization name ("Revoir Software"). Each has a color dot, type icon (Globe/Smartphone/Wrench), and truncated name.

3

Active highlight. The currently selected project (Revoir iOS) has a subtle coral tint background and a coral checkmark.

4

Create action. "Create Project" at the bottom navigates to /admin/settings/projects/new. Shown in muted text with a folder-plus icon.

Scene 4 — No Projects (Single-Product Org)
When an organization has no projects configured (most early customers), the project switcher is hidden entirely. The sidebar shows only the brand header and navigation. This is the current behavior — multi-product support is additive, not mandatory.

Admin Dashboard

Total Submissions
847
Open
124
Active Users
2,340
Votes This Week
562
Triage Queue
Open Push notification scheduling is unreliable
42 votes
Review Add relationship timeline export
38 votes

Design Notes

1

No switcher, no separator. When projects.length === 0, the ProjectSwitcher component is not rendered and the separator below it is also hidden. Clean, no wasted space.

2

Backward compatible. This is the exact current behavior. Existing single-product orgs see no change. Multi-product support is purely additive.

3

No project tags on items. Without projects, triage items don't need project context — everything belongs to the single implicit project.

4

Layout unchanged. Admin layout passes projects={[]} (default). The sidebar and main content render exactly as they do today.

Scene 5 — Project Context Data Flow
How the project filter propagates from the sidebar through the URL, into server components, and down to client components. This is the architectural backbone of multi-product support.

Server → Client Data Flow

AdminLayout (server)
Sidebar (client)
passes projects[], currentProjectId, organizationName
ProjectSwitcher
URL: ?project=uuid
on select, updates search param via router.push()
URL: ?project=uuid
Page (server)
Next.js reads searchParams.project in page server component
Page (server)
Supabase .eq('project_id', id)
filters all queries to the selected project
Sidebar buildHref()
/admin/surveys?project=uuid
preserves ?project param on every nav link

Component Prop Chain

Source Component Props Notes
layout.tsx AdminLayout Fetches projects from Supabase Server component, queries organizations + future projects table
AdminLayout Sidebar projects, currentProjectId, organizationName All optional — defaults to empty array / null / "Organization"
Sidebar ProjectSwitcher projects, currentProjectId, organizationName Only rendered when projects.length > 0
Sidebar Nav Links buildHref(path) appends ?project= Reads from useSearchParams or currentProjectId prop
URL Page Components searchParams.project Each page server component reads the project filter from URL

i18n Keys Required

Key English Value Used By
admin.projects.switchProject Switch project ProjectSwitcher (aria-label)
admin.projects.allProjects All Projects ProjectSwitcher trigger + dropdown
admin.projects.searchProjects Search projects... CommandInput placeholder
admin.projects.noProjects No projects found CommandEmpty state
admin.projects.createProject Create Project Create action in dropdown
admin.nav.apiKeys API Keys Sidebar nav item
admin.nav.helpDocs Help & Docs Sidebar nav item (external link to /docs)
common.poweredBy Powered by Sidebar footer

Implementation Sequence

1

Add i18n keys to src/messages/en.jsonadmin.projects.* and admin.nav.apiKeys

2

Update admin layout — fetch org name from Supabase, pass to Sidebar. Projects array stays empty until projects table exists.

3

Create projects table (future) — migration adds projects table with organization_id FK, plus project_id column on submissions.

4

Wire layout to projects (future) — query projects table in layout, pass to Sidebar. Filter all page queries by project.