# TOML Editor (toml.giit.ch) > Free TOML editor in the browser, no sign-up, documents kept in the browser. Edit TOML (pyproject.toml, Cargo.toml, app settings) with syntax highlighting next to a foldable tree of the data, change keys and values right in the tree with comments and formatting kept, see problems with line and column, check the data against a JSON Schema, and convert to JSON, YAML, CSV or XML. - Language: English at /, 13 other languages at /de/, /fr/, /it/, /es/, /pt/, /nl/, /pl/, /tr/, /ru/, /uk/, /zh/, /ja/, /ko/ - Cost: free - Data: documents stay in the browser (localStorage) unless the user sets up a webhook to their own server, or a website that embeds the editor receives it (postMessage) and saves it on its own server. A document sent to post.php by a form (viewer) is passed to the browser in memory and not stored on the server. The server logs requests (IP address, address requested), and page views are counted anonymously. - TOML 1.0, read by the editor's own parser (as strict as Python's tomllib): tables, arrays of tables, dotted keys, inline tables, all string forms, integers in four bases, floats with inf/nan, dates and times; comments kept. ## Features - Code and tree side by side: tables and arrays fold, every value shows its type (string, number, boolean, object, array; dates and times are strings tagged date-time, date or time), `{3}` / `[5]` count the entries, the path of the selected value is shown (`$.items[3].name`), search in keys and values. A table written in several places ([headers], dotted keys) is one entry. - A click in the tree selects that entry in the code; the code cursor marks its value in the tree. - Editing in the tree: keys and values (strings, numbers, booleans, dates; literal strings kept where they fit), the type of a value, entries added, duplicated, moved and removed. Each change is a small edit of the code at that place - the rest keeps its formatting and comments - and one undo step. A renamed key changes in every header and dotted key that names it; new tables become [sections] at a section boundary; changes TOML cannot express in place are refused with a message. TOML has no null. - Problems with line and column: syntax errors (keys or tables defined twice, a table after dotted keys, text without quotes, leading zeros, dates that do not exist, a time without seconds, unknown escapes), and - when the user chooses a JSON Schema from their documents - every place that does not fit (type, required, properties, additionalProperties, enum, const, pattern, format, minimum/maximum, minLength/maxLength, items/prefixItems, minItems/maxItems, uniqueItems, allOf/anyOf/oneOf/not, if/then/else, $ref inside the schema). A `$schema` address is never fetched. - Format (key = value with one space around =, no indentation, an empty line before each header, comments kept); convert to JSON, YAML, JSON Lines, CSV (an array of tables is a table) and XML, dates becoming text; JSON, JSON Lines, YAML, CSV and XML files open as TOML (null left out, a value that is no table under the key `value`). - Export: .toml as it is, JSON, YAML, CSV, the tree as plain text, or all as ZIP. - Templates: pyproject.toml, Cargo.toml, Hugo site, Netlify, table (array of tables). - My documents: any number of documents in the browser - open, rename, duplicate, download and delete. - Light, dark or automatic color theme. ## Writing for a user (for AI assistants) Any AI can put a document into the user's open editor with a link; no server, no API key: - `https://toml.giit.ch/#b64=` - `https://toml.giit.ch/#toml=` - `https://toml.giit.ch/#z=` (shorter) - Add `&mode=add` to merge TOML into the current document: the keys of the table go into the root table (existing keys get the new values, new keys are added to their table). Only the changed places of the code change; comments stay. - Add `&file=new&name=` to make a new document next to the user's others, or `&file=` to change that one. Without `&file=` the open document changes. - Long documents: split the encoded text and send one link per part with `&part=N&of=M&id=`. Open the link in the user's browser if you can, otherwise give it to the user to click. The user can undo every change. In the editor, "AI Assistant" > "Copy prompt" gives the AI these instructions together with the current document, the selected path and the problems. ## Saving on your own server (webhook) Set under "Save to server" (cloud button), or for one document with `?webhook=`: only for that one document and only while the page is open - a link never stores a webhook. At the top level the user is asked first; inside a page (iframe or opener) it only works together with `?src=` and only for the document opened with it. On "Save" (Ctrl+S), or automatically a few seconds after each change if chosen, the browser sends: POST Content-Type: application/json Authorization: Bearer (only if a token is set) {"editor":"toml","event":"save","id":"","name":"", "content":"","updated":""} `content` is the code exactly as in the editor (a string, with its comments). One request carries at most 40 MB; the server's error text (e.g. for 413) is shown to the user. The server must answer CORS requests from https://toml.giit.ch (Access-Control-Allow-Origin, and Access-Control-Allow-Headers: Content-Type, Authorization). `?src=` opens a .yaml file from a URL (CORS needed), `&name=` names it. ## Embedding in a website A guide for developers with examples, in every language of the editor: [https://toml.giit.ch/embed/](https://toml.giit.ch/embed/) (`//embed/`, e.g. `/de/embed/`). The complete protocol follows here. Messages (postMessage; check `event.origin === "https://toml.giit.ch"` and `event.source === iframe.contentWindow`): - Editor -> page: `{type:"tomleditor:ready", version:2, editor:"toml", window:false}` when it can take a document. - Page -> editor: `{type:"tomleditor:load", name, content}` opens the document (content is the TOML text as a string). - Editor -> page: `{type:"tomleditor:loaded", id, name}`, then `{type:"tomleditor:change", id, name, content}` on each edit (not after load), and `{type:"tomleditor:save", id, name, content, editor, event, updated}` when the user clicks Save or presses Ctrl+S. - Page -> editor: `{type:"tomleditor:get"}` asks for a `tomleditor:save` message; `{type:"tomleditor:save"}` saves as if the user had clicked Save. In embedded mode the page text below the editor is hidden and a Save button is shown. The TOML Editor's documents have no files of their own: no message carries `assets`, and `assets` in `load` is ignored. The other giit editors (JSON Editor json.giit.ch with `jsoneditor:`, LaTeX Editor latex.giit.ch with `latexeditor:`, SVG Editor svg.giit.ch with `svgeditor:`) speak the same protocol. Optional fields of `tomleditor:load`: - `tidy: true` - the editor tidies this document as part of the load, as its Tidy / Format button does (`?tidy=1` in the editor's address does it for every document). No `tomleditor:change` is sent for it, `tomleditor:get` returns the tidied code, Undo does not go back before it; code the editor cannot read is loaded as it is. - `context: {host, title, rules}` - plain text about the page (rules up to 2000 characters). "Copy prompt" in the AI Assistant then tells the AI that the document belongs to that page and is saved back there, includes the rules, and leaves out how to build a webhook server. - `hook: {url, token}` - a webhook (https) for this document only, used on Save in addition to the message; kept in memory only (never stored, gone on reload). If the server answers with an error, its `{"error": "…"}` (or `message`, or a short text) is shown to the user. AI Assistant in a frame: add `allow="clipboard-write"` to the iframe so "Copy prompt" can use the clipboard (without it the editor falls back to the old copy command or shows the prompt to copy by hand). Links from an AI cannot reach an editor inside another website (the browser keeps its storage and channels apart), so in a frame the prompt and the dialog ask to paste the AI's whole answer into the editor; use the own window (below) if links should work. `tomleditor:get` is always answered with a `tomleditor:save` message, also when nothing changed. ### All messages at a glance Editor -> page (sent to the page around the editor, or to window.opener in its own window): - `tomleditor:ready` {version:2, editor, window} - can take a document - `tomleditor:loaded` {id, name, target?} - after each load; remember the id (target:"new" for a new document from the AI, which is not yours) - `tomleditor:change` {id, name, content} - a real edit of your document (not after load) - `tomleditor:save` {editor, event, id, name, content, updated} - Save / Ctrl+S (from anywhere in the editor), or the answer to get - `tomleditor:closing` {id, name, unsaved, content?} - own window closes (always sent; content only when unsaved, id null before the first load) - `tomleditor:reload` {id, unsaved} - inside your page, F5 / Ctrl+R / Cmd+R do not reload the editor; ask the user yourself (Ctrl+W cannot be caught by a page) - `tomleditor:key-request` {reason:"missing"} - the editor has no AI key in this session yet `?embed=1&save=0` hides the editor's Save button (Ctrl+S still sends `tomleditor:save`) - for pages with their own Save button. `?theme=light`, `?theme=dark` or `?theme=auto` (with or without `embed`) fixes the color theme for that page load and hides the theme switch; the user's own stored choice is not changed. Other values are ignored. `?lang=de` shows the editor's interface in German (menus, buttons, dialogs, messages), `?lang=en` in English (the default); the choice is remembered in the browser. The AI prompt is always English. Page -> editor (only from the page around the editor or the opener; after its first message only from that origin; pages without a real origin are ignored): - `tomleditor:load` {name, content, context?, hook?, ai?, from?, target?} - open your document; from:"ai" shows a note, target:"new" opens it as a separate document in the user's browser - `tomleditor:get` - answered with `tomleditor:save` of your document (id and content null before the first load) - `tomleditor:save` - press Save - `tomleditor:ai` {label?, prompt?, endpoint?, key?, base?} or {clear:true} - AI through your server Your document is the one your page loaded (or opened with ?src=). change, save, closing and get are only ever about it - never about other documents in the user's browser, also when the user opens them in the editor. A load replaces only a document that came from your page before (same name and origin), never the user's own; the AI settings and the hook from load apply only while your document is open. Your document is kept in memory only - it is never stored in the user's browser and is gone when the editor closes. ### AI through your own server (prompt and session key) The editor has no backend; your site keeps the keys and the results. Hand the editor your prompt, an endpoint and a key for this editor session - in `tomleditor:load` as `ai: {…}`, or at any time as its own message: {type:"tomleditor:ai", label:"Example Admin", prompt:"", endpoint:"https://your-site.com/api/ai-result", key:"", base:true} Fields left out keep their value; `{type:"tomleditor:ai", clear:true}` ends it. One key per editor session: once the editor has a key it keeps it until the session ends or `clear`, and does not take a different one. `base:false` leaves out the editor's own instructions. The AI dialog shows "Connected to