Skip to content

Permission Denied

A 403 that names who can grant what was refused, because the next question is always "then who can" and a support link is the wrong answer to it.

2 blocks42 lineslucide-reactAdded 9 Sept 2026

What's included

  • app/permission-denied-page.tsx
  • 2 blocks it is built from, installed with it
  • Needs lucide-react

Works with

  • React
  • Next.js
  • Tailwind CSS
  • TypeScript

npx hoverlab add permission-denied-page

Or over MCP, from your editor's agent — no account needed.

License

Free to read, copy and install, for personal and non-commercial projects. Shipping it in client work or a paid product needs Pro ($79 once). The source lands in your repo and stops being ours — no attribution, nothing to upgrade.

Was this useful?

Preview

You do not have access to this

The page exists and you are signed in — your account just is not on the list for it. Nothing has gone wrong, and nothing you do here will change that except asking.

Resource
northwind / billing-service
Signed in as
you@company.com

Who can let you in

  • Priya RamanWorkspace admin
  • Tom OkaforProject owner
Request access
Back to where you were

If access was granted while this page was open, reload to pick it up.

Who can grant this

Ask one of them rather than opening a ticket — this is a role change, and they can make it without us.

Members

4 of 10 seats used

  • Ada Lovelace

    ada@acme.com

  • Marco Silva

    marco@acme.com

  • Priya Raman

    priya@acme.com

  • alex@contractor.devInvite pending

The real page, rendered in your current theme — every section below is a live block, not a screenshot.

Built from

All blocks
  1. Permission Denied (403)The state where the page exists and the account is not on the list: names who can grant access, sends the request, and leaks nothing about what is inside.
  2. Team Members & InvitesMember list with role selects, pending invites shown inline, and the last owner locked so a workspace cannot be orphaned.

Only want one section? Open it and copy that block instead — browse Empty & Error States.

Shipped in these templates

Want the whole project rather than this one screen? A template ships every route, the theme tokens and the layout.

Source

app/permission-denied-page.tsx
/**
 * A 403, with the one thing a 403 almost never includes: a way forward.
 *
 * Permission screens tell you that you cannot do something and stop. That
 * is accurate and useless — the reader's next question is always "then who
 * can", and answering it is the difference between a dead end and a
 * two-minute detour.
 *
 * So the denial is first and the team list is under it, naming the people
 * who can grant what was refused. The obvious wrong answer is a support
 * link: this is almost never a support problem, it is an admin sitting two
 * desks away, and routing it through a ticket queue is how a thirty-second
 * fix becomes a day.
 *
 * Worth saying plainly since this page is copied into real products: the
 * roster below has to be filtered to people who can actually grant the
 * specific permission. A list of everyone in the workspace is the same
 * dead end with more names on it.
 */

import * as React from 'react'
import { PermissionDeniedState } from '@/components/permission-denied-state'
import { SettingsTeamMembers } from '@/components/settings-team-members'

export default function PermissionDeniedPage() {
  return (
    <main className="min-h-screen bg-background text-foreground">
      <PermissionDeniedState />

      <section className="mx-auto w-full max-w-3xl px-6 pt-4">
        <h2 className="text-lg font-bold tracking-tight">Who can grant this</h2>
        <p className="mt-1 text-sm text-muted-foreground">
          Ask one of them rather than opening a ticket — this is a role
          change, and they can make it without us.
        </p>
      </section>

      <SettingsTeamMembers />
    </main>
  )
}

How to use it

  1. 1. Copy each of the 2 blocks above into components/ — each block page has its own copy button.
  2. 2. Drop this file at app/permission-denied-page.tsx. The imports already point at @/components/…, so they resolve with no edits.
  3. 3. Delete the sections you do not want. Every block takes props, so the copy changes without the layout moving.

For AI

The component, its props, the design tokens it expects and the command that installs it — as one prompt. Paste it into Claude, Cursor, v0 or ChatGPT and what they build around it will match the rest of the catalog instead of inventing its own system.

See the prompt

More System Pages

Open the full page for this page

404 Page

Drops straight into app/not-found.tsx, and keeps the site header and footer — on a 404 the navigation is the most useful thing on screen.

System Pages1 blocks62 lines
Open the full page for this page

Server Error

Retry first, because a 500 is our failure and offering navigation implies the rest of the site works — which is exactly what is in doubt.

System Pages2 blocks44 lines
Open the full page for this page

Scheduled Maintenance

Planned downtime with an actual end time on it — "back soon" is not a time, and a maintenance page without one looks like an outage nobody has noticed.

System Pages2 blocks35 lines
Take 1 of 2
Open the full page for this page

Status Page

Written for the person refreshing it during an outage: current state above the fold, the maintenance window as a real block with an end time, and a component list that names what still works.

System Pages6 blocks155 lines
Take 1 of 2
Open the full page for this page

Legal Document

Terms, privacy, DPA and cookies in one frame — the docs layout, because people arrive at a legal page looking for a specific clause and a wall of text makes that a Ctrl-F expedition.

System Pages3 blocks50 lines
Take 2 of 2
Open the full page for this page

Status Page 02

The status page read during diligence rather than during an outage: ninety days of uptime, the latency curve, and every incident carrying its post-mortem — including the bad one.

System Pages7 blocks237 lines
Take 2 of 2
Open the full page for this page

Legal Document 02

One document with a plain-language column beside each clause, for the reader who cannot name the clause they need — and the cookie control inline, because a banner is unreachable the moment it has been dismissed.

System Pages6 blocks200 lines