# AGENTS.md

Tibi CMS starter template — Svelte 5 SPA with esbuild, SSR via goja, and Playwright tests.

## Skill auto-improvement

Skills in `.agents/skills/` are **automatically updated** when the agent discovers patterns, gotchas, or workflows that are:
- Generic enough to apply across projects (not project-specific workarounds)
- Missing from the current skill documentation
- Important enough to prevent the same mistake in future projects

If you see an agent updating a skill file, it is capturing reusable knowledge. Review skill diffs to stay informed about evolving conventions.

## Token header distinction

- **System-level API** (raw tibi-server project CRUD, raw admin reload, server ops): use `X-Admin-Token` header
- **Collection-level API** (CRUD on content, navigation, etc.): use the header name defined by the collection permission key. In this starter that is typically `Token` via permission entries such as `token:${ADMIN_TOKEN}`.
- **User-level API** (JWT-authenticated requests): use `X-Auth-Token` header

## Medialib image URL pattern

In this starter, medialib URLs are derived from the entry ID plus the stored relative `file.src` value. If `file.src` is `file/example.jpg`, the project-local URL is `/api/medialib/{entryId}/file/example.jpg`.
Shared widgets such as `MedialibImage` append responsive filters as query params, for example `/api/medialib/{entryId}/file/example.jpg?filter=l-webp`.
These `/api/...` URLs are starter-local proxy URLs. Do not hardcode `file/file`.

## Project overview

- **Frontend**: Svelte 5 SPA in `frontend/src/`, esbuild, Tailwind CSS 4.
- **Backend**: tibi-server with hooks in `api/hooks/`, collections in `api/collections/`.
- **SSR**: goja (Go JS runtime) in `api/hooks/ssr/`.
- **Tests**: Playwright in `tests/` (API, E2E, mobile, visual).
- **Types**: `types/global.d.ts` (project), `tibi-types/` (read-only, from sibling repo).

## Key constraints

- **Dev servers always run in Docker** — never `yarn dev` or `yarn start` locally.
- `yarn` is for standalone tasks: `build`, `build:server`, `validate`.
- Bootstrap details (placeholder replacement, docker setup) → `tibi-project-setup` skill.
- Build checklist for full website projects → `.agents/BUILD_CHECKLIST.md`.
- Starter maintenance current state → `.agents/STARTER_ALIGNMENT_STATUS.md`.
- Starter maintenance and upstream/reference alignment workflow → `.agents/STARTER_ALIGNMENT_PLAN.md`.

## Project delivery workflow

When building a new website project from this starter, work through `.agents/BUILD_CHECKLIST.md` **phase by phase**. Do not skip phases, even when individual checklist items are already satisfied by the starter defaults.

For each phase:

1. Load the required skills listed in that phase.
2. Create or update the required project artifacts.
3. Work through every `[ ]` implementation check.
4. Run the listed validation commands. A phase is not done until all validations pass.
5. Mark each `[ ]` as `[x]` only when the concrete check is satisfied and its validation command passes cleanly.
6. Confirm all exit criteria before moving to the next phase.

The checklist covers the full delivery lifecycle: bootstrap → architecture → collections → types → frontend → SSR → hooks/actions → permissions → audit → media/SEO → optional branches → ops/deploy → tests → final verification.

## Quick reference

| Action | Command |
|--------|---------|
| Start dev stack | `make docker-up` or `make docker-start` |
| Restart frontend | `make docker-restart-frontend` |
| Logs | `make docker-logs` |
| Build frontend | `yarn build` |
| Build SSR | `yarn build:server` |
| Validate | `yarn validate` |
| Run all tests | `yarn test` |
| Run E2E tests | `yarn test:e2e` |
| Run API tests | `yarn test:api` |

## Testing notes

