Files
honeyDueWeb/CLAUDE.md
T
Trey t 42e7bedea4 Replace hand-rolled auth with Ory Kratos browser flows
The honeyDue Go API no longer owns identity — Ory Kratos at
NEXT_PUBLIC_KRATOS_URL does. Rewrite the web app's auth layer to use Kratos
browser self-service flows and the ory_kratos_session cookie.

- Kratos client (src/lib/kratos/): flow init/fetch/submit, whoami, logout,
  message helpers, and the useKratosFlow lifecycle hook.
- Generic flow renderer (src/components/auth/): KratosFlowForm renders
  ui.nodes (inputs, oidc social buttons, hidden csrf), KratosMessages
  surfaces flow-level messages, AuthGate guards /app via whoami.
- Auth pages (login/register/forgot-password/verify-email/reset-password)
  rewritten as Kratos login/registration/recovery/verification/settings
  flows. Password change in settings now uses the Kratos settings flow.
- Proxy + serverFetch forward the ory_kratos_session cookie to the Go API
  instead of "Authorization: Token". Deleted /api/auth/{login,logout,me}.
- Middleware does a cheap ory_kratos_session cookie pre-filter; AuthGate's
  whoami call is authoritative.
- auth store rewritten around whoami + GET /auth/me; removed dead auth API
  functions, types/auth, validations/auth, code-input.
- Added NEXT_PUBLIC_KRATOS_URL to config (.env.example) and CLAUDE.md.

npm run build passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:16:49 -05:00

7.9 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 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=<id>.
  • The page reads ?flow=<id>, fetches the flow definition (ui.nodes / ui.action / ui.method), and renders it generically via <KratosFlowForm>.
  • 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: <AuthGate> (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 <AuthGate> (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/.