- Einstieg: Schnellstart + Neues Projekt aus Starter-Skill, Was-ist-Tibi mit Backend/Website-Trennung - Projekt: Sammlungen, Felder, Abfragen, Rechte, Hooks, Dateien, i18n, Suche, SSR, Pagebuilder, Jobs, Audit, Deploy, LLM, MCP - Hook-Referenz: 66 Symbole mit Signatur + Beispiel + Fehlerfall (5 Kapitel) - Admin: Ansichten, Editor, Medien, Exporte, Aktionen, Rechte, KI, Setup, Customizing - Anwender: 11 Anleitungen im professionellen Du-Ton, 30 Corporate-Screenshots - Referenz: Schemas, Token-Köpfe, Fehlerbilder, Shortcuts, OpenAPI-Platzhalter - ADR-0001 bis 0003, Coverage-Skript (282 Items) + Map, Plan-Dateien
6.3 KiB
title, description
| title | description |
|---|---|
| Sammlungen anlegen | Eigene Collection in api/collections definieren: Schema, Meta, Indizes, Suche. |
import { Aside, Steps, FileTree } from '@astrojs/starlight/components';
Eine Sammlung (Collection) ist eine Tabelle deines Projekts.
Du legst sie als YAML-Datei in api/collections/ an.
Der Dateiname ist frei, entscheidend ist das Feld name.
Beispiel-Sammlungen zum Abschauen: content, navigation, medialib, tag, comment.
- api/
- collections/
- content.yml
- navigation.yml
- medialib.yml
- tag.yml
- comment.yml
- collections/
Minimal-Beispiel
Die kleinste Sammlung braucht name und permissions (beides Pflicht laut Schema) — fields ist dagegen optional.
Abgeschaut von tag.yml (vereinfacht):
# api/collections/notiz.yml
# yaml-language-server: $schema=../../tibi-types/schemas/config/collection.schema.json
name: notiz
uploadPath: ../media/notiz
audit:
enabled: true
permissions:
public:
methods:
get: true
user:
methods:
get: true
post: true
put: true
delete: true
indexes:
- name: name_unique
key:
- name
unique: true
background: true
search:
- name: default
mode: regex
fields: [name, text]
fields:
- name: name
type: string
meta:
label: { de: "Name", en: "Name" }
- name: text
type: string
meta:
label: { de: "Text", en: "Text" }
- Datei
api/collections/<name>.ymlanlegen, Schema-Zeile aus dem Beispiel kopieren. namekleinschreiben, keine Umlaute und keine Leerzeichen (content,tag,commentals Vorbild).permissionssetzen — sonst liest niemand die Daten (Details: Rechte und Tokens).uploadPathsetzen, auch wenn die Sammlung keine Dateien enthält (../media/<name>wie in allen Starter-Sammlungen).- Projekt neu laden, damit der tibi-server die Datei einliest.
- Testen:
POSTanlegen, doppelten Wert schicken →409bei Unique-Index.
Meta: Label, Gruppe, Icon, Vorschau
meta steuert, wie tibi-admin die Sammlung anzeigt.
Pflicht ist nichts davon — aber ohne label rätst du im Admin.
| Schlüssel | Wirkung | Beispiel aus dem Starter |
|---|---|---|
label |
Anzeigename (de/en) |
tag.yml: { de: "Schlagwörter", en: "Tags" } |
group |
Gruppierung in der Navigation | content, content, community (comment.yml) |
muiIcon |
Icon im Admin | label, menu, chat, folder-multiple-image |
imageUrl |
Vorschaubild für Karten | Unsplash-URL in content.yml |
preview |
Listenvorschau: label, secondary, tertiary, image |
content.yml: label: name, secondary: path, tertiary: lang |
viewHint |
Darstellungsart im Admin | siehe unten |
sidebar |
Eigene Seitenleiste mit Gruppen | content.yml: publishing, seo |
i18n.entry |
Übersetzungs-Kopplung | content.yml: languageField: lang, groupField: translationKey |
Felder positionierst du mit meta.position: main, sidebar:<gruppe> oder sidebar:settings.
Beispiel: lang liegt in content.yml auf sidebar:settings, active auf sidebar:publishing.
viewHint aus dem Starter (geprüft, alle drei Varianten):
viewHint: cards— Kartenansicht (content.yml).viewHint.media— Medienansicht mit Upload und KI-Alt-Text (medialib.yml).viewHint.navigation— Baumansicht mitnodesFieldunddeclaredTrees(navigation.yml, Bäume: Header/Footer je Sprache).
Indizes und Suche
Indizes
Jeder Eintrag in indexes braucht nur key (name ist freiwillig).
key ist eine Liste von Feldnamen, Text-Index mit "$text:$**".
# aus content.yml — Text-Index plus zwei Unique-Indizes
indexes:
- name: content_text
key:
- "$text:$**"
defaultLanguage: none
background: true
- name: path_lang
key:
- path
- lang
unique: true
background: true
- name: translation
key:
- translationKey
- lang
unique: true
background: true
unique: true schützt vor Doppelten: der zweite POST mit gleichem path + lang scheitert — modern mit 409, im Legacy-Default (Standard) mit 500 (siehe Fehlerbilder).
So erzwingt der Starter auch einzelne Navigationsbäume (type_language in navigation.yml) und einzelne Tag-Namen (name_unique in tag.yml).
Suche
Jeder Eintrag in search braucht nur name und mode (fields ist freiwillig).
Vier Modi kommen im Starter vor:
| Modus | Wofür | Beispiel |
|---|---|---|
regex |
Einfache Teilstringsuche | tag.yml, navigation.yml, comment.yml: default |
ngram |
Fehlertolerante Fuzzy-Suche | content.yml: fuzzy mit autoRegenerate: true |
vector |
Semantische Vektorsuche | content.yml: semantic mit vector: { provider: bge_m3 } |
combined |
Hybrid aus semantisch + fuzzy (RRF) | content.yml: combined mit rrf: { k: 60, topK: 100 } |
Abfrage dazu: GET …/content?q=…&qName=combined.
Details stehen unter Lesen und suchen.
Häufige Fehler
| Fehlerbild | Ursache | Lösung |
|---|---|---|
409 beim Anlegen |
unique-Index verletzt (path+lang, translationKey+lang, Tag-name) |
Vor POST per filter prüfen, ob der Datensatz schon existiert |
project not found |
Projekt nicht registriert oder Namespace falsch | Siehe Neues Projekt Schritt 5 |
| Validierung schlägt fehl | Pflichtfeld fehlt oder pattern verletzt (z. B. path ohne führenden /) |
Feldregeln stehen unter Felder und Widgets |
| Öffentlich leere Liste, mit Token voll | active:true fehlt — der filter_public-Hook filtert alles weg |
Siehe Rechte und Tokens |
| Datei-Upload landet falsch | uploadPath fehlt oder zeigt ins falsche Verzeichnis |
../media/<name> wie in allen Starter-Sammlungen setzen |
Verifiziert am e3f92eb 2026-10-14 (tibi-svelte-starter), am 4c55f82 2026-10-12 (tibi-types).