DocsReference

createApp

Every option of createApp and every member of the app object it returns.

import { createApp } from 'locosdk/server'

const app = createApp({ schema, app: config.app, pages: { '/*': index } })
app.serve()

How to use it: Server: hooks, routes, crons.

Options#

optiondefaultwhat
schemarequiredthe defineSchema(...) of schema.ts
appnonethe identity of loco.config.ts: names the mails, serves the logo at /api/_/logo
dir'data'the data folder: <dir>/app.db, <dir>/storage/, <dir>/backups/
migrations[]{ file, up(m) } items, run once each before the schema sync, in file order
pages{}Bun.serve routes of HTML imports, { '/*': index }. /api/* never falls through to a page
metalocal values{ appName, appURL, senderName, senderAddress }: the {APP_NAME} and {APP_URL} of mails, the sender, the public URL of the MCP server
mailsending throwsa transport: smtpTransport(config), or memoryTransport() in tests
devNODE_ENV !== 'production'hot reload on the pages, no cap on live codes
rateLimits*:auth 5 per 3 sPocketBase's rate limit rules: { label, maxRequests, duration }. A list given here replaces the default, so name *:auth again
storagediskStorage('<dir>/storage')where file fields live: diskStorage(path) or s3Storage(config)
backupsno cron, keep all, on disk{ cron, maxKeep, storage }, storage is 'disk' or an S3 config
trustedProxy{ headers: [], useLeftmostIP: false }the headers that carry the real client IP
restart() => process.exit(0)how the process comes back after a restore
mcpoffthe app as an MCP server at /mcp: The MCP server

The app object#

memberwhat
schemathe live schema, after the sync
dbthe bun:sqlite database. app.db.query(sql).all(...params), every value bound. No rules
recordsthe trusted records service: list, getOne, getFirst, create, update, delete, transaction, batch. No rules, full validation, after success hooks fire
mail.send(message)send through the transport and the onMailerSend chain
metathe resolved meta
route(method, path, handler, ...middlewares)a custom route: Hooks
on*the hooks: Hooks
cron(name, spec, fn)a schedule, UTC, five fields or @hourly @daily @weekly @monthly @yearly
dispatch(request, { auth, body, context })an internal request through the router: the route's middlewares and hooks run. What MCP tools call
backupscreate(name?), list(), restore(key), active
storagethe file storage
serve({ port? })listen on port, else PORT, else 8090. Port 0 picks a free one. Returns Bun's Server
close()stop the server and the crons, close the database

Under bun --hot, a second createApp on the same dir retires the first: its crons stop and its database closes. Bun keeps the socket.

Boot, in order#

  1. Retire an earlier app on the same dir (a hot reload).
  2. Open <dir>/app.db (WAL, foreign keys on, a 10 s busy timeout).
  3. Run the migrations not yet applied, then sync the schema: additive changes apply, a destructive one stops the boot with every problem listed (Schema as code). The sync also checks each auth collection's options and mints a token secret where one is missing.
  4. Mount the routes: records, auth, files, /api/health, backups, the changelog, the user copy, MCP when it is on, the logo.
  5. Start the crons: the built in hourly cleanup, and the backup cron when backups.cron is set.

This page as markdown