feat: enhance medialib image handling and add asset URL resolution

- Implemented `resolveApiAssetUrl` function to normalize asset URLs based on API base.
- Updated `MedialibImage` component to utilize new asset URL resolution and added support for alt text and class properties.
- Enhanced image loading behavior with improved width measurement and focal point handling.
- Added placeholder image handling and improved accessibility with alt text.
- Introduced new test script for auditing broken links in skill documentation.
- Expanded seeded test content to include medialib entries and updated related tests for pagebuilder previews.
- Improved global setup and teardown logging for clarity on seeded content management.
This commit is contained in:
2026-05-17 00:52:41 +00:00
parent 958b45272d
commit 4020ad62c5
44 changed files with 4276 additions and 867 deletions
+106 -23
View File
@@ -2,6 +2,27 @@
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.
@@ -16,6 +37,23 @@ Tibi CMS starter template — Svelte 5 SPA with esbuild, SSR via goja, and Playw
- `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
@@ -39,9 +77,10 @@ Tibi CMS starter template — Svelte 5 SPA with esbuild, SSR via goja, and Playw
## API access
- `Token` header with `ADMIN_TOKEN` from `api/config.yml.env`.
- `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
@@ -54,26 +93,6 @@ Tibi CMS starter template — Svelte 5 SPA with esbuild, SSR via goja, and Playw
Generated dev defaults in `api/config.yml.env` may be committed. Production values are overwritten in CI/CD via secrets.
## Reference repositories (sibling repos)
| Repo | Path | Key file |
|------|------|----------|
| **tibi-types** | `../../cms/tibi-types` | `index.d.ts` (context types), `schemas/config/collection.schema.json` |
| **tibi-server** | `../../cms/tibi-server` | `docs/` (19 files: collections, hooks, auth, actions, SSE, jobs, etc.) |
| **tibi-admin-nova** | `../../cms/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/api/collections/` (examples)
- **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`
## TypeScript
```json
@@ -85,6 +104,53 @@ Generated dev defaults in `api/config.yml.env` may be committed. Production valu
- **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",
{ active: true },
"sort",
undefined,
undefined,
undefined,
undefined,
"blocks.heroImage.image:medialib"
)
// Ergebnis: entry._lookup enthält die aufgelösten Referenzen
```
Der `lookup`-Parameter muss als 8. Argument an `getCachedEntries` übergeben werden. Ohne lookup bleiben Referenzfelder reine ID-Werte ohne `_lookup`.
## Tailwind CSS 4
Canonical v4 syntax — no v3 legacy classes:
@@ -92,7 +158,7 @@ Canonical v4 syntax — no v3 legacy classes:
| v3 | v4 |
|----|----|
| `bg-gradient-to-*` | `bg-linear-to-*` |
| `aspect-[4/3]` | `aspect-4/3` |
| `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!` |
@@ -112,7 +178,7 @@ Use these tables as the lookup index. Each skill is a deep-dive for its domain.
| Skill | When |
|-------|------|
| `content-authoring` | Add pages, block types, collections |
| `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 |
@@ -128,6 +194,7 @@ Use these tables as the lookup index. Each skill is a deep-dive for its domain.
| `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
@@ -136,3 +203,19 @@ Use these tables as the lookup index. Each skill is a deep-dive for its domain.
| `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 |