Quickstart

This guide will get you all set up and ready to use Evolu.

Installation

Evolu offers SDKs for a variety of frameworks, including React, Svelte, React Native, Expo, and others. Below, you can see how to install the SDKs for each framework.

npm install @evolu/common@preview @evolu/react@preview @evolu/react-web@preview

Define your Schema

First, define your database schema—tables, columns, and types.

Evolu uses Type for data modeling. Instead of plain JS types like string or number, we recommend using branded types to enforce domain rules.

schema.ts

import {
  FiniteNumber,
  id,
  json,
  maxLength,
  NonEmptyString,
  NonEmptyString1000,
  nullOr,
  object,
  SqliteBoolean,
} from "@evolu/common";

const TodoId = id("Todo");
type TodoId = typeof TodoId.Type;

const TodoCategoryId = id("TodoCategory");
type TodoCategoryId = typeof TodoCategoryId.Type;

// A custom branded Type.
const NonEmptyString50 = maxLength(50)(NonEmptyString);
// string & Brand<"MinLength1"> & Brand<"MaxLength50">
type NonEmptyString50 = typeof NonEmptyString50.Type;

// SQLite supports JSON-compatible values.
const Person = object({
  name: NonEmptyString50,
  // Did you know that JSON.stringify converts NaN (a number) into null?
  // Now, imagine that `age` accidentally becomes null. To prevent this, use FiniteNumber.
  age: FiniteNumber,
});
type Person = typeof Person.Type;

// SQLite stores JSON-compatible values as strings. Fortunately, Evolu provides
// a convenient `json` Type Factory for type-safe JSON serialization and parsing.
const PersonJson = json(Person, "PersonJson");
// string & Brand<"PersonJson">
type PersonJson = typeof PersonJson.Type;

const Schema = {
  todo: {
    id: TodoId,
    title: NonEmptyString1000,
    // SQLite doesn't support the boolean type; it uses 0 (false) and 1 (true) instead.
    // SqliteBoolean provides seamless conversion.
    isCompleted: nullOr(SqliteBoolean),
    categoryId: nullOr(TodoCategoryId),
    personJson: nullOr(PersonJson),
  },
  todoCategory: {
    id: TodoCategoryId,
    name: NonEmptyString50,
  },
};

Branded types allow TypeScript to enforce constraints like max length or non-empty values.

Create Evolu Instance

After defining the schema, create an Evolu instance for your environment.

import { createEvolu, getOrThrow, SimpleName } from "@evolu/common";
import { createUseEvolu, EvoluProvider } from "@evolu/react";
import { evoluReactWebDeps } from "@evolu/react-web";

const evolu = createEvolu(evoluReactWebDeps)(Schema, {
	name: getOrThrow(SimpleName.from("your-app-name")),
	syncUrl: "https://your-sync-url", // optional, defaults to https://free.evoluhq.com
});

// Wrap your app with <EvoluProvider>
<EvoluProvider value={evolu}>
	{/* ... */}
</EvoluProvider>

// Create a typed React Hook returning an instance of Evolu
const useEvolu = createUseEvolu(evolu);

// Use the Hook in your app
const { insert, update } = useEvolu();

Mutate data

const { insert, update } = useEvolu();

const result = insert("todo", { title: "New Todo", isCompleted: false });

if (result.ok) {
  update("todo", { id: result.value.id, isCompleted: true });
}

To delete a row, set isDeleted to true and filter it out in your queries.

Query data

Evolu uses type-safe TypeScript SQL query builder Kysely, so autocompletion works out-of-the-box.

Let's start with a simple Query.

const allTodos = evolu.createQuery((db) => db.selectFrom("todo").selectAll());

Once we have a query, we can load or subscribe to it.

import { useQuery } from "@evolu/react";
// ...
const todos = useQuery(allTodos);

Protect data

Privacy is essential for Evolu, so all data are encrypted with an encryption key derived from a safely generated cryptographically strong password called mnemonic.

import { useAppOwner } from "@evolu/react";
// ...
const owner = useAppOwner();
if (owner) console.log(owner.mnemonic);
// this will print the mnemonic in the console

Delete data

To clear all local data from the device:

evolu.resetAppOwner();

Restore data

To restore synced data on any device:

evolu.restoreAppOwner(mnemonic);

That’s it. Evolu offers a minimal API designed for a great developer experience.

Was this page helpful?