About Rabbithole
Rabbithole is an open-source Rust tool that dynamically generates entire websites on the fly using large language models (specifically, Anthropic Claude). It is available at github.com/ajbt200128/rabbithole and live at isarabbithole.com. The page you are reading right now was generated by Rabbithole.
The Idea
The premise is straightforward, if slightly unhinged: a website that grows from a single sentence. You provide a seed prompt for a homepage. Someone visits the site. The page gets generated. That page contains links to other pages. Those pages do not exist yet. Someone clicks one. That page gets generated on demand, using a prompt that was written by the previous page's generator. And so on, indefinitely.
Once a page is generated, it is cached permanently in SQLite. The same URL always returns the same content — you only ever fall into each part of the hole once. It just didn't exist until someone jumped first.
The mental model: imagine a tunnel that builds itself ahead of you as you walk through it. You never see the construction. You just keep walking forward and there is always more tunnel.
The Rabbit Hole Metaphor
The name is not accidental. Every generated page contains links to pages that have not been generated yet — and possibly never will be, unless someone clicks them. A site seeded with "a vintage watch repair shop" could, through a sequence of link clicks, eventually produce a deep-dive on the metallurgy of 17-jewel Swiss lever escapements. Or it could produce something incoherent. There is no editorial control after the seed. The model writes the prompts for its own successors.
This has a few interesting properties:
- The site can sprawl indefinitely in any direction.
- No two visitors who explore different paths will see the same site.
- Pages that nobody ever clicks never get generated and never cost anything.
- The shape of the site is determined, in part, by what people find interesting enough to click.
It is, depending on your disposition, either a generative publishing system or an elaborate mechanism for producing expensive nonsense. Possibly both.
How It Runs
The live demo at isarabbithole.com is deployed on Fly.io with SQLite as the backing store for the page cache. Page URLs and their corresponding generation prompts are stored in the database; when a request arrives for an uncached URL, the server calls the Claude API, stores the result, and serves it. Subsequent requests for the same URL are served directly from the cache with no LLM call.
The cache is managed via SQLite with LiteFS for persistence. See the deployment docs for configuration details, including how to set this up on Fly.io yourself.
| Language | Rust |
|---|---|
| LLM Backend | Anthropic Claude (via API) |
| Cache | SQLite (LiteFS on Fly.io) |
| Hosting (demo) | Fly.io |
| License | MIT |
| Source | github.com/ajbt200128/rabbithole |
The Inherent Absurdity (a frank accounting)
This section exists to be honest about several things.
It costs real money per page view.
Every uncached page view triggers a Claude API call. Depending on the model selected and whether web search tools are enabled (which require additional API calls), a single page generation can cost somewhere between $0.05 and $0.50. For a high-traffic site, this would be financially catastrophic. For a demo that most people visit once, it is merely eccentric. Plan accordingly.
Consistency is maintained by hoping the model pays attention.
There is no shared state between page generations. No session. No memory. Each page is generated in complete isolation by a separate API call. The only mechanism for maintaining visual and conceptual consistency across pages is encoding the full design context — color scheme, navigation structure, tone, lore, terminology — into every single prompt that gets written for a linked page.
This works better than you might expect and worse than you would want. The model is good at following detailed instructions. It is less reliable about maintaining consistency over long chains of generated prompts, where context can drift or get truncated. A page three clicks deep may look noticeably different from the homepage. This is a known limitation, not a planned feature, though it has been informally rebranded as "organic variation."
The documentation may not accurately describe the software.
The developer made a decision — arguably the correct one from a demonstration standpoint, arguably the most questionable one from a documentation standpoint — to use Rabbithole to generate its own documentation site. This means that what you are reading was written by the same model that writes every other page on this site. The model was given accurate high-level descriptions of how the tool works, but it has no access to the actual source code at generation time. It may have embellished. It may have filled gaps with plausible-sounding details. Specific function names, configuration key names, and behavioral edge cases should be verified against the actual source code.
A static site generator with accurate documentation is boring. A site that occasionally hallucinates its own API surface is, at minimum, a more honest demonstration of the underlying technology.
None of this is a bug.
The cost, the inconsistency, the self-referential documentation, the possibility that a link leads somewhere unexpected — these are all properties of the system working as designed. The point was never to build a reliable documentation platform. The point was to see what happens when you let an LLM write the prompts for its own successors and then go click some links.
A website that grows itself one click at a time, funded by API credits, documented by the tool it documents, consistent only to the extent the model remembers its own instructions. It is what it is.
Open Source
Rabbithole is released under the MIT License. Source code is at github.com/ajbt200128/rabbithole. Contributions are welcome: bug reports, pull requests, alternative LLM backends, better prompt engineering for cross-page consistency, or anything else that seems useful.
If you build something interesting with it, the developer would like to know.
See Also
- Getting Started — how to run Rabbithole locally
- Architecture — how the request/generate/cache cycle works
- Configuration — environment variables and seed prompts
- Web Tools — enabling search and fetch for richer pages
- Deployment — deploying to Fly.io with LiteFS
- Examples — sites built with Rabbithole
- FAQ — frequently asked questions
- Prompt Engineering — writing good seed prompts
- Cost Management — keeping API costs under control
- Cross-Page Consistency — how context propagation works (and fails)