Files
rustycms/CLAUDE.md

119 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RustyCMS AI Context
> **Für AI-Tools**: Diese Datei (CLAUDE.md) wird von Claude Code gelesen.
> Cursor liest `.cursor/rules/project.mdc`.
> Beide Dateien haben identischen Inhalt — beim Ändern bitte **beide** aktualisieren.
---
## Projektstruktur
```
rustycms/
├── src/ # Rust API
│ ├── api/
│ │ ├── handlers.rs # AppState + alle Content-Handler
│ │ ├── response.rs # format_references, expand/collapse_asset_urls
│ │ ├── assets.rs # Asset-Endpoints (Upload, Serve, Delete, Folders)
│ │ └── routes.rs # Axum-Router
│ ├── schema/
│ │ └── validator.rs # normalize_reference_arrays (single + array refs)
│ └── store/ # FileStore / SqliteStore
├── types/ # Schema-Definitionen (*.json5)
├── content/ # Inhalte als JSON5-Dateien
│ └── assets/ # Bild-Assets (mit Unterordnern)
└── admin-ui/ # Next.js Admin UI (Port 3001)
├── src/components/ # React-Komponenten
├── src/lib/api.ts # API-Client
└── messages/ # i18n (en.json, de.json)
```
## Dev starten
```bash
./dev.sh # API (Port 3000) + Admin UI (Port 3001)
cd admin-ui && npm run dev # nur Admin UI
cargo run # nur API
```
## Konfiguration
Alle Optionen per Env-Variable (`.env.example` als Vorlage) oder CLI-Flag:
| Env-Variable | CLI-Flag | Default | Zweck |
|---|---|---|---|
| `RUSTYCMS_TYPES_DIR` | `--types-dir` | `./types` | Schema-Definitionen |
| `RUSTYCMS_CONTENT_DIR` | `--content-dir` | `./content` | Content-Dateien |
| `RUSTYCMS_BASE_URL` | — | `http://host:port` | Öffentliche API-URL (für Asset-URLs) |
| `RUSTYCMS_API_KEY` | — | unset | Auth für POST/PUT/DELETE |
| `RUSTYCMS_LOCALES` | — | unset | z.B. `de,en` (erstes = Default) |
| `RUSTYCMS_STORE` | — | `file` | `file` oder `sqlite` |
| `RUSTYCMS_CORS_ORIGIN` | — | `*` | Erlaubte CORS-Origin |
| `RUSTYCMS_CACHE_TTL_SECS` | — | `60` | Response-Cache TTL (0 = aus) |
## Asset-URL-Strategie
Assets werden immer mit **relativem Pfad** auf Disk gespeichert:
```
src: "/api/assets/ordner/datei.jpg"
```
Die API expandiert beim Ausliefern automatisch abhängig vom Kontext:
- **GET mit `_resolve`** (Frontend-Consumer): relativ → `https://api.example.com/api/assets/...`
- **GET ohne `_resolve`** (Admin UI bearbeitet): Pfad bleibt relativ
- **POST/PUT** (Speichern): absolute URLs werden vor dem Schreiben kollabiert
Implementierung: `src/api/response.rs``expand_asset_urls()` / `collapse_asset_urls()`
## Collection-Hierarchie (wichtig!)
| Collection | Zweck | Pflichtfelder |
|---|---|---|
| `img` | Rohes Bild-Asset | `src` (relativer Pfad), `description` |
| `image` | Layout-Komponente | `name`, `img` (Referenz auf `img`-Collection) |
**Regel:** `postImage` → referenziert `img` direkt. `row1Content` / `row2Content` etc. → erwarten `image`-Einträge, **nicht** `img`.
Workflow beim Hinzufügen eines Bildes zu einer Content-Row:
1. `img`-Eintrag erstellen (`src: "/api/assets/..."`)
2. `image`-Eintrag erstellen (referenziert den `img`-Eintrag)
3. `image`-Slug in `rowXContent` des Posts eintragen
## Referenz-Handling
### ReferenceOrInlineField (Admin UI)
- `value` ist String → Reference-Modus (Slug-Picker)
- `value` ist Objekt ohne `_slug` → Inline-Modus (Felder direkt eingeben)
- `value` ist Objekt mit `_slug` → aufgelöste Referenz vom API → wird automatisch zu Reference-Modus normalisiert
Normalisierung: `admin-ui/src/components/ReferenceOrInlineField.tsx` via `normalizedValue` memo.
### Normalisierung beim Schreiben (Rust)
`validator::normalize_reference_arrays()` konvertiert vor dem Speichern:
- Einzelne `reference`/`referenceOrInline`-Felder: `{_slug: "foo", ...}``"foo"`
- Array-Items: gleiche Normalisierung per Element
- Aufgerufen in `create_entry` und `update_entry`
## Admin UI Konventionen
- **i18n**: next-intl, Cookie-basiert. Neue Keys immer in **beiden** Dateien eintragen: `admin-ui/messages/en.json` + `messages/de.json`
- **Tailwind v4**: `@plugin "tailwindcss-animate"` (nicht `@import`)
- **Kein Dark Mode**: `@media (prefers-color-scheme: dark)` wurde entfernt, keine `dark:`-Klassen
- **Scroll**: `html, body { height: 100%; overflow: hidden }` — Sidebar scrollt unabhängig von der Seite
- **Neue Komponente**: immer prüfen ob Übersetzungs-Namespace in beiden Message-Dateien vorhanden
## Axum Routing
Literale Routen haben Vorrang vor Wildcard-Routen — Reihenfolge egal, Axum löst korrekt auf:
```rust
.route("/api/assets/folders", get(...).post(...)) // matcht vor:
.route("/api/assets/*path", get(...).delete(...))
```
## Rust-spezifisch
- `clap` braucht Feature `"env"` für Env-Var-Support bei CLI-Args
- `AppState` in `src/api/handlers.rs` — alle neuen geteilten Ressourcen hier hinzufügen
- Hot-Reload: Änderungen in `types/` werden automatisch geladen (kein Neustart nötig)
- Cache wird bei Schreib-Operationen invalidiert (`cache.invalidate_collection()`)