JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q60825F
  • License MIT

React bindings for Zanzo ReBAC. O(1) permission checks via ZanzoProvider and useZanzo hook.

Package Exports

  • @zanzojs/react

Readme

@zanzojs/react

npm version React Compatible

React bindings for ZanzoJS.

Checking permissions on the frontend needs to be instant. You don't want to make an HTTP request every time a button renders, and you shouldn't ship heavy graph traversal logic to the browser.

@zanzojs/react solves this by consuming a "Flat Snapshot" generated by your backend. It evaluates permissions strictly synchronously in O(1) time limits.

Installation

This package requires @zanzojs/core and react as peer dependencies.

pnpm add @zanzojs/core @zanzojs/react

Step-by-Step Guide

1. Generate the Snapshot (Backend)

When a user logs into your app, or loads a Server Component in Next.js, you calculate their entire permission graph once by providing their tuples to the ZanzoEngine and generating a snapshot.

import { createZanzoSnapshot, ZanzoEngine } from '@zanzojs/core';
import { schema } from './zanzo.config'; 
import { db, zanzoTuples } from './db';
import { like } from 'drizzle-orm';

export async function getUserSnapshot(userId: string) {
  // Fetch all tuples related to this user from the DB
  const userTuples = await db.select().from(zanzoTuples).where(like(zanzoTuples.subject, `User:${userId}%`));
  
  // Create a fresh engine per request — never reuse a shared instance
  const requestEngine = new ZanzoEngine(schema);
  requestEngine.addTuples(userTuples);
  
  // Extract a flattened JSON dictionary
  return createZanzoSnapshot(requestEngine, `User:${userId}`);
}

2. The Context Provider (Frontend)

Wrap your application (or the authenticated portion of it) with <ZanzoProvider>. It expects the snapshot object you just generated.

'use client';

import { ZanzoProvider } from '@zanzojs/react';
import type { CompiledPermissions } from '@zanzojs/core';

interface AppLayoutProps {
  children: React.ReactNode;
  snapshot: CompiledPermissions; 
}

export default function AppLayout({ children, snapshot }: AppLayoutProps) {
  return (
    <ZanzoProvider snapshot={snapshot}>
      {children}
    </ZanzoProvider>
  );
}

3. The useZanzo Hook (Client Components)

Any child component within the provider can now instantly check access using the custom hook.

'use client';

import { useZanzo } from '@zanzojs/react';

export function EditDocumentButton({ documentId }: { documentId: string }) {
  const { can } = useZanzo();

  // Instant dictionary lookup! 
  // No lag, no re-renders, no network requests.
  if (!can('write', `Document:${documentId}`)) {
    return <span className="text-gray-500">Read Only View</span>;
  }

  return <button className="bg-blue-500 text-white">Edit Document</button>;
}

Behavior Notes

By intentionally offloading the graph logic to the server, these React tools rely on point-in-time snapshots. If a user's permissions change deeply in the backend, the React app won't know until you fetch and provide a new snapshot to the ZanzoProvider. We recommend re-fetching snapshots on critical path navigations.

Documentation

For backend compilation instructions, refer to the ZanzoJS Monorepo.