Resolved: light

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.

Save the Dogs

Welcome back

Sign in to the Save the Dogs portal.

By continuing you agree to the Terms and Privacy Policy.

<AuthPage> — centered AuthScreen card · brand mark · email + password form · secondary links · footer
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

<ErrorPage> — 404 not-found: detail ref + Go to dashboard / Home + support footer

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

<ErrorPage code='500'> — error face: ServerCrash badge + Retry
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).

Save the Dogs

We'll be right back

We're doing some quick upkeep to keep things running smoothly. Thanks for your patience.

Questions? hello@savethedogs.io

<MaintenancePage> — default downtime gate: brand + wrench badge + ETA + status action
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.

No volunteers yet
Invite your first volunteer to get started.

Need help? Email ops@savethedogs.io

<EmptyStatePage variant='empty'> — first-run card + primary CTA
No matches
Try a different filter or search term.
<EmptyStatePage variant='no-results'> — no matches + secondary Clear filters
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.

Save the Dogs

Terms · Privacy

<OrganizationSelectionPage> — workspace picker: three org rows (Avatar + RolePill + chevron)
Save the Dogs

Choose a workspace

You're not a member of any organization yet

No organizations yet
Create one to get started

Terms · Privacy

<OrganizationSelectionPage organizations={[]}> — first-run empty state
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).

tsx
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.

tsx
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.

tsx
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>