System & lifecycle
Whole-screen lifecycle states. ErrorPage, MaintenancePage, EmptyStatePage and OrganizationSelectionPage are the full templates; NotFoundPage, SuccessConfirmationPage and VerificationPage are configured presets of ErrorPage / EmptyStatePage / AuthPage.
These are the dead-ends and ceremonies — every copy/icon/tone default is inherited from the underlying ds/surface screen, so most presets only override a line of copy and the action row. All server-safe.
AuthPage
The chrome-less full-screen auth ceremony: a centered AuthScreen card with brand mark, title, the form in children, secondary links and a footer. No TitleBar or breadcrumbs. VerificationPage below is a stepped preset of it.
Welcome back
Sign in to the Save the Dogs portal.
By continuing you agree to the Terms and Privacy Policy.
- children (required)
- The form (inputs + submit). title / description head the card; brand defaults to the app logo.
- secondary / footer / aside
- secondary is the links row under the form; footer the terms/privacy line; aside an optional marketing panel on wide screens.
- steps / error
- steps renders a ProgressSteps rail for invite/setup wizards; error renders a standard error banner above the form. Server-safe.
ErrorPage
A full-screen error: a centered card with a tinted icon badge, code, heading + description, and an actions row, over the app background.
404
We couldn't find that page
The link may be broken, or the page may have moved. Check the address or head back to your dashboard.
Reference: req_8f21c
Still stuck? Email ops@savethedogs.io
500
Something went wrong
We hit an unexpected error on our end. Try again in a moment — if it keeps happening, let us know.
Reference: err_a04d7
- code / title / description / icon / tone
- All ErrorScreenProps; every copy/icon/tone default is inherited from ds/surface ErrorScreen.
- children / actions / footer
- children is the detail slot (an error id / support ref); actions is the button row (pre-built <Button>/<Link> ELEMENTS, never handlers); footer is the support line.
- server-safe
- ErrorScreen has no 'use client' / hooks — render straight from a Next error boundary.
MaintenancePage
A planned-downtime screen: the brand mark + a wrench icon, an ETA/status detail slot and an actions row (e.g. a 'Status page' link).
We'll be right back
We're doing some quick upkeep to keep things running smoothly. Thanks for your patience.
Questions? hello@savethedogs.io
- title / description / icon / brand
- All MaintenanceScreenProps; defaults: brand=<Logo glyph={<PawPrint/>} word='Save the Dogs'/>, icon=<Wrench/>.
- children / actions / footer
- children is the detail slot (ETA line, status banner, affected-areas list); actions is the button/link row (e.g. a 'Status page' link element).
- server-safe
- Pure passthrough to ds/surface MaintenanceScreen — server-render it.
EmptyStatePage
A full-page empty state: a centered EmptyState card (icon + title + description + a primary CTA), with an optional brand mark above it.
Need help? Email ops@savethedogs.io
- title (required)
- The empty-state heading (matches @phauna/ds EmptyState.title).
- description / icon / action / variant
- icon is a badge/illustration element; action is the primary CTA element; variant 'empty' (default) | 'no-results' | 'error' | 'permission'.
- brand / footer
- Optional brand mark above the card (no default — calm) and a small footer line. Server-safe.
OrganizationSelectionPage
An org-picker ceremony: the AuthPage chrome over a list of selectable organization rows, with an empty state when there are none.
Choose a workspace
You belong to 3 organizations
Terms · Privacy
Choose a workspace
You're not a member of any organization yet
Terms · Privacy
- organizations (required)
- The selectable org rows/cards (each a caller-built element node) — rendered as a list under the AuthPage chrome.
- emptyState
- Shown instead of the list when organizations is empty (e.g. a 'create your first org' EmptyState).
- AuthPage props
- Spreads AuthPageProps minus children/steps/error (title / description / etc.). Server-safe.
NotFoundPage
This is ErrorPage configured as a 404 — ErrorScreen's defaults ARE the not-found case, so this alias just supplies the 'Go home' actions (the thinnest preset in the cluster).
import { ErrorPage } from "@/components/ds/recipes";
import { Button } from "@/components/ui";
<ErrorPage
actions={
<>
<Button href="/">Go home</Button>
<Button variant="ghost" href="/admin">Back to admin</Button>
</>
}
/>
// ErrorScreen defaults already supply code="404", icon=<SearchX/>, title="Page not found", description.SuccessConfirmationPage
This is EmptyStatePage configured as a success confirmation — a positive check icon + 'all done' copy + a next-step CTA, instead of the neutral 'nothing here yet' look.
import { EmptyStatePage } from "@/components/ds/recipes";
import { Button } from "@/components/ui";
import { CheckCircle2 } from "lucide-react";
<EmptyStatePage
icon={<CheckCircle2 className="size-8 text-[var(--color-good)]" />}
title="You're all set!"
description="Your foster profile is submitted. We'll reach out within 48 hours."
action={<Button href="/portal">Go to your portal</Button>}
/>VerificationPage
This is AuthPage configured as a verification step — a ProgressSteps rail (Verify = current), a code-entry form, an error banner on a bad code, and a Resend secondary row.
import { AuthPage } from "@/components/ds/recipes";
<AuthPage
title="Verify your email"
description="Enter the 6-digit code we sent to jordan@example.org."
steps={[
{ label: "Account", status: "completed" },
{ label: "Verify", status: "current" },
{ label: "Done", status: "pending" },
]}
error={badCode ? "That code didn't match. Try again." : undefined}
secondary={<><button onClick={resend}>Resend code</button> · <a href="/login">Use another way</a></>}
>
<OtpForm onSubmit={verify} />
</AuthPage>