# CLAUDE.md

This file provides guidance to Claude Code when working with this repository.

## Quick Reference

- **Project**: Customer Connect — Angular 20 SPA for Zero Trust network access management
- **Detailed docs**: See `/docs/` directory for component APIs, workflows, and data model
- **State management**: `SetupDataService` (`src/lib/shared/setup-data.service.ts`) is the single source of truth

## Commands

```bash
npx tsc --noEmit   # Type-check only (use when needed)
npm start          # Dev server (user runs this, NOT you)
npm run build      # Production build (user runs this, NOT you)
```

> **Node.js**: Requires v20.19+ or v22.12+. Use `nvm use 20.19.3` if needed.

> **IMPORTANT**: Do NOT run `npm start`, `npm run build`, or any build commands. The user handles builds. Only use `npx tsc --noEmit` for type-checking when explicitly needed.

## Architecture

**Angular 20** with **standalone components** (no NgModules). All components use `standalone: true` and declare their own `imports: []` array.

### Key Patterns

1. **Dependency Injection** — Use `inject()` function, NOT constructor injection:
   ```typescript
   private router = inject(Router);
   private setupData = inject(SetupDataService);
   ```

2. **Template Control Flow** — Use `@for`, `@if`, `@else` syntax, NOT `*ngFor` / `*ngIf`:
   ```html
   @if (condition) {
     <div>Content</div>
   } @else {
     <div>Other content</div>
   }
   ```

3. **No Arrow Functions in Templates** — Move `.map()`, `.filter()`, `.join()` etc. to component methods.

4. **Font Awesome Icons - CRITICAL** ⚠️ — **ALWAYS** use static `@if/@else` branches with hardcoded class names, **NEVER** use dynamic `[class]` binding:

   **❌ WRONG - Causes phantom rectangles/pseudo-elements:**
   ```html
   <!-- DO NOT DO THIS - creates visual bugs -->
   <i class="fa-solid" [class.fa-chevron-down]="!expanded" [class.fa-chevron-up]="expanded"></i>
   <i class="fa-solid" [class.fa-check]="isValid"></i>
   ```

   **✅ CORRECT - Always use separate @if/@else with full class names:**
   ```html
   <!-- Chevron icons (common case) -->
   @if (expanded) {
     <i class="fa-solid fa-chevron-up"></i>
   } @else {
     <i class="fa-solid fa-chevron-down"></i>
   }

   <!-- Role-based icons -->
   @if (role === 'Operator') {
     <i class="fa-solid fa-user-gear"></i>
   } @else if (role === 'Monitor') {
     <i class="fa-solid fa-eye"></i>
   } @else {
     <i class="fa-solid fa-user"></i>
   }
   ```

   **Why:** Font Awesome's `autoReplaceSvg: 'nest'` mode uses a mutation observer. Dynamic `[class]` binding triggers the observer twice, leaving stray `::before` pseudo-elements that appear as empty rectangles. This is especially noticeable with chevrons and toggle icons. **Always use static @if/@else branches to avoid this bug.**

### Routing

- Routes: `src/app/app.routes.ts`
- Root component: `src/app/app.ts` (renders `<router-outlet />` only)
- New pages: `src/lib/features/<feature-name>/`
- **User flow details**: See `docs/workflows/user-flow.md`

## Styling System

**Three layers:**

1. **Tailwind CSS** (CDN-based, no npm package)
2. **Component CSS** — Semantic classes with rem units (1rem = 14px)
3. **CSS Variables** — Design system tokens in `src/styles.css`

**Critical CSS variables:**
- `var(--brand-primary)` / `var(--brand-primary-hover)` — Brand colors (runtime-updated)
- `var(--border-color)` / `var(--border-color-light)` / `var(--border-color-dark)` — Border colors
- See `docs/styling-guide.md` for complete list

**Unit system:** Use rem units (base 14px). Exception: `1px` borders stay in pixels.

## State Management

`SetupDataService` (`src/lib/shared/setup-data.service.ts`) is the **single source of truth**:

- `providerData` / `customerData` — Organization details
- `branding` — Theme colors, logo (runtime CSS variable updates via `applyBrandingVars()`)
- `locations[]` — Customer locations
- `connectorTemplates[]` — Reusable connector configs
- `accessPolicies[]` — Automated connectivity rules
- `users[]` / `connections[]` — User management and network connections
- `mockMode` — Toggle via `toggleMockMode()`

**Getter-proxy pattern** in components:
```typescript
get customerName(): string  { return this.setupData.customerData.name; }
set customerName(v: string) { this.setupData.customerData.name = v; }
```

See `docs/data-model.md` for full data structure details.

## Shared Components

- `<app-header>` — Application header with app switcher, user menu, mock data toggle
- `<app-setup-shell activeStep="...">` — Customer setup workflow shell
- `<app-provider-setup-shell activeStep="...">` — Provider setup workflow shell
- `<app-setup-footer (back)="..." (continue)="...">` — Sticky footer with navigation buttons
- `<app-nf-logo [size]="...">` — NetFoundry logo SVG
- `<app-network-map>` — Reusable Leaflet-based geographic map for infrastructure visualization

See `docs/components/setup-shell.md` and `docs/components/network-map.md` for detailed component APIs.

## Connector Types

Four types with consistent color-coding:

- **Device** (blue `#2563eb`) — Local forwarding to 127.0.0.1
- **Gateway** (green `#16a34a`) — Configurable target forwarding
- **Clientless** (purple `#9333ea`) — Application domain/URL access (requires `publicDomain` field)
- **SDK Embedded** (orange `#ea580c`) — No app configuration needed

## Page Conventions

Every wizard page must:

1. **Wrap in shell**: `<app-setup-shell activeStep="step-id">` or `<app-provider-setup-shell activeStep="step-id">`
2. **Use setup footer**: `<app-setup-footer (back)="onBack()" (continue)="onContinue()" />`
3. **Include page header**: `.page-header` with `.breadcrumb` and `<h1>`
4. **Register route**: Add to `src/app/app.routes.ts` AND corresponding shell component's step list
5. **Primary action buttons**: Use `class="btn-primary"` to pick up `var(--brand-primary)` automatically

## Assets

Organized in `src/assets/`:
- `icons/` — SVG icons, favicons
- `svgs/` — SVG logos and graphics
- `fonts/` — Custom web fonts
- `data/` — JSON, YAML, CSV files
- `mockups/` — UI mockups for design reference

Access in code: `/assets/{category}/{filename}`

## Documentation

Detailed documentation is in the `/docs/` directory:

- **Components**: `docs/components/` — Shell components, modals, connections
- **Workflows**: `docs/workflows/` — User flow, routing details
- **Data Model**: `docs/data-model.md` — Interfaces, state management, methods
- **Styling**: `docs/styling-guide.md` — CSS variables, design tokens, external dependencies

**When to reference docs:**
- Component APIs and detailed behavior → `docs/components/`
- User flow and routing details → `docs/workflows/user-flow.md`
- Data structures and interfaces → `docs/data-model.md`
- Styling patterns and design tokens → `docs/styling-guide.md`

## Critical Gotchas

1. **Font Awesome icons - MOST COMMON BUG** ⚠️: **NEVER use dynamic `[class]` binding** (causes phantom rectangles/empty boxes). Always use static `@if/@else` branches with full class names. This especially affects chevrons, arrows, and toggle icons. See Key Patterns #4 above for examples.
2. **No arrow functions in templates**: Move all array methods to component methods
3. **CSS variables for brand colors**: Always use `var(--brand-primary)` for primary action buttons
4. **Border colors**: Use `style="border-color: var(--border-color)"` instead of Tailwind classes
5. **Assets path**: Use `/assets/...` not relative paths
6. **Mock data**: When adding new state, update both `loadMockData()` and `clearMockData()` in `SetupDataService`
7. **Page header positioning**: The global `.page-header` class only provides `transition` for scroll shadows. Each component must define its own `position: sticky` and `top` values in component CSS. Do NOT add `top` positioning to global styles.

## External Dependencies (CDN Only)

- Tailwind CSS (no npm package installed)
- Font Awesome 6.4.0
- Google Fonts (Inter + Russo One)
- Leaflet.js (map preview)
- Angular Material (tooltips only)

**Do not install Tailwind via npm** without updating the build pipeline.
