Client Portal Dashboard¶
SCOPE_ITEM: Client-facing dashboard that provides an at-a-glance overview of projects, KPIs, recent activity, and action items. First screen after login — must load fast and surface what matters.
Decision Tree¶
IF: Client has a single active project. THEN: Dashboard is the project detail view (skip project list).
IF: Client has multiple active projects. THEN: Dashboard shows project cards with status, drill down to detail.
IF: Client needs KPI visibility (SLA metrics, spend, usage). THEN: Include KPI widget section with configurable metrics.
IF: Portal is project delivery focused. THEN: Include milestone timeline or Gantt view.
IF: Portal is account management focused. THEN: Include contract status, SLA compliance, support ticket overview.
Widget Patterns¶
KPI Cards¶
SCOPE_ITEM: Numeric metrics with trend indicators.
INCLUDES: - Value display (formatted number, currency, or percentage). - Trend indicator (up/down arrow with change vs previous period). - Comparison period label ("vs last month"). - Loading skeleton during data fetch. - Click-to-drill-down (navigate to detail view).
┌─────────────────────┐ ┌─────────────────────┐
│ Active Projects │ │ Open Tickets │
│ ┌────┐ │ │ ┌────┐ │
│ │ 3 │ ↑ +1 │ │ │ 2 │ ↓ -1 │
│ └────┘ vs last mo │ │ └────┘ vs last mo │
└─────────────────────┘ └─────────────────────┘
┌─────────────────────┐ ┌─────────────────────┐
│ Documents Shared │ │ Outstanding Amount │
│ ┌────┐ │ │ ┌────────────┐ │
│ │ 47 │ ↑ +12 │ │ │ EUR 3,450 │ ! │
│ └────┘ vs last mo │ │ └────────────┘ │
└─────────────────────┘ └─────────────────────┘
Common KPIs by Variant¶
| Variant | KPIs |
|---|---|
| Professional services | Active projects, hours this month, documents shared, outstanding invoices |
| Project delivery | Milestones completed, days to deadline, open issues, budget utilisation |
| Account management | SLA compliance %, open tickets, contract renewal date, monthly usage |
Implementation¶
SCOPE_ITEM: Server-side KPI computation with caching.
INCLUDES: - KPI queries executed server-side (Next.js Server Components or API). - Cache per client (Redis, 5-minute TTL, invalidate on data change). - KPI definitions stored in config (not hardcoded). - Graceful error handling (show "—" if query fails, not error page).
CHECK: KPI queries must be scoped to client_id (multi-tenancy).
CHECK: Comparison period calculation must handle edge cases
(client created mid-month, no data for previous period).
Project Status Display¶
Project Cards¶
SCOPE_ITEM: Overview cards for each active project.
INCLUDES: - Project name and brief description. - Current status badge (colour-coded: on track, at risk, delayed, completed). - Completion percentage (progress bar). - Next milestone name and due date. - Assigned team members (avatars). - Last activity timestamp. - Click to navigate to project detail.
Project Detail View¶
SCOPE_ITEM: Detailed project information page.
INCLUDES: - Project description and scope. - Status and phase indicator. - Milestone list with status (completed, in progress, upcoming). - Timeline visualisation (vertical or horizontal). - Team members with roles and contact options. - Recent activity log (filtered to this project). - Project documents (filtered to this project). - Project messages (filtered to this project).
OPTIONAL: - Gantt chart (Recharts or custom SVG, read-only for clients). - Budget overview (allocated, spent, remaining — if company shares). - Time tracking summary (hours logged this period). - Issue / snag list with status.
Milestone Timeline¶
SCOPE_ITEM: Visual representation of project milestones.
INCLUDES: - Vertical timeline with milestone nodes. - Each node: name, target date, actual date (if completed), status. - Status colours: completed (green), in progress (blue), upcoming (grey), overdue (red). - Today marker on timeline.
● Discovery complete ✓ 15 Jan 2026
│
● Design approved ✓ 02 Feb 2026
│
◉ Development Phase 1 ●● 15 Mar 2026 (in progress)
│
○ User testing · 01 Apr 2026
│
○ Go-live · 15 Apr 2026
OPTIONAL: - Dependency lines between milestones. - Milestone completion notification to client. - Client approval action on deliverable milestones.
Real-Time Data¶
Data Refresh Strategy¶
IF: Portal is low-traffic (clients check periodically). THEN: Refresh on page load + manual refresh button.
IF: Portal is used for active project monitoring. THEN: Add polling (60-second interval) or SSE for live updates.
Polling (Default)¶
SCOPE_ITEM: Periodic data refresh without full page reload.
INCLUDES:
- React Query (TanStack Query) with refetchInterval: 60000.
- Stale-while-revalidate pattern (show cached data while fetching).
- Manual refresh button (refetch all queries).
- "Last updated" timestamp per widget.
CHECK: Polling interval must be >30 seconds to avoid unnecessary load.
CHECK: React Query staleTime should be 30 seconds (reduce refetches
on navigation within the portal).
Server-Sent Events (Optional)¶
OPTIONAL: SCOPE_ITEM: Push updates to client browser on data change.
INCLUDES:
- SSE endpoint (/api/events/[clientId]).
- Events: project_status_changed, document_shared, message_received,
invoice_created, milestone_completed.
- Client reconnection with Last-Event-ID for missed events.
- Connection heartbeat (30-second keepalive).
CHECK: SSE is simpler than WebSocket and sufficient for portal updates.
CHECK: SSE connections must be authenticated and scoped to client_id.
CHECK: Max 1 SSE connection per browser tab (handle in frontend).
Customisable Layouts¶
OPTIONAL: SCOPE_ITEM: Company can configure dashboard layout per client or per client type.
Admin Layout Configuration¶
INCLUDES: - Widget library (KPI card, project list, activity feed, documents, messages, invoices, calendar). - Drag-and-drop grid layout editor (admin side). - Layout templates per client type (services, project, account). - Per-client override (customise specific client's dashboard).
Implementation¶
INCLUDES:
- Layout stored as JSON in client_organisations.settings.
- Default layout per portal variant.
- React grid layout (react-grid-layout library).
- Widget components are lazy-loaded (code splitting per widget).
{
"dashboard_layout": [
{ "widget": "kpi_cards", "x": 0, "y": 0, "w": 12, "h": 2 },
{ "widget": "project_list", "x": 0, "y": 2, "w": 8, "h": 4 },
{ "widget": "activity_feed", "x": 8, "y": 2, "w": 4, "h": 4 },
{ "widget": "documents_recent", "x": 0, "y": 6, "w": 6, "h": 3 },
{ "widget": "messages_unread", "x": 6, "y": 6, "w": 6, "h": 3 }
]
}
Activity Feed¶
SCOPE_ITEM: Chronological log of recent events relevant to the client.
INCLUDES: - Event types: document shared, message received, project status changed, milestone completed, invoice created, ticket updated. - Actor display (team member name + avatar). - Relative timestamps ("2 hours ago", "yesterday"). - Click-to-navigate to the source item. - Maximum display: 20 most recent events, "View all" link.
Implementation¶
CREATE TABLE activity_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
client_org_id UUID REFERENCES client_organisations(id),
project_id UUID REFERENCES projects(id),
event_type TEXT NOT NULL,
title TEXT NOT NULL,
description TEXT,
actor_id UUID REFERENCES users(id),
target_type TEXT, -- document, message, project, invoice, ticket
target_id UUID,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_activity_client_date
ON activity_events (client_org_id, created_at DESC);
CHECK: Activity events are created by triggers in the service layer (not database triggers — keep logic in application code). CHECK: Activity feed query must be indexed and fast (<100ms). CHECK: Events older than 90 days can be archived to reduce table size.
Performance Requirements¶
CHECK: Dashboard initial load: <2 seconds (including KPI data). CHECK: Widget data fetch: <500ms per widget. CHECK: Activity feed: <200ms for latest 20 events. CHECK: Project list: <300ms for up to 50 active projects. CHECK: Polling: no visible flicker on refetch (stale-while-revalidate).
Scoping Questions¶
CHECK: How many active projects does a typical client have? CHECK: What KPIs should be visible to clients? CHECK: Does the client need a project timeline or Gantt view? CHECK: Is real-time data needed or is periodic refresh sufficient? CHECK: Should the dashboard layout be customisable per client? CHECK: What actions should clients be able to take from the dashboard? CHECK: Does the company want to control which data clients can see?