- Tests read `CODING_URL` from `.env`. Ensure it serves both `/` and `/api/...`.
- After changes, run only affected specs: `npx playwright test tests/e2e/filename.spec.ts`.
- CI runs `yarn validate` but not Playwright (needs MongoDB + tibi-server).

## API access

- `Token` header with `ADMIN_TOKEN` from `api/config.yml.env` when the collection permission key is `token:${ADMIN_TOKEN}`.
- Collection `user:` permissions apply to JWT auth (`X-Auth-Token`), not static `Token:`.
- For write access via `ADMIN_TOKEN`, add `"token:${ADMIN_TOKEN}": { methods: { post: true, put: true } }` to the collection permissions.
- The current deploy scripts call the reverse-proxied reload endpoint on `LIVE_URL` or `STAGING_URL` with `Authorization: Bearer ${ADMIN_TOKEN}`. Treat that as a separate project-local proxy surface from raw tibi-server project CRUD APIs.

## Required secrets

| Secret | Location | Purpose |
| --- | --- | --- |
| `ADMIN_TOKEN` | `api/config.yml.env` | API/admin access token |
| `ADMIN_ASSET_VERSION` | `api/config.yml.env` | Cache-busting for admin bundle (auto-generated) |
| `.basic-auth-web` | project root (git-ignored) | BrowserSync basic auth |
| `.basic-auth-code` | project root (git-ignored) | Code-Server basic auth |

Generated dev defaults in `api/config.yml.env` may be committed. Production values are overwritten in CI/CD via secrets.

## TypeScript

```json
"include": ["frontend/src/**/*", "types/**/*", "./../../cms/tibi-types", "api/**/*"]
```

- Domain types (entities, block props, API responses) be strict. `any`/`[key: string]: any` OK for inherently dynamic data (MongoDB filters, CMS fields, hook payloads).
- No `@ts-ignore` — use `/** @type {…} */` cast instead.
- **Zero warnings policy**: always run `yarn validate` after changes; fix all warnings.
- Svelte 5 with Runes: `$props()`, `$state()`, `$derived()`, `$effect()`.

## Svelte 5 patterns

- **Prop destructuring**: Destructuring `block` from `$props()` into local variables triggers `state_referenced_locally` warnings. The values capture initial state and lose reactivity. Either access through the parent object (`block.headline`) or use `$derived` for each value.
- **`$derived.by()`**: Use for multi-statement derived values: `let filtered = $derived.by(() => { if (x) return a; return b; })`
- **`class:` directive**: Invalid with `/` in class names like `class:text-white/85`. Use ternary in `class` attribute instead: `class={condition ? 'text-white/85' : ''}`.

## Reference repositories (sibling repos)

| Repo | Path | Key file |
|------|------|----------|
| **tibi-types** | `../tibi-types` | `index.d.ts` (context types), `schemas/config/collection.schema.json` |
| **tibi-server** | `../tibi-server` | `docs/` (20 files: collections, hooks, auth, actions, SSE, jobs, etc.) |
| **tibi-admin-nova** | `../tibi-admin-nova` | `types/admin.d.ts` (all admin config types) |

### When to consult which repo

- **Collection YAML** → `tibi-server/docs/04-collections.md` + `tibi-types/schemas/config/collection.schema.json`
- **Hooks** → `tibi-server/docs/06-hooks.md` + `tibi-types/index.d.ts`
- **Admin UI config** → `tibi-admin-nova/types/admin.d.ts` + `tibi-admin-nova/docs/collection-config.md`
- **Permissions** → `tibi-server/docs/05-authentication.md`
- **Actions/forms** → `tibi-server/docs/19-actions.md`
- **Realtime/SSE** → `tibi-server/docs/07-realtime.md`
- **Images/uploads** → `tibi-server/docs/08-file-upload-images.md`
- **LLM integration** → `tibi-server/docs/09-llm-integration.md`
- **Field-level permissions** → `tibi-server/docs/17-field-level-permissions.md`

## API lookup für aufgelöste Referenzen

