Reference.
Your first handler.
Save this as app.lua. A package holds an optional handler plus JSON page files. Returning nil falls back to a matching static JSON page.
Built-in Lua functions.
| Function | What it does |
|---|---|
| ctx.method | GET or POST. |
| ctx.path | The requested site path, e.g. / or /sign. |
| ctx.fields | String and boolean form values. Validate them on the server. |
| ctx.requestId | A request identifier used for replay and duplicate handling. |
| ctx.page.document(title, children) | Build a version 1 page document. |
| ctx.page.<component>{...} | Construct any component in the table below. |
| ctx.read(key, default) | Read this site’s stored data; returns default if missing. |
| ctx.write(key, value) | Persist JSON-compatible data on POST. Use letters, digits and hyphens, 2 to 40 characters, for compatibility with local hosts. |
The cloud environment exposes assert, error, ipairs, pairs, next, pcall, select, tonumber, tostring, type and the math, string, table, utf8 libraries. No os, io, require, package, load, debug, shell or network access.
Each cloud request starts in a fresh isolated VM. Keep state in ctx.read and ctx.write, not global variables. Local owner-installed Lua runs with the computer's privileges and is not sandboxed.
Everything a page can be made of.
JSON pages use {"version":1,"title":"Hello","children":[...]}. Every node has a type. Lua builders add the type for you.
| Component | Props | Notes |
|---|---|---|
| heading / paragraph | text | Titles and wrapped body text. |
| list | items: string[] | Up to 128 list items. |
| link | text, href | A relative site path, hub:// address or ln:// address. |
| image | rows: string[], text? | CC palette digits 0-f, spaces transparent. Up to 128 x 64 pixels. |
| section / columns | children | Group nodes; columns stack on narrow terminals. |
| form | action, children | Submits POST fields to a path on the same site. No nested forms. |
| input | name, text, password? | String field, up to 2,048 characters. password: true masks terminal input. |
| checkbox | name, text | Sends true or false. |
| select | name, text, options | Sends a selected string; 1 to 32 options. |
| submit | text | Submits its containing form. |
Form field names use letters, digits, underscores or hyphens, up to 40 characters. All fields must be inside a form. Input is untrusted: check types, length and allowed choices in the handler.
Send something back.
Redirects stay on the same site. The cloud protocol supports page, redirect and error responses. Local hosts also accept a bounded resource response, but uploaded assets are not part of the current Hub package format.
Limits.
- Other package files must be valid page JSON. Concurrent conflicting storage writes are rejected; reload before resubmitting.
- Lua also has a 64 MiB JavaScript heap. These are ceilings, not guaranteed capacity. Per-caller, per-site and platform rate limits apply; replay IDs prevent silent duplicate form execution.
- Password masking only hides typing. Site operators receive every submitted field. Never reuse a real password in a demo; there are no site-user accounts, sessions or password hashing built in.
- Cloud requests use HTTPS. Local modem connections need seeded cryptography, and fingerprint verification for independently verified identities.
- History stores addresses and the browser caches GET pages, so do not return secrets in cacheable pages. Check service status.
At your computer.
| Command | What it does |
|---|---|
| lantern edit | Create, edit, validate, preview, host or upload a local site. The editor offers six templates. |
| lantern host | Serve a site over modems from this computer. |
| lantern publish <name> | Upload a draft to the Hub with an upload key. |
| lantern doctor | Check HTTP access, files and versions. |
| lantern update / repair | Update or repair from a trusted offline installer. |
| lantern uninstall | Remove Lantern; keeps your data. |
lantern editlantern hub://help/Update and repair take a trusted offline installer path; uninstall keeps user data. New to all this? Follow the beginner walkthrough.