The website for the Aether programming language, and its interactive REPL,
served by Aether's own std.http server.
serve.ae serves the static site and the REPL API. It replaces the original
Go/Echo backend entirely.
- Static pages and assets from
static/. GET /api/lesson/:nbrreturns a lesson{ title, theory, starter_code }fromresources/lessons/.PUT /api/execcompiles and runs the submitted source withae runand returns{ stdout, stderr }. This is the live playground backend.GET /healthzliveness.
It uses std.http (server, routing, zero-copy static files), std.io
(lesson files off disk), and std.json (escaped responses).
ae run serve.ae # http://localhost:1323/
or build a binary and run it from the repository root, so static/ and
resources/ resolve:
ae build serve.ae -o aesite-serve
./aesite-serve
./test.sh
Builds serve.ae, starts it, exercises every route, and exits non-zero on
any failure. CI runs exactly this.
Pushes to main run .github/workflows/deploy.yml:
- build
serve.aeand run./test.sh, - publish
static/to GitHub Pages at aether-lang.dev.
The custom domain is set by static/CNAME. On the registrar, point the apex
at GitHub Pages with four A records: 185.199.108.153, 185.199.109.153,
185.199.110.153, 185.199.111.153.
The live REPL backend (/api/exec running real Aether) is the next step. It
deploys as the serve.ae server on a host of its own, since Pages serves
static content only.
static/repl.html is a self-contained playground. Lessons load from
static/lessons.json (baked by tools/genlessons.ae, which also stores each
lesson's real output), so lessons, theory, and a sample run work on a static
host such as GitHub Pages with no server.
On load it probes /healthz. If a live serve.ae backend answers, Run
executes whatever is in the editor against it; otherwise Run shows the
precomputed output for the unedited lesson and points you at ae run for
local execution. To target a backend on another origin, set its URL in the
<meta name="aesite-exec"> tag and allow CORS there.
Regenerate lessons after editing resources/lessons/:
ae run tools/genlessons.ae
The static site works on its own. To make the playground run edited code, deploy
serve.ae as a backend and point the site at it.
Deploy with the included Dockerfile (the image keeps the Aether toolchain so
/api/exec can compile and run code). On Fly.io:
fly launch --no-deploy # once, creates the app from fly.toml
fly deploy
Then set the backend origin in static/repl.html:
<meta name="aesite-exec" content="https://your-app.fly.dev">
The playground probes /healthz and, when it answers, runs the editor's code there.
/api/exec runs ARBITRARY submitted code, i.e. arbitrary native code on the
host. It is hardened, not sandboxed: each request compiles in a fresh temp dir,
then the binary runs as a non-root user in a private network namespace
(unshare, no outbound access) under ulimits (CPU, file size) and a 10s
timeout, with output capped. Aether's containment model is language-level and
does not constrain untrusted external programs, so that is deliberately not
relied on here. A public deployment MUST add real OS isolation, e.g.
docker run --rm --read-only --tmpfs /tmp --pids-limit=256 \
--memory=512m --cpus=1 -p 8080:8080 aesite
plus rate limiting, and ideally a per-request microVM (Firecracker/gVisor). Run it somewhere disposable, never on a host with secrets or writable mounts.
static/Docs/ is generated from the language's markdown docs. Regenerate after
they change:
python3 tools/gendocs.py ~/Documents/git/aether/docs static/Docs
It converts every top-level *.md to a styled page (grouped sidebar, syntax
highlighting, cross-links rewritten to /Docs/*.html) and refreshes
static/docs.html. Output is committed and served as-is by Pages.
serve.ae # the Aether server
test.sh # integration smoke test
static/ # HTML, CSS, Docs/, CNAME
resources/lessons/<n>/ # content.html, code.ae, title.txt
tools/gendocs.py # markdown -> static/Docs/ generator
tools/genlessons.ae # resources/lessons -> static/lessons.json
Dockerfile, fly.toml # optional live exec backend
.github/workflows/ # CI + Pages deploy