A Scala 3 web framework
Your data model is the source of truth.
Declare a model, and Eezo derives tables, forms, and HTTP routes. Server-side rendering with functional, direct-style Scala. Fast dev feedback, deploys with one command.
Install the command line
curl -fsSL https://eezo.io/install | bashNeeds JDK 25 and sbt. Read the script first if you like.
- Scala 3
- JDK 25
- Postgres
- MIT
case class Book(
id: Id[Book],
title: String,
author: String,
pages: Int
) derives Table, Form, Resource- GET
/books - GET
/books/new - POST
/books - GET
/books/:id - GET
/books/:id/edit - PUT
/books/:id - DELETE
/books/:id
0 clicks
This box is a live component: Component[State] on the server, events up and patches down over websocket, with no JS needed.
Four kinds of docs
How it works
- 1
eezo new myUnicornScaffold
A Main, one route, plus build files. Nothing to configure.
- 2
eezo devServe
Restarts on save. A broken compile keeps the old code serving.
- 3
eezo deployShip
Stages the jars, builds the image, migrates, waits for health.
Check out a full dev cycle in the deploy walkthrough.
What you get
One declaration
derives Table, Form, ResourceDeclare your model, and Eezo derives its tables & database API, its HTML form and all CRUD HTTP routes from one case class.
The filename is the route
app/Health.scala mounts GET /healthYour own routes come from the file layout. You can override a derived route on the same path.
Direct style
Request => ResponseA handler is a function. Eezo runs on virtual threads, so feel free to block on the database, call an API, or return a page.
Migrations from the model
eezo freeze, then eezo migrateEezo detects schema diffs as you change your data model. Commit them to fingerprinted SQL migrations. On deploy they run before the new code takes traffic.
Live pages
Component[State]Write UIs with a Scala functional DSL. State lives on the server, and the browser gets a thin client. UI sends events, server renders UI. No need for JavaScript.
Guarded by declaration
given Owned[Post, User] = ...Control route protection, and get your owner type if successful (e.g. a user). In an application with a guard, a route that says nothing is a compile error.
Take the layers you need
An application has a database layer, an http layer, or both. Import the right artifact for your app.
"io.eezo" %% "eezo-http"HttpApp · http only
See hello →"io.eezo" %% "eezo-db"DbApp · database only
See reminders →"io.eezo" %% "eezo"EezoApp · all
See blog →
Ready when you are.
Eezo is pre-release: dev is ongoing, and the source is open.