local‑first all the things

Evolu is a local-first platform. Apps store data in SQLite on each device and sync it end-to-end encrypted through relays you can host yourself.

Evolu Library is ready. Evolu local‑first runs in production in Trezor Suite; general release is coming.

import {
  createQueryBuilder,
  id,
  NonEmptyTrimmedString100,
  nullOr,
  SqliteBoolean,
  sqliteTrue,
} from "@evolu/common";

// Evolu Schema supports any Standard Schema compatible library, such as Zod.
// This one uses Evolu Type.
export const Schema = {
  todo: {
    id: id("Todo"),
    title: NonEmptyTrimmedString100,
    isCompleted: nullOr(SqliteBoolean),
  },
};

// Type-safe SQL, built with Kysely.
const createQuery = createQueryBuilder(Schema);

export const todosQuery = createQuery((db) =>
  db
    .selectFrom("todo")
    .select(["id", "title", "isCompleted"])
    .where("isDeleted", "is not", sqliteTrue)
    .orderBy("createdAt"),
);

Simple, strict, secure, honest

Data lives in SQLite tables you query with type-safe SQL. No complex abstractions.

All constraints are branded types. Broken invariants throw before invalid state spreads.

End-to-end encrypted and post-quantum resistant by default.

Limits are documented: what relays can see, and the trade-offs behind design decisions.

Built with Evolu

  • Trezor SuiteIn production

    SatoshiLabs integrates Evolu with local authentication backed by Trezor.

  • LinkyIn production

    A Bitcoin wallet and messaging app in one.

  • PaykyIn development

    A local-first payment terminal for bank transfers, cash, and Bitcoin Lightning.

Local-first

Local‑first apps keep data on the user's device and use servers only to sync and back it up. They work offline, and users keep their data even when the company behind an app changes its plans. Read why the world needs local‑first apps.

SQLite everywhere
Browsers, React Native (Expo), and Electron, with React, Vue, and Svelte bindings. On the web, Evolu compiles plain SQLite from sqlite.org's source, checked against the hash sqlite.org publishes.
Type-safe SQL
Kysely queries whose results update when local or synced data changes.
Any schema library
Define columns with Evolu Type or any Standard Schema library, such as Zod.
End-to-end encrypted
Relays store and forward encrypted changes they can't read. The privacy docs explain what relays can see.
Relays you can host
The relay is MIT-licensed and self-hostable. Use several at once, so sync survives an outage.
History included
Every synced change is kept, so you can travel in time. Devices converge deterministically, and the last writer wins per column.

Evolu Library

The TypeScript library Evolu is built on, ready to use on its own. It's written test‑first: its tests are the runnable specification, and most modules have full test coverage. The source and unit tests ship in the npm package, and every example in its API reference is type-checked and run, so developers and agents learn from verified code.

Typed errors. No try/catch. Exhaustive error handling.

Runtime types with typed errors and formatters. All constraints are branded.

Structured concurrency with dependency injection. Plain async functions, no generators.

Helpers for Array, Object, Set, String, Eq, Order, Time, and more.

Resource management with the JavaScript using keyword.

Invariants types can't express are asserted at runtime. Use them in your tests too.

One documented style for names, errors, and dependencies, so every module reads the same.

Tree-shakable, with few dependencies. Types, Tasks, and logging in 9.3 kB.

import { Age, assertType, type Brand } from "@evolu/common";

// Every constraint a Type checks is a brand, so its type says what was checked.
assertType<
  Age,
  number &
    Brand<"NonNaN"> &
    Brand<"Finite"> &
    Brand<"Int"> &
    Brand<"NonNegative"> &
    Brand<"LessThan200"> &
    Brand<"Age">
>();

Made by Daniel Steigerwald

When I started Evolu, I knew I didn't know everything, so I built on popular functional programming libraries. That was a compromise, because depending on code I don't understand is a kind of vendor lock‑in too. So I wrote Evolu Library. For structured concurrency and resource management, I studied how other languages, frameworks, and libraries handle them. It was an incredible journey, and I stand behind how Evolu works today.

I've also learned that tests can show bugs but never prove their absence. Formal verification can, so future versions of Evolu will be formally verified.

Evolu is designed to fit in one developer's head: one author, one consistent design, and design decisions explained next to the code.

Sponsor on GitHub · The story behind Evolu

Own your data. Own your apps.