Documentation
How-to guides
Recipes for a task you already know you want done: the steps, the code, and nothing else.
- Create a CRUD app
The shortest path from an empty directory to seven working routes over a Postgres table. If you'd rather have each step explained, the two tutorials your first…
- Write a handwritten route
Mount a page or an endpoint from a file under app/, read what the request carries, and answer it.
- Take over one of the seven derived routes
Replace a derived page with one you wrote and keep the other six, or remove an action from a resource altogether.
- Mount routes under a prefix
Serve part of the table under /admin, with the pages' own links, forms and redirects moving with it.
- Change the schema
Add, rename or drop a column or a table, and get the change into every database the application runs against.
- Configure the database connection
Tell the application where its Postgres is, size the pool, and keep several applications apart in one database.
- Add authentication
Put a login page in front of routes, decide per action who may take it, and scope a model's rows to their owner. Adding sign in walks through the same steps…
- Add a live component
Embed server-held, self-updating state in an ordinary page with no JavaScript of your own. A live page, from nothing is the long version.
- Share state between live pages
Make two browsers converge on one value with a Topic, and keep handle honest while they do.
- Call an external API from a live component
Do slow work off the page thread and patch the outcome in when it lands.
- Refuse a request, recover from one, answer your own errors
Three things a handler does with a failure: throw a refusal, map its own exception to a status, or recover inside a transaction. Failures is the one-page model…
- Test an application
Drive the route table in a unit test, boot against a real Postgres, and test a live component as plain functions.
- Run a job instead of a server
An application on the database layer alone, whose boot is a unit of work over rows: run once, on a schedule, or by a cron.
- Log through Logback instead of java.util.logging
Swap the logging backend eezo, Jetty and HikariCP share by default for Logback, without ending up with two providers on the classpath.
- Deploy
Ship an application to Fly.io with one command, from a laptop or from CI, and what to change for a live application, a custom domain, or another host. The…