Render UI based on authorization decisions. Pair with server-side enforcement for mutations and protected data.
import { AuthorProvider } from "author-js/react";
<AuthorProvider authorization={author} entityType="User" entity={user}>
<App />
</AuthorProvider>| Prop | Description |
|---|---|
authorization |
author.js instance |
entity |
Default actor for child checks |
mode |
Defaults to frontend |
context |
Default context for child checks |
children |
React children |
Set shared context once at the provider:
<AuthorProvider authorization={author} entityType="User" entity={user} context={{ tenantId }}>
<App />
</AuthorProvider>Render children when allowed.
import { Can } from "author-js/react";
<Can do="update" on="Project" resource={project}>
<EditButton />
</Can>With a fallback:
<Can
do="update"
on="Project"
resource={project}
fallback={<DisabledEditButton />}
>
<EditButton />
</Can>Renders null while loading.
Render children when denied.
import { Cannot } from "author-js/react";
<Cannot do="delete" on="Project" resource={project}>
<p>You cannot delete this project.</p>
</Cannot>For custom loading, error, or layout behavior.
import { useCan } from "author-js/react";
function EditProjectButton({ project }: { project: Project }) {
const permission = useCan({
do: "update",
on: "Project",
resource: project,
});
if (permission.loading) return null;
if (permission.error) return <span>Could not check permissions</span>;
if (!permission.allowed) return null;
return <EditButton />;
}Inverted useCan. When allowed is true, the actor is denied the action.
import { useCannot } from "author-js/react";
const { allowed: isDenied, loading } = useCannot({
do: "delete",
on: "Project",
resource: project,
});
if (isDenied) return <p>You cannot delete this project.</p>;Read provider context directly.
import { useAuthor } from "author-js/react";
const { authorization, entity, mode, context } = useAuthor();Hook return shape:
type UseCanResult = {
allowed: boolean;
loading: boolean;
error: Error | null;
decision: Decision | null;
};Use i to check a different actor than the provider default.
<Can i={serviceAccount} do="read" on="Project" resource={project}>
<span>Service account can read this project</span>
</Can>Component context merges with provider context. Component keys override provider keys.
<Can
do="read"
on="Report"
resource={report}
context={{ tenantId, rollout: "beta" }}
>
<ReportPreview />
</Can>Import from author-js/next/client in client components:
import { AuthorProvider, Can } from "author-js/next/client";