Add to Existing Project

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

Prerequisites

Installation

Install the Zero package:

npm install @rocicorp/zero
Not using npm?

Zero's server component depends on @rocicorp/zero-sqlite3, which contains a binary that requires running a postinstall script. Most alternative package managers (non-npm) disable these scripts by default for security reasons. Here's how to enable installation for common alternatives:

pnpm

For pnpm, either:

  • Run pnpm approve-builds to approve all build scripts, or
  • Add the specific dependency to your package.json:
"pnpm": {
  "onlyBuiltDependencies": [
    "@rocicorp/zero-sqlite3"
  ]
}

Bun

For Bun, add the dependency to your trusted dependencies list:

"trustedDependencies": [
  "@rocicorp/zero-sqlite3"
],

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-dev

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 yet support SSR. See SSR for details on disabling SSR for your framework.

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.