Hackage without a server
hackage.aihc.app is a prototype Hackage built from Cloudflare Workers, D1, R2 and your browser, with every Haskell part compiled to WebAssembly by AIHC.
hackage.aihc.app is a prototype of hackage.haskell.org with no server. No VM, no database process, no documentation build farm. Here is what it looks like and how it is built.
Same package, two sites
text-2.1.4 package page at 1280×800. Drag the divider.The data is the same Cabal file. The design is borrowed from crates.io: one page per package, with tabs for the README, API, dependencies, dependents, changelog and Cabal fields. Every page is rendered on the server and works without JavaScript.
The architecture
hackage.haskell.org runs hackage-server, a long-running process on a machine that someone maintains. hackage.aihc.app has no machine:
- Site Worker renders the pages and handles search and imports. It parses Cabal files with
aihc-cabal-syntax, compiled to Wasm. - D1 holds versions and the search and dependency indexes. R2 holds the files: Cabal files, READMEs, source archives and documentation.
- Workflow Worker runs the dependency solver, the same one the compiler uses, compiled to Wasm. It fetches only the Cabal files it needs, never the full Hackage index.
hackage.haskell.org stays the source of truth. The site only reads from it.
Documentation is built by the reader
Data.Text from text-2.1.4. The right-hand side was generated in a browser.There is no documentation server. When a package has no docs, its API tab offers to build them. The browser downloads the sources and runs aihc-haddock, compiled to Wasm, in a Web Worker. The result is a JSON model of the API, which the browser uploads. The Worker renders it to HTML when someone reads the page, so readers need neither JavaScript nor Wasm.
An upload starts as a community result. The Workflow then rebuilds it with the same aihc-haddock binary, and marks it verified if the output matches.
Why this shape
Serverless. Nothing to patch, restart or keep running. Cost follows storage and requests, not uptime, and the expensive work runs on the reader’s CPU.
WebAssembly. The same compiler output runs in the browser, a Worker and a Workflow. Next up: a Haskell interpreter in the browser, so each package page gets a REPL with that package loaded.
Consistent styling. Documentation is data, so one renderer draws every package, in the same palette, fonts and light and dark themes as this blog.
What is missing
It is a prototype. There are no accounts or package uploads, only imported versions, and the generated docs still miss some types and cross-package links. The source is on GitHub. To try it, pick a package and open its API tab.