Doku-Seiten
Die Doku-Ebene @lupinum/ginko-docs. Eine ganze Doku-Seite aus Markdown-Dateien oder eine Doku in einer bestehenden Seite. Optionen, Startseite, Blog, Changelog, Farben.
Was die Ebene mitbringt
@lupinum/ginko-docs ist eine Nuxt-Ebene (Layer) für Dokumentation. Diese Doku ist damit gebaut. Du schreibst die Seiten als Markdown-Dateien in content/docs/; die Ebene bringt alles drumherum:
- eine Kopfzeile mit Suche (⌘K), Sprachmenü und Hell/Dunkel-Schalter,
- die Seitennavigation mit Abschnitten und Reitern, Brotkrumen, ein Inhaltsverzeichnis, das beim Scrollen mitläuft, und Links auf die vorige und nächste Seite,
- die Markdown-Komponenten von
@lupinum/ginko-components(Hinweise, Tabs, Schritte, Code-Gruppen und mehr), - Formeln mit KaTeX und
mermaid-Diagramme, nur auf Seiten geladen, die sie nutzen, - „Seite kopieren“ als Markdown, „Diese Seite bearbeiten“ und „Problem melden“,
- auf Wunsch eine Startseite, einen Blog mit RSS und einen Changelog.
Jede Seite gibt es auch als Markdown für Agenten, und die Ebene bringt einen MCP-Zugang zur Doku. Die Seite SEO und Agenten erklärt beides.
Eine Doku-Seite starten
Am schnellsten geht es mit dem Starter:
npm create ginko@latest meine-doku -- --preset docs --locale deEr legt eine Seite mit zwei Beispielseiten an. Von Hand installierst du die Pakete:
npm install @lupinum/ginko @lupinum/ginko-content @lupinum/ginko-i18n @lupinum/ginko-docsDann beschreibst du die Doku in ginko.config.ts:
// ginko.config.ts
import { defineSite } from '@lupinum/ginko'
import { components, docsCollection } from '@lupinum/ginko-docs/config'
const locales = ['de', 'en'] as const
export default defineSite({
site: 'meine-doku',
name: 'Meine Doku',
url: 'https://docs.example.com',
timeZone: 'Europe/Vienna',
locales,
currency: 'EUR',
pages: { home: { de: '/', en: '/en' } },
components,
bricks: { docs: docsCollection({ locales }) },
})components ist die Komponenten-Registry von @lupinum/ginko-components, die die Ebene mitbringt. Damit prüft Ginko jeden Komponenten-Tag und jede Prop in deinen Seiten. Ohne sie geht ein vertipptes ::calout ohne Fehler durch.
In nuxt.config.ts erweiterst du die Ebene:
// nuxt.config.ts
import ginko from './ginko.config.ts'
export default defineNuxtConfig({
compatibilityDate: '2026-10-01',
extends: ['@lupinum/ginko-docs'],
modules: ['@lupinum/ginko/nuxt'],
ginko,
})Die Doku-Seiten liegen unter /docs/<slug>, in anderen Sprachen unter /<sprache>/docs/<slug>. docsCollection({ locales, base: '/handbuch' }) verschiebt sie. Ohne Startseite öffnet / die erste Doku-Seite.
Die Ebene findet ihre Inhalte über den Schlüssel des Bausteins. Behalte diese Namen: docs, home, posts, authors und changelog. Nur docs ist Pflicht.
Nur der Doku-Baustein darf anders heißen, etwa wissen auf einer deutschen Seite. Gib den Schlüssel dem Baustein und der Ebene: docsCollection({ locales, brick: 'wissen' }) in ginko.config.ts und ginkoDocs: { brick: 'wissen' } in nuxt.config.ts. Links auf seine Seiten heißen dann $wissen.<seite>.
Seiten schreiben
Jede Datei in content/docs/ ist eine Seite. Die Zahl im Dateinamen legt die Reihenfolge fest, wie auf Inhalte aus Dateien. Neben title und description kennt das Frontmatter:
| Feld | Wirkung |
|---|---|
navTitle | Ein kurzer Titel für Seitennavigation, Brotkrumen und die Links „Zurück“ und „Weiter“, wenn der Titel dort zu lang ist. |
section | Beginnt in der Seitennavigation eine Gruppe mit dieser Überschrift. Die folgenden Seiten gehören bis zur nächsten section dazu. |
tab | Beginnt einen Reiter über der Seitennavigation, zum Beispiel „Anleitung“ und „Referenz“. Seiten folgen dem Reiter davor. |
parent | Hängt die Seite unter eine andere: parent: docs/<name>. |
icon | Ein Iconify-Name wie lucide:rocket, vor dem Titel in der Navigation. Nur in der Hauptsprache setzen. |
badge | Ein kurzes Kennzeichen nach dem Titel, zum Beispiel „Beta“. |
Braucht deine Seite keine Reiter, Kennzeichen und Symbole, lässt docsCollection({ locales, navExtras: false }) die Felder tab, badge und icon weg. Wer die Seiten im Studio pflegt, sieht dann nur Text, Abschnitt, übergeordnete Seite und Kurztitel. Setz es, wenn die Seite neu ist: Auf einer Seite mit veröffentlichten Seiten entfernt es Felder, und das lehnt die Plattform ab; leg die drei Felder dann still (retired).
Die lucide-Symbole sind installiert. Ein anderes Iconify-Set geht, sobald du es installierst (npm install -D @iconify-json/<set>). Die Symbole werden beim Build gebündelt; die Seite ruft keinen Symbol-Dienst auf.
Optionen
Die Optionen stehen in der app.config.ts der Seite. Alle sind optional:
// app/app.config.ts
export default defineAppConfig({
docs: {
title: 'Meine Doku', // Text in der Kopfzeile neben dem Logo (Standard: `name` aus ginko.config.ts)
logo: { light: '/logo.svg', dark: '/logo-dark.svg' }, // `wordmark: true`, wenn das Bild den Namen enthält
theme: 'default', // Farbvorlage: 'default' (Smaragd auf Zink) oder 'green' (Grün auf Schiefer)
nav: [{ id: 'guide', href: '/guide' }], // Links in der Kopfzeile nach Doku, Blog und Changelog
social: [{ icon: 'docs:github', href: 'https://github.com/me/docs', label: 'GitHub' }],
banner: { id: 'v2', href: '/docs/changes' }, // ein Hinweis über der Kopfzeile, den Leser schließen können
repository: { url: 'https://github.com/me/docs', branch: 'main' }, // „Diese Seite bearbeiten“, „Problem melden“
markdownActions: { copy: true, openIn: ['chatgpt', 'claude'] }, // „Seite kopieren“ und die Chats seines Menüs
footer: { links: [{ id: 'github', href: 'https://github.com/me/docs' }], attribution: true },
},
})Die Texte von nav, footer.links und banner kommen aus den Textdateien der Seite, so hat jede Sprache ihre eigenen. Jede id wählt einen Text:
{ "docs": { "banner": { "v2": "Version 2 ist da." }, "nav": { "guide": "Anleitung" }, "footer": { "github": "GitHub" } } }- Die Datei liegt unter
i18n/de.json(undi18n/en.jsonund so weiter). Die Seite Sprachen erklärt die Textdateien. - Interne Pfade in
nav,footer.linksundbanner.hreffolgen der Sprache des Lesers:/guidewird zu/en/guide. Absolute URLs bleiben, wie sie sind. - Wer den Hinweis schließt, sieht ihn nicht wieder. Eine neue
idzeigt ihn allen. - Eingebaute
social-Symbole:docs:github,docs:discord,docs:x,docs:bluesky,docs:mastodon,docs:linkedin,docs:youtube. Jeder andere Iconify-Name geht auch. repositoryergänzt jede Seite aus einer Datei um „Diese Seite bearbeiten“, und bei GitHub um „Problem melden“. Für andere Hosts setzt du die VorlageneditUrl({url},{branch},{source}) undissueUrl({url},{title},{page}).- Seiten von der Plattform zeigen ohne weitere Angabe kein „Diese Seite bearbeiten“, damit Besucher keinen Link ins Studio sehen.
studioEditLink: truefügt ihn hinzu und führt zum Formular der Seite im Studio. Setz es für Doku, die nur Bearbeiter lesen.
Startseite
docsHome() ergänzt eine Startseite: eine Datei content/home.md, dazu home.<sprache>.md pro Übersetzung. Das Frontmatter füllt den Kopf der Seite und das Raster der Merkmale. Der Text unter dem Frontmatter folgt darauf und kann jede Komponente nutzen.
// ginko.config.ts
import { docsCollection, docsHome } from '@lupinum/ginko-docs/config'
// …
bricks: { home: docsHome(), docs: docsCollection({ locales }) },---
title: Doku für meine Bibliothek.
description: Ein Satz dazu, was sie tut.
install: npm install my-library
links:
- { label: Loslegen, href: /docs/einfuehrung }
- { label: GitHub, href: https://github.com/me/lib }
features:
- { icon: lucide:zap, title: Schnell, description: Warum sie schnell ist., href: /docs/tempo }
---install zeigt einen Befehl mit Kopier-Knopf. links hat bis zu zwei Knöpfe; der erste ist der wichtigste. Eine eigene app/pages/index.vue der Seite gewinnt gegen die Startseite.
Blog und Changelog
Beide sind optional. Trage die Bausteine und ihre Seiten in ginko.config.ts ein; die Ebene ergänzt dann die Seiten und die Links in der Kopfzeile:
// ginko.config.ts
import { blogCollections, blogPages, changelogCollection, changelogPages, docsCollection } from '@lupinum/ginko-docs/config'
export default defineSite({
// …
pages: { home: { de: '/', en: '/en' }, blog: blogPages({ locales }), changelog: changelogPages({ locales }) },
bricks: { docs: docsCollection({ locales }), ...blogCollections({ locales }), changelog: changelogCollection() },
})- Beiträge sind Dateien in
content/posts/, zum Beispielcontent/posts/1.hallo.md. Das Frontmatter hattitle,description,date(YYYY-MM-DD),authors,image,tagsundslug. Ein Beitrag liegt unter/blog/<slug>; die Liste unter/blogzeigt den neuesten zuerst. - Autoren sind YAML-Dateien in
content/authors/, zum Beispielcontent/authors/jana.ymlmitname,role,avatarundurl. Ein Beitrag nennt sie über die ID:authors: [authors/jana]. Autoren haben keine eigene Seite. - RSS:
/blog/rss.xml, für andere Sprachen/<sprache>/blog/rss.xml. Der Feed enthält Titel und Beschreibung, nicht den ganzen Text. - Changelog: eine Datei pro Version in
content/changelog/, mitversionunddateim Frontmatter. Schreib den Dateinamen ohne Punkte (v1-2-0.md), denn ein Punkt gilt als Sprache. Die Seite/changelogzeigt alle Versionen, die neueste zuerst, jede mit einem Anker wie#v1-2-0.
blogPages und changelogPages tragen die Listenseiten in pages ein, damit die Sitemap und der statische Build sie kennen. Fehlen sie, warnt der Build.
Farben und Schriften
Farben, Radius, Schriften und Maße sind CSS-Tokens, und jeder Wert deiner Seite gewinnt über die Vorgaben. Die Tokens, die zwei Presets, hell und dunkel und die Override-Stellen stehen auf Aussehen anpassen. Alle öffentlichen Exporte der Ebene stehen auf Exporte der Doku-Ebene.
In einer bestehenden Seite
Die Ebene kann eine Doku auch in eine Seite bringen, die schon ein eigenes Design, eigene Seiten und ein eigenes Layout hat, zum Beispiel ein Handbuch unter /handbuch auf einer Firmenseite. Erweitere die Ebene wie oben und trage den Doku-Baustein neben die eigenen Bausteine ein:
// ginko.config.ts der bestehenden Seite
import { components, docsCollection } from '@lupinum/ginko-docs/config'
// …
components: { ...components /* , die eigenen Komponenten der Seite: derselbe Name gewinnt */ },
bricks: { docs: docsCollection({ locales, base: '/handbuch' }) /* , die eigenen Bausteine */ },- Nur die Doku-Seiten kommen dazu. Die Ebene meldet die Doku unter ihrer
basean,/blogund/changelognur, wenn es diese Bausteine gibt, und/nur, wenn die Seite keine eigene Startseite hat. Eine Seite, die die Seite selbst definiert, gewinnt immer. - Der Rahmen der Seite bleibt. Mit einem eigenen
layouts/default.vuebehält die Seite ihre Kopf- und Fußzeile, und die Doku (Navigation, Seite, Inhaltsverzeichnis) sitzt darin. Auf dem Handy öffnet sich die Navigation aus einer Leiste über der Seite. - Nichts läuft aus. Jede Regel der Ebene hängt an einer Klasse
docs-. Suche, Sprachmenü und Hell/Dunkel-Schalter sind Komponenten, die die Seite in ihre eigene Kopfzeile setzen kann:<DocsSearch />,<DocsLanguage />,<DocsThemeToggle />. Diese drei sind die öffentlichen Komponenten (<DocsThemeToggle segmented />zeigt den Dreifach-Schalter Auto/Hell/Dunkel). Alle anderenDocs*-Komponenten und dieuseDocs*-Composables sind intern und können sich ändern. - Titel: Seiten bekommen den Titel
Seite · Name der Seitevon Ginko (seo.titleTemplateindefineSite). EintitleTemplateinapp.headoder von nuxt-seo-utils gilt für sie nicht, so erscheint der Name nie doppelt. - Gestaltung: Ordne die Design-Tokens der Seite den Token-Namen auf Aussehen anpassen zu. Zwei Layout-Tokens richten die Doku an der Seite aus:
--docs-max(die Breite des Inhaltsbereichs der Seite) und--docs-top(die Höhe einer festen Kopfzeile, oder ein kleiner Abstand, wenn die Kopfzeile wegscrollt).
:root {
--primary: var(--color-brand);
--radius: 0.75rem;
--docs-max: 82.5rem;
--docs-top: 4.5rem;
}