Building Blocks for the Web

Clean, modern building blocks for Codex, Claude Code, OpenTeam.AI-UI MCP, and other MCP-powered AI workflows. Give AI production-ready UI it can assemble, adapt, and ship under your OpenTeam.AI commercial license.

Files
components/admin/previews/admin-account-dropdown-preview.tsx
import { AdminAccountDropdownPreview } from "@/components/admin/account-dropdown"

export const description =
  "A rich account dropdown preview with upgrade, billing, notifications, and sign out actions."

export const iframeHeight = "760px"

export function AdminAccountDropdownBlock() {
  return (
    <div className="flex min-h-[700px] items-center justify-center bg-[radial-gradient(circle_at_top,_rgba(59,130,246,0.12),_transparent_40%)] p-6">
      <AdminAccountDropdownPreview />
    </div>
  )
}
An admin account dropdown with upgrade, billing, notifications, and sign-out actions.
admin-account-dropdown-01
Files
components/admin/previews/admin-sidebar-preview.tsx
import { AdminPageShell } from "@/components/admin/page-shell"

export const description =
  "An admin sidebar shell with grouped navigation, collapsible page groups, and a footer account menu."

export const iframeHeight = "960px"

export function AdminSidebarBlock() {
  return (
    <AdminPageShell currentPath="/users">
      <div className="grid gap-6">
        <div className="rounded-[28px] border bg-card p-6">
          <p className="text-sm font-medium tracking-[0.24em] text-muted-foreground uppercase">
            Admin Sidebar
          </p>
          <h1 className="mt-3 text-3xl font-semibold tracking-tight">
            Browse every core workspace page from one shell
          </h1>
          <p className="mt-2 max-w-2xl text-muted-foreground">
            This block mirrors the UI Dashboard navigation model with grouped
            sections, nested routes, badge support, and an account dropdown in
            the footer.
          </p>
        </div>
        <div className="grid gap-4 md:grid-cols-3">
          {["Dashboard", "Tasks", "Chats"].map((item) => (
            <div key={item} className="rounded-[24px] border bg-card p-5">
              <div className="text-lg font-medium">{item}</div>
              <p className="mt-2 text-sm text-muted-foreground">
                Preview the navigation state AI can reuse when installing admin
                pages into a customer project.
              </p>
            </div>
          ))}
        </div>
      </div>
    </AdminPageShell>
  )
}
An admin sidebar shell with grouped navigation, collapsible page groups, and a footer account menu.
admin-sidebar-01
Files
app/dashboard/page.tsx
"use client"

import * as React from "react"

import { AdminPageShell } from "@/components/admin/page-shell"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
} from "@/components/ui/tabs"

export const description =
  "A full admin dashboard page with KPI cards, release pipeline activity, and team performance snapshots."

export const iframeHeight = "1100px"

const kpis = [
  { label: "Active workspaces", value: "184", change: "+12% this month" },
  { label: "Registry installs", value: "12.4k", change: "+31% week over week" },
  { label: "Open support chats", value: "27", change: "5 urgent" },
  { label: "Revenue on books", value: "$84.9k", change: "+18% this quarter" },
]

const releases = [
  { label: "Portal UI download rollout", progress: 88 },
  { label: "Admin block registry publish", progress: 64 },
  { label: "Customer MCP onboarding docs", progress: 92 },
]

