algernon
CategoryServer Applications
SubcategoryServer Applications
Stars3,031
HTTP/2 web server with built-in support for Lua, Markdown, GCSS and Amber
About algernon
This large README is shown as a plain-text preview. Read the full README at the source
<!--
title: Algernon
description: Web server with built-in support for Lua, Teal, Markdown, Pongo2, Amber, Sass, SCSS, GCSS, JSX, TypeScript, Bolt, PostgreSQL, SQLite, Redis, Valkey, MariaDB, MySQL, MSSQL, Tollbooth, Pie, Permissions2, users and permissions, IPv6, React19
keywords: web server, QUIC, lua, teal, markdown, pongo2, application server, http, http2, HTTP/2, HTTP/3, go, golang, algernon, JSX, TSX, TypeScript, React, BoltDB, Bolt, PostgreSQL, SQLite, Redis, Valkey, MariaDB, MySQL, Three.js, ipv6, react19
theme: material
-->
<!--<a href="https://github.com/xyproto/algernon"><img src="https://algernon.roboticoverlords.org/img/algernon_logo.png" style="margin-left: 2em"></a>-->

[](https://github.com/xyproto/algernon/actions/workflows/build.yml)
[](https://godoc.org/github.com/xyproto/algernon)
[](https://raw.githubusercontent.com/xyproto/algernon/main/LICENSE)
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fxyproto%2Falgernon?ref=badge_shield)
[](https://stand-with-ukraine.pp.ua)
Web server with built-in support for HTTP/2, HTTP/3 (QUIC), Lua, Teal, Markdown, Pongo2, HyperApp, Amber, Sass(SCSS), GCSS, JSX, TypeScript, Ollama (LLMs), BoltDB (built-in, stores the database in a file, like SQLite), Redis, Valkey, PostgreSQL, SQLite, MariaDB, MySQL, MSSQL, IPv6, npm-less React 19, rate limiting, graceful shutdown, plugins, users and permissions.
All in one small self-contained executable.
Distro Packages
---------------
[](https://repology.org/project/algernon/versions)
Quick installation
------------------
Requires Go 1.26 or later.
go install github.com/xyproto/algernon@latest
Or manually (development version):
```
git clone https://github.com/xyproto/algernon
cd algernon
go build -mod=vendor
./welcome.sh
```
Releases and pre-built images
-----------------------------
See the [release](https://github.com/xyproto/algernon/releases/latest) page for releases for a variety of platforms and architectures.
Getting Started
---------------
See [TUTORIAL.md](TUTORIAL.md).
Docker
------
The [Docker image](https://hub.docker.com/r/xyproto/algernon/tags) is less than 17MB and can be tried out (on `x86_64`) with:
```
mkdir localhost
echo 'hi!' > localhost/index.md
docker run -it -p4000:4000 -v .:/srv/algernon xyproto/algernon
```
And then visiting `http://localhost:4000` in a browser.
Technologies
------------
Written in [Go](https://golang.org). Uses [Bolt](https://github.com/coreos/bbolt) (built-in), [MySQL](https://github.com/go-sql-driver/mysql), [PostgreSQL](https://www.postgresql.org/), SQLite or Valkey/[Redis](https://redis.io) (recommended) for the database backend, [permissions2](https://github.com/xyproto/permissions2) for handling users and permissions, [gopher-lua](https://github.com/yuin/gopher-lua) for interpreting and running Lua, optional [Teal](https://github.com/teal-language/tl) for type-safe Lua scripting, [http2](https://github.com/bradfitz/http2) for serving HTTP/2, [quic-go](https://github.com/quic-go/quic-go) for serving QUIC, [gomarkdown/markdown](https://github.com/gomarkdown/markdown) for Markdown rendering, [amber](https://github.com/eknkc/amber) for Amber templates, [Pongo2](https://github.com/flosch/pongo2) for Pongo2 templates, [Sass](https://github.com/wellington/sass)(SCSS) and [GCSS](https://github.com/yosssi/gcss) for CSS preprocessing. [logrus](https://github.com/Sirupsen/logrus) is used for logging, [esbuild](https://github.com/evanw/esbuild) for bundling and converting JSX/TSX to JavaScript, [tollbooth](https://github.com/didip/tollbooth) for rate limiting and [pie](https://github.com/natefinch/pie) for plugins.
Design decisions
----------------
* HTTP/2 over SSL/TLS (https) is used by default, if a certificate and key is given.
* If not, regular HTTP is used.
* HTTP/3 (QUIC) can be enabled with a flag.
* /data and /repos have user permissions, /admin has admin permissions and / is public, by default. This is configurable.
* The following filenames are special, in prioritized order:
* index.lua is Lua code that is interpreted as a handler function for the current directory.
* index.html is HTML that is outputted with the correct Content-Type.
* index.md is Markdown code that is rendered as HTML.
* index.txt is plain text that is outputted with the correct Content-Type.
* index.pongo2, index.po2 or index.tmpl is Pongo2 code that is rendered as HTML.
* index.amber is Amber code that is rendered as HTML.
* index.hyper.js, index.hyper.jsx or index.happ is JSX+HyperApp code that is rendered as HTML.
* index.jsx is a React JSX/JavaScript file that is rendered as HTML with bundled JavaScript.
* index.tsx is a React TSX/TypeScript file that is rendered as HTML with bundled JavaScript.
* index.tl is Teal code that is interpreted as a handler function for the current directory.
* index.prompt is a content-type, an Ollama model, a blank line and a prompt, for generating content with LLMs.
* data.lua is Lua code, where the functions and variables are made available for Pongo2, Amber and Markdown pages in the same directory.
* If a single Lua script is given as a command line argument, it will be used as a standalone server. It can be used for setting up handlers or serving files and directories for specific URL prefixes.
* style.gcss is GCSS code that is used as the style for all Pongo2, Amber and Markdown pages in the same directory.
* The following filename extensions are handled by Algernon:
* Markdown: .md (rendered as HTML)
* Pongo2: .po2, .pongo2 or .tpl (rendered as any text, typically HTML)
* Amber: .amber (rendered as HTML)
* Sass: .scss (rendered as CSS)
* GCSS: .gcss (rendered as CSS)
* JSX: .jsx (rendered as JavaScript/ECMAScript)
* TypeScript: .ts, .tsx (rendered as JavaScript/ECMAScript)
* Lua: .lua (a script that provides its own output and content type)
* Teal: .tl (same as .lua but with type safety)
* HyperApp: .hyper.js or .hyper.jsx (rendered as HTML)
* Other files are given a mimetype based on the extension.
* Directories without an index file are shown as a directory listing, where the design is hard coded.
* UTF-8 is used whenever possible.
* The server can be configured by command line flags or with a lua script, but no configuration should be needed for getting started.
Features and limitations
------------------------
* Supports HTTP/2, with or without HTTPS (browsers may require HTTPS when using HTTP/2).
* Also supports HTTP/3 (QUIC) and regular HTTP.
* Can use Lua scripts as handlers for HTTP requests.
* The Algernon executable is compiled to native and is reasonably fast.
* Works on Linux, macOS and 64-bit Windows.
* The [Lua interpreter](https://github.com/yuin/gopher-lua) is compiled into the executable.
* The [Teal typechecker](https://github.com/teal-language/tl) is loaded into the Lua VM.
* Live editing/preview when using the auto-refresh feature.
* The use of Lua allows for short development cycles, where code is interpreted when the page is refreshed (or when the Lua file is modified, if using auto-refresh).
* Self-contained Algernon applications can be zipped into an archive (ending with `.zip` or `.alg`) and be loaded at start.
* Built-in support for [Markdown](https://github.com/gomarkdown/markdown), [Pongo2](https://github.com/flosch/pongo2), [Amber](https://github.com/eknkc/amber), [Sass](https://github.com/wellington/sass)(SCSS), [GCSS](https://github.com/yosssi/gcss) and [JSX/TSX](https://github.com/evanw/esbuild).
* Redis is used for the database backend, by default.
* Algernon will fall back to the built-in Bolt database if no Redis server is available.
* The HTML title for a rendered Markdown page can be provided by the first line specifying the title, like this: `title: Title goes here`. This is a subset of MultiMarkdown.
* No file converters needs to run in the background (like for SASS). Files are converted on the fly.
* If `-autorefresh` is enabled, the browser will automatically refresh pages when the source files are changed. Works for Markdown, Lua error pages and Amber (including Sass, GCSS and *data.lua*). This only works on Linux and macOS, for now. If listening for changes on too many files, the OS limit for the number of open files may be reached.
* Includes an interactive REPL.
* If only given a Markdown filename as the first argument, it will be served on port 3000, without using any database, as regular HTTP. This can be handy for viewing `README.md` files locally. Use `-m` to display it in a browser and only serve it once.
* Full multi-threading. All available CPUs will be used.
* Supports rate limiting, by using [tollbooth](https://github.com/didip/tollbooth).
* The `help` command is available at the Lua REPL, for a quick overview of the available Lua functions.
* Can load plugins written in any language. Plugins must offer the `Lua.Code` and `Lua.Help` functions and talk JSON-RPC over stderr+stdin. See [pie](https://github.com/natefinch/pie) for more information. Sample plugins for Go and Python are in the `plugins` directory.
* Thread-safe file caching is built-in, with several available cache modes (for only caching images, for example).
* Can read from and save to JSON documents. Supports simple JSON path expressions (like a simple version of XPath, but for JSON).
* If cache compression is enabled, files that are stored in the cache can be sent directly from the cache to the client, without decompressing.
* Files that are sent to the client are compressed with [gzip](https://golang.org/pkg/compress/gzip/#BestSpeed), unless they are under 4096 bytes.
* When using PostgreSQL, the HSTORE key/value type is used (available in PostgreSQL version 9.1 or later).
* No external dependencies, only pure Go.
* Requires Go >= 1.26 or a version of GCC/`gccgo` that supports Go 1.26.
* The Lua implementation used in Algernon (gopherlua) does not support `package.loadlib`.
* Full support for IPv6.
Q&A
---
Q:
> What is the benefit of using this? In what scenario would this excel? Thanks. -- [mtw@HN](https://news.ycombinator.com/item?id=19583144).
A:
> Good question. I'm not sure if it excels in any scenario. There are specialized web servers that excel at caching or at raw performance. There are dedicated backends for popular front-end toolkits like Vue or React. There are dedicated editors that excel at editing and previewing Markdown, or HTML.
>
> I guess the main benefit is that Algernon covers a lot of ground, with a minimum of configuration, while being powerful enough to have a plugin system and support for programming in Lua. There is an auto-refresh feature that uses Server Sent Events, when editing Markdown or web pages. There is also support for the latest in Web technologies, like HTTP/2, QUIC and TLS 1.3. The caching system is decent. And the use of Go ensures that also smaller platforms like NetBSD and systems like Raspberry Pi are covered. There are no external dependencies, so Algernon can run on any system that Go can support.
>
> The main benefit is that is is versatile, fresh, and covers many platforms and use cases.
>
> For a more specific description of a potential benefit, a more specific use case would be needed.
Installation
------------------
##### macOS
* Install [Homebrew](https://brew.sh), if needed.
* `brew install algernon`
##### Arch Linux
* `pacman -S algernon`
##### Any system where Go is available
This method is using the latest commit from the main branch:
go install github.com/xyproto/algernon@main
If neeed, add `~/go/bin` to the path. For example: `export PATH=$PATH:$HOME/go/bin`.
Utilities
---------
* Comes with the `alg2docker` utility (in `containers/alg2docker`), for creating Docker images from Algernon web applications (`.alg` files).
* [http2check](https://github.com/xyproto/http2check) can be used for checking if a web server is offering [HTTP/2](https://tools.ietf.org/html/rfc7540).
Overview
--------
Running Algernon:
<img src="https://raw.github.com/xyproto/algernon/main/img/algernon_gopher.png">
Screenshot of an earlier version:
<img src="https://raw.github.com/xyproto/algernon/main/img/algernon_redis_054.png">
---
The idea is that web pages can be written in Markdown, Pongo2, Amber, HTML or JSX (+React or HyperApp), depending on the need, and styled with CSS, Sass(SCSS) or GCSS, while data can be provided by a Lua or Teal script that talks to Redis, BoltDB, PostgreSQL, MSQL or MariaDB/MySQL.
Amber and GCSS is a good combination for static pages, that allows for more clarity and less repetition than HTML and CSS. It˙s also easy to use Lua for providing data for the Amber templates, which helps separate model, controller and view.
Pongo2, Sass and Lua or Teal also combines well. Pongo2 is more flexible than Amber.
The auto-refresh feature is supported when using Markdown, Pongo2 or Amber, and is useful to get an instant preview when developing.
The JSX to JavaScript (ECMAscript) transpiler is built-in.
Redis is fast, scalable and offers good [data persistence](https://redis.io/topics/persistence). This should be the preferred backend.
Bolt is a [pure key/value store](https://github.com/coreos/bbolt), written in Go. It makes it easy to run Algernon without having to set up a database host first.
MariaDB/MySQL support is included because of its widespread availability.
PostgreSQL is a solid and fast database that is also supported.
Screenshots
-----------
<img src="https://raw.github.com/xyproto/algernon/main/img/algernon_markdown.png">
*Markdown can easily be styled with Sass or GCSS.*
---
<img src="https://raw.github.com/xyproto/algernon/main/img/algernon_lua_error.png">
*This is how errors in Lua scripts are handled, when Debug mode is enabled.*
---
<img src="https://raw.github.com/xyproto/algernon/main/img/algernon_threejs.png">
*One of the poems of Algernon Charles Swinburne, with three rotating tori in the background.*
*Uses CSS3 for the Gaussian blur and [three.js](https://threejs.org) for the 3D graphics.*
---
<img src="https://raw.github.com/xyproto/algernon/main/img/prettify.png">
*Screenshot of the <strong>prettify</strong> sample. Served from a single Lua script.*
---
<img src="https://raw.github.com/xyproto/algernon/main/img/algernon_react.png">
*JSX transforms are built-in. Using [React](https://facebook.github.io/react/) together with Algernon is easy.*
Samples
-------
The sample collection can be downloaded from the `samples` directory in this repository, or here: [samplepack.zip](https://algernon.roboticoverlords.org/samplepack.zip).
Getting started
---------------
##### Run Algernon in "dev" mode
This enables debug mode, uses the internal Bolt database, uses regular HTTP instead of HTTPS+HTTP/2 and enables caching for all files except: Pongo2, Amber, Lua, Teal, Sass, GCSS, Markdown and JSX.
* `algernon -e`
Then try creating an `index.lua` file with `print("Hello, World!")` and visit the served web page in a browser.
##### Configure the required ports for local use
* You may need to change the firewall settings for port 3000, if you wish to use the default port for exploring the samples.
* For the auto-refresh feature to work, port 5553 must be available (or another host/port of your choosing, if configured otherwise).
##### Prepare for running the samples
git clone https://github.com/xyproto/algernon
cd algernon
make
##### Launch the "welcome" page
* Run `./welcome.sh` to start serving the "welcome" sample.
* Visit `http://localhost:3000/`
##### Create your own Algernon application, for regular HTTP
* `mkdir mypage`
* `cd mypage`
* Create a file named `index.lua`, with the following contents:
`print("Hello, Algernon")`
* Start `algernon --httponly --autorefresh`.
* Visit `http://localhost:3000/`.
* Edit `index.lua` and refresh the browser to see the new result.
* If there were errors, the page will automatically refresh when `index.lua` is changed.
* Markdown, Pongo2 and Amber pages will also refresh automatically, as long as `-autorefresh` is used.
##### Create your own Algernon application, for HTTP/2 + HTTPS
* `mkdir mypage`
* `cd mypage`
* Create a file named `index.lua`, with the following contents:
`print("Hello, Algernon")`
* Create a self-signed certificate, just for testing:
* `openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3000 -nodes`
* Press return at all the prompts, but enter `localhost` at *Common Name*.
* For production, store the keys in a directory with as strict permissions as possible, then specify them with the `--cert` and `--key` flags.
* Start `algernon`.
* Visit `https://localhost:3000/`.
* If you have not imported the certificates into the browser, nor used certificates that are signed by trusted certificate authorities, perform the necessary clicks to confirm that you wish to visit this page.
* Edit `index.lua` and refresh the browser to see the result (or a Lua error message, if the script had a problem).
There is also a small [tutorial](TUTORIAL.md).
Using AI / LLMs / Ollama
------------------------
* The `ollama` server must be running locally, or a `host:port` must be set in the `OLLAMA_HOST` environment variable.
For example, using the default `qwen2.5-coder:1.5b` model (will be downloaded at first use, the size is 637 MiB and it should run anywhere).
```
lua> ollama()
Autumn leaves, crisp air, poetry flowing - this is what comes to mind when I think of Algernon.
lua> ollama("Write a haiku about software developers")
The software developer,
In silence, tapping at keys,
Creating digital worlds.
```
Using `OllamaClient` and the `mixtral` model (will be downloaded at first use, the size is 26 GiB and it might require quite a bit of RAM and also a fast CPU and/or GPU).
```
lua> oc = OllamaClient("mixtral")
lua> oc:ask("Write a quicksort function in OCaml")
Sure! Here's an implementation of the quicksort algorithm in OCaml:
let rec qsort = function
| [] -> []
| pivot :: rest ->
let smaller, greater = List.partition (fun x -> x < pivot) rest in
qsort smaller @ [pivot] @ qsort greater
This function takes a list as input and returns a new list with the same elements but sorted in ascending order using the quicksort algorithm. The `qsort` funct.
Here are some examples of using the `qsort` function:
# qsort [5; 2; 9; 1; 3];;
- : int list = [1; 2; 3; 5; 9]
# qsort ["apple"; "banana"; "cherry"];;
- : string list = ["apple"; "banana"; "cherry"]
# qsort [3.14; 2.718; 1.618];;
- : float list = [1.618; 2.718; 3.14]
I hope this helps! Let me know if you have any questions or need further clarification.
```
Example use of finding the distance between how the LLM models interpret the prompts:
```
lua> oc = OllamaClient("llama3")
lua> oc:distance("cat", "dog")
0.3629187146002938
lua> oc:distance("cat", "kitten")
0.3584441305547792
lua> oc:distance("dog", "puppy")
0.2825554473355113
lua> oc:distance("dog", "kraken", "manhattan")
7945.885516248905
lua> oc:distance("dog", "kraken", "cosine")
0.5277307399621305
```
As you can tell, according to Llama3, "dog" is closer to "puppy" (0.28) than "cat" is to "kitten" (0.36) and "dog" is very different from "kraken" (0.53).
The available distance measurement algorithms are: `cosine`, `euclidean`, `manhattan`, `chebyshev` and `hamming`. The default metric is `cosine`.
Frequently Asked Questions
What is algernon?
algernon is a Server Applications library for the Go programming language. HTTP/2 web server with built-in support for Lua, Markdown, GCSS and Amber
How many GitHub stars does algernon have?
algernon has 3,031 GitHub stars in the directory's latest synchronization.
How do I install algernon?
Install algernon with the Go module system using `go get xyproto/algernon`. Check the repository for the current installation instructions.
What category does algernon belong to?
algernon is listed under Server Applications, specifically Server Applications.