Eigene Seiten und Solid
Serverseitig gerenderte Anwendungsseiten in die Fibel-Shell einbinden und ihren Markdown-Inhalt für Suche und Dokumentationsassistent erhalten.
Eigene Seiten platzieren Anwendungsausgaben im normalen Routing und Layout von Fibel. Header, Sidebar, Suche, Theme, SEO, Markdown-Routen und Dokumentationsassistent bleiben bei Fibel. Die Host-Anwendung rendert weiterhin ihre eigenen Komponenten.
Eine framework-neutrale Seite ergänzen
Seitendefinitionen werden in die Fibel-Konfiguration aufgenommen:
import { defineFibel } from "@k2b/fibel";
export default defineFibel({
title: "Cloud UI",
locales: [
{ code: "en", label: "English" },
{ code: "de", label: "Deutsch" },
],
pages: [
{
path: "/panel-header",
title: "PanelHeader",
description: "Ein einheitlicher Bereich für Titel und Aktionen.",
section: "Komponenten",
order: 10,
content: {
default: panelHeaderMarkdown,
de: panelHeaderMarkdownDe,
},
render: ({ content }) =>
`<section class="panel-showcase">${content.html}</section>`,
},
],
});Fibel erzeugt die Seite unter jedem konfigurierten Locale. Im Beispiel entstehen /en/panel-header und /de/panel-header.
content.default ist der sprachneutrale Fallback. Locale-Schlüssel überschreiben ihn nur dort, wo eine Übersetzung vorliegt. Ein einzelner String reicht aus, wenn alle Locales denselben Inhalt erhalten sollen.
Der Render-Callback erhält beide Formen:
content.markdownwird von der Suche indexiert und über rohe.md-Routen,llms.txtsowie das bestehenderead_doc-Tool des Assistenten bereitgestellt.content.htmlwird einmal mit dem Markdown-Renderer von Fibel erzeugt und kann auf der Seite angezeigt werden.
Damit bleiben die durchsuchbare Erklärung und die sichtbare Komponentendokumentation in einer Quelle. Fibel leitet keine Dokumentation aus gerendertem HTML ab.
Die bisherigen context-Eigenschaften der Definition und des Render-Callbacks bleiben als deprecated Aliase für die Migration erhalten. Fibel warnt bei ihrer Verwendung. Enthält eine Definition sowohl content als auch context, hat content Vorrang.
Das Body-Layout wählen
layout: "article" ist der Standard. Dieses Layout ergänzt den eigenen Body um Seitentitel, Beschreibung, Chips, Markdown-Typografie und Vor-/Zurück-Navigation.
layout: "full" behält Header, Sidebar, Footer, Suche und Assistent, stellt der Komponente aber einen breiteren Body ohne Artikel-Chrome bereit:
{
path: "/catalog",
title: "Komponentenkatalog",
description: "Gemeinsame UI-Komponenten durchsuchen.",
layout: "full",
content: catalogMarkdown,
render: ({ content }) =>
`<div class="catalog">${content.html}</div>`,
}Solid-Komponenten und Islands rendern
Der optionale Einstiegspunkt @k2b/fibel/solid verbindet eine eigene Seite mit einem bestehenden @k2b/ssr-Renderer. Er registriert weder ein Bun-Plugin noch baut er Assets oder mountet eine SSR-Route.
// src/ssr.ts
import { createConfig } from "@k2b/ssr";
import {
fibelSsrTemplate,
type FibelSsrTemplateOptions,
} from "@k2b/fibel/solid";
export const { config, plugin, html } =
createConfig<FibelSsrTemplateOptions>({
rootDir: import.meta.dir,
template: fibelSsrTemplate,
});Dieser Renderer wird an solidPage übergeben:
import { defineFibel } from "@k2b/fibel";
import { solidPage } from "@k2b/fibel/solid";
import { html } from "./ssr";
import PanelHeaderPage from "./PanelHeaderPage";
export default defineFibel({
title: "Cloud UI",
pages: [
solidPage({
html,
path: "/panel-header",
title: "PanelHeader",
description: "Ein einheitlicher Bereich für Titel und Aktionen.",
section: "Komponenten",
content: panelHeaderMarkdown,
component: ({ content }) => (
<PanelHeaderPage documentation={content.html} />
),
}),
],
});Normale .tsx-Komponenten werden auf dem Server gerendert. Importe aus .island.tsx oder .client.tsx folgen den üblichen Regeln von @k2b/ssr. Island-Props müssen serialisierbar bleiben.
Der Host mountet config an seiner einzigen /_ssr-Route und nutzt plugin() für Development- und Produktions-Builds. Fibel ergänzt weder einen weiteren Service noch einen eigenen Build-Befehl.
Wenn der Host bereits eine @k2b/ssr-Konfiguration mit einem anderen HTML-Template besitzt, entsteht nur für den html-Renderer eine zweite Konfiguration. Routen und Builds verwenden weiterhin die ursprüngliche Konfiguration und ihr Plugin:
const siteSsr = createConfig<PageOptions>({
rootDir: import.meta.dir,
template: siteTemplate,
});
const fibelSsr = createConfig<FibelSsrTemplateOptions>({
rootDir: import.meta.dir,
template: fibelSsrTemplate,
});
export const ssrConfig = siteSsr.config;
export const plugin = siteSsr.plugin;
export const html = siteSsr.html;
export const fibelHtml = fibelSsr.html;Beide Renderer verweisen auf denselben /_ssr-Pfad. Nur siteSsr.plugin() wird registriert; es findet alle Islands unter dem gemeinsamen rootDir.
Seiten einer Collection zuordnen
Bei einer Fibel-Instanz mit collections ordnet collection eine benutzerdefinierte oder Solid-Seite deren Routen, Sidebar, Such-Scope, Assistant-Kontext, MCP-Ergebnissen und Discovery-Ausgaben zu. Ohne Angabe gilt defaultCollection.
Mit collection: "ui" liegt das vorherige solidPage-Beispiel unter /en/ui/panel-header, wenn die Collection ui ihren standardmäßigen Pfad /ui verwendet. Der Leitfaden zu Inhaltssammlungen beschreibt die vollständige Konfiguration und den URL-Vertrag.
Getrennte Instanzen wählen
Getrennte Fibel-Instanzen eignen sich, wenn unabhängige Suchindizes, Assistenten-Konversationen, Plugins, MCP-Endpunkte oder Betriebsgrenzen erforderlich sind. Sie können trotzdem in einem Hono-Prozess und einem Deployment laufen:
import { Hono } from "hono";
import {
createFibelApp,
defineFibel,
type FibelHeaderConfig,
} from "@k2b/fibel";
const cloudHeader = {
title: "Cloud",
homeHref: ({ locale }) => `/${locale}`,
links: [
{
label: "Docs",
href: ({ locale }) => `/docs/${locale}`,
activeWhen: "/docs",
},
{
label: "UI",
href: ({ locale }) => `/ui/${locale}`,
activeWhen: "/ui",
},
],
} satisfies FibelHeaderConfig;
const docs = await createFibelApp(
defineFibel({
title: "Cloud Docs",
routing: { basePath: "/docs" },
header: cloudHeader,
}),
);
const ui = await createFibelApp(
defineFibel({
title: "Cloud UI",
routing: { basePath: "/ui" },
header: {
...cloudHeader,
searchLabel: "Cloud UI durchsuchen",
searchPlaceholder: "Komponenten durchsuchen...",
},
pages: uiPages,
}),
);
export default new Hono()
.mount("/docs", docs.fetch)
.mount("/ui", ui.fetch);Jede Instanz besitzt ihre Sidebar, ihren Suchindex, ihren Assistenten-Kontext, ihre Discovery-Dateien und ihre pfadgebundene Chat-Session. Provider und Rate-Limiter können zwischen den Assistant-Plugins geteilt werden, damit ein gemeinsames Prozessbudget gilt.
Den Header wiederverwenden oder entfernen
Standard-Layout und externe Seiten verwenden denselben framework-neutralen Renderer:
import { renderFibelHeader } from "@k2b/fibel/layout";
const header = renderFibelHeader({
title: "Cloud",
homeHref: "/de",
links: [
{ label: "Docs", href: "/docs/de" },
{ label: "UI", href: "/ui/de", active: true },
],
theme: "light",
search: false,
});Der Renderer liefert das kanonische Header-Markup von Fibel. Interaktive Controls setzen die regulären Fibel-Styles und Client-Assets voraus.
Eine äußere Anwendungsshell kann ausschließlich den integrierten Header entfernen:
import { defaultPlugins } from "@k2b/fibel";
import { layoutPlugin } from "@k2b/fibel/plugins";
const plugins = [
...defaultPlugins().filter((plugin) => plugin.name !== "layout"),
layoutPlugin({ header: false }),
];Sidebar, Body, Search-Shortcut, Footer und Assistent bleiben erhalten.