export default function AdminDashboardPage() {
  return (
    <AdminPageShell currentPath="/dashboard">
      <div className="space-y-6">
        <div className="flex flex-col gap-4 rounded-[28px] border bg-card p-6 lg:flex-row lg:items-end lg:justify-between">
          <div className="space-y-2">
            <p className="text-sm font-medium tracking-[0.24em] text-muted-foreground uppercase">
              Dashboard
            </p>
            <h1 className="text-3xl font-semibold tracking-tight">
              Track launches, customers, and product momentum
            </h1>
            <p className="max-w-2xl text-muted-foreground">
              A compact operations view for teams shipping UI through the
              registry, Gateway, and Codex MCP workflows.
            </p>
          </div>
          <div className="flex gap-2">
            <Button variant="outline">Export report</Button>
            <Button>Create briefing</Button>
          </div>
        </div>

        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
          {kpis.map((kpi) => (
            <Card key={kpi.label} className="rounded-[24px]">
              <CardHeader className="pb-3">
                <CardDescription>{kpi.label}</CardDescription>
                <CardTitle className="text-3xl">{kpi.value}</CardTitle>
              </CardHeader>
              <CardContent>
                <Badge variant="secondary">{kpi.change}</Badge>
              </CardContent>
            </Card>
          ))}
        </div>

        <Tabs defaultValue="overview" className="space-y-4">
          <TabsList>
            <TabsTrigger value="overview">Overview</TabsTrigger>
            <TabsTrigger value="pipeline">Pipeline</TabsTrigger>
            <TabsTrigger value="team">Team</TabsTrigger>
          </TabsList>

          <TabsContent
            value="overview"
            className="grid gap-4 xl:grid-cols-[1.4fr_minmax(0,1fr)]"
          >
            <Card className="rounded-[28px]">
              <CardHeader>
                <CardTitle>Launch health</CardTitle>
                <CardDescription>
                  Track critical rollout work across UI packaging and Portal
                  hosting.
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-4">
                {releases.map((release) => (
                  <div key={release.label} className="space-y-2">
                    <div className="flex items-center justify-between text-sm">
                      <span className="font-medium">{release.label}</span>
                      <span className="text-muted-foreground">
                        {release.progress}%
                      </span>
                    </div>
                    <div className="h-3 overflow-hidden rounded-full bg-muted">
                      <div
                        className="h-full rounded-full bg-blue-600"
                        style={{ width: `${release.progress}%` }}
                      />
                    </div>
                  </div>
                ))}
              </CardContent>
            </Card>
            <Card className="rounded-[28px]">
              <CardHeader>
                <CardTitle>Recent wins</CardTitle>
                <CardDescription>
                  Highlights from the last 7 days.
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-4">
                {[
                  "Gateway install flow matched with one-step UI installation.",
                  "Codex MCP can now discover and install admin page blocks.",
                  "Portal now serves UI artifacts directly from /download/ui/*.",
                ].map((item) => (
                  <div key={item} className="rounded-2xl border p-4 text-sm">
                    {item}
                  </div>
                ))}
              </CardContent>
            </Card>
          </TabsContent>

          <TabsContent value="pipeline" className="grid gap-4 lg:grid-cols-3">
            {["Build", "Review", "Ship"].map((stage, index) => (
              <Card key={stage} className="rounded-[28px]">
                <CardHeader>
                  <CardTitle>{stage}</CardTitle>
                  <CardDescription>
                    {index === 0
                      ? "Features actively being built."
                      : index === 1
                        ? "Items waiting on stakeholder approval."
                        : "Changes scheduled for release."}
                  </CardDescription>
                </CardHeader>
                <CardContent className="space-y-3">
                  {Array.from({ length: 3 }).map((_, cardIndex) => (
                    <div
                      key={cardIndex}
                      className="rounded-2xl border bg-muted/40 p-4"
                    >
                      <div className="font-medium">
                        {stage} item {cardIndex + 1}
                      </div>
                      <div className="mt-1 text-sm text-muted-foreground">
                        Demo content designed for Codex to inspect and adapt.
                      </div>
                    </div>
                  ))}
                </CardContent>
              </Card>
            ))}
          </TabsContent>

          <TabsContent value="team" className="grid gap-4 md:grid-cols-2">
            {["Engineering", "Support", "Growth", "Operations"].map((team) => (
              <Card key={team} className="rounded-[28px]">
                <CardHeader>
                  <CardTitle>{team}</CardTitle>
                  <CardDescription>
                    Current focus and velocity snapshot.
                  </CardDescription>
                </CardHeader>
                <CardContent className="space-y-3">
                  <div className="flex items-center justify-between rounded-2xl border p-4">
                    <span className="text-sm font-medium">
                      Open initiatives
                    </span>
                    <span className="text-2xl font-semibold">
                      {team === "Engineering" ? 18 : team === "Support" ? 6 : 9}
                    </span>
                  </div>
                  <div className="flex items-center justify-between rounded-2xl border p-4">
                    <span className="text-sm font-medium">
                      Completed this week
                    </span>
                    <span className="text-2xl font-semibold">
                      {team === "Engineering"
                        ? 11
                        : team === "Support"
                          ? 14
                          : 8}
                    </span>
                  </div>
                </CardContent>
              </Card>
            ))}
          </TabsContent>
        </Tabs>
      </div>
    </AdminPageShell>
  )
}
A full admin dashboard page with KPI cards, release pipeline activity, and team performance snapshots.
admin-dashboard-01
Files
app/tasks/page.tsx
import { AdminPageShell } from "@/components/admin/page-shell"
import { TasksTable } from "@/components/admin/tasks-table"