Beim Laden von Collections können Fremdschlüssel via `lookup`-Parameter automatisch aufgelöst werden:

```ts
// entries mit aufgelösten medialib-Bildern laden
const entries = await getCachedEntries<"content">("content", {
	filter: { active: true },
	sort: "sort",
	lookup: "blocks.heroImage.image:medialib"
})
// Ergebnis: entry._lookup enthält die aufgelösten Referenzen
```

Der `lookup`-Parameter wird im Optionen-Objekt an `getCachedEntries` übergeben. Ohne lookup bleiben Referenzfelder reine ID-Werte ohne `_lookup`.

## Tailwind CSS 4

Canonical v4 syntax — no v3 legacy classes:

| v3 | v4 |
|----|----|
| `bg-gradient-to-*` | `bg-linear-to-*` |
| `aspect-[4/3]` | `aspect-[4/3]` (v4 hat nur `aspect-square`/`aspect-video` als Built-in-Utilities; benutzerdefinierte Ratios bleiben arbitrary) |
| `!bg-brand-600` | `bg-brand-600!` |
| `hover:!bg-brand-700` | `hover:bg-brand-700!` |

## Architecture skills (loaded on demand)

Use these tables as the lookup index. Each skill is a deep-dive for its domain.

### 1. Project start and solution design

| Skill | When |
|-------|------|
| `tibi-project-setup` | Bootstrap a new project from scratch |
| `website-solution-architecture` | Translate requirements into collections, blocks, SSR, workflows |
| `security-hardening-and-token-strategy` | Token strategy, secrets, hook risk surfaces, CORS |

### 2. Content model and editor UX

| Skill | When |
|-------|------|
| `content-authoring` | Add pages, block types, collections, and required type/registry wiring |
| `nova-pagebuilder-modeling` | Block schemas, preview, drillDown, dependsOn |
| `nova-navigation-modeling` | Header/footer trees, viewHint.navigation, declaredTrees |
| `admin-ui-config` | Field widgets, sidebar, layout, choices, foreign refs |
| `media-seo-publishing` | Image fields, alt/caption, SEO, publication model |
| `permissions-and-editor-workflows` | Field-level readonly/hidden, 3-layer cascade, custom roles |
| `nova-ai-editor-features` | AI-assisted alt text, LLM actions, token budgets |

### 3. Backend behavior

| Skill | When |
|-------|------|
| `tibi-hook-authoring` | Write/debug server-side hooks (goja) |
| `tibi-actions-and-forms` | Contact forms, newsletter, webhooks, action endpoints |
| `scheduled-jobs-and-automation` | Cron tasks, cleanup, reports, sync |
| `realtime-and-live-workflows` | SSE channels, live notifications, preview refresh |
| `audit-and-compliance` | Audit logging, retention, audit.return filtering, source semantics |

### 4. Frontend and delivery

| Skill | When |
|-------|------|
| `frontend-architecture` | SPA router, stores, Svelte 5 patterns, API layer |
| `tibi-ssr-caching` | SSR rendering, cache invalidation, 404 signaling |
| `playwright-testing` | Deterministic seed data, API/E2E/admin/visual tests |
| `deployment` | Production deployment setup, Basispanel subdomains, CI, rsync, staging |

### 5. Operations and diagnostics

| Skill | When |
|-------|------|
| `mongodb-and-indexes` | Mongo prerequisites, replica set, indexes, persistence, backup assumptions |
| `monitoring-and-performance` | OpenAPI, metrics, Sentry, reachability and observability checks |
| `troubleshooting-and-debugging` | Common stack failures, hook/runtime debugging, config/auth diagnosis |

### 6. AI, search, and enterprise

| Skill | When |
|-------|------|
| `search-and-embeddings` | Search modes, embedding providers, regeneration, semantic retrieval |
| `multi-tenancy-and-orgs` | Org/team isolation, enterprise permissions, visibility vs working rights |
