Skip to main content

Quick Start

This guide shows how to add typed permissions to a React application using react-ability-kit in a few minutes.

1. Install

Install the package:

npm install react-ability-kit

2. Define your permission vocabulary

Create a file called ability.ts.

This file defines:

  • Actions (what users can do)
  • Subjects (what resources those actions apply to)
import { createAbilityKit, createReactAbilityKit } from "react-ability-kit";

export type Actions = "read" | "create" | "update" | "delete" | "manage";

export type SubjectsMap = {
Invoice: { id: string; ownerId: string; status: "draft" | "sent" | "paid" };
User: { id: string; role: "admin" | "member" };
};

export const abilityKit = createAbilityKit<Actions, SubjectsMap>();
export const reactAbilityKit = createReactAbilityKit<Actions, SubjectsMap>();

3. Define your policies

Create a file called policy.ts.

Policies describe what each user is allowed to do.

import { abilityKit } from "./ability";

type AppUser = {
id: string;
role: "admin" | "member";
};

export function buildAbilityFor(user: AppUser | null) {
const { defineRules, createAbility } = abilityKit;

const rules = defineRules((allow, deny) => {
if (!user) {
allow("read", "Invoice");
return;
}

if (user.role === "admin") {
allow("manage", "Invoice");
allow("manage", "User");
return;
}

allow("read", "Invoice", (i) => i.ownerId === user.id);
allow("update", "Invoice", (i) => i.ownerId === user.id && i.status === "draft");

deny("delete", "Invoice");
});

return createAbility(rules);
}

4. Use permissions in React

Wrap your application with AbilityProvider and use the <Can /> component to conditionally render UI based on permissions.

import { reactAbilityKit, type SubjectsMap } from "./ability";
import { buildAbilityFor } from "./policy";

const user = { id: "u1", role: "member" } as const;

const invoice = {
id: "i1",
ownerId: "u1",
status: "sent",
} as SubjectsMap["Invoice"];

export default function App() {
const ability = buildAbilityFor(user);
const { AbilityProvider, Can } = reactAbilityKit;

return (
<AbilityProvider ability={ability}>
<h1>Permission Demo</h1>

<Can I="update" a="Invoice" this={invoice} fallback={<p>No edit access</p>}>
<button>Edit Invoice</button>
</Can>

<Can I="delete" a="Invoice" fallback={<p>No delete access</p>}>
<button>Delete Invoice</button>
</Can>
</AbilityProvider>
);
}

What happens here?

  • The policy defines the rules.
  • buildAbilityFor(user) creates an ability instance.
  • <Can /> checks permissions before rendering UI.

Example behavior:

ActionResult
Update own draft invoice✅ allowed
Update sent invoice❌ blocked
Delete invoice❌ blocked

Next Steps

Explore the rest of the documentation to learn more: