Guide
Learn how to build a minimal Evolu application. You can use Next.js (opens in a new tab) or any other React (opens in a new tab) meta-framework.
Define Data
To start using Evolu, define schemas for your database and export React Hooks.
import * as Schema from "@effect/schema/Schema";
import * as Evolu from "evolu";
const TodoId = Evolu.id("Todo");
type TodoId = Schema.To<typeof TodoId>;
const TodoTable = Schema.struct({
id: TodoId,
title: Evolu.NonEmptyString1000,
isCompleted: Evolu.SqliteBoolean,
});
type TodoTable = Schema.To<typeof TodoTable>;
const Database = Schema.struct({
todo: TodoTable,
});
export const {
useQuery,
useMutation,
useOwner,
useOwnerActions,
useEvoluError,
} = Evolu.create(Database);
Validate Data
Learn more about Schema (opens in a new tab).
import * as Schema from "@effect/schema/Schema";
import * as Evolu from "evolu";
Schema.parse(Evolu.String1000)(title);
Mutate Data
Mutation API is designed for local-first apps to ensure changes are always merged without conflicts.
const { create, update } = useMutation();
create("todo", { title, isCompleted: false });
update("todo", { id, isCompleted: true });
Query Data
Evolu uses type-safe TypeScript SQL query builder kysely (opens in a new tab), so autocompletion works out-of-the-box.
const { rows } = useQuery(
(db) => db.selectFrom("todo").select(["id", "title"]).orderBy("updatedAt"),
// (row) => row
({ title, ...rest }) => title && { title, ...rest }
);
Protect Data
Evolu encrypts data with Mnemonic, a safe autogenerated password based on bip39 (opens in a new tab).
const owner = useOwner();
alert(owner.mnemonic);
Delete Data
Leave no traces on a device.
const ownerActions = useOwnerActions();
if (confirm("Are you sure? It will delete all your local data."))
ownerActions.reset();
Restore Data
Restore data elsewhere. Encrypted data can only be restored with a Mnemonic.
const ownerActions = useOwnerActions();
ownerActions.restore(mnemonic).then((either) => {
if (either._tag === "Left") alert(JSON.stringify(either.left, null, 2));
});
Handle Errors
Evolu useQuery
and useMutation
never fail, it's the advantage of local first apps, but Evolu, in rare cases, can.
const evoluError = useEvoluError();
useEffect(() => {
// eslint-disable-next-line no-console
if (evoluError) console.log(evoluError);
}, [evoluError]);