Skip to content
LexerLangv0.1.0

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.

LexerLang
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 with

Run it:

Terminal
lexer serve app.lexer --watch

Open 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:

LexerLang
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:

LexerLang
# 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>`)
LexerLang
$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#

LexerLang
$app.static({url_path: "/public", directory: path.pwd + "/public"})

public/site.css is then served at /public/site.css.

Running in the background#

Terminal
lexer serve app.lexer --background

The process detaches from the terminal and out() output goes to .logs/ in the working directory. To see and stop what is running:

Terminal
lexer status
lexer logs <pid> --follow
lexer stop <pid>

Production mode#

Terminal
lexer serve app.lexer --production

Error 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:

LexerLang
use modes

if mode == modes.development then
    out("development")
end if

Next#

lexer serve with its flags, and the syntax.