Tippe, um Seiten und Abschnitte zu finden.

Zum Inhalt
Ginko

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:

Terminal
npm create ginko@latest meine-doku -- --preset docs --locale de

Er legt eine Seite mit zwei Beispielseiten an. Von Hand installierst du die Pakete:

Terminal
npm install @lupinum/ginko @lupinum/ginko-content @lupinum/ginko-i18n @lupinum/ginko-docs

Dann beschreibst du die Doku in ginko.config.ts:

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:

ts
// 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:

FeldWirkung
navTitleEin kurzer Titel für Seitennavigation, Brotkrumen und die Links „Zurück“ und „Weiter“, wenn der Titel dort zu lang ist.
sectionBeginnt in der Seitennavigation eine Gruppe mit dieser Überschrift. Die folgenden Seiten gehören bis zur nächsten section dazu.
tabBeginnt einen Reiter über der Seitennavigation, zum Beispiel „Anleitung“ und „Referenz“. Seiten folgen dem Reiter davor.
parentHängt die Seite unter eine andere: parent: docs/<name>.
iconEin Iconify-Name wie lucide:rocket, vor dem Titel in der Navigation. Nur in der Hauptsprache setzen.
badgeEin 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:

ts
// 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:

json
{ "docs": { "banner": { "v2": "Version 2 ist da." }, "nav": { "guide": "Anleitung" }, "footer": { "github": "GitHub" } } }
  • Die Datei liegt unter i18n/de.json (und i18n/en.json und so weiter). Die Seite Sprachen erklärt die Textdateien.
  • Interne Pfade in nav, footer.links und banner.href folgen der Sprache des Lesers: /guide wird zu /en/guide. Absolute URLs bleiben, wie sie sind.
  • Wer den Hinweis schließt, sieht ihn nicht wieder. Eine neue id zeigt 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.
  • repository ergänzt jede Seite aus einer Datei um „Diese Seite bearbeiten“, und bei GitHub um „Problem melden“. Für andere Hosts setzt du die Vorlagen editUrl ({url}, {branch}, {source}) und issueUrl ({url}, {title}, {page}).
  • Seiten von der Plattform zeigen ohne weitere Angabe kein „Diese Seite bearbeiten“, damit Besucher keinen Link ins Studio sehen. studioEditLink: true fü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.

ts
// ginko.config.ts
import { docsCollection, docsHome } from '@lupinum/ginko-docs/config'

// …
  bricks: { home: docsHome(), docs: docsCollection({ locales }) },
md
---
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:

ts
// 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 Beispiel content/posts/1.hallo.md. Das Frontmatter hat title, description, date (YYYY-MM-DD), authors, image, tags und slug. Ein Beitrag liegt unter /blog/<slug>; die Liste unter /blog zeigt den neuesten zuerst.
  • Autoren sind YAML-Dateien in content/authors/, zum Beispiel content/authors/jana.yml mit name, role, avatar und url. 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/, mit version und date im Frontmatter. Schreib den Dateinamen ohne Punkte (v1-2-0.md), denn ein Punkt gilt als Sprache. Die Seite /changelog zeigt 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:

ts
// 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 base an, /blog und /changelog nur, 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.vue behä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 anderen Docs*-Komponenten und die useDocs*-Composables sind intern und können sich ändern.
  • Titel: Seiten bekommen den Titel Seite · Name der Seite von Ginko (seo.titleTemplate in defineSite). Ein titleTemplate in app.head oder 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).
css
:root {
  --primary: var(--color-brand);
  --radius: 0.75rem;
  --docs-max: 82.5rem;
  --docs-top: 4.5rem;
}