# Phase 1 — Foundation

Scaffold the project, wire up auth, build the app shell, and establish the design system.

## Checklist

- [ ] Next.js 15 project init with App Router + TypeScript
- [ ] Tailwind CSS 4 configuration
- [ ] shadcn/ui setup (install CLI, add base components)
- [ ] TypeScript types from API DTOs (all request/response shapes)
- [ ] API client layer (typed fetch wrappers, token injection, error handling)
- [ ] Auth flows: Login, Register, Verify Email, Forgot/Reset Password
- [ ] Auth middleware (route protection, token cookie)
- [ ] App shell: sidebar nav + top bar
- [ ] Design system: color tokens matching mobile app
- [ ] Theme switcher (11 themes, persisted to localStorage)

## 1. Project Scaffold

```bash
npx create-next-app@latest honeyDueAPI-Web --typescript --tailwind --eslint --app --src-dir
cd honeyDueAPI-Web
npx shadcn@latest init
```

Install core dependencies:
```bash
npm install @tanstack/react-query zustand react-hook-form @hookform/resolvers zod
npm install lucide-react recharts @dnd-kit/core @dnd-kit/sortable
npm install -D vitest @playwright/test
```

## 2. TypeScript Types

Generate TypeScript types matching the Go API DTOs. Source from:
- `honeyDueAPI-go/internal/dto/requests/` — request shapes
- `honeyDueAPI-go/internal/dto/responses/` — response shapes
- `honeyDueAPI-go/internal/models/` — entity shapes

Key types to define in `src/lib/types/`:

```
types/
├── api.ts          # ApiResult<T>, PaginatedResponse, ErrorResponse
├── auth.ts         # LoginRequest, RegisterRequest, UserResponse, TokenResponse
├── residence.ts    # Residence, ResidenceDetail, MyResidencesResponse, CreateResidenceRequest
├── task.ts         # Task, TaskDetail, TaskColumnsResponse, CreateTaskRequest, TaskCompletionRequest
├── contractor.ts   # Contractor, ContractorDetail, CreateContractorRequest
├── document.ts     # Document, DocumentDetail, CreateDocumentRequest
├── subscription.ts # SubscriptionStatus, FeatureBenefit, UpgradeTrigger
├── lookups.ts      # TaskCategory, TaskPriority, TaskFrequency, ContractorSpecialty
└── notification.ts # NotificationPreference, Notification
```

## 3. API Client Layer

Create typed fetch wrappers in `src/lib/api/`:

```
api/
├── client.ts       # Base fetch wrapper (token injection, error handling, base URL)
├── auth.ts         # login(), register(), forgotPassword(), resetPassword()
├── residences.ts   # getResidences(), getResidence(), createResidence(), updateResidence(), deleteResidence()
├── tasks.ts        # getTasks(), getTasksByResidence(), createTask(), updateTask(), completeTask(), etc.
├── contractors.ts  # getContractors(), getContractor(), createContractor(), etc.
├── documents.ts    # getDocuments(), getDocument(), createDocument(), uploadFile(), etc.
├── lookups.ts      # getStaticData(), getUpgradeTriggers()
├── subscription.ts # getSubscriptionStatus(), etc.
└── notifications.ts # getPreferences(), updatePreference(), etc.
```

**Base client pattern:**

```typescript
// src/lib/api/client.ts
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'https://honeyDue.treytartt.com/api';

async function apiFetch<T>(
  path: string,
  options: RequestInit = {}
): Promise<T> {
  const res = await fetch(`${API_BASE_URL}${path}`, {
    ...options,
    credentials: 'include', // Send httpOnly cookie
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
  });

  if (!res.ok) {
    const error = await res.json().catch(() => ({ detail: 'Unknown error' }));
    throw new ApiError(res.status, error.detail || error.message);
  }

  return res.json();
}
```

## 4. Auth Flows

### Pages

| Route | Screen | Components |
|-------|--------|------------|
| `/login` | Login form | Email, password, "Forgot password?" link, social sign-in buttons |
| `/register` | Registration form | First name, last name, email, password, confirm password |
| `/verify-email` | Email verification | Code input, resend button |
| `/forgot-password` | Forgot password | Email input, submit |
| `/reset-password` | Reset password | New password, confirm, token from URL |

### Auth Token Strategy

```
Login → Server returns token → API route stores token in httpOnly cookie → Client redirects to /app
                                                                          ↓
                                                               All subsequent requests include cookie
                                                                          ↓
                                                               Next.js middleware reads cookie for route protection
```

- Token format: `Token <hex>` (Django-compatible, same as mobile)
- Cookie: `httpOnly`, `SameSite=Strict`, `Secure` in production
- Next.js middleware in `src/middleware.ts` checks cookie existence for protected routes

