Your first IDOP document, from scratch
An IDOP document is a folder of ordinary web files — HTML, CSS, JavaScript,
optionally WebAssembly — plus one manifest, packed into a single .idop file.
Anyone can open it in an IDOP Reader, and the data it saves travels inside the
file. This guide takes ten minutes and needs only Node.js 20 or later.
1. Get the tool
Download idop.mjs — one file, no
installation, no dependencies, no network. It carries the same validator as
IDOP Cloud, so a file it accepts is a file every conforming Reader accepts.
node idop.mjs --version
2. Start a document
node idop.mjs init counter --title "Counter"
This creates:
counter/
idop.json the manifest: who made it and what it needs
code/index.html the entry point
code/style.css
code/main.js an ES module; it counts how often the document was opened
idop.json says "auto" where the document’s identity goes. The first
pack fills in a document id, a revision id and the dates, and writes them
back, so the document keeps the same identity from one build to the next.
3. Write it like a web page
Edit the files as you would a small website, with three differences:
- The outside world goes through
idop. There is no network:fetchreads files from your package (fetch('data.json')), never from the internet. If the document needs an API, declare it as a capability (step 6). - State lives in the file.
idop.storage.write('notes.json', text)andidop.storage.writeBytes('photo.png', bytes)store data that the Reader writes into the.idopfile when the user saves. - No inline scripts, no remote URLs, no
eval. Put scripts in files; bundle fonts and images.
Everything else works as you expect: ES modules importing each other, CSS,
SVG, canvas, <dialog>, WebAssembly (WebAssembly.instantiateStreaming(fetch('engine.wasm'))),
and dedicated workers (new Worker('worker.js')). To let the user keep a
copy of something, call idop.ui.saveFile({ name, data }); to read one of
their files, idop.ui.openFile({ accept: ['.csv'] }); to print,
idop.ui.print(). Each of these opens the Reader’s own dialog — the user stays
in control.
For editor help, add the types:
idop-runtime.d.ts
and put /// <reference path="./idop-runtime.d.ts" /> at the top of a file.
4. Check and build
node idop.mjs validate counter
node idop.mjs pack counter -o counter.idop
A refusal names a stable code — look it up in the
error registry. pack is
deterministic: the same folder always gives the same bytes.
5. Open it
Drag counter.idop onto IDOP Cloud, or open it
with any IDOP Reader. Click around, save, close, open again: the count is still
there, because it is in the file.
node idop.mjs inspect counter.idop # what the file declares and asks for
node idop.mjs unpack counter.idop -o counter-copy # back to a folder
6. When it needs the network
Declare exactly what it needs in idop.json; the Reader asks the user and
attaches any key itself — the document never sees it:
"optionalCapabilities": [{
"id": "weather", "type": "network",
"origins": ["https://api.example.com"], "methods": ["GET"],
"purpose": "Show today's forecast"
}]
const { status, body } = await idop.network.request({
capability: 'weather',
url: 'https://api.example.com/today',
});
Prefer optionalCapabilities, and make the document useful without them.
7. Let an AI write it
Give any capable model the IDOP builder prompt and describe what you want; paste its files into a folder and run step 4. With an MCP-capable assistant connected to IDOP Cloud, it can create the document in your cloud directly.
Reference
- IDOP Format Specification 1.0 — the rules
- Conformance suite — test your own Reader or tool
- Manifest schema