A permissions error that names the missing role, lists the people who can grant it with their portraits, and floats a live access request card on an image tile beside the copy.
A permissions error that names the missing role, lists the people who can grant it with their portraits, and floats a live access request card on an image tile beside the copy.
Upgrade to Pro
Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.
Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.
Radix flavor
npx shadcn add "https://ui.beste.co/r/error37?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/error37?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/error37.tsx, the notification20 request piece it floats on the tile (installed to components/beste/piece/notification20.tsx), and the button21 component it uses for the actions.
The installed file exports error37Demo alongside the block: the exact props behind the preview above. Spread it to get a working error page in one line.
import { Error37, error37Demo } from "@/components/beste/block/error37";
export default function ForbiddenPage() {
return <Error37 {...error37Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Error37 } from "@/components/beste/block/error37";
import { Notification20 } from "@/components/beste/piece/notification20";
import { ShieldCheck } from "lucide-react";
export default function ForbiddenPage() {
return (
<Error37
code="Error 403"
heading="You are signed in, but not into this"
description="This record sits behind the clinical role, which your account does not hold."
buttons={[
{ label: "Request access", href: "/access/request" },
{ label: "Back to the workspace", href: "/app" },
]}
media={
<Notification20
icon={ShieldCheck}
title="Access request"
meta="Your request goes to the record owner"
primaryLabel="Send request"
secondaryLabel="Cancel"
/>
}
image={{ src: "/backdrops/green.jpg", alt: "Deep green gradient backdrop" }}
approversLabel="Who can grant this"
approvers={[
{
name: "Elena Rourke",
role: "Practice lead, Bramble Health",
avatar: { src: "/people/elena.jpg", alt: "Portrait of Elena Rourke" },
},
]}
footnote="The decision and its timestamp are written into the audit log."
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
code | string | – | Small status line above the heading |
heading | string | – | Error heading, rendered as the page h1 |
description | string | – | Supporting paragraph, capped at max-w-md |
buttons | ActionLink[] | [] | Actions in source order, first solid and the rest outlined |
media | ReactNode | – | Live asset on the tile, notification20 in the demo |
image | { src: string; alt: string } | – | Backdrop behind the media tile |
approversLabel | string | – | Small label above the approver list |
approvers | Approver[] | [] | People who can grant the missing role |
footnote | string | – | Audit note under the approvers |
className | string | – | Extra classes for the outer section |
type ActionLink = {
label: string;
href: string;
};
type Approver = {
name: string;
role: string;
avatar: { src: string; alt: string };
};min-w-0 with truncate on both lines, so a long name or role ellipsizes rather than pushing the portrait out of the row.size-10 with shrink-0, so the row height stays constant however long the text is.primary, later ones are outline.border-t on its own container, so removing approvers removes the rule with it rather than leaving a stray divider.lg:grid-cols-2 with lg:items-center, so the tile stays centered against a copy column whose height varies with the number of approvers.error16
Permission-denied page for team apps: an accent lock chip and bold headline on the left, the signed-in account card with an account switch link and a square-bullet list of access requirements on the right.
error23
Monochrome permission page: a display headline over a request pill that swaps to a sent confirmation, a ruled record of the project, owner and visibility, and an overlapping avatar row of current members.
error9
Left-aligned 404 for documentation and marketing sites: the requested path is shown struck through in monospace above a did-you-mean box linking to the closest matching page.
error35
A calm server-error page with a monospace code, an oversized light heading, recovery actions, an image tile floating a live uptime strip, and a hairline table carrying the incident reference.