# honeyDue Web (`honeyDueAPI-Web`) Next.js web client for the honeyDue property management platform. Talks to the Go REST API backend. ## Build & Run ```bash 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 ory_kratos_session cookie, forwards it as a Cookie header) ``` Identity is owned by **Ory Kratos** (`NEXT_PUBLIC_KRATOS_URL`). The browser holds an `ory_kratos_session` cookie set by Kratos. The Next.js `/api/proxy/[...path]` catch-all route forwards that cookie to the Go API, which validates the session against Kratos. The Go API no longer does auth (no `Authorization: Token`). ### Auth (Ory Kratos) Login / registration / recovery (forgot-password) / email verification / password changes use **Kratos browser self-service flows**: - Auth pages (`src/app/(auth)/...`) initialize a flow by hard-navigating the browser to `{kratos}/self-service/{type}/browser`; Kratos sets a flow cookie and redirects back with `?flow=`. - The page reads `?flow=`, fetches the flow definition (`ui.nodes` / `ui.action` / `ui.method`), and renders it generically via ``. - Social sign-in (Apple/Google) = the `oidc` nodes in the flow. - `src/lib/kratos/` holds the client (`getFlow`, `submitFlow`, `whoami`, `logout`, ...) and the `useKratosFlow` hook. - Route protection: `` (in `src/app/app/layout.tsx`) calls `{kratos}/sessions/whoami`; the middleware does a cheap `ory_kratos_session` cookie pre-filter. ### Directory Structure ``` src/ ├── app/ │ ├── (auth)/ # Kratos self-service flow pages (login/register/recovery/verify) │ ├── 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`): Cheap pre-filter on the `ory_kratos_session` cookie. Redirects users without the cookie to `/login` for protected routes. Skips API routes, static files, and public paths. The authoritative session check is `` (`whoami`). ## 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-sage` variants defined in CSS custom properties - Font: `font-heading` for headings (tracking-tight), system font for body - Toast notifications via `sonner` — use `toast.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_KRATOS_URL` | Ory Kratos public API URL (identity) | `https://auth.myhoneydue.com` | | `NEXT_PUBLIC_POSTHOG_KEY` | PostHog analytics key | — | | `NEXT_PUBLIC_POSTHOG_HOST` | PostHog host | — | See `.env.example` for the full list. ## 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/`.