export const description =
  "A task management page with local search, filters, status badges, and pagination."

export const iframeHeight = "1100px"

export default function AdminTasksPage() {
  return (
    <AdminPageShell currentPath="/tasks">
      <div className="space-y-6">
        <div className="rounded-[28px] border bg-card p-6">
          <p className="text-sm font-medium tracking-[0.24em] text-muted-foreground uppercase">
            Tasks
          </p>
          <h1 className="mt-3 text-3xl font-semibold tracking-tight">
            Manage roadmap work, launches, and follow-ups
          </h1>
          <p className="mt-2 max-w-2xl text-muted-foreground">
            This page is intentionally UI-only so teams can swap in real APIs,
            persistence, and actions after install.
          </p>
        </div>
        <TasksTable />
      </div>
    </AdminPageShell>
  )
}
A task management page with local-state filtering, sorting, and paginated table controls.
admin-tasks-01
Files
app/apps/page.tsx
"use client"

import * as React from "react"

import { AdminPageShell } from "@/components/admin/page-shell"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"

export const description =
  "A catalog page for app integrations with local filtering, sort controls, and connection state."

export const iframeHeight = "1100px"

type AppCard = {
  name: string
  category: "Communication" | "Productivity" | "Payments"
  connected: boolean
  description: string
}

const apps: AppCard[] = [
  {
    name: "Slack",
    category: "Communication",
    connected: true,
    description:
      "Send rollout updates and approval requests into shared channels.",
  },
  {
    name: "Notion",
    category: "Productivity",
    connected: true,
    description:
      "Sync launch docs, specs, and meeting notes directly into workspaces.",
  },
  {
    name: "GitHub",
    category: "Productivity",
    connected: true,
    description:
      "Track PR status, CI health, and branch activity from one place.",
  },
  {
    name: "Stripe",
    category: "Payments",
    connected: false,
    description:
      "Monitor billing events, subscriptions, and customer payment health.",
  },
  {
    name: "Linear",
    category: "Productivity",
    connected: false,
    description:
      "Link product workstreams to launch tasks and support follow-ups.",
  },
  {
    name: "Zoom",
    category: "Communication",
    connected: false,
    description:
      "Schedule customer check-ins and review demos without leaving the dashboard.",
  },
]

