I’m occasionally asked how I put my site together. In short, AsciiDoc and MathJax. And for the pages that run code, mostly Haste.

On some pages, there’s an Easter egg of sorts. Replace html with lhs in the URL to see its source:

Other times, the secret extension is txt, such as the source of this page:

I have a few public repos containing the source of entire subsites, such as:

Those who can’t, do anyway

I’m neither a frontend engineer nor a web designer, but I find what I do works well enough.

I write best with a text editor using old-school text file and email conventions, such as minus signs or asterisks for list bullet points, and LaTeX notation for equations. The minimalist distraction-free environment makes me want to churn out line after line. Or maybe it subconsciously reminds me of long and glorious coding sessions, of heated debates on mailing lists, and of rushing to meet thesis deadlines, and I just go with the flow.

AsciiDoc turns classic text file flourishes into pretty HTML, and MathJax turns LaTeX into pretty equations rendered with JavaScript. I first encountered AsciiDoc when looking at Git documentation, and I wound up choosing it over its competitors for the same reasons Linus Torvalds did: it’s fairly well-defined and powerful, yet the source resembles the text files I once downloaded from BBS’s and studied on a 80x25 character terminal. (Though one annoyance is dealing with tildes in URLs, like on this very page!)

A custom script automates building pages. It deals with things like CSS; Google Analytics; including a menu HTML file if appropriate. This lets me acheive my ideal workflow: type, type, type, run script, type, type, type…

I’m unsure about publishing my script because it also performs some egregiously idiosyncratic source transformations. It’s a long story, whose sordid details I reveal next.

The limits of mathematics

I once used itex2MML, which defaults to LaTeX delimiters, that is, dollar signs for inline equations and backslash-square brackets for display equations.

AsciiDoc with MathJax is different, and in some ways better. They use characters that clearly indicate whether they’re starting or ending an inline equation as opposed to the same symbol (dollar sign) all the time. If I were starting out today, I would follow their guidelines.

I was too lazy and too stubborn to change existing documents and my habits, so my script translates dollar signs to the correct notation. I’d advise against following my lead because my fragile search-and-replace gets some cases wrong, which I must work around carefully. My script is also tied to Asciidoc; these days there’s Asciidoctor, which I heard improves on the original.


My script changes LaTeX-style code blocks (\begin{code} and \end{code}) into AsciiDoc code blocks, so that the same file can serve as a Haskell program as well as a webpage documenting the program.

I often use the the Haste compiler to compile the Haskell featured on a webpage to produce JavaScript that demonstrate it, such as a Tic-tac-toe player using minimax search with alpha-beta pruning. Conditional compilation lets me run the program locally as well as on the browser.

Sadly, the Haste compiler no longer seems to be maintained. Its bugs and limitations may never be fixed, and forget about using newer Haskell libraries.

The Asterius compiler is a promising alternative. Asterius compiles to WebAssembly, which may mean better performance. It also outputs several files, which is good for sharing the same content across multiple pages, though it is a mild nusiance for my build scripts. Asterius worked well for a first-order logic theorem prover which Haste was unable to handle.

Last, and least, for completeness I should mention my own compilers. One of them supports a subset of Haskell that’s large enough to self-host and produces WebAssembly. It can compile Haskell on the browser and run it and I’m proud it could handle an experimental PuzzleScript interpreter. Even though my compiler performs few optimizations, some of the interpreted games are playable. (Or perhaps it’s because modern machines and WebAssembly engines are so fast!)

Ben Lynn 💡