The source of toon.ar.io: the TOON Protocol landing page, the docs and the ecosystem page.
index.html the landing page: hand-written; build.py copies the stylesheet into it
docs/*.html built from src/docs/*.html by build.py
ecosystem/index.html built from src/ecosystem.html by build.py
apps/index.html built from src/apps.html: every app, in the shape of a marketplace
agents/index.html built from src/agents.html: every agent that speaks TOON
install.sh the installer at https://toon.ar.io/install.sh: a stub that hands over to toon_cli's
assets/site.css the one stylesheet, shared by every page
assets/fonts/ Archivo 800 and JetBrains Mono, self-hosted, latin subsets
assets/icon/ the mark, as SVG and PNG
build.py the only build step; standard library only
manifest.template.json the Arweave path manifest, regenerated by build.py
src/ the page fragments you edit
The only script on the site is the copy button on the landing page. The site is stored on Arweave and reached through the ArNS name
toon. Each revision of the landing page is bought as a paid TOON write through the live
node, and the docs page "Proof" (src/docs/proof.html) embeds the receipts of the revisions
before it.
-
The landing page is
index.html. Edit its markup directly, except the header and the footer, whichbuild.pywrites between the<!-- header -->and<!-- footer -->markers from the same templates every other page uses. Its<style>block is a copy ofassets/site.cssthatbuild.pyrefreshes on every build, so the one file stands alone, as every earlier revision did, while the stylesheet has a single source. Editassets/site.css, never the copy. -
The look follows the mark in
assets/icon/: cream, charcoal, gold and grey, with a dark scheme forprefers-color-scheme: dark. Display type is Archivo 800, labels and code are JetBrains Mono, both served fromassets/fonts/; nothing is loaded from another host. -
A docs page is a body fragment in
src/docs/<slug>.html. The title, summary, section and order come fromNAVinbuild.py. Every<h2>gets an anchor and an entry in the page's table of contents. End each page with a<p class="source">naming the repository file it was written from, so the next editor can check it against the source. -
The apps, agents and ecosystem pages are
src/apps.html,src/agents.htmlandsrc/ecosystem.html. A new app or agent is one<li>in the grid and a bump of the count in the page header. Each card's stars, language and version are typed by hand fromgh api repos/<owner>/<name>; reread them before a publish. -
Then run the build:
python3 build.py
Preview with any static server, for example python3 -m http.server 8765, then open
http://127.0.0.1:8765/.
-
Prices. The "Priced live" tiles and the endpoints table on the ecosystem page are a snapshot read off the live node's
GET /ilp. Reread it and update the dates if a price changed. -
Release tags. The version named in
src/docs/install.htmlis toon_cli's latest release (gh release list -R toon-protocol/toon_cli); the Docker tag insrc/docs/run-a-node.htmlis the connector's (gh release list -R toon-protocol/connector). -
Docs drift. Each docs page names the repository file it was written from. Diff that file against the last time the page was touched.
-
Receipts. Add the landing-page revision being replaced to the list in
src/docs/proof.htmland to the JSON in its<details>block: its Arweave transaction id (thex-arns-resolved-idheader ofcurl -sI https://toon.ar.io),sha256sumof the file as served, byte size, the claim on each hop, and the block date. A page cannot contain its own hash, so this is always done for the previous revision, never the current one. -
Links. Every link must resolve. Internal links are checked by the script below; external ones with curl (npmjs.com, basescan and the Solana explorer block curl and must be checked in a browser).
python3 build.py grep -ho 'href="https\?://[^"]*"' index.html docs/*.html apps/*.html agents/*.html ecosystem/*.html | sed 's/href="//;s/"$//' | sort -u \ | while read u; do printf '%s %s\n' "$(curl -s -o /dev/null -w '%{http_code}' -L "$u")" "$u"; done | grep -v '^200'
-
One script.
grep -rl '<script' --include='*.html' . | grep -v ^./srcmust print only./index.html, whose one script is the copy-button handler at the end of the body: it touches the clipboard and nothing else, makes no request, and the page works without it. No page may reference another host for a stylesheet, font or image. The typing tape in the operators section is a CSS animation over real commands in workflow order; reduced motion holds its first line.
Every install command on the site reads curl -fsSL https://toon.ar.io/install.sh | sh.
That path is served by the site itself, from install.sh in the manifest, so it only works
once a revision that carries the file is live on Arweave. Until then the gateway answers
the path with the landing page, and piping that into sh fails. Check before and after a
publish: curl -fsSL https://toon.ar.io/install.sh | head -1 must print #!/bin/sh.
Upload every file that manifest.template.json lists through the store app behind the live
node, paid by the KiB with a voucher on an x402 channel. Fill each file's transaction id
into the manifest, upload the manifest, and point the ArNS record toon at the manifest's
transaction id. The manifest serves index.html at the root and every other path beneath
it, so toon.ar.io/docs/run-a-node.html resolves. The first paid writes are documented at
boughtviatoonnode.ar.io.
Revisions 1 to 8 of the landing page (2026-08-27 to 2026-10-03) were authored directly as one HTML file and are listed, with receipts, in the page itself. This repository starts at revision 9, which added the docs and the ecosystem page.