export default function AdminAppsPage() {
  const [search, setSearch] = React.useState("")
  const [filter, setFilter] = React.useState("all")
  const [sort, setSort] = React.useState<"asc" | "desc">("asc")

  const filteredApps = React.useMemo(() => {
    return [...apps]
      .filter((app) => {
        const matchesSearch =
          search.trim() === "" ||
          [app.name, app.category, app.description]
            .join(" ")
            .toLowerCase()
            .includes(search.toLowerCase())
        const matchesFilter =
          filter === "all" ||
          (filter === "connected" ? app.connected : !app.connected)

        return matchesSearch && matchesFilter
      })
      .sort((left, right) =>
        sort === "asc"
          ? left.name.localeCompare(right.name)
          : right.name.localeCompare(left.name)
      )
  }, [filter, search, sort])

  return (
    <AdminPageShell currentPath="/apps">
      <div className="space-y-6">
        <div className="rounded-[28px] border bg-card p-6">
          <p className="text-sm font-medium tracking-[0.24em] text-muted-foreground uppercase">
            Apps
          </p>
          <h1 className="mt-3 text-3xl font-semibold tracking-tight">
            Review integrations and connection health
          </h1>
          <p className="mt-2 max-w-2xl text-muted-foreground">
            A UI-only app catalog that teams can wire to real integrations after
            install.
          </p>
        </div>

        <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
          <div className="flex flex-1 flex-col gap-3 sm:flex-row">
            <input
              value={search}
              onChange={(event) => setSearch(event.target.value)}
              placeholder="Filter apps..."
              className="h-10 rounded-xl border bg-background px-3 text-sm"
            />
            <select
              value={filter}
              onChange={(event) => setFilter(event.target.value)}
              className="h-10 rounded-xl border bg-background px-3 text-sm"
            >
              <option value="all">All apps</option>
              <option value="connected">Connected</option>
              <option value="not-connected">Not connected</option>
            </select>
          </div>
          <div className="flex gap-2">
            <Button variant="outline" onClick={() => setSort("asc")}>
              A–Z
            </Button>
            <Button variant="outline" onClick={() => setSort("desc")}>
              Z–A
            </Button>
          </div>
        </div>

        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          {filteredApps.map((app) => (
            <div key={app.name} className="rounded-[28px] border bg-card p-5">
              <div className="mb-6 flex items-start justify-between gap-3">
                <div className="flex size-12 items-center justify-center rounded-2xl bg-muted text-lg font-semibold">
                  {app.name.slice(0, 2)}
                </div>
                <Badge variant={app.connected ? "default" : "outline"}>
                  {app.connected ? "Connected" : "Available"}
                </Badge>
              </div>
              <div className="space-y-2">
                <div className="flex items-center justify-between gap-3">
                  <h2 className="text-xl font-semibold">{app.name}</h2>
                  <span className="text-xs tracking-[0.2em] text-muted-foreground uppercase">
                    {app.category}
                  </span>
                </div>
                <p className="text-sm text-muted-foreground">
                  {app.description}
                </p>
              </div>
              <div className="mt-6">
                <Button
                  variant={app.connected ? "outline" : "default"}
                  className="w-full"
                >
                  {app.connected ? "Manage connection" : "Connect app"}
                </Button>
              </div>
            </div>
          ))}
        </div>
      </div>
    </AdminPageShell>
  )
}
A catalog page for app integrations with local filtering, sort controls, and connection state.
admin-apps-01
Files
app/chats/page.tsx
"use client"

import * as React from "react"

import { AdminPageShell } from "@/components/admin/page-shell"
import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Separator } from "@/components/ui/separator"
import { IconPlaceholder } from "@/components/icon-placeholder"

export const description =
  "A local-state chats page with inbox navigation, conversation history, and a composer."

export const iframeHeight = "1100px"

type Conversation = {
  id: string
  name: string
  title: string
  unread: number
  messages: Array<{ sender: string; text: string; time: string }>
}

const conversations: Conversation[] = [
  {
    id: "conv-1",
    name: "Alice Johnson",
    title: "Product Lead",
    unread: 2,
    messages: [
      {
        sender: "Alice",
        text: "Can we ship the admin blocks this week?",
        time: "9:14 AM",
      },
      {
        sender: "You",
        text: "Yes, the first-wave registry plan is already in motion.",
        time: "9:18 AM",
      },
      {
        sender: "Alice",
        text: "Perfect. I want Codex to discover them out of the box.",
        time: "9:22 AM",
      },
    ],
  },
  {
    id: "conv-2",
    name: "Marcus Chen",
    title: "Solutions Engineer",
    unread: 1,
    messages: [
      {
        sender: "Marcus",
        text: "Customer wants users and tasks pages as reusable templates.",
        time: "Yesterday",
      },
      {
        sender: "You",
        text: "We are packaging both as installable blocks.",
        time: "Yesterday",
      },
    ],
  },
  {
    id: "conv-3",
    name: "Priya Raman",
    title: "Operations",
    unread: 0,
    messages: [
      {
        sender: "Priya",
        text: "The Portal download route looks stable now.",
        time: "Mon",
      },
      {
        sender: "You",
        text: "Great, I am documenting the one-step install flow.",
        time: "Mon",
      },
    ],
  },
]

