Dashboard & Analytics
/w/[slug]/dashboard is the first screen after someone picks a workspace: KPIs, a short activity chart, feed items, and buttons into the rest of the app.
Dashboard components
The dashboard is composed of four main sections, all loaded server-side in parallel for fast initial render.
KPI cards
Four metric cards showing key workspace stats:
| Card | Metric | Source |
|---|---|---|
| Total Products | Count of active products | products table (where deleted_at IS NULL) |
| Active Members | Count of workspace members | memberships table |
| New This Week | Products created in the last 7 days | products table with date filter |
| Current Plan | Active subscription plan name | subscriptions table |
Where to customize
Edit src/app/(app)/w/[workspaceSlug]/dashboard/kpi-cards.tsx to:
- Change which metrics are displayed
- Add new KPI cards for your own entities
- Modify the card layout or styling
Example: adding a custom KPI card
To add a "Total Tasks" card for your own entity:
// In kpi-cards.tsx, add to the stats array:
{
label: "Total Tasks",
value: taskCount,
icon: CheckSquare,
description: "Active tasks in this workspace",
}
Activity chart
A 30-day area chart showing daily workspace activity (audit events per day). Powered by Recharts with the shadcn chart wrapper.
How it works
The chart uses a PostgreSQL function daily_audit_counts(workspace_id, days) that returns a table of (day, count) pairs. Days with no activity return 0.
SELECT * FROM daily_audit_counts('workspace-uuid', 30);
-- Returns: [(2026-04-16, 12), (2026-04-15, 8), ...]
Where to customize
Edit src/app/(app)/w/[workspaceSlug]/dashboard/activity-chart.tsx to:
- Change the time range (default: 30 days)
- Change the chart type (area, bar, line)
- Add multiple data series
- Change colors and labels
Activity feed
A timeline of the 10 most recent workspace events, showing who did what and when.
Each entry displays:
- Actor name and email
- Action description (human-readable)
- Relative timestamp ("2 hours ago")
Where to customize
- Activity feed component:
src/components/activity-feed/ - Action labels:
src/components/activity-feed/action-labels.ts-- maps action strings (likeproduct.created) to display text (like "created a product")
When you add new features, register their audit actions in action-labels.ts:
// src/components/activity-feed/action-labels.ts
export const ACTION_LABELS: Record<string, string> = {
"product.created": "created a product",
"product.updated": "updated a product",
// Add your own:
"task.created": "created a task",
"task.assigned": "assigned a task",
};
Quick actions
Role-gated shortcut buttons for common operations:
| Action | Visible to | Links to |
|---|---|---|
| Create Product | OWNER, ADMIN, MEMBER | Products page |
| Invite Member | OWNER, ADMIN | Members page |
| View Billing | OWNER | Billing page |
Where to customize
Edit src/app/(app)/w/[workspaceSlug]/dashboard/quick-actions.tsx to:
- Add new quick action buttons for your own features
- Change which roles can see each action
- Update the links and icons
Adding your own dashboard widgets
To add a custom widget to the dashboard:
- Create a new component in
src/app/(app)/w/[workspaceSlug]/dashboard/ - Fetch data in the server component at
src/app/(app)/w/[workspaceSlug]/dashboard/page.tsx - Pass the data to your client component
Example: adding a "Recent Tasks" widget
// 1. Fetch in page.tsx (add to the existing Promise.all):
const recentTasks = await supabase
.from("tasks")
.select("id, title, status, created_at")
.eq("workspace_id", workspace.id)
.order("created_at", { ascending: false })
.limit(5);
// 2. Render in the page:
<RecentTasks tasks={recentTasks.data ?? []} />
Audit log page
The audit log at /w/[slug]/audit provides a full, filterable view of all workspace events. Accessible to OWNER and ADMIN roles.
Features
- Pagination for browsing through events
- Filter by actor (select which user's actions to view)
- Filter by action (multi-select: product.created, member.invited, etc.)
- Filter by date range (from/to date pickers)
- Event details: actor, action, resource, metadata, timestamp
Where to customize
- Audit log page:
src/app/(app)/w/[workspaceSlug]/audit/page.tsx - Audit table component:
src/app/(app)/w/[workspaceSlug]/audit/audit-log-table.tsx - Audit log insertion:
src/lib/audit/insert-log.ts
Adding audit entries for new features
Every server action should call insertAuditLog() after a successful mutation:
import { insertAuditLog } from "@/lib/audit/insert-log";
await insertAuditLog({
workspaceId,
actorUserId: user.id,
action: "task.created",
resourceType: "task",
resourceId: task.id,
metadata: { title: task.title },
});