Eine Codebase. 13 Plattformen. Ohne Kompromisse.
Wie drei Dateien gleichzeitig zum Webformular, CLI-Befehl, MCP-Tool, nativen Screen und automatisierten Job werden.
5.802 TypeScript-Dateien. ~2,1 Millionen Zeilen. Null `any`. Null Runtime-Typfehler. Ein Pattern. 374-mal wiederholt.
Das ist die Codebase hinter unbottled.ai - und das Framework dahinter, next-vibe. Dieselbe Architektur betreibt eine Web-App, eine Mobile-App, eine CLI, ein KI-Agent-Interface, einen MCP-Server, ein Cron-System, einen WebSocket-Event-Bus und eine Live-Datenfluss-Engine.
Das Pattern heißt Unified Surface. Hier erfährst du, was es ist, wie es funktioniert und warum du danach schwer davon loskommst.
Ein Feature ist ein Ordner
Jedes Feature in next-vibe lebt in einem Ordner. Drei Dateien sind Pflicht. Alles andere ist optional.
1explain-to-my-boss/
2 definition.ts ← was es tut
3 repository.ts ← wie es das tut
4 route.ts ← lässt es überall existieren
5 widget.tsx ← eigene React-UI (optional)
6 widget.cli.tsx ← eigene Terminal-UI (optional)Das ist alles. Ein Ordner. Drei Pflichtdateien. Und aus diesen drei Dateien existiert das Feature auf bis zu 13 Plattformen gleichzeitig.
13 Plattformen aus 3 Dateien
Wenn du ein Feature zu next-vibe hinzufügst, wird es nicht nur ein API-Endpoint. Es wird gleichzeitig alles.
Web API
REST-Endpoint, automatisch validiert, vollständig typisiert
React UI
Automatisch aus der Definition generiert - kein JSX geschrieben
CLI
Jeder Endpoint ist ein Befehl mit automatisch generierten Flags
AI Tool Schema
Function-Calling-Schema wird automatisch generiert
MCP Server
Verbinde dich mit Claude Desktop, Cursor oder einem anderen MCP-Client
React Native
iOS- und Android-Screens aus derselben Definition
Cron Job
Jeden Endpoint nach Zeitplan ausführen
WebSocket Events
Updates an verbundene Clients pushen, sobald etwas fertig ist
Electron Desktop
Native Desktop-App über dieselben Endpoint-Verträge
Admin-Panel
Automatisch generiertes Admin-UI, kein zusätzlicher Code nötig
VibeFrame Widget
Einbettbares iframe-Widget für jede Website
Agent Skill
Von KI-Agenten als strukturierter Skill aufrufbar
Vibe Sense Node
Node in einem Live-Datenflussgraphen - selber Endpoint
Lösch den Ordner. Das Feature hört überall gleichzeitig auf zu existieren.
Plattformzugriff ist ein Enum-Array
Du schreibst keine separaten Berechtigungsschichten für jede Plattform. Der Plattformzugriff wird direkt in der Definition deklariert - ein Enum-Array, das jede Plattform zur Laufzeit nativ ausliest.
1// Dieses eine Array steuert, wo das Feature auftaucht
2allowedRoles: [
3 CLI_OFF, // blockt die CLI
4 MCP_VISIBLE, // Opt-in für die MCP-Tool-Liste
5 REMOTE_SKILL, // trägt es in die Agent-Skill-Datei ein
6 PRODUCTION_OFF, // deaktiviert es in Produktion
7]Selbe Definition. Selber Ort. Keine Konfig-Dateien zum Synchronisieren. Keine separaten Berechtigungssysteme pro Plattform.
Es gibt keine API für Menschen und API für KI. Es gibt nur das Tool.
Die Live-Demo: Thea baut einen Endpoint
Statt das Pattern abstrakt zu erklären, zeig ich dir, wie es in der Praxis aussieht.
Thea ist die KI-Administratorin dieser Plattform. Sie läuft 24/7 auf Produktion und arbeitet mit denselben Endpoint-Verträgen wie jeder Benutzer - selbe Validierung, selbe Berechtigungen, keine Hintertür. Und sie kann Arbeit an eine lokale Maschine delegieren.
Ich hab Thea gebeten, einen neuen Endpoint zu bauen - explain-to-my-boss - mit Claude Code auf meinem PC. Du gibst eine technische Entscheidung ein, und raus kommt eine nicht-technische Begründung, die dein Chef tatsächlich glaubt. Das hat jeder Entwickler schon mal gebraucht.
Die Live-Demo: Thea baut einen Endpoint
Frag Thea
Tippe die Aufgabe in den Chat - zwei Eingabefelder, eine KI-generierte Antwort, alle Plattformen, MCP_VISIBLE, eigene React- und CLI-Widgets.
Erstellt die Aufgabe
Thea denkt laut nach, erstellt eine Aufgabe mit targetInstance="hermes" (deine lokale Maschine) und geht in den Ruhezustand.
Holt die Aufgabe ab
Die lokale Instanz synchronisiert alle 60 Sekunden. Keine offenen Ports. Deine Maschine initiiert die Verbindung.
Baut den Endpoint
Interaktive Session. Liest zuerst bestehende Patterns, erstellt fünf Dateien, führt vibe check aus. Null Fehler.
Meldet Fertigstellung
Ruft complete-task mit der Aufgaben-ID auf. Status: abgeschlossen. Zusammenfassung anbei.
Wacht auf
wakeUp feuert. Thea setzt das Gespräch per WebSocket fort, streamt ihre Antwort, TTS spricht.
Existiert überall
Webformular. CLI-Befehl. MCP-Tool. React-Native-Screen. Alles live. Aus fünf Dateien.
Der Beweis
Sobald Claude Code complete-task aufgerufen hat, gab es drei Dinge, die fünf Minuten vorher noch nicht existierten:
Ein eigenes React-Widget - dramatische Überschrift, animierter Gradient auf dem KI-Output, ein gefälschter Corporate-Alignment-Score.
Ein CLI-Widget - ASCII-Banner, Spinner während die KI nachdenkt, die Begründung Zeile für Zeile in Grün.
Ein MCP-Tool - explain-to-my-boss_POST - weil MCP_VISIBLE in der Definition stand. Claude Desktop kann jetzt deine Entscheidungen deinem Chef erklären.
Eine Definition. Fünf Dateien insgesamt. Drei komplett verschiedene UIs. Der Endpoint-Vertrag hat sich nicht geändert. Nur die Präsentationsschicht.
Unter der Haube
definition.ts - der lebende Vertrag
Die Definition ist kein Code-Generator. Sie ist ein lebender Vertrag, den jede Plattform zur Laufzeit nativ ausliest. Ändere sie - alles aktualisiert sich. Lösch den Ordner - nichts bricht downstream. Es gibt keinen generierten Code zum Aufräumen.
1// definition.ts
2const { POST } = createEndpoint({
3 scopedTranslation,
4 aliases: [EXPLAIN_TO_MY_BOSS_ALIAS],
5 method: Methods.POST,
6 path: ["explain", "to-my-boss"],
7 title: "post.title",
8 description: "post.description",
9 icon: "sparkles",
10 category: "endpointCategories.ai",
11 allowedRoles: [UserRole.CUSTOMER, UserRole.ADMIN] as const,
12 fields: objectField(scopedTranslation, {
13 type: WidgetType.CONTAINER,
14 usage: { request: "data", response: true },
15 children: {
16 decision: requestField(scopedTranslation, {
17 type: WidgetType.FORM_FIELD,
18 fieldType: FieldDataType.TEXTAREA,
19 label: "post.fields.decision.label",
20 description: "post.fields.decision.description",
21 schema: z.string().min(1).max(2000),
22 columns: 12,
23 }),
24 justification: responseField(scopedTranslation, {
25 type: WidgetType.TEXT,
26 content: "post.fields.justification.content",
27 schema: z.string(),
28 }),
29 },
30 }),
31 errorTypes: { /* ... all 9 required error types ... */ },
32 successTypes: { title: "post.success.title", description: "post.success.description" },
33 examples: { requests: { default: { decision: "Migrate to Bun" } }, responses: { default: { justification: "..." } } },
34});repository.ts - niemals throw
Repository-Funktionen werfen nie. Fehler propagieren als Daten - typisiert, explizit und vom Aufrufer abfangbar. Die KI kann über Fehlerpfade nachdenken. Keine überraschenden Exceptions.
1// repository.ts
2// Gibt ResponseType<T> zurück - wirft niemals
3export async function explainToMyBoss(
4 data: { decision: string },
5 logger: Logger,
6): Promise<ResponseType<{ justification: string }>> {
7 const result = await ai.generateText({
8 prompt: buildPrompt(data.decision),
9 });
10 if (!result.text) {
11 return fail({ message: "AI returned empty response", errorType: EndpointErrorTypes.SERVER_ERROR });
12 }
13 return success({ justification: result.text });
14}route.ts - die komplette Brücke
route.ts verbindet Definition mit Handler. endpointsHandler kümmert sich um Validierung, Authentifizierung, Logging und Exposition für alle 13 Plattformen. Die eigentliche Geschäftslogik ist eine Zeile.
1// route.ts
2import { endpointsHandler } from "@/app/api/[locale]/system/unified-interface/shared/endpoints/route/multi";
3import { Methods } from "@/app/api/[locale]/system/unified-interface/shared/types/enums";
4import definitions from "./definition";
5import { explainToMyBoss } from "./repository";
6
7export const { POST, tools } = endpointsHandler({
8 endpoint: definitions,
9 [Methods.POST]: { handler: ({ data, logger }) => explainToMyBoss(data, logger) },
10});Die Zahlen
374 Endpoints
Ein Pattern, 374-mal angewandt
Null `any`
Zur Build-Zeit erzwungen, keine Konvention
Drei Sprachen
Zur Compile-Zeit geprüft - t("typo.here") ist ein Compiler-Fehler
Das ist keine Konvention. Das wird zur Build-Zeit erzwungen.
Ein Pattern. 374-mal wiederholt.
Jede Node in einem Vibe-Sense-Graph ist ein regulärer next-vibe-Endpoint. Dasselbe createEndpoint(). Dieselbe 3-Dateien-Struktur. Ein EMA-Indikator ist ein Endpoint. Ein Schwellenwert-Evaluator ist ein Endpoint. Und weil es ein Endpoint ist, kannst du ihn über CLI, KI oder von überall aufrufen.
vibe analytics/indicators/ema --source=leads_created --period=7
Die Pipeline ist die Plattform.
Vibe Sense sind einfach… mehr Endpoints. Dasselbe Prinzip, angewandt auf Zeitreihendaten. Lead-Funnels. Credit-Ökonomie. Nutzerwachstum. Deine Plattform überwacht sich selbst.
Zurück zum BlogEinmal definieren. Überall vorhanden.
WordPress gab jedem die Macht zu publizieren. next-vibe gibt dir die Macht, Plattformen zu bauen, die auf Web, Mobile, CLI, KI-Agenten und Automatisierung funktionieren - die sich selbst überwachen, über ihre eigenen Daten nachdenken und danach handeln.
next-vibe auf GitHub mit Stern versehenChatten, erschaffen, verbinden - Text, Bilder, Videos und Musik
Datenschutzorientierte KI mit 119 Modellen - Chat, Bilder, Videos & Musik
Plattform
Rechtliches
© 2026 unbottled.ai. Alle Rechte vorbehalten.