Skip to content
LexerLangv0.1.0

Production

--production, the error page, event ids and what to watch when deploying.

Terminal
lexer serve app.lexer --production

or:

Terminal
LEXER_ENV=production lexer serve app.lexer

The CLI wins: when --production is given, the environment variable is not consulted.

The error page#

This is the only thing the mode changes:

Text
development:  sayfa calistirilamadi: /path/app.lexer:25:19: tanimsiz degisken: $yok
production:   sayfa calistirilamadi (olay: 4b17df5d3b21)

The detail is written to the log file under the same id. You find the logged line from the code the user reports, and no file path, line number or variable name leaks to the browser.

When --production is given and --log is not, out.log becomes the default.

Which address to listen on#

LexerLang
$app = new http_server({host: "127.0.0.1", port: 3500})

If nginx terminates TLS and sets the security headers, the application should not be reachable from outside. Listening on 0.0.0.0 means the site can be reached around nginx — without HTTPS and without those headers.

Things to watch when deploying#

A restart is needed#

Pages are read from disk on every request, so changing a .md or .lx file does not require a restart. However:

  • Things built at startup — the search index, connections opened with services.once — are only refreshed by a restart.
  • The cache looks at the file's mtime, and rsync -a preserves mtime; a new version carrying an old mtime can stay stale in the cache.

Both end with the same fix:

Terminal
systemctl restart lexersite

minify#

$app.compress() turns on minify and gzip together. Minify collapses whitespace in the body without looking at the content type, which damages responses where line endings matter, such as robots.txt. To separate them:

LexerLang
$app.listen({port: 3500, minify: false, gzip: true})

Content type#

In this runtime $res.send() sets the Content-Type to text/html under all circumstances. Only $res.json() sends the right type.

Addresses such as sitemap.xml, robots.txt and markdown sources need their type corrected in nginx — see nginx and systemd.

The stakes are concrete: as long as the sitemap goes out as text/html, Google Search Console rejects it as "Sitemap is an HTML page", even when the XML itself is flawless.

No file serving#

$res cannot serve a file from disk. Files requested from the rootfavicon.ico, apple-touch-icon.png, site.webmanifest — have to come from nginx; the browser asks for the first two from the root even when no <link> points there.

Version stamps on asset URLs#

If /public/ is served with a long cache, an unstamped URL lets the old file survive in the browser after a deploy:

LexerLang
$doc.head.add(`<link rel="stylesheet" href="/public/lexer.css?v=2026091901">`)

That is not only a late update but a broken intermediate state: if a button in the new HTML carries data-tema-dugme while the old JS looks for [data-tema], the button does nothing at all. Because CSS and JS change together, the stamp should be shared and bumped on every deploy.

Next#

nginx and systemd.