export default function AdminChatsPage() {
  const [search, setSearch] = React.useState("")
  const [selectedId, setSelectedId] = React.useState(conversations[0].id)
  const selectedConversation =
    conversations.find((conversation) => conversation.id === selectedId) ??
    conversations[0]

  const filteredConversations = conversations.filter((conversation) =>
    [conversation.name, conversation.title]
      .join(" ")
      .toLowerCase()
      .includes(search.toLowerCase())
  )

  return (
    <AdminPageShell currentPath="/chats">
      <div className="grid gap-6 xl:grid-cols-[340px_minmax(0,1fr)]">
        <div className="rounded-[28px] border bg-card p-4">
          <div className="mb-4 flex items-center justify-between gap-3">
            <div>
              <p className="text-sm font-medium tracking-[0.24em] text-muted-foreground uppercase">
                Chats
              </p>
              <h1 className="mt-2 text-2xl font-semibold tracking-tight">
                Inbox
              </h1>
            </div>
            <Button size="icon" variant="outline">
              <IconPlaceholder
                lucide="SquarePenIcon"
                tabler="IconEdit"
                hugeicons="Edit01Icon"
                phosphor="PencilSimpleIcon"
                remixicon="RiEditLine"
              />
            </Button>
          </div>
          <Input
            value={search}
            onChange={(event) => setSearch(event.target.value)}
            placeholder="Search chats..."
          />
          <div className="mt-4 space-y-2">
            {filteredConversations.map((conversation) => {
              const active = conversation.id === selectedConversation.id

              return (
                <button
                  key={conversation.id}
                  type="button"
                  onClick={() => setSelectedId(conversation.id)}
                  className={
                    active
                      ? "w-full rounded-2xl border bg-muted px-4 py-3 text-left"
                      : "w-full rounded-2xl border px-4 py-3 text-left"
                  }
                >
                  <div className="flex items-center gap-3">
                    <Avatar className="size-10 rounded-2xl bg-muted">
                      <AvatarFallback className="rounded-2xl">
                        {conversation.name
                          .split(" ")
                          .map((part) => part[0])
                          .join("")
                          .slice(0, 2)}
                      </AvatarFallback>
                    </Avatar>
                    <div className="min-w-0 flex-1">
                      <div className="flex items-center justify-between gap-3">
                        <span className="truncate font-medium">
                          {conversation.name}
                        </span>
                        {conversation.unread ? (
                          <span className="rounded-full bg-primary px-2 py-0.5 text-xs text-primary-foreground">
                            {conversation.unread}
                          </span>
                        ) : null}
                      </div>
                      <p className="truncate text-sm text-muted-foreground">
                        {conversation.title}
                      </p>
                    </div>
                  </div>
                </button>
              )
            })}
          </div>
        </div>

        <div className="rounded-[28px] border bg-card">
          <div className="flex items-center justify-between gap-3 border-b px-6 py-4">
            <div>
              <h2 className="text-xl font-semibold">
                {selectedConversation.name}
              </h2>
              <p className="text-sm text-muted-foreground">
                {selectedConversation.title}
              </p>
            </div>
            <div className="flex gap-2">
              <Button size="icon" variant="outline">
                <IconPlaceholder
                  lucide="PhoneIcon"
                  tabler="IconPhone"
                  hugeicons="CallIcon"
                  phosphor="PhoneIcon"
                  remixicon="RiPhoneLine"
                />
              </Button>
              <Button size="icon" variant="outline">
                <IconPlaceholder
                  lucide="VideoIcon"
                  tabler="IconVideo"
                  hugeicons="VideoReplayIcon"
                  phosphor="VideoCameraIcon"
                  remixicon="RiVidiconLine"
                />
              </Button>
            </div>
          </div>
          <div className="space-y-4 px-6 py-6">
            {selectedConversation.messages.map((message, index) => {
              const fromYou = message.sender === "You"

              return (
                <div
                  key={`${message.time}-${index}`}
                  className={
                    fromYou ? "flex justify-end" : "flex justify-start"
                  }
                >
                  <div
                    className={
                      fromYou
                        ? "max-w-xl rounded-3xl rounded-br-md bg-primary px-4 py-3 text-primary-foreground"
                        : "max-w-xl rounded-3xl rounded-bl-md bg-muted px-4 py-3"
                    }
                  >
                    <p className="text-sm leading-6">{message.text}</p>
                    <p
                      className={
                        fromYou
                          ? "mt-2 text-right text-xs text-primary-foreground/80"
                          : "mt-2 text-xs text-muted-foreground"
                      }
                    >
                      {message.time}
                    </p>
                  </div>
                </div>
              )
            })}
          </div>
          <Separator />
          <div className="flex gap-3 px-6 py-4">
            <Input placeholder="Type a message..." />
            <Button>Send</Button>
          </div>
        </div>
      </div>
    </AdminPageShell>
  )
}
A local-state chats page with inbox navigation, conversation history, and a composer.
admin-chats-01
Files
app/users/page.tsx
import { AdminPageShell } from "@/components/admin/page-shell"
import { UsersTable } from "@/components/admin/users-table"

