TOML-Editor
Editor öffnen

Den TOML-Editor in deine Website einbinden

Für Entwicklerinnen und Entwickler: So setzt du den TOML-Editor in deine eigene Seite - in einem iframe, in einem eigenen Fenster oder als Ansicht nur zum Lesen -, und so gelangen Dokumente, gespeicherte Fassungen und Ergebnisse einer KI zwischen dem Editor und deinem Server hin und her. Du brauchst keine Anmeldung und keinen Schlüssel von uns.

Jede https-Seite (und localhost) kann den Editor mit einem <iframe> und ?embed=1 einbetten - ohne Anmeldung, ohne Schlüssel. Eingebettet blendet der Editor den Seitentext aus und zeigt einen Speichern-Knopf. Das Dokument kommt auf vier Arten hinein und wieder heraus.

1. Eine Datei über einen Link öffnen, auf deinem Server speichern

src= öffnet eine Datei (dein Server muss CORS erlauben), webhook= lässt «Speichern» (Ctrl+S) das Dokument an diese Adresse senden. Füge &auto hinzu, um nach jeder Änderung zu speichern.

<iframe src="https://toml.giit.ch/de/?embed=1&src=https://your-site.com/config/app.toml&webhook=https://your-site.com/save.php"
        allow="clipboard-write" style="width:100%;height:800px;border:0"></iframe>

Der Webhook erhält einen POST mit JSON { editor: "toml", event: "save", id, name, content, updated }. Ein Link enthält kein Token (es würde in Serverprotokollen und im Browserverlauf landen). Ein Webhook in der Adresse eignet sich deshalb für eine Speicheradresse, die keines benötigt, etwa auf localhost oder in deinem Intranet. Für einen öffentlichen Server übergib den Webhook mit einem Token in tomleditor:load (hook: { url, token }) und prüfe es, wie dieses kleine PHP-Skript:

<?php
header('Access-Control-Allow-Origin: https://toml.giit.ch');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Allow-Methods: POST, OPTIONS');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') exit;
if (($_SERVER['HTTP_AUTHORIZATION'] ?? '') !== 'Bearer SECRET') { http_response_code(403); exit; }
$d = json_decode(file_get_contents('php://input'), true);
$name = preg_replace('/[^\w\- ]/u', '_', $d['name']);
file_put_contents(__DIR__ . "/config/$name.toml", $d['content']);
echo '{"ok":true}';

2. Deine Seite hält das Dokument (postMessage)

Der Editor meldet tomleditor:ready, deine Seite antwortet mit tomleditor:load, der Editor meldet tomleditor:loaded, tomleditor:change bei echten Änderungen und tomleditor:save, wenn gespeichert wird. Deine Seite kann tomleditor:get (den aktuellen Stand) oder tomleditor:save (Speichern drücken) senden. Gespeichert wird dann über dein eigenes Login und deine eigene Sitzung.

<iframe id="ed" src="https://toml.giit.ch/de/?embed=1" allow="clipboard-write" style="width:100%;height:800px;border:0"></iframe>
<script>
const ed = document.getElementById('ed');
const ORIGIN = 'https://toml.giit.ch';

addEventListener('message', async e => {
  if (e.source !== ed.contentWindow || e.origin !== ORIGIN) return;
  const m = e.data;
  if (m.type === 'tomleditor:ready') {              // der Editor ist bereit: ihm das Dokument geben
    ed.contentWindow.postMessage({
      type: 'tomleditor:load',
      name: 'Settings',
      content: await (await fetch('/config/app.toml')).text()
    }, ORIGIN);
  }
  if (m.type === 'tomleditor:change') document.title = '● not saved';   // eine echte Änderung
  if (m.type === 'tomleditor:save') {               // es wurde auf "Speichern" geklickt
    await fetch('/api/save', { method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: m.name, content: m.content }) });
    document.title = 'Saved';
  }
});

// Ein Speichern-Knopf auf deiner eigenen Seite: die Antwort kommt als tomleditor:save
function saveNow() { ed.contentWindow.postMessage({ type: 'tomleditor:get' }, ORIGIN); }
</script>

KI-Assistent in deiner Seite: Er funktioniert auch im Frame. Mit allow="clipboard-write" am iframe nutzt «Prompt kopieren» direkt die Zwischenablage (sonst greift der Editor auf den alten Kopierbefehl zurück oder zeigt den Prompt zum Kopieren von Hand). Ein Link der KI erreicht keinen Editor in einer anderen Website. Darum bittet der Editor die KI und dich, stattdessen die ganze Antwort der KI in den Editor einzufügen - oder den Editor in einem eigenen Fenster zu öffnen.

