Features

What Laterite gives you.

A working admin, a portable data layer, localization, plugins, and the security groundwork every application needs, built to stay out of your way as the app grows.

Descriptor-driven admin

Lists, forms, filters, and navigation are serde descriptor structs. Generic handlers render them, so a new screen is a value you write, not a controller you wire by hand. Descriptors are YAML-loadable, so screens can live in configuration. Field types are an open registry (text inputs, select, a searchable reference picker), list cells render by column type, and a form's writes go through a persister you can swap.

Portable data layer

Queries and migrations are built with sea-query over sqlx and run unchanged on PostgreSQL, MySQL, and SQLite. Backend quirks (booleans, key columns, casts, upserts, returning ids) are handled by polyfills, so you write natural Rust types. The full test suite runs against all three databases on every push.

Reversible migrations

Each migration is a Rust unit with up and down. A runner applies them in order and tracks history per module, so a module carries its own version history and can be rolled back, reset, or refreshed from the command line.

Role-based permissions and an audit log

Permissions are dotted strings carried by descriptors and enforced by middleware. Roles group them; per-user overrides take precedence when you need to grant or revoke for one account. A screen with a form must declare its permission, or the app refuses to boot. Every privilege and data mutation lands in an append-only audit log, with a read-only view in the admin for anyone permitted to see it.

Localized from the start

Every user-facing string in the admin is a translatable value: a bare string does not compile. Each request resolves a locale from the operator's preference, the browser's language, and the application's default, and dates render in that locale. Translations are standard PO catalogs contributed by modules, so a new language is a file, and lat i18n extracts, checks, and reports coverage.

Plugins as folders

A plugin is a crate under plugins/<author>/<plugin>/. lat plugin sync registers it, the admin enables or disables it, and its migrations and screens arrive with it. Plugins are isolated at boot: one that fails is quarantined with its dependents and logged, and the rest of the application comes up. Every plugin declares the database capabilities it needs, checked before it loads.

Forms that validate, sessions that protect

Form submissions run through a rule engine (required, length, email, URL, unique) and re-render with per-field errors. Every admin form carries a CSRF token and every request passes an origin check, with flash messages that survive the redirect after a save. Credentials are hashed with Argon2id, and repeated failed logins lock an account without needing Redis.

Server-rendered, no JS framework

The admin is Askama templates with HTMX. Interactions happen over small HTML swaps, so there is no separate front-end build, no client state to keep in sync, and one small vanilla-JS island only where a widget needs it.

A command-line tool that finds its way

lat new is a guided installer: it prompts for the application name, timezone, and database, creates the database, applies the migrations, and creates the first administrator. lat serve runs the app, lat doctor checks that it is ready, and lat admin creates or recovers an administrator. Run from anywhere inside an application, each command reads what the app already states, its config and its database, and asks only for what it cannot find.

On the road to 1.0

Laterite is pre-1.0 and ships in themed minor releases. Next come CMS pages and themes with a runtime template engine; then mail, background jobs, realtime, and cache as swappable drivers, with a database-backed default so a PostgreSQL deployment needs nothing else and Redis stays optional; then user-defined content types that become real tables; and the plugin marketplace that 1.0 freezes the public API for. The changelog records each step as it lands.

Start building.

Get started