An app’s shape
An app is a folder. Where a file lives decides what it does, so there's no config to write.
index.html # static page, served as is
pages/ app.tsx # browser modules, TypeScript compiled on the fly
routes/ # server-rendered pages: docs/sync.md is /docs/sync
islands/ # interactive components inside server pages
functions/ # /api/fn/<name>, run in the sandbox
hooks/ # <collection>.ts: beforeCreate, beforeUpdate…
jobs/ # scheduled: schedule = "0 7 * * *"
agents/ # react to changes in a collection
views/ # live views, state on the server
i18n.json # translations
sluurp-deps.json # packages added with sluurp add, with hashes
vendor/ # their sources
schema.json # collections, fields and rulesWhere server code runs
Functions, hooks, jobs, agents, views and server pages run in a QuickJS sandbox. It has no file system, no network and no process, and each call has a memory limit and a timeout. Server code accesses data only through server, the same collections API the browser uses, acting as the caller, so every rule still applies.
Server files can import the app’s own modules by relative path (../lib/marks.ts, ./room, a folder’s index.ts) and JSON files. Sluurp bundles them into the single module the sandbox runs; imports don’t grant any extra access.
Several apps, one server
sluurp serve --public ./school --public reports=./reports --public wiki=./wikiThe first app is served at /, each named one at its own path (/reports/, /wiki/) with its own functions and jobs.
The UI kit
sluurp/kit is a shadcn-style component library: Button, Card, Dialog, Select, Tabs, Table, Command, Sidebar and more, built on sluurp/ui, a small signals + JSX runtime. Tailwind works without a build step: the stylesheet is generated from the classes the app uses. See UI kit for the full list and a live demo.