--- kind: task slug: wire-workspace-home-dashboard title: Replace hardcoded dashboard mocks with real tRPC queries plan_slug: daily-driver-finish epic_slug: shipping-the-shell status: ready priority: P0 tenant_id: global owner: unassigned cursor_todo_id: null updated_at: "2026-06-01" --- # Task summary `apps/web/app/(app)/[workspaceSlug]/page.tsx` currently renders a hardcoded `stats` array (`"24"`, `"8"`, `"12"`) and a hardcoded `recent` list. Replace both with real tRPC calls so the home page reflects actual workspace state. ## Description The page is a Client Component (`"use client"`). It already pulls `currentWorkspace` from `useWorkspaceStore`. What it needs: 1. **Stats card**: replace the three `stats` entries with counts derived from `objects` filtered by workspace. Suggested: - "Open tasks" — count of `objects` where `type = 'task'` and `status` is not in a "done" set, scoped by workspace_id. - "Due this week" — same scope, additionally filtered by `due_at <= now + 7 days`. If `objects` doesn't have a due-date column yet, drop this card rather than fake it. - "Lists" / "Projects" — count of `objects` where `type` is in `('project', 'space', 'group')`. 2. **Recent list**: replace the static `recent` array with the 5 most-recently-updated objects in the workspace. Use the existing `objects` router. If no suitable procedure exists, add one as `objects.listRecent({ limit: 5 })` — workspace-scoped via `workspaceProcedure` in `apps/web/server/trpc.ts`. 3. **Loading + empty states**: use the same `Card` skeleton pattern already in `apps/web/app/(app)/[workspaceSlug]/teams/page.tsx` (`MemberCardSkeleton`). When the workspace has no objects, render a friendly empty state with a "Create your first project" CTA that opens the existing `CreateObjectDialog`. ### Constraints - Don't add a new column to `objects` unless you also add a Drizzle migration. Prefer to drop a card rather than schema-creep this task. - All queries MUST filter by `workspace_id`. Use `workspaceProcedure`, never a raw procedure that pulls the slug from the URL without re-checking. - No raw `fetch` against `/api/trpc` — use `api.objects.<...>.useQuery()` via `@trpc/react-query`. ## Subtasks - [ ] Audit `apps/web/server/routers/objects.ts` for existing `count` / `listRecent` procedures. - [ ] Add the missing procedure(s) if needed, with zod inputs and workspace scoping. - [ ] Replace `stats` and `recent` arrays in `[workspaceSlug]/page.tsx` with `api.objects.*.useQuery()` calls. - [ ] Add a skeleton state and an empty state. - [ ] Wire the empty-state CTA to `CreateObjectDialog`. ## Owner or assignee Unassigned ## Status ready ## Estimation M ## Acceptance criteria - [ ] No hardcoded numbers or hardcoded titles remain in `apps/web/app/(app)/[workspaceSlug]/page.tsx`. - [ ] Loading state renders without a flash of zeros. - [ ] Empty state for a brand-new workspace renders a CTA. - [ ] All queries filter by `workspace_id`. ## Links to related Epic / Plan - Epic: `./Epic-shipping-the-shell.md` - Plan: `../Plan-daily-driver-finish.md`