Your first server
From a ten-line file to a working site; --watch, routing and a shared layout.
Create a directory and put a file called app.lexer in it.
package hello
use http_server, html_document
$app = new http_server
$doc = new html_document
$doc.title = 'Hello'
$doc.body.add(`<h1>Hello world</h1>`)
with $app
.document.add($doc)
.listen({port: 3000})
end withRun it:
lexer serve app.lexer --watchOpen http://localhost:3000. When you save the file the server shuts down gracefully and comes back up; refreshing the browser is enough.
Line by line#
package hello — every file starts with a package name.
use http_server, html_document — the built-in modules you will use. A module that is not imported is not in scope.
$app = new http_server — the server object. Variables start with $.
$doc.body.add(...) — a backtick block produces raw HTML. Interpolated values are escaped; the tags stay raw.
with $app ... end with — consecutive calls on the same object, without repeating $app.
More than one page#
With a route table instead of a single document, addresses other than / respond too:
package site
use http_server, html_document
$app = new http_server({port: 3000})
$app.routes.add({
"/": func($req, $res) as void
$doc = new html_document
$doc.title = 'Home'
$doc.body.add(`<h1>Home</h1>`)
$res.document($doc)
end func
"/product/:id": func($req, $res) as void
$doc = new html_document
$doc.title = 'Product'
$doc.body.add(`<h1>Product ` + $req.params.id + `</h1>`)
$res.document($doc)
end func
})
$app.listen()At /product/42, $req.params.id is "42". An address that matches nothing returns 404.
If a handler finishes without calling send, document or redirect, that is an error — it does not quietly return a blank page.
A shared layout#
The <head> and page frame that repeat on every page live in their own file:
# layout.lx
package layout
use html_document
$doc = new html_document
$doc.type = html_document.types.LAYOUT
$doc.head.add(`<link rel="stylesheet" href="/public/site.css">`)
$doc.body.add(`<header>My site</header><main>${children}</main>`)$app.layout(path.pwd + "/layout.lx")${children} is where the page's own body goes. The layout applies only to pages served with $res.document($doc); $res.send() sends a raw body and bypasses it.
Static files#
$app.static({url_path: "/public", directory: path.pwd + "/public"})public/site.css is then served at /public/site.css.
Running in the background#
lexer serve app.lexer --backgroundThe process detaches from the terminal and out() output goes to .logs/ in the working directory. To see and stop what is running:
lexer status
lexer logs <pid> --follow
lexer stop <pid>Production mode#
lexer serve app.lexer --productionError detail is removed from the browser; only an event id is returned, and the detail goes to the log file. The mode can also be read from inside the language:
use modes
if mode == modes.development then
out("development")
end ifNext#
lexer serve with its flags, and the syntax.