L'Editor Typst mostra il tuo codice e le pagine compilate uno accanto alle altre. Esegue il vero compilatore Typst nel tuo browser come WebAssembly, quindi le pagine appaiono esattamente come nel PDF - titoli, elenchi, tabelle, formule, figure, note a piè di pagina, riferimenti e le tue regole #set e #show. Un clic su qualsiasi testo della pagina ti porta al suo punto nel codice, e puoi modificare il testo direttamente sulla pagina.
Tutto funziona nel tuo browser. I documenti non vengono caricati, non serve registrarsi e non c'è pubblicità.
Markup, codice, formule, stringhe e commenti nei loro colori, numeri di riga, elenchi che continuano con Invio, e gli errori del compilatore con riga, colonna e suggerimento.
Typst 0.14 compilato in WebAssembly funziona in un worker accanto all'editor e compila un attimo dopo ogni modifica - la scrittura resta fluida.
Fai clic su un testo sulla pagina per cambiarlo lì; la modifica va nel codice. Un clic su una formula o un'immagine salta al suo punto nel codice.
Carta, margini, colonne, carattere, dimensione, lingua, testo giustificato, titoli numerati e numeri di pagina - le impostazioni modificano le regole #set del tuo codice.
Aggiungi immagini, CSV, JSON, YAML, bibliografie, caratteri e altri file .typ a un documento e usali con image, csv, json o #import.
Un PDF dal compilatore con testo vero e selezionabile, ogni pagina in PNG, JPG, WebP o SVG, oppure il sorgente .typ con i suoi file in ZIP.
Qualsiasi pagina https (e localhost) può integrare l'editor con un <iframe> e ?embed=1 - senza registrazione, senza chiave. Integrato, l'editor nasconde questo testo e mostra un pulsante Salva. Ci sono due modi per far entrare e uscire il documento.
src= apre un file (il tuo server deve consentire CORS), webhook= fa sì che «Salva» (Ctrl+S) invii il documento a quell'indirizzo. Aggiungi &token=… per un'intestazione Authorization: Bearer … e &auto per salvare dopo ogni modifica.
<iframe src="https://typst.giit.ch/?embed=1&src=https://your-site.com/docs/flyer.typ&webhook=https://your-site.com/save.php"
allow="clipboard-write" style="width:100%;height:800px;border:0"></iframe>
Il webhook riceve un POST con JSON { editor, event: "save", id, name, content, assets, updated }. Un piccolo script PHP che lo salva:
<?php
header('Access-Control-Allow-Origin: https://typst.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__ . "/docs/$name.typ", $d['content']);
echo '{"ok":true}';
L'editor dice typsteditor:ready, la tua pagina risponde con typsteditor:load, l'editor segnala typsteditor:loaded, typsteditor:change alle modifiche reali e typsteditor:save quando l'utente salva. La tua pagina può inviare typsteditor:get (lo stato attuale) o typsteditor:save (premi Salva). Il salvataggio passa così dal tuo login e dalla tua sessione.
<iframe id="ed" src="https://typst.giit.ch/?embed=1" allow="clipboard-write" style="width:100%;height:800px;border:0"></iframe>
<script>
const ed = document.getElementById('ed');
const ORIGIN = 'https://typst.giit.ch';
addEventListener('message', async e => {
if (e.source !== ed.contentWindow || e.origin !== ORIGIN) return;
const m = e.data;
if (m.type === 'typsteditor:ready') { // l'editor è pronto: passagli il documento
ed.contentWindow.postMessage({
type: 'typsteditor:load',
name: 'Flyer',
content: await (await fetch('/docs/flyer.typ')).text(),
assets: { 'logo.png': 'data:image/png;base64,…' } // immagini facoltative and data files
}, ORIGIN);
}
if (m.type === 'typsteditor:change') document.title = '● not saved'; // una modifica reale
if (m.type === 'typsteditor:save') { // l'utente ha fatto clic su "Salva"
await fetch('/api/save', { method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: m.name, content: m.content, assets: m.assets }) });
document.title = 'Saved';
}
});
// Un pulsante Salva sulla tua pagina: la risposta arriva come typsteditor:save
function saveNow() { ed.contentWindow.postMessage({ type: 'typsteditor:get' }, ORIGIN); }
</script>
Assistente IA nella tua pagina: funziona anche nel riquadro. Con allow="clipboard-write" sull'iframe, «Copia il prompt» usa direttamente gli appunti (altrimenti l'editor ricorre al vecchio comando di copia, o mostra il prompt da copiare a mano). Un link inviato dall'IA non può raggiungere un editor dentro un altro sito web, quindi l'editor dice all'IA e all'utente di incollare invece l'intera risposta dell'IA nell'editor - oppure di aprire l'editor in una finestra propria.
window.open("https://typst.giit.ch/?embed=window", "typsteditor-17") apre l'editor completo in una finestra propria e usa gli stessi messaggi con window.opener. Lì lo raggiungono i link di un'IA. typsteditor:load può portare anche context: { host, title, rules } - il prompt per l'IA dice allora a chi appartiene il documento e segue le tue regole - e hook: { url, token, assets: false }, un webhook solo per questo documento che non viene mai salvato. Chiudere la finestra con modifiche non salvate invia typsteditor:closing. typsteditor:pdf chiede il PDF del documento della pagina e lo riceve come data URI, creato dal compilatore Typst con testo vero e selezionabile.
Passa all'editor il tuo prompt, un indirizzo sul tuo sito e una chiave per questa sessione dell'editor. La finestra dell'IA mostra allora «Connesso a» il tuo sito, ciò che dici all'IA e la scelta modificare il documento attuale o crearne uno nuovo; Copia il prompt mette tutto insieme. L'IA invia il risultato con la chiave al tuo server, e la tua pagina lo apre nell'editor - un nuovo documento si apre separatamente e resta nel browser dell'utente. Una chiave per sessione dell'editor: resta valida finché l'editor è aperto, e solo finché non ne ha una l'editor la chiede con typsteditor:key-request. L'editor non invia mai la chiave di sua iniziativa e non la salva mai; l'indirizzo deve essere https sul tuo host o su un suo sottodominio.
const key = async () => (await fetch('/api/ai-key.php?doc=17')).json(); // una chiave per sessione dell'editor
const k = await key();
ed.contentWindow.postMessage({ type: 'typsteditor:load', name: 'Flyer', content, ai: {
label: 'My Site', prompt: 'Keep the [[placeholders]]. Write in German.',
endpoint: 'https://your-site.com/api/ai-result.php', key: k.key } }, ORIGIN);
// ricorda l'id da typsteditor:loaded e ignora change/save/closing con un altro id
// solo finché l'editor non ha una chiave:
if (m.type === 'typsteditor:key-request') { const k = await key(); ed.contentWindow.postMessage({ type: 'typsteditor:ai', key: k.key }, ORIGIN); }
// finché l'editor è aperto, avvisa il tuo server ogni minuto; chiudere l'editor o la pagina annulla la chiave
setInterval(() => fetch('/api/ai-key.php?alive=' + k.key.slice(0, 8)), 60000);
// il tuo server ha un risultato (polling, SSE …): target è "current" o "new"
ed.contentWindow.postMessage({ type: 'typsteditor:load', name: 'Flyer', content: draft, from: 'ai', target }, ORIGIN);
<?php // api/ai-key.php - la chiave di questa sessione dell'editor dell'utente connesso (la chiama la tua pagina)
session_start(); // verifica che l'utente possa modificare questo documento
$key = bin2hex(random_bytes(24));
$_SESSION['ai'][hash('sha256', $key)] = ['doc' => (int)$_GET['doc'], 'seen' => time()]; // o nel tuo database; ?alive= aggiorna seen
echo json_encode(['key' => $key]);
<?php // api/ai-result.php - l'IA invia qui (niente intestazioni CORS: le IA lo chiamano da un server)
$key = preg_replace('/^Bearer\s+/', '', $_SERVER['HTTP_AUTHORIZATION'] ?? '');
$row = find_key(hash('sha256', $key)); // il tuo database: non annullata, vista negli ultimi 3 minuti
if (!$row) { http_response_code(401); exit('{"ok":false,"error":"key not valid"}'); }
$d = json_decode(file_get_contents('php://input', false, null, 0, 2000000), true);
save_draft($row['doc'], $d['content'], $d['target'] === 'new' ? 'new' : 'current'); // la tua pagina lo mostra con typsteditor:load
echo '{"ok":true}';
Crea chiavi con almeno 128 bit casuali, salvane solo l'hash, lega ciascuna all'utente connesso, al documento e a questa sessione dell'editor, creane una per sessione, mantienila valida solo finché la tua pagina segnala la sessione come aperta, e annullala quando l'editor o la pagina si chiude.
L'intero protocollo è in llms.txt - dallo a un'IA e costruirà il collegamento per il tuo sistema. L'Editor LaTeX funziona allo stesso modo con il prefisso latexeditor: - latex.giit.ch.
No. L'editor e il compilatore Typst funzionano interamente nel tuo browser. I tuoi documenti, immagini e file non vengono mai inviati a un server, a meno che tu stesso non configuri un webhook verso il tuo server.
Sì. L'editor esegue Typst 0.14 compilato in WebAssembly (typst.ts), quindi le pagine e il PDF sono gli stessi della riga di comando di Typst. Viene caricato una volta (circa 11 MB) e poi conservato dal tuo browser.
Fai clic su «Esporta», scegli PDF e fai clic su «Scarica». Il PDF arriva direttamente dal compilatore Typst, con testo vero che si può selezionare e cercare.
Non direttamente: l'editor non carica nulla da altri server, quindi #import "@preview/…" segnala un problema che nomina il pacchetto. Puoi aggiungere i file .typ di un pacchetto al documento nella scheda Immagini e importarli per nome di file.
I caratteri forniti con Typst: Libertinus Serif (quello predefinito), New Computer Modern con il suo carattere per le formule, e DejaVu Sans Mono per il codice. Aggiungi i tuoi file .otf o .ttf a un documento e usali con #set text(font: "Name").
Trascina o incolla un'immagine nell'editor, oppure aggiungila nella scheda Immagini a destra. Viene salvata con il documento nel tuo browser e usata da #image("name.png"). I file CSV, JSON, YAML e .bib funzionano allo stesso modo.
Sì, qualsiasi IA - ChatGPT, Claude, Gemini, Copilot o l'IA del tuo strumento di programmazione. Fai clic su «Assistente IA», poi su «Copia il prompt», incollalo nella tua IA e dille cosa deve scrivere. L'IA risponde con un link; fai clic su di esso e il documento appare nel tuo editor. «Annulla» ritira ogni modifica.
Sì. Integralo con un iframe e scambia documenti con postMessage, oppure lascia che invii ogni versione salvata al tuo server con un webhook. Trovi esempi in Usare l'editor sul tuo sito web.
No. L'editor è gratuito, senza pubblicità e senza registrazione.