# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

```bash
npm start          # Dev server at http://localhost:4200
npm run build      # Production build (SSR)
npm test           # Run unit tests with Vitest
ng generate component features/my-feature/components/my-comp  # Scaffold component (SCSS, type=component)
node dist/hurler-webdesign-saas/server/server.mjs  # Run SSR server after build
```

## Architecture

Angular 21 app with SSR (`@angular/ssr`) and Vitest for testing. The backend is a **Directus CMS** at `https://backend.hurler-webdesign.de` — all blog content is fetched via `BlogService` using Angular's `HttpClient`.

### Folder structure

```
src/app/
  core/          # Services, models, directives — singleton, app-wide
  features/      # Route-level modules (landing, blog, dashboard)
    landing/     # Landingpage with Navigation, Hero, Features, Pricing, Projects, Footer
    blog/        # BlogList + BlogDetail pages, fetched from Directus
  shared/        # Reusable UI components (Button, NavMenu, ToggleTheme)
src/environments/ # Config constants (Directus URL, OpenPanel credentials)
src/styles/      # Global SCSS: abstracts (functions, mixins), base (tokens, typography), layout
```

### Path aliases (tsconfig)

| Alias | Resolves to |
|---|---|
| `@core/*` | `src/app/core/*` |
| `@features/*` | `src/app/features/*` |
| `@shared/*` | `src/app/shared/*` |

Routes use lazy-loaded components via `loadComponent`.

### Styling conventions

- **SCSS** everywhere; `src/styles/abstracts/` is globally included via `stylePreprocessorOptions.includePaths`
- Use `@use 'abstracts'` to access mixins/functions
- Design tokens live in `src/styles/base/_tokens.scss` as CSS custom properties (OKLCH color space, fluid typography with `clamp()`)
- Dark mode via `[data-theme="dark"]` attribute on `<html>`, managed by `ThemeService` (uses Angular Signals + `localStorage`)
- Breakpoints: `sm` (400px), `md` (700px), `lg` (1200px) — use `@include breakpoint('md')` mixin
- Max content width: 1200px — use `@mixin container-wrapper`

### Analytics

OpenPanel is configured in `src/environments/openpanel.ts` and provided app-wide via `provideOpenPanel()` in `app.config.ts`. The `OpenpanelDirective` (`@core/directives`) enables declarative event tracking.

### Angular patterns used

- Standalone components throughout (no NgModules)
- `inject()` function instead of constructor injection
- Angular Signals for reactive state (`ThemeService`, etc.)
- `provideHttpClient(withFetch())` + `provideClientHydration(withEventReplay())` for SSR hydration
- German locale (`de`) registered and set as `LOCALE_ID`
