Add to Existing Project

Zero integrates effortlessly into JavaScript or TypeScript projects, whether you're using React, Vue, Svelte, Solid, or vanilla JavaScript.

Prerequisites

  • A PostgreSQL database with Write-Ahead Logging (WAL) enabled. See Connecting to Postgres for setup instructions.

Installation

Install the Zero package:

npm install @rocicorp/zero

Note: If you're using pnpm or bun, additional steps are required to install native binaries. Refer to Not using npm? for details.

Environment Variables

Configure Zero by creating a .env file in your project root:

ZERO_UPSTREAM_DB="postgresql://user:password@127.0.0.1/postgres"
ZERO_REPLICA_FILE="/tmp/sync-replica.db"

Replace the placeholders with your database connection details. For more options, see configuration options.

Starting the Server

Start the Zero server using the CLI:

npx zero-cache

The server runs on port 4848 by default. To verify, open http://localhost:4848 in your browser. If everything is configured correctly, you'll see "OK".

Defining Your Schema

Define your data model schema as described in the Zero schema documentation.

Example:

// schema.ts
import {createSchema, table, string} from '@rocicorp/zero';

const message = table('message')
  .columns({
    id: string(),
    body: string(),
  })
  .primaryKey('id');

export const schema = createSchema({
  tables: [message],
});

export type Schema = typeof schema;

If you're using Prisma or Drizzle, you can convert their schemas to Zero schemas using tools listed in the community section.

Permissions

Update schema.ts to include permissions for your tables. For example, to allow all users to read and write to the message table, add the following:

// schema.ts
import {ANYONE_CAN_DO_ANYTHING, definePermissions} from '@rocicorp/zero';

export const permissions = definePermissions<unknown, Schema>(schema, () => ({
  message: ANYONE_CAN_DO_ANYTHING,
}));

For more details, see permissions.

Creating a Zero Instance

To create a Zero client instance:

import {Zero} from '@rocicorp/zero';

const z = new Zero({
  userID: 'anon',
  server: 'http://localhost:4848',
  schema,
});

In production, avoid hardcoding the server URL. Use environment variables like import.meta.env.VITE_PUBLIC_SERVER or process.env.NEXT_PUBLIC_SERVER.

Reading Data

To read data, use the materialize method on a Query from the Zero instance. This creates a materialized view that listens for real-time updates to the data:

const view = z.query.message.materialize();
view.addListener(data => console.log('Data updated:', data));

When the view is no longer needed, ensure you clean up by destroying it:

view.destroy();

For more details, see Reading Data with ZQL.

React

React developers can use the useZero hook for seamless integration. See Integrations React for more details.

SolidJS

For SolidJS, use the createZero function instead of new Zero.

Refer to Integrations SolidJS for additional information.

Other Frameworks

For other frameworks, see the UI frameworks documentation.

Writing Data

Zero supports both simple and advanced data mutations. For basic use cases, use the CRUD mutator:

z.mutate.message.insert({id: nanoid(), body: 'Hello World!'});

For more complex scenarios, such as custom business logic, use custom mutators to define tailored mutation behavior.

Server-Side Rendering (SSR)

Zero does not currently support SSR. Use client-only patterns to prevent SSR execution:

Next.js

Add the use client directive.

SolidStart

Wrap components that use Zero with the clientOnly higher-order component.

The standard clientOnly pattern uses dynamic imports, but note that this approach (similar to React's lazy) works with any function returning a Promise<{default: () => JSX.Element}>. If code splitting is unnecessary, you can skip the dynamic import.

TanStack Start

Use React's lazy for dynamic imports.

Deployment

Ensure all .env variables are set in the production environment. For Zero cache deployment, see Deployment. For frontend deployment, consult your framework's documentation.