Template
chore: YAML-Schemas in Dateiköpfe, tibi-types auf 4c55f82
deploy to production / deploy (push) Successful in 43s
deploy to production / deploy (push) Successful in 43s
- yaml-language-server-Schema direkt in jeder api-YAML statt .vscode/yaml.schemas-Mapping (exakter pro Datei, kein Glob-Rätsel) - erweiterte meta.agent-Doku in den Collections - tibi-types-Submodul auf 4c55f82 (meta.agent- + meta.query-Schemas)
This commit is contained in:
1 parent
7ef080ba88
commit
45a021fb53
10 files changed
+18
-21
No files matched your search
Vendored
-11
@@ -4,17 +4,6 @@
|
|||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.formatOnPaste": true,
|
"editor.formatOnPaste": true,
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"yaml.schemas": {
|
|
||||||
"./../../cms/tibi-types/schemas/config/project.schema.json": "api/config.y*ml",
|
|
||||||
// +([^/]) = nur Dateien direkt in api/collections/: der YAML-LS matcht mit
|
|
||||||
// picomatch { bash: true }, wo "*" auch "/" trifft und sonst fields/,
|
|
||||||
// fieldLists/ und lib/ fälschlich zusätzlich das Collection-Schema bekämen
|
|
||||||
"./../../cms/tibi-types/schemas/config/collection.schema.json": "api/collections/+([^/]).y*ml",
|
|
||||||
"./../../cms/tibi-types/schemas/config/field.schema.json": "api/collections/fields/*.y*ml",
|
|
||||||
"./../../cms/tibi-types/schemas/config/field-list.schema.json": "api/collections/fieldLists/*.y*ml",
|
|
||||||
"./../../cms/tibi-types/schemas/config/job.schema.json": "api/jobs/*.y*ml",
|
|
||||||
"./../../cms/tibi-types/schemas/config/asset.schema.json": "api/assets/*.y*ml"
|
|
||||||
},
|
|
||||||
"yaml.customTags": ["!include scalar"],
|
"yaml.customTags": ["!include scalar"],
|
||||||
"filewatcher.commands": [
|
"filewatcher.commands": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=../../tibi-types/schemas/config/collection.schema.json
|
||||||
name: comment
|
name: comment
|
||||||
uploadPath: ../media/comment
|
uploadPath: ../media/comment
|
||||||
audit:
|
audit:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=../../tibi-types/schemas/config/collection.schema.json
|
||||||
########################################################################
|
########################################################################
|
||||||
# Content collection — CMS-managed pages with pagebuilder blocks
|
# Content collection — CMS-managed pages with pagebuilder blocks
|
||||||
########################################################################
|
########################################################################
|
||||||
@@ -38,8 +39,8 @@ meta:
|
|||||||
translationKey: "required, e.g. home/ueber-uns/kontakt; unique per lang"
|
translationKey: "required, e.g. home/ueber-uns/kontakt; unique per lang"
|
||||||
blocks: "type selects visible fields via dependsOn $parent.type"
|
blocks: "type selects visible fields via dependsOn $parent.type"
|
||||||
examples: [{ name: "Startseite", path: "/", lang: "de", translationKey: "home", active: true }]
|
examples: [{ name: "Startseite", path: "/", lang: "de", translationKey: "home", active: true }]
|
||||||
workflows: ["filter before create (path+lang) to stay idempotent; 409 means exists", "after PUT/DELETE verify /de and /api/content?lookup; SSR invalidates via clear_cache hooks"]
|
workflows: ["filter before create (path+lang) to stay idempotent; 409 means exists", "after PUT/DELETE verify /de and anonymous SSR HTML (window.__SSR_CACHE__: navigation count>0, heroImage/image with _lookup); PAT-only lookup success is NOT sufficient; SSR invalidates via clear_cache hooks"]
|
||||||
hints: ["richtext image only renders when _lookup.image.file.src exists", "hero fallback is gradient when no image"]
|
hints: ["richtext image only renders when _lookup.image.file.src exists", "hero fallback is gradient when no image", "images/nav invisible publicly until their medialib/navigation docs carry active:true (verified incident 2026-10-05)"]
|
||||||
|
|
||||||
hooks:
|
hooks:
|
||||||
get:
|
get:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=../../../tibi-types/schemas/config/image-filter.schema.json
|
||||||
xs-webp:
|
xs-webp:
|
||||||
- width: 100
|
- width: 100
|
||||||
height: 100
|
height: 100
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=../../tibi-types/schemas/config/collection.schema.json
|
||||||
########################################################################
|
########################################################################
|
||||||
# Media library — reusable uploaded assets referenced via foreignMedia
|
# Media library — reusable uploaded assets referenced via foreignMedia
|
||||||
########################################################################
|
########################################################################
|
||||||
@@ -42,12 +43,12 @@ meta:
|
|||||||
file.type_like: ^(?!image/|video/|audio/).+
|
file.type_like: ^(?!image/|video/|audio/).+
|
||||||
agent:
|
agent:
|
||||||
purpose: "Reusable uploads referenced via foreignMedia (blocks.heroImage.image, blocks.image)."
|
purpose: "Reusable uploads referenced via foreignMedia (blocks.heroImage.image, blocks.image)."
|
||||||
instructions: "Upload file as object {src:'data:<mime>;base64,...', path:'name.jpg'} (path optional). Stored as {src:'<field>/name.jpg', path, type}. Never {filename,data}, never file as plain string. Public read URL: /api/medialib/<entryId>/<src> plus ?filter=l-webp for raster images. downscale max 2048px applies on upload."
|
instructions: "Upload file as object {src:'data:<mime>;base64,...', path:'name.jpg'} (path optional). Stored as {src:'<field>/name.jpg', path, type}. Never {filename,data}, never file as plain string. Public read URL: /api/medialib/<entryId>/<src> plus ?filter=l-webp for raster images. downscale max 2048px applies on upload. GOTCHA 2026-10-05: filter_public.js forces active:true on anonymous reads although this schema declares no active field – without stored active:true every medialib lookup stays unresolved publicly (plain IDs, no _lookup, HeroBlock renders gradient fallback and Richtext images vanish) although PAT reads succeed. Always store active:true on every medialib doc."
|
||||||
fieldHints:
|
fieldHints:
|
||||||
file: "required, widget file, max 50MB"
|
file: "required, widget file, max 50MB"
|
||||||
alt: "object {de,en}, used by MedialibImage for accessibility"
|
alt: "object {de,en}, used by MedialibImage for accessibility"
|
||||||
examples: [{ title: "Demo Hero 1200", file: { src: "data:image/jpeg;base64,...", path: "demo-hero-1200.jpg" } }]
|
examples: [{ title: "Demo Hero 1200", file: { src: "data:image/jpeg;base64,...", path: "demo-hero-1200.jpg" }, active: true }]
|
||||||
hints: ["list with select excluding file.data to avoid context bloat", "verify file.src starts with <field>/ after create"]
|
hints: ["list with select excluding file.data to avoid context bloat", "verify file.src starts with <field>/ after create", "missing active:true => public lookups unresolved (verified incident 2026-10-05)"]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=../../tibi-types/schemas/config/collection.schema.json
|
||||||
########################################################################
|
########################################################################
|
||||||
# Navigation collection — header and footer navigation entries
|
# Navigation collection — header and footer navigation entries
|
||||||
########################################################################
|
########################################################################
|
||||||
@@ -51,12 +52,12 @@ meta:
|
|||||||
label: { de: "Einstellungen", en: "Settings" }
|
label: { de: "Einstellungen", en: "Settings" }
|
||||||
agent:
|
agent:
|
||||||
purpose: "Header/footer trees per language, rendered by App.svelte from elements."
|
purpose: "Header/footer trees per language, rendered by App.svelte from elements."
|
||||||
instructions: "Singletons: type header/footer x language de/en (unique type+language). elements: {name, page->content.id} internal, {name, external:true, externalUrl} external, optional hash without #. Always request lookup elements.page:content; href = localizedPath(_lookup.page.path) + hash."
|
instructions: "Singletons: type header/footer x language de/en (unique type+language). elements: {name, page->content.id} internal, {name, external:true, externalUrl} external, optional hash without #. Always request lookup elements.page:content; href = localizedPath(_lookup.page.path) + hash. GOTCHA 2026-10-05: filter_public.js forces active:true on anonymous reads although this schema declares no active field – without stored active:true the header/footer query returns count 0 publicly (PAT reads still succeed). Always store active:true on every navigation doc."
|
||||||
fieldHints:
|
fieldHints:
|
||||||
type: "header or footer"
|
type: "header or footer"
|
||||||
language: "de or en"
|
language: "de or en"
|
||||||
examples: [{ language: "de", type: "header", elements: [{ name: "Start", page: "<content.id>" }] }]
|
examples: [{ language: "de", type: "header", elements: [{ name: "Start", page: "<content.id>" }] }]
|
||||||
hints: ["page holds content.id, resolve via _lookup.page.path", "never hardcode /de prefix in DB"]
|
hints: ["page holds content.id, resolve via _lookup.page.path", "never hardcode /de prefix in DB", "missing active:true => public nav empty + SSR count 0 (verified incident 2026-10-05)"]
|
||||||
|
|
||||||
hooks:
|
hooks:
|
||||||
get:
|
get:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=../../tibi-types/schemas/config/collection.schema.json
|
||||||
########################################################################
|
########################################################################
|
||||||
# SSR Dummy collections
|
# SSR Dummy collections
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=../../tibi-types/schemas/config/collection.schema.json
|
||||||
########################################################################
|
########################################################################
|
||||||
# Tags — verwaltete Schlagwörter für Mediathek und andere Collections
|
# Tags — verwaltete Schlagwörter für Mediathek und andere Collections
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|||||||
+3
-2
@@ -1,3 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=../tibi-types/schemas/config/project.schema.json
|
||||||
namespace: __TIBI_NAMESPACE__
|
namespace: __TIBI_NAMESPACE__
|
||||||
|
|
||||||
meta:
|
meta:
|
||||||
@@ -8,8 +9,8 @@ meta:
|
|||||||
lookup: "content: blocks.heroImage.image:medialib, blocks.image:medialib; navigation: elements.page:content; comments via aggregate on comment.contentId"
|
lookup: "content: blocks.heroImage.image:medialib, blocks.image:medialib; navigation: elements.page:content; comments via aggregate on comment.contentId"
|
||||||
rendering: "App.svelte loads getCachedEntries(content, {lang, path, active:true} + lookup); BlockRenderer maps Hero/Features/Richtext/Accordion/ContactForm; images only via widgets/MedialibImage.svelte"
|
rendering: "App.svelte loads getCachedEntries(content, {lang, path, active:true} + lookup); BlockRenderer maps Hero/Features/Richtext/Accordion/ContactForm; images only via widgets/MedialibImage.svelte"
|
||||||
designGuide: "Future free code/HTML blocks: add block type in content.blocks (type + fields with dependsOn $parent.type), Svelte component in frontend/src/blocks/ + case in BlockRenderer.svelte, keep admin preview contract; Svelte 5 runes ($props/$state/$derived, never destructure block), SSR-safe (window guards), MedialibImage is the only image boundary (file.src or data URI, no ?filter on data URIs), Tailwind v4 canonical (bg-linear-to-*, aspect-video/square else arbitrary, trailing ! e.g. bg-brand-600!), i18n via svelte-i18n ($_), always pass foreignMedia lookup explicitly"
|
designGuide: "Future free code/HTML blocks: add block type in content.blocks (type + fields with dependsOn $parent.type), Svelte component in frontend/src/blocks/ + case in BlockRenderer.svelte, keep admin preview contract; Svelte 5 runes ($props/$state/$derived, never destructure block), SSR-safe (window guards), MedialibImage is the only image boundary (file.src or data URI, no ?filter on data URIs), Tailwind v4 canonical (bg-linear-to-*, aspect-video/square else arbitrary, trailing ! e.g. bg-brand-600!), i18n via svelte-i18n ($_), always pass foreignMedia lookup explicitly"
|
||||||
workflows: ["Create page (name, path, lang, translationKey, active:true) -> fill blocks -> link navigation -> verify /de plus /api/content?lookup -> respect SSR cache (POST creates, PUT/DELETE invalidate via clear_cache hooks)", "Upload image (medialib file {src:data URI, path}) -> put ID into heroImage.image or blocks.image -> verify with lookup (file.src must be <field>/<name>)"]
|
workflows: ["Create page (name, path, lang, translationKey, active:true) -> fill blocks -> link navigation -> set active:true on touched navigation/medialib docs -> verify /de plus anonymous SSR (navigation count>0, _lookup resolved) -> respect SSR cache (POST creates, PUT/DELETE invalidate via clear_cache hooks)", "Upload image (medialib file {src:data URI, path} + active:true) -> put ID into heroImage.image or blocks.image -> verify with anonymous lookup (file.src must be <field>/<name>), PAT-only success is not sufficient"]
|
||||||
hints: ["Public reads need active:true plus publication window (filter_public)", "path pattern ^/[a-z0-9-/]*$ (lowercase, no umlauts)", "translationKey+lang and path+lang are unique: always set translationKey, else second doc collides on null/de", "File upload: {src:'data:<mime>;base64,...', path:'n.jpg'} (path optional); stored {src:'<field>/n.jpg', type}; never {filename,data}, never file as plain string", "Reads with select/projection excluding file.data (else context bloat); file.src is enough", "SSR cache lives in ssr collection with dependencies content:<id>/content:*/medialib:*/navigation:*/comment:*; after manual MCP writes use ssr?clear=1 if needed"]
|
hints: ["Public reads need active:true plus publication window (filter_public) – applies to content AND navigation AND medialib. Navigation/medialib schemas declare no active field, yet anonymous/SSR queries return empty without it: always store active:true on those docs too (accepted as extra field). Symptom of missing flag: header/footer nav count 0 and medialib lookups unresolved (plain IDs, no _lookup) although PAT reads succeed", "path pattern ^/[a-z0-9-/]*$ (lowercase, no umlauts)", "translationKey+lang and path+lang are unique: always set translationKey, else second doc collides on null/de", "File upload: {src:'data:<mime>;base64,...', path:'n.jpg'} (path optional); stored {src:'<field>/n.jpg', type}; never {filename,data}, never file as plain string", "Reads with select/projection excluding file.data (else context bloat); file.src is enough", "SSR cache lives in ssr collection with dependencies content:<id>/content:*/medialib:*/navigation:*/comment:*; after manual MCP writes use ssr?clear=1 if needed", "Verify public rendering via anonymous SSR HTML (window.__SSR_CACHE__: navigation count>0, heroImage/image with _lookup), never trust PAT-only lookups"]
|
||||||
imageUrl:
|
imageUrl:
|
||||||
eval: "$projectBase + '_/assets/img/admin-pic.svg'"
|
eval: "$projectBase + '_/assets/img/admin-pic.svg'"
|
||||||
i18n:
|
i18n:
|
||||||
|
|||||||
+1
-1
Submodule tibi-types updated: 5e04a1ca3a...4c55f82446.
Reference in new issue
Block a user