Host the graph anywhere: okf render
🇧🇷 Ler em portuguêsThe best way to read an OKF bundle is as a graph. okf server boots that view in a browser: concepts as nodes, links as edges, every body rendered from disk as you click. But a server is a process, and a process needs somewhere to run. For a bundle you want to publish once and leave up, that is a real ask: a box, a port, something to keep alive.
The graph wanted a server, and not everyone has one
GitHub Pages does not run your Ruby. Neither does an object-store bucket, a CI artifact page, or the file you drop in a chat to show a teammate what you documented. Each of those hosts static files and nothing else, and until now the graph could not live there. You could ship the bundle, but not the view of it. The one place the graph was easy to reach was the one place you already had a server.
One file, the whole bundle
okf 1.6.0 adds okf render. It writes the exact page okf server serves, as a single self-contained HTML file with the bundle baked in:
okf render docs/ > public/index.html
That is the whole publish step. Commit the file to a gh-pages branch, or upload it to a bucket, and the graph is a URL. Open it from your disk with a double-click and it behaves the same, with no process behind it. Whatever okf server shows you, the file shows you, offline from the first paint. Search, the type and directory filters, the index map, the update log, the Mermaid diagrams: all of it, out of one file.
okf render writes is the one okf server boots: the rail, the search, the filters, and the graph, all out of one file you can host anywhere. This is okf's own bundle, opened from disk.The same page, one switch apart
The trick is that there is no second page. render and server are the same template, and the only thing that changes is where the browser reads from. Under the server, the page fetches each body, description, catalog, index, and log live over HTTP as you click. Under render there is no server to answer those reads, so the whole bundle rides inside the file, and the same reads resolve from that embedded payload instead of the network. One switch picks the source; every getter in the page honors it. That is why the two modes never drift apart: they are one implementation with two backends, not two viewers to keep in sync.
No looser than the live server
Baking a bundle into a page raises the obvious question: can a hostile Markdown body now script whoever opens the file? No, and for the same reasons the server is safe. The embedded data is escaped so it cannot break out of its script tag, and every body still renders through DOMPurify before it reaches the page. Both defenses that guard the live server guard the static file too. A rendered graph is a snapshot of the bundle, not a new way in.
The one honest trade-off is weight. Every body is inlined, so a large bundle makes a large file, and for a bundle too big to ship whole the streaming okf server stays the right tool. Most bundles are not that big, and for them a single file you can host anywhere is the easier answer.
Also in 1.6.0: the official Docker image
The same release ships another way to reach okf without setting anything up: the official image at ghcr.io/serradura/okf, the whole CLI with no Ruby to install, built from source and published multi-arch on every release tag. It has its own write-up in Run okf anywhere. The short version is that between the image and okf render, both the tool and its graph now go places that used to need a setup step first.
One command writes the whole graph as a file. The docs page has the full reference; the demo is the same view, served live.