export const description =
  "A user management page with invite actions, role filtering, and account status badges."

export const iframeHeight = "1100px"

export default function AdminUsersPage() {
  return (
    <AdminPageShell currentPath="/users">
      <div className="space-y-6">
        <div className="rounded-[28px] border bg-card p-6">
          <p className="text-sm font-medium tracking-[0.24em] text-muted-foreground uppercase">
            Users
          </p>
          <h1 className="mt-3 text-3xl font-semibold tracking-tight">
            Invite teammates, assign roles, and review account health
          </h1>
          <p className="mt-2 max-w-2xl text-muted-foreground">
            A flexible user admin block designed for Codex to inspect and adapt
            inside customer projects.
          </p>
        </div>
        <UsersTable />
      </div>
    </AdminPageShell>
  )
}
A user management page with local-state filtering, role controls, and paginated table interactions.
admin-users-01
Files
app/sign-in/page.tsx
import { SignInCard } from "@/components/admin/auth-forms"
import { AdminAuthLayout } from "@/components/admin/auth-layout"

export const description = "A polished sign-in page for the admin suite."

export const iframeHeight = "900px"

export default function AdminAuthSignInPage() {
  return (
    <AdminAuthLayout>
      <SignInCard />
    </AdminAuthLayout>
  )
}
A single-column admin sign-in page with local demo actions.
admin-auth-sign-in-01
Files
app/sign-in-2/page.tsx
import { SignInCard } from "@/components/admin/auth-forms"
import { AdminAuthLayout } from "@/components/admin/auth-layout"

export const description =
  "A split-layout sign-in page with a visual dashboard preview."

export const iframeHeight = "900px"

export default function AdminAuthSignInSplitPage() {
  return (
    <AdminAuthLayout split>
      <SignInCard />
    </AdminAuthLayout>
  )
}
A two-column admin sign-in page with a branded shell and local demo interactions.
admin-auth-sign-in-2col-01
Files
app/sign-up/page.tsx
import { SignUpCard } from "@/components/admin/auth-forms"
import { AdminAuthLayout } from "@/components/admin/auth-layout"

export const description = "An admin sign-up page for creating a new workspace."

export const iframeHeight = "900px"

