The soft reset to 77073ba inadvertently staged deletions of all phase 2
and 3 artifacts. This commit restores them from their source commits so
subsequent task commits build on the complete prior-phase foundation:
- components/mobile/{BottomNav,HeaderBar,KpiCardMobile,MoreDrawer,NeedsAttentionStrip,WorkerStatusRow}
- app/mobile/layout.tsx, dashboard/page.tsx, analyzer/page.tsx
- app/api/mobile/dashboard/route.ts
- All .planning/** files from phases 01-04
- CLAUDE.md, app/layout.tsx, app/styles/brand.css, public/manifest.json
10 KiB
Phase 02: Mobile Shell + More Drawer — Context
Gathered: 2026-05-03
Status: Ready for planning
Source: PRD Express Path (docs/superpowers/specs/2026-05-03-mobile-shell-design.md)
This phase delivers the new /mobile/* shell — the chrome that wraps every mobile page going forward. Specifically:
- A new
app/mobile/layout.tsxwith: sticky header (Wulf mark + Bell + avatar), scrollable content area, fixed bottom nav. - A 5-cell bottom nav: 4 primary tabs (Dashboard / Tickets / Finance / Analyzer) + a 5th "More" cell.
- A shadcn
Sheetdrawer that fully replaces the standalone/mobile/navpage — opened from the More cell AND from the header avatar — with three sections (Mobile sections, Full site, Account). - Deletion of
app/mobile/nav/page.tsxin the same change.
The four primary tabs route to existing pages (Dashboard, Tickets, Finance) plus /mobile/analyzer which does NOT yet exist as a route — Phase 2 only adds the nav entry; Phase 6 builds the page itself. Until Phase 6, tapping Analyzer should land on a placeholder route or 404 — the planner should pick one and keep it consistent (recommend a minimal placeholder app/mobile/analyzer/page.tsx returning "Coming soon" so the bottom nav doesn't 404).
Out of this phase: content of any mobile page (Dashboard restyle, Tickets restyle, etc.) — those are Phases 3–7.
## Implementation DecisionsRoutes & files (locked)
- Replace in place — no
/mobile-v2, no parallel routes. Editapp/mobile/layout.tsxdirectly. - Delete
app/mobile/nav/page.tsxas part of the drawer ship — same commit/PR as the new layout. - Add a placeholder
app/mobile/analyzer/page.tsxso the new bottom-nav Analyzer tab doesn't 404 before Phase 6 lands. Minimal "coming soon" component is sufficient. Mark this as deferred-cleanup in the plan so Phase 6 knows it owns the real page. - All existing
/mobile/*paths preserved (/mobile/dashboard,/mobile/tickets,/mobile/tickets/[id],/mobile/finance,/mobile/engagementif it exists).
Header (SHELL-02..04)
- Sticky top,
bg-background/95 backdrop-blur, bottom border. - Left slot: Wulf mark logo (use the actual brand mark asset, NOT a text-only fallback) + "Pulse" wordmark. Linked to
/mobile/dashboard. - Right slot order:
Bellicon button → compactAvatar(h-7 w-7).- Bell: placeholder only —
aria-label="Notifications", emptyonClick, keyboard-focusable. NO menu, NO badge logic, NO popover. Phase out-of-scope says "Real notification list behind the Bell icon — placeholder only this iteration". - Avatar: tapping opens the More drawer (acts as second entry point; the bottom-bar More button is the first).
- Bell: placeholder only —
- No page title in the header — pages render their own H1.
- Honor
pt-safe(orpt-[env(safe-area-inset-top)]) — Phase 1'spt-safeutility is available inapp/styles/brand.css.
Content area (SHELL-05)
<main>between header and bottom nav, scrollable.- Bottom padding = bottom-nav height + safe-area inset, so content doesn't hide under the bar. Use
pb-safe(Phase 1 utility) plus a fixed offset for the nav (e.g.,pb-[calc(theme(spacing.16)+env(safe-area-inset-bottom))]or similar — pick a concrete value during planning).
Bottom nav (SHELL-06, NAV-01..03)
-
Fixed, full-width,
border-t bg-background, wrapped inmax-w-lg mx-autoto share the gutter with content. -
5 cells: 4 tabs + More.
-
Tabs (in order, left to right):
Tab Icon (lucide) Route Dashboard LayoutDashboard/mobile/dashboardTickets Ticket/mobile/ticketsFinance DollarSign/mobile/financeAnalyzer Sparkles/mobile/analyzer -
Active state:
text-primary. Inactive:text-muted-foreground. Active detection viapathname.startsWith(href). -
More cell (5th):
Menuicon labeled "More". Opens the Sheet drawer.
More drawer (DRAWER-01..06)
- shadcn
Sheetcomponent. PickrightORbottomand stay consistent — recommendrightfor one-handed reachability with right-thumb users; planner can override. Document the choice in the plan. - Three sections, top-to-bottom:
- Mobile sections — Engagement (
/mobile/engagement). (NoExternalLinkicon — it's an in-shell route.) - Full site — link list to desktop-only pages, each with
ExternalLinkicon hint:- Quotes
- Configuration Items
- Backup Status
- Ticket Digest
- Admin / Sync
- Account — current user (avatar + email, read-only display) and a Sign out action.
- Sign out:
signOut()thenrouter.push('/auth/sign-in'). Use the existing Better AuthsignOutfromlib/auth-client.ts(or wherever the client SDK exports it — planner verifies during build).
- Sign out:
- Mobile sections — Engagement (
- Replaces
/mobile/navpage — deleteapp/mobile/nav/page.tsx. Anyone navigating to/mobile/navdirectly should not see the old standalone page; either redirect to/mobile/dashboardor rely on Next.js 404. Recommend NO redirect (just delete) — the URL was never bookmarked-worthy.
Existing infrastructure to consume
- Auth/session:
useSession()from Better Auth client (existing).lib/auth-client.ts. - Theme tokens / Wulf brand:
app/styles/brand.cssprovides--wulf-blue,pt-safe,pb-safe(from Phase 1). - Brand assets:
/public/branding/wulf-mark.png(mark) and/public/branding/wulf-wordmark.png(wordmark) — used in header. - shadcn primitives:
Sheet,Avatar,Buttonare already incomponents/ui/. Verify before planning; if any are missing, planner adds vianpx shadcn add.
Claude's Discretion
- Exact bottom-nav height (recommend
h-16= 64px to match touch-target guidelines). - Bottom nav micro-typography (label size, icon size) — keep consistent with existing mobile look.
- Animation/transition specifics for the Sheet (use shadcn defaults).
- Whether the avatar in the header is a real user image or initials fallback — use
AvatarwithAvatarImage+AvatarFallback(initials). Planner picks the source. - File organization for the new shell components (e.g.,
components/mobile/HeaderBar.tsx,components/mobile/BottomNav.tsx,components/mobile/MoreDrawer.tsx) — encouraged for testability and Phase 3+ reuse, but not required by the spec.
<canonical_refs>
Canonical References
Downstream agents MUST read these before planning or implementing.
Spec & roadmap (load-bearing — every decision derives from these)
docs/superpowers/specs/2026-05-03-mobile-shell-design.md— full spec; §3 (Navigation) and §5 (Shell) are the primary scope of this phase. §3.2 (More drawer) is the secondary scope. §1, §2, §7 set goal/audience/non-goals..planning/ROADMAP.md— Phase 2 entry with 6 success criteria..planning/REQUIREMENTS.md— IDs SHELL-01..06, NAV-01..03, DRAWER-01..06 (15 total).
Project conventions
CLAUDE.md— repo guide. Tailwind 4, shadcn/ui, no new state libs, no SWR/react-query, no Zod in API routes.DESIGN.md— design tokens, navigation IA, current cleanup backlog (read before touching shared UI).ARCHITECTURE.md— read if questions about data flow / runtime topology arise (not strictly needed for shell work).
Existing code to read or pattern-match against
app/mobile/layout.tsx— current layout, replaced by this phase. Read to understand what's there before deleting.app/mobile/nav/page.tsx— current standalone nav page, replaced by drawer + deleted.app/layout.tsx— root layout, NOT modified by this phase. Already exports manifest + viewport from Phase 1.app/styles/brand.css—pt-safe,pb-safe,--wulf-blueavailable; new utilities can be added here if needed.components/ui/sheet.tsx,components/ui/avatar.tsx,components/ui/button.tsx— shadcn primitives. Planner reads these for prop signatures.lib/auth-client.ts— Better Auth client SDK.signOut()lives here.components/navigation/app-navigation.tsx— DESKTOP nav component. Reference only — DO NOT modify; this phase only touches/mobile/*.
</canonical_refs>
## Specific Ideas- Wulf mark + wordmark: use
<Image src="/branding/wulf-mark.png" />+ the wordmark image side-by-side; or rebuild as inline SVG if existing brand component is available. Planner verifies during build. - Sign-out flow:
await signOut(); router.push('/auth/sign-in');— singleonClickhandler on the Sign out button. Wrap in try/catch and toast on failure (sonner is the project's toast library). - Active tab detection:
pathname.startsWith(href)— handles nested routes (e.g.,/mobile/tickets/123highlights Tickets). Edge case:/mobile/dashboardmatches/mobile/dashboard/anythingcorrectly; the four routes are non-overlapping prefixes so no special-case needed. - Drawer entry from header avatar: lift the Sheet's
openstate to a layout-level state hook (or use a small Zustand-free pattern with React state + ref) so both the bottom-bar More button AND the avatar can trigger it. - Sheet side choice: spec says "right or bottom — pick one and stay consistent". Recommend
right(more natural for a settings-style menu). Ifbottom, ensure it doesn't conflict with the bottom nav bar visually.
- Real notification list behind the Bell — explicitly out of scope (§7). Bell stays a placeholder.
- Tablet breakpoint (
md:max-w-2xl) — explicitly deferred (§4, §7). Keepmax-w-lg. - Service worker / offline — explicitly out of scope across all phases (§4, §7).
- Dashboard / Tickets / Finance / Analyzer / Engagement page restyles — Phases 3–8.
/mobile/analyzerreal page — Phase 6. This phase only adds the nav entry + a placeholder page (or accepts the route 404s until Phase 6 — planner picks).- Theme toggle in drawer — not in spec. Don't add.
- Sign-out confirmation dialog — not in spec. Single tap signs out.
Phase: 02-mobile-shell-more-drawer
Context gathered: 2026-05-03 via PRD Express Path (docs/superpowers/specs/2026-05-03-mobile-shell-design.md)