Skip to content

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?