Oracolo
Oracolo is what happens when a personal blog stops being a database account and starts being a small, portable reader for one public key. You write in Nostr, Oracolo turns those signed events into a site, and the whole thing can be downloaded as one HTML file or served through oracolo.me.
A blog that can fit in your pocket
If you have ever moved a blog from one platform to another, you know the strange feeling: your words are yours in theory, but the real shape of the work belongs to a dashboard, a theme engine, an export format, a company account and a pile of URLs you hope will not break. Oracolo starts from a more stubborn idea. The blog can be a reader for your Nostr identity. The posts are not born inside Oracolo's database. They are Nostr events, signed by your key, published to relays, then collected into a personal site.
That is why Oracolo feels smaller than most publishing tools, and more interesting than a small tool should be. The project describes itself as a Nostr blog in a single html file plus a dynamic blog service. The official README says the downloadable HTML weighs about 500Kb, which is tiny in a world where many websites load more than that before showing a sentence. The page can run without a traditional app backend. You can host it like any static site, keep the file, or even treat it as a digital business card. The writing itself still lives on Nostr.
The important distinction is this: Oracolo is not an editor competing with Habla, YakiHonne or Highlighter. It assumes you can already publish from a Nostr client that understands long-form content. Its job begins after that. It asks, "Given an author key, what should a personal website show?" Then it gives you a way to answer that question with a handful of meta tags, a visual wizard, or a hosted subdomain that encodes the same choices.
That makes Oracolo one of the cleanest examples of a Nostr-native publishing pattern. The site is not the source of truth. The author's key is. The website is a presentation layer you can remake, move, replace, download, point at a domain or discard without losing the signed events beneath it. For a reader, that is subtle. For a writer, it changes the emotional contract. You are not merely "posting on Oracolo." You are using Oracolo to gather what your key has already said.
The author key is the spine
Open the configuration trail and you immediately see the spine of the whole product: an author identifier. The simplest version is a meta tag with an npub. The code also handles hex public keys, NIP-05 names and nprofile values. That last one matters because NIP-19 nprofiles can carry relay hints, so the page does not have to guess blindly where your events might live. A plain npub says who you are. A richer pointer can help the app find you.
In practice, Oracolo takes that identity and looks for three kinds of public material. Long-form articles are Nostr kind 30023 events, the format used by many Nostr writing clients for durable posts with titles and summaries. Short notes are kind 1 events, the familiar social note format. Images are kind 20 events, the picture-first media format that newer Nostr apps use for visual feeds. Oracolo does not flatten those into one anonymous stream. It treats them as separate editorial materials, because a blog front page behaves differently when a 2,000 word essay, a short thought and a photograph all share the same author.
The code follows that separation. Its blog component builds sources for articles, notes and images, then renders blocks from those sources. Its utility layer reads title, summary and image tags from long-form posts, handles image metadata for kind 20 material, shortens and links plain note content, and resolves references to Nostr entities. NIP-05 support lets a human-readable name become a public key by fetching the well-known JSON file from a domain. That is the kind of small plumbing you barely notice when it works, but it is what makes a public-key website feel less like a terminal exercise.
There is also a quiet editorial boundary here. Oracolo is only as coherent as the events it can find and understand. If your long-form posts have useful titles, summaries and images, the site can feel intentional. If your relays are scattered, your metadata is thin or your writing client publishes in surprising ways, Oracolo has less to work with. That is not a flaw so much as a reminder: Nostr publishing is a chain. Writer, client, event kind, tags, relays, renderer. A personal site is the visible end of that chain.
Blocks turn a feed into a front page
The clever part of Oracolo is not merely that it fetches events. A raw event feed is not a homepage. It is a pipe. A homepage needs rhythm. It needs a place for the newest article, a place for notes, a row of images, maybe a topic menu, maybe a cluster of older essays. Oracolo's answer is the content block.
In the downloadable file, blocks are configured through meta tags. A block can ask for articles, notes or images. It can request a count, choose a visual style and filter out very short items with a minimum character length. A simple article grid might ask for five long-form posts. A notes block might ask for ten notes in a slide layout, but only notes above 500 characters. An image block might ask for a grid of twenty photographs. The README documents the public styles as list, grid and slide; the current source also has handling that reaches into board and wall style names for notes. That is a small hint that the project has grown from a single-file experiment into a more flexible layout engine.
Pins are especially useful. Instead of simply asking for the latest items, a block can pin events by using the last characters of an event ID. That lets a writer treat the Nostr archive like a shelf. You can keep a manifesto, introduction or evergreen essay visible even when new notes arrive. The result is more like editing than filtering. You are not building a theme from scratch, but you are deciding what the reader meets first.
This is where Oracolo earns its name on the apps page. It turns the protocol's pile of signed events into something a normal reader can browse. The protocol gives you ownership and portability. The block system gives you taste. The wizard gives you a way to express that taste without opening a code editor. NostrApps highlights this exact path: use the online wizard, arrange content blocks, export one HTML file or use the free service and point your domain. That is the product in one sentence, but the lived version is richer: your public key becomes a little magazine.
Relays are the invisible editorial room
A Nostr blog sounds romantic until you ask the practical question: where does the page find the posts? Oracolo makes relay choice part of the configuration. You can provide hardcoded relays with a meta tag. If you do not, the app tries to load the author's relay list and works from there, following the outbox-style habit of asking where this author tends to publish. That connects Oracolo to NIP-65, the relay list metadata pattern that helps clients stop treating every relay as equally likely to have every event.
The implementation is worth reading because it shows how much small judgment sits behind a calm web page. Oracolo batches relay work, queries sources, filters root notes, applies minimum length rules and plucks the amount each block needs. It uses the write relays for fetching author material and read relays for reply/comment behavior. The page footer can show which relays it is connecting to, which is exactly the kind of honest detail a Nostr reader should learn to look for.
Relays are not just technical plumbing. They shape the visible archive. If a relay is down, rate-limited, missing an old article or not on the author's list, a page can look emptier than the author's actual history. If you hardcode relays, you gain control but create a maintenance duty. If you let the page discover relays from the author's metadata, you gain convenience but inherit whatever that metadata says. Oracolo cannot make those tradeoffs disappear. It makes them legible enough that a serious writer can choose.
That is also why the single-file idea is more nuanced than it first sounds. The file can be portable, but the live content still depends on relays and media URLs. The HTML is your reader. The signed events are your archive. The relay network is the room where the reader goes looking. If you want a blog that survives boring real-world failures, you should care about all three.
Comments without surrendering the page
One of the oldest reasons people stay on large publishing platforms is comments. A static site is lovely until the conversation disappears. Oracolo's comment option tries to keep the social layer attached to the post without dragging the whole blog back into a platform account. In the configuration, comments can be enabled with a meta tag. The README points to NIP-07 and NIP-46 login for that flow, and the code imports window.nostr.js when comments are active. The article component then uses zapthreads around the Nostr event anchor, with reply relays passed into the component.
For a reader, that means the comment area is not a local WordPress-style box with a hidden account database. It is a Nostr conversation attached to a Nostr event. You sign through a browser signer, or through remote signing when the setup supports it, and the conversation can be followed outside Oracolo as well. That is a healthier shape for a public discussion, at least in principle, because the page is not pretending to own the conversation.
There are still adult caveats. Browser signing deserves attention. NIP-07 exposes a window.nostr capability through an extension, so permission discipline matters. NIP-46 remote signing lets a web app request signatures from a signer elsewhere, which can be convenient, but only if the user understands what is being approved. Oracolo's comment feature is therefore not a magic safety blanket. It is a Nostr-native way to keep replies near the article, and it should be judged by the same questions you would bring to any signer flow: what is being signed, by whom, through which relays, and can I verify it later?
The web service behind the simple idea
The phrase "single HTML file" can make Oracolo sound like a toy. The repository tells a larger story. Beside the Svelte and TypeScript front end, the project includes a Go service. The Go side is not there to replace the static file. It is there to make personalized blog URLs and custom domains easier.
The service reads configuration from chained subdomains. The first meaningful piece is the author, usually an npub or nprofile. Then compact prefixes describe the page structure. The `ba-` prefix adds an articles block, `bn-` adds a notes block, `bi-` adds an images block, `t-` adds topic filtering, `c-` enables comments and `ft-` sets force-theme to dark or light. The code turns that compressed domain language back into the same meta tags the downloadable file uses. It is a strange little trick, but a practical one: domains have length limits, and configuration has to fit inside them.
The DNS move is important. Oracolo's hosted service can serve a personalized blog from an auto-configured Oracolo domain, and an external domain can point at that target with a CNAME. The Go handlers include CNAME detection, a Caddy ask endpoint for certificate decisions, and a SQLite-backed domain tracker that records first seen, last seen, request count and target subdomain. The service uses the BASE_DOMAIN environment value to know what domain it is responsible for. Under the hood, dependencies include go-nostr for Nostr work, freecache for caching, zerolog for logs and sqlite for domain tracking.
This is the part of Oracolo that will either delight or annoy you depending on your temperament. If you love low-tech publishing, the single-file version is the cleanest artifact. If you want a friendlier path for non-technical writers, the wizard and service matter more. Oracolo carries both. It lets the same publishing model sit on a static host, a downloaded file, an Oracolo subdomain or your own domain pointed through the service.
What it is good at, and what it is not
Oracolo is strongest when a writer already thinks in public keys and wants a personal site without surrendering the archive to another platform. It is good for essays, notes, image strips, small personal pages, temporary pages, portfolio-like homepages and "this is my Nostr work" pages. It is especially appealing when the author wants the site to be simple enough to understand. A file. A key. A few blocks. A set of relays. A domain if you want one.
It is not the right tool if you expect a full editorial CMS, team permissions, scheduled newsletters, analytics dashboards, private drafts, media processing pipelines or guaranteed SEO structure. The early public post by dtonon on Stacker News even framed the first version as a didactic experiment rather than a production-grade platform. The current v1.0 release is more capable, with content blocks, the wizard and the blog engine, but the spirit is still clear. Oracolo is a lean Nostr publishing surface, not a corporate content machine.
That restraint is part of its charm. The web has spent years teaching writers that publishing must involve a thick admin interface. Oracolo argues for a thinner layer. Use a Nostr editor to write. Use your key as identity. Use relays as distribution. Use Oracolo to present the work. If the presentation layer stops pleasing you, replace it. Your articles are still signed events. Your identity did not live inside the theme.
But do not confuse that with automatic permanence. You still need good relay habits. You still need reliable media hosting for images. You still need to understand what happens when a signer extension is used for comments. You still need to keep your own copy of the HTML if self-hosting matters to you. Oracolo is elegant because it lowers the platform burden. It does not remove the need to care for your archive.
The builder trail
The public project trail points to dtonon, also known as Daniele in Nostr contexts. The GitHub repository is dtonon/oracolo, MIT licensed, created on May 20, 2024. At this research pass it shows 190 stars, 10 forks, 9 open issues and 205 commits. The language mix is mostly Svelte, with SCSS, TypeScript and Go making up the rest of the visible stack. The latest tagged release is v1.0, published on March 26, 2025, with the title "Content blocks, web wizard and blog engine." That release is the line where the project becomes more than the original single-file demo.
The front end uses Svelte 4, TypeScript, nostr tools from the JSR/NPM bridge, @nostr/gadgets, Showdown for markdown rendering, Splide for carousel behavior, window.nostr.js for signer integration and zapthreads for comment threads. The code path is readable enough that a curious writer can actually inspect it. Configuration is parsed from meta tags, user identity is resolved, relays are loaded, blocks are built, events are fetched and the page renders articles, notes and images from those sources.
The Go service is equally revealing because it shows the other half of the product: making a static idea convenient on the public web. It parses NIP-19 entities, rewrites subdomain configuration into HTML meta tags, serves generated blogs, handles magic CNAME behavior and tracks domains. You can see the product philosophy in that split. The Svelte app is for the page a reader sees. The Go app is for the hosting shape around it.
So, who is Oracolo for? The best answer is not "everyone who wants a blog." It is for the writer who likes the idea that the site is a wrapper, not a jail. It is for the Nostr user who wants long-form writing to have a home page without building a whole site. It is for the technical reader who wants to see how far a public key, a few event kinds and one HTML file can go. And it is for the web romantic who still believes a personal page should be small enough to understand.
Sources worth opening
This article keeps claims close to the public project trail: the official project, the repository, source files, release notes, the NostrApps listing and the relevant NIPs.
- Official Oracolo project site
- dtonon/oracolo GitHub repository
- Oracolo README and configuration guide
- Oracolo v1.0 release: content blocks, wizard and blog engine
- Oracolo package.json front-end stack
- Oracolo go.mod service dependencies
- src/config.ts: author, relays, topics and content blocks
- src/Blog.svelte: article, note and image sources
- src/App.svelte: app startup, comments and download path
- src/Note.svelte: event display and zapthreads comments
- html_modifier.go: subdomain configuration parser
- handlers.go: service routing, CNAME handling and BASE_DOMAIN
- NostrApps Oracolo listing
- dtonon's early Stacker News post about Oracolo
- NIP-23 long-form content
- NIP-65 relay list metadata
- NIP-07 window.nostr browser signing
- NIP-46 remote signing
- NIP-19 bech32 identifiers
- NIP-68 picture-first feeds and kind 20 media
- NIP-25 reactions
- NIP-27 text note references
- Nostr protocol NIPs repository
- NIP-01 basic protocol flow
- NIP-05 DNS identifiers