3. In einem eigenen Fenster

window.open("https://toml.giit.ch/de/?embed=window", "tomleditor-17") öffnet den vollen Editor in einem eigenen Fenster, das dieselben Meldungen mit window.opener austauscht. Links einer KI erreichen ihn dort. tomleditor:load kann auch context: { host, title, rules } mitgeben - der KI-Prompt sagt dann, wohin das Dokument gehört, und befolgt deine Regeln - sowie hook: { url, token }, einen Webhook nur für dieses Dokument, der nie gespeichert wird. Wird das Fenster mit ungespeicherten Änderungen geschlossen, kommt tomleditor:closing.

4. KI über deinen eigenen Server

Gib dem Editor deinen eigenen Prompt, eine Adresse auf deiner Website und einen Schlüssel für diese Editor-Sitzung. Der KI-Dialog zeigt dann «Verbunden mit» deiner Website, was du der KI sagst, und die Wahl das aktuelle Dokument ändern oder ein neues erstellen; Prompt kopieren setzt alles zusammen. Die KI sendet ihr Ergebnis mit dem Schlüssel an deinen Server, und deine Seite öffnet es im Editor - ein neues Dokument öffnet sich separat und bleibt im Browser der Person, die schreibt. Ein Schlüssel pro Editor-Sitzung: Er bleibt gültig, solange der Editor offen ist, und nur solange er keinen hat, fragt der Editor mit tomleditor:key-request danach. Der Editor sendet den Schlüssel selbst nie und speichert ihn nie; die Adresse muss https auf deinem eigenen Host oder einer Subdomain davon sein.

const key = async () => (await fetch('/api/ai-key.php?doc=17')).json();   // ein Schlüssel pro Editor-Sitzung
const k = await key();
ed.contentWindow.postMessage({ type: 'tomleditor:load', name: 'Settings', content, ai: {
  label: 'My Site', prompt: 'Keep every key and every comment.',
  endpoint: 'https://your-site.com/api/ai-result.php', key: k.key } }, ORIGIN);
// die id aus tomleditor:loaded merken und change/save/closing mit anderer id ignorieren
// nur solange der Editor keinen Schlüssel hat:
if (m.type === 'tomleditor:key-request') { const k = await key(); ed.contentWindow.postMessage({ type: 'tomleditor:ai', key: k.key }, ORIGIN); }
// solange der Editor offen ist, jede Minute deinem Server melden; Schliessen des Editors oder der Seite macht den Schlüssel ungültig
setInterval(() => fetch('/api/ai-key.php?alive=' + k.key.slice(0, 8)), 60000);
// dein Server hat ein Ergebnis (Polling, SSE …): target ist "current" oder "new"
ed.contentWindow.postMessage({ type: 'tomleditor:load', name: 'Settings', content: draft, from: 'ai', target }, ORIGIN);

Erzeuge Schlüssel mit mindestens 128 Zufallsbits, speichere nur ihren Hash, binde jeden an die angemeldete Person, das Dokument und diese Editor-Sitzung, erzeuge einen pro Sitzung, lass ihn nur gültig, solange deine Seite die Sitzung als offen meldet, und mach ihn ungültig, wenn der Editor oder die Seite schliesst.

Das ganze Protokoll steht in llms.txt - gib es einer KI, und sie baut die Anbindung für dein System. Die anderen giit-Editoren funktionieren gleich, mit ihrem eigenen Präfix - editors.giit.ch.

Dokument nur anzeigen (Viewer)

?viewer=1 zeigt nur das fertige Dokument: kein Code, keine Werkzeuge, nichts lässt sich ändern, und im Browser wird nichts gespeichert. Das Dokument kommt über einen Link (#b64=, ?src=), von deiner Seite mit tomleditor:load oder per POST als normales Formular an post.php: das Feld content als Text oder b64 als Base64, optional name, höchstens 20 MB Text.

<form method="post" action="https://toml.giit.ch/post.php?viewer=1" target="_blank">
  <input type="hidden" name="lang" value="de">
  <input type="hidden" name="name" value="Report">
  <input type="hidden" name="b64" value="…">
  <button>Open</button>
</form>

Ohne viewer=1 öffnet sich das Dokument im normalen Editor. So oder so bleibt es nur im Arbeitsspeicher: Es wird weder auf dem Server gespeichert noch unter "Meine Dokumente" abgelegt. Direkt geöffnet sagt der Viewer, dass der Inhalt von Dritten stammt.