Total rebrand across Web project: - Package name: casera-web -> honeydue-web - Cookie: casera-token -> honeydue-token - Theme store: casera-theme -> honeydue-theme - File sharing: .casera -> .honeydue, component/function renames - casera-file-handler.tsx -> honeydue-file-handler.tsx - All UI text, metadata, OG tags updated - Domains: casera.treytartt.com -> honeyDue.treytartt.com - Demo data emails updated - All documentation updated Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.7 KiB
honeyDue Web (honeyDueAPI-Web)
Next.js web client for the honeyDue property management platform. Talks to the Go REST API backend.
Build & Run
npm run dev # Dev server (localhost:3000)
npm run build # Production build (catches type errors)
npm run lint # ESLint
npm run test:e2e # Playwright end-to-end tests
npm run test:e2e:ui # Playwright with UI
npm run analyze # Bundle analysis
Stack
- Framework: Next.js 16 (App Router, React 19)
- Styling: Tailwind CSS v4 + shadcn/ui (Radix primitives)
- State: Zustand (auth, onboarding, theme), TanStack React Query (server state)
- Forms: React Hook Form + Zod validation
- Drag & Drop: @dnd-kit (kanban boards)
- Charts: Recharts
- Icons: Lucide React
- Analytics: PostHog
- Testing: Playwright (E2E), Vitest (unit)
Architecture
Request Flow
Browser → Next.js page (client component)
→ apiFetch("/tasks/") → /api/proxy/tasks (Next.js route handler)
→ Go API (reads honeydue-token httpOnly cookie, forwards as Authorization header)
Auth tokens are stored as httpOnly cookies (honeydue-token), never exposed to JS. The Next.js /api/proxy/[...path] catch-all route forwards requests to the Go API.
Directory Structure
src/
├── app/
│ ├── (auth)/ # Login, register, forgot-password (public)
│ ├── api/proxy/ # Catch-all proxy to Go API
│ ├── app/ # Authenticated app pages
│ │ ├── contractors/ # Contractor CRUD
│ │ ├── documents/ # Document management
│ │ ├── residences/ # Residence CRUD + detail with kanban
│ │ ├── settings/ # User settings, theme
│ │ └── tasks/ # Task CRUD, kanban board
│ ├── demo/ # Demo mode (fake data, no auth)
│ └── page.tsx # Landing page
├── components/
│ ├── contractors/ # Contractor cards, forms
│ ├── dashboard/ # Stats, activity, template suggestions
│ ├── demo/ # Demo banner
│ ├── documents/ # Document cards, forms
│ ├── forms/ # Auth form wrapper
│ ├── layout/ # TopBar, MobileNav, Sidebar
│ ├── notifications/ # Notification components
│ ├── onboarding/ # Onboarding flow
│ ├── residences/ # Residence cards, forms, summary, share
│ ├── settings/ # Theme picker
│ ├── shared/ # PageHeader, EmptyState, ErrorBanner, etc.
│ ├── sharing/ # Share code UI
│ ├── tasks/ # TaskCard, TaskForm, KanbanBoard, KanbanColumn
│ └── ui/ # shadcn primitives (button, card, dialog, etc.)
├── lib/
│ ├── api/ # API client functions per domain
│ │ ├── client.ts # apiFetch (client-side) + serverFetch (server-side)
│ │ ├── tasks.ts # Task API (CRUD, kanban, completions)
│ │ ├── residences.ts # Residence API (CRUD, sharing, reports)
│ │ ├── contractors.ts
│ │ ├── documents.ts
│ │ └── ...
│ ├── hooks/ # React Query hooks per domain
│ │ ├── use-tasks.ts # useTasks, useTask, useCreateTask, etc.
│ │ ├── use-residences.ts
│ │ └── ...
│ ├── demo/ # Demo mode: DataProvider abstraction
│ │ ├── data-provider-context.tsx # React context
│ │ ├── real-provider.ts # Real API calls
│ │ ├── demo-provider.ts # Fake data
│ │ └── mock-data/ # Static demo data
│ ├── themes/ # Theme system (Warm Sage palette)
│ ├── validations/ # Zod schemas
│ └── utils.ts # cn() helper
├── stores/
│ ├── auth.ts # Zustand: user, token, login/logout
│ ├── onboarding.ts # Zustand: onboarding state
│ └── theme.ts # Zustand: theme preferences
└── styles/
└── themes.css # CSS custom properties for theme
Key Patterns
Data fetching: All server data uses React Query hooks (use-*.ts). Hooks call API functions from lib/api/. API functions call apiFetch() which proxies through Next.js.
Demo mode: The app supports a /demo route with fake data. Components use useDataProvider() to get API functions and basePath — this returns either real or demo implementations depending on the route.
Kanban boards: Tasks display in kanban columns (overdue, due_soon, in_progress, not_started, completed). Uses @dnd-kit for drag-and-drop. Column names match Go API: overdue_tasks, due_soon_tasks, in_progress_tasks, not_started_tasks, completed_tasks.
Middleware (src/middleware.ts): Checks honeydue-token cookie. Redirects unauthenticated users to /login for protected routes. Skips API routes, static files, and public paths.
Conventions
- All pages under
/app/are"use client"components - Use
apiFetch()for client-side API calls,serverFetch()for server components/route handlers - React Query hooks go in
src/lib/hooks/use-{domain}.ts - API client functions go in
src/lib/api/{domain}.ts - shadcn components in
src/components/ui/— don't modify these directly - Custom components use Tailwind classes, warm shadow CSS variables (
--shadow-warm-sm,--shadow-warm-md) - Brand colors:
primary(sage green),brand-clay,brand-sagevariants defined in CSS custom properties - Font:
font-headingfor headings (tracking-tight), system font for body - Toast notifications via
sonner— usetoast.success(),toast.error() - Form validation with Zod schemas in
src/lib/validations/ - Icons from
lucide-react— keep consistent sizes (size-4 for inline, size-5 for cards)
Environment Variables
| Variable | Description | Default |
|---|---|---|
NEXT_PUBLIC_API_URL |
Go API URL (client-side) | https://honeyDue.treytartt.com/api |
API_URL |
Go API URL (server-side, no proxy) | Falls back to NEXT_PUBLIC_API_URL |
NEXT_PUBLIC_POSTHOG_KEY |
PostHog analytics key | — |
NEXT_PUBLIC_POSTHOG_HOST |
PostHog host | — |
Common Tasks
Add a new page: Create src/app/app/{route}/page.tsx (client component). Add nav item to src/components/layout/nav-items.ts.
Add a new API domain: Create src/lib/api/{domain}.ts with typed functions using apiFetch(). Create src/lib/hooks/use-{domain}.ts with React Query hooks. Add demo provider methods if needed.
Add a shadcn component: npx shadcn@latest add {component} — installs to src/components/ui/.