export default function AdminAuthSignUpPage() {
  return (
    <AdminAuthLayout>
      <SignUpCard />
    </AdminAuthLayout>
  )
}
A sign-up page for admin workspaces with local demo state.
admin-auth-sign-up-01
Files
app/forgot-password/page.tsx
import { ForgotPasswordCard } from "@/components/admin/auth-forms"
import { AdminAuthLayout } from "@/components/admin/auth-layout"

export const description =
  "A reset-password request page for the admin authentication flow."

export const iframeHeight = "900px"

export default function AdminForgotPasswordPage() {
  return (
    <AdminAuthLayout>
      <ForgotPasswordCard />
    </AdminAuthLayout>
  )
}
A forgot-password page for admin workspaces with a local email reset flow.
admin-auth-forgot-password-01
Files
app/otp/page.tsx
import { OtpCard } from "@/components/admin/auth-forms"
import { AdminAuthLayout } from "@/components/admin/auth-layout"

export const description =
  "A two-factor authentication step for the admin auth journey."

export const iframeHeight = "900px"

export default function AdminOtpPage() {
  return (
    <AdminAuthLayout>
      <OtpCard />
    </AdminAuthLayout>
  )
}
A one-time password verification page for admin authentication flows.
admin-auth-otp-01
Files
app/errors/unauthorized/page.tsx
import { AdminErrorPage } from "@/components/admin/error-page"

export const description = "A 401 unauthorized error page for the admin suite."

export const iframeHeight = "820px"

export default function AdminUnauthorizedPage() {
  return (
    <AdminErrorPage
      code="401"
      title="Unauthorized"
      description="Please sign in with the correct credentials before accessing this workspace."
    />
  )
}
An unauthorized error page for admin experiences with a dashboard recovery action.
admin-error-unauthorized-01
Files
app/errors/forbidden/page.tsx
import { AdminErrorPage } from "@/components/admin/error-page"

export const description = "A 403 forbidden error page for the admin suite."

export const iframeHeight = "820px"

export default function AdminForbiddenPage() {
  return (
    <AdminErrorPage
      code="403"
      title="Forbidden"
      description="You do not have permission to view this admin resource."
    />
  )
}
A forbidden error page for admin experiences with local recovery actions.
admin-error-forbidden-01
Files
app/errors/not-found/page.tsx
import { AdminErrorPage } from "@/components/admin/error-page"

export const description = "A 404 not found error page for the admin suite."

export const iframeHeight = "820px"

export default function AdminNotFoundPage() {
  return (
    <AdminErrorPage
      code="404"
      title="Not found"
      description="The page you requested does not exist or has been moved to a new route."
    />
  )
}
A not-found page for admin routes with clear recovery actions and messaging.
admin-error-not-found-01
Files
app/errors/internal-server-error/page.tsx
import { AdminErrorPage } from "@/components/admin/error-page"

export const description =
  "A 500 internal server error page for the admin suite."

export const iframeHeight = "820px"

export default function AdminInternalServerErrorPage() {
  return (
    <AdminErrorPage
      code="500"
      title="Internal server error"
      description="Something unexpected happened while rendering this admin page."
    />
  )
}
An internal server error page for admin workflows with a dashboard fallback action.
admin-error-internal-server-01
Files
app/errors/maintenance-error/page.tsx
import { AdminErrorPage } from "@/components/admin/error-page"

export const description =
  "A maintenance-mode page for planned downtime or scheduled updates."

export const iframeHeight = "820px"

export default function AdminMaintenanceErrorPage() {
  return (
    <AdminErrorPage
      code="503"
      title="Maintenance mode"
      description="This workspace is temporarily unavailable while we apply updates and polish."
      actionLabel="Check status"
    />
  )
}
A maintenance error page for admin workspaces with soft recovery messaging.
admin-error-maintenance-01
Files
app/settings/page.tsx
import { ProfilePanel } from "@/components/admin/settings-panels"
import { AdminSettingsShell } from "@/components/admin/settings-shell"

export const description =
  "A profile settings page for personal and public account details."

export const iframeHeight = "1100px"