### Auth Store (Zustand)

```typescript
// src/stores/auth.ts
interface AuthState {
  user: UserResponse | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  login: (email: string, password: string) => Promise<void>;
  register: (data: RegisterRequest) => Promise<void>;
  logout: () => Promise<void>;
  fetchUser: () => Promise<void>;
}
```

## 5. App Shell

### Layout Structure

```
┌─────────────────────────────────────────────────────┐
│  Top Bar: Logo | Search (optional) | Profile Menu   │
├──────────┬──────────────────────────────────────────┤
│          │                                          │
│ Sidebar  │              Main Content                │
│          │                                          │
│ 🏠 Home  │                                          │
│ 🏘 Resid │                                          │
│ ✅ Tasks │                                          │
│ 👷 Contr │                                          │
│ 📄 Docs  │                                          │
│          │                                          │
│ ──────── │                                          │
│ ⚙ Setti │                                          │
│          │                                          │
├──────────┴──────────────────────────────────────────┤
│  (mobile: bottom tab bar instead of sidebar)        │
└─────────────────────────────────────────────────────┘
```

- **Desktop (≥1024px)**: Collapsible sidebar + top bar
- **Tablet (768-1023px)**: Collapsed sidebar (icons only) + top bar
- **Mobile (<768px)**: Bottom tab bar (matches iOS app), no sidebar

### Navigation Items

| Icon | Label | Route |
|------|-------|-------|
| Home | Home | `/app` |
| Building | Residences | `/app/residences` |
| CheckSquare | Tasks | `/app/tasks` |
| HardHat | Contractors | `/app/contractors` |
| FileText | Documents | `/app/documents` |
| Settings | Settings | `/app/settings` |

## 6. Design System

### Color Tokens

Map the mobile app's color palette to CSS custom properties and Tailwind config:

```css
/* src/styles/theme.css */
:root {
  /* Default theme (matches iOS appPrimary, etc.) */
  --color-primary: #07A0C3;       /* BlueGreen */
  --color-secondary: #0055A5;     /* Cerulean */
  --color-accent: #F5A623;        /* BrightAmber */
  --color-error: #DD1C1A;         /* PrimaryScarlet */
  --color-bg-primary: #FFF1D0;    /* Cream */
  --color-bg-secondary: #F0F4F8;  /* Blue-gray */
  --color-text-primary: #1A1A1A;
  --color-text-secondary: #6B7280;
  --color-text-on-primary: #FFFFFF;
}

[data-theme="dark"] {
  --color-bg-primary: #0A1929;
  --color-bg-secondary: #1A2A3A;
  --color-text-primary: #F0F0F0;
  --color-text-secondary: #9CA3AF;
}
```

### 11 Themes

Match the mobile app's theme system:

| Theme | Primary | Secondary |
|-------|---------|-----------|
| Default | #07A0C3 | #0055A5 |
| Teal | TBD | TBD |
| Ocean | TBD | TBD |
| Forest | TBD | TBD |
| Sunset | TBD | TBD |
| Monochrome | TBD | TBD |
| Lavender | TBD | TBD |
| Crimson | TBD | TBD |
| Midnight | TBD | TBD |
| Desert | TBD | TBD |
| Mint | TBD | TBD |

Theme values sourced from `HoneyDueKMM/composeApp/src/commonMain/.../ui/theme/ThemeColors.kt`.

### Spacing

```css
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 12px;
--spacing-lg: 16px;
--spacing-xl: 24px;
```

## 7. TanStack Query Setup

```typescript
// src/lib/hooks/useResidences.ts
export function useResidences() {
  return useQuery({
    queryKey: ['residences'],
    queryFn: () => api.residences.getResidences(),
    staleTime: 60 * 60 * 1000, // 1 hour (matches mobile cache timeout)
    refetchOnWindowFocus: true,
  });
}
```

## 8. Lookups Initialization

Match the mobile pattern — after login, fetch `/api/static_data/` and `/api/upgrade-triggers/`:

```typescript
// After successful login
await queryClient.prefetchQuery({
  queryKey: ['lookups'],
  queryFn: () => api.lookups.getStaticData(),
  staleTime: Infinity, // ETag-based, manually invalidate
});
```

## Deliverables

At the end of Phase 1, you should have:
1. A working Next.js app with Tailwind + shadcn/ui
2. Login and registration flows that authenticate against the Go API
3. A protected app shell with sidebar navigation
4. A design system with color tokens matching the mobile app
5. Typed API client with error handling
6. Theme switching (light/dark + 11 color themes)