export default function AdminSettingsProfilePage() {
  return (
    <AdminSettingsShell
      currentPath="/settings"
      title="Settings"
      description="Manage your workspace profile, preferences, and display options."
    >
      <ProfilePanel />
    </AdminSettingsShell>
  )
}
A profile settings page with editable links, bio, and public profile details.
admin-settings-profile-01
Files
app/settings/account/page.tsx
import { AccountPanel } from "@/components/admin/settings-panels"
import { AdminSettingsShell } from "@/components/admin/settings-shell"

export const description =
  "An account settings page for language and account metadata."

export const iframeHeight = "1100px"

export default function AdminSettingsAccountPage() {
  return (
    <AdminSettingsShell
      currentPath="/settings/account"
      title="Settings"
      description="Manage your workspace profile, preferences, and display options."
    >
      <AccountPanel />
    </AdminSettingsShell>
  )
}
An account settings page with editable account details and language preferences.
admin-settings-account-01
Files
app/settings/appearance/page.tsx
import { AppearancePanel } from "@/components/admin/settings-panels"
import { AdminSettingsShell } from "@/components/admin/settings-shell"

export const description =
  "An appearance settings page for theme and font selection."

export const iframeHeight = "1100px"

export default function AdminSettingsAppearancePage() {
  return (
    <AdminSettingsShell
      currentPath="/settings/appearance"
      title="Settings"
      description="Manage your workspace profile, preferences, and display options."
    >
      <AppearancePanel />
    </AdminSettingsShell>
  )
}
An appearance settings page with theme and typography controls for admin workspaces.
admin-settings-appearance-01
Files
app/settings/notifications/page.tsx
import { NotificationsPanel } from "@/components/admin/settings-panels"
import { AdminSettingsShell } from "@/components/admin/settings-shell"

export const description =
  "A notification preferences page with delivery and email controls."

export const iframeHeight = "1100px"

export default function AdminSettingsNotificationsPage() {
  return (
    <AdminSettingsShell
      currentPath="/settings/notifications"
      title="Settings"
      description="Manage your workspace profile, preferences, and display options."
    >
      <NotificationsPanel />
    </AdminSettingsShell>
  )
}
A notifications settings page with delivery preferences and channel toggles.
admin-settings-notifications-01
Files
app/settings/display/page.tsx
import { DisplayPanel } from "@/components/admin/settings-panels"
import { AdminSettingsShell } from "@/components/admin/settings-shell"

export const description =
  "A display settings page for toggling visible admin navigation sections."

export const iframeHeight = "1100px"

export default function AdminSettingsDisplayPage() {
  return (
    <AdminSettingsShell
      currentPath="/settings/display"
      title="Settings"
      description="Manage your workspace profile, preferences, and display options."
    >
      <DisplayPanel />
    </AdminSettingsShell>
  )
}
A display settings page with density, sidebar, and dashboard preference controls.
admin-settings-display-01
Files
components/admin/previews/admin-suite-preview.tsx
import { AdminPageShell } from "@/components/admin/page-shell"

export const description =
  "A composed admin template that installs the full first-wave shell plus dashboard, task, chat, user, auth, error, and settings pages."

export const iframeHeight = "960px"

export function AdminSuiteBlock() {
  return (
    <AdminPageShell currentPath="/dashboard">
      <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        {[
          "Dashboard",
          "Tasks",
          "Apps",
          "Chats",
          "Users",
          "Auth",
          "Errors",
          "Settings",
        ].map((item) => (
          <div key={item} className="rounded-[24px] border bg-card p-5">
            <div className="text-lg font-medium">{item}</div>
            <p className="mt-2 text-sm text-muted-foreground">
              Installed together through <code>admin-suite-01</code> so Codex
              can explore the entire admin surface area in one pass.
            </p>
          </div>
        ))}
      </div>
    </AdminPageShell>
  )
}
A composed admin template that installs the full first-wave shell plus dashboard, task, chat, user, auth, error, and settings pages.
admin-suite-01