# Appetite — Shape Up Project Management Dashboard Template

> For teams running six-week cycles: a shape up project management dashboard template with pitches, a betting table and hill charts. 8 routes, HTML and React.

- Price: $39, one-time
- License: Standard
- Version: 1.3.4
- Category: Dashboard
- Editions: React, HTML
- Dark mode: Yes
- Stack: Next.js >=15 <17, React >=19 <20, Tailwind CSS >=4 <5
- Dependencies: `lucide-react`, `recharts`

## What's inside

- 8 pages
- 42 components
- 109 design tokens plus 109 dark overrides

## Pages

| Path | Sections |
| --- | --- |
| `/` | `app-shell`, `bet-index`, `attention-queue`, `cycle-shape` |
| `/pitches` | `app-shell`, `pitch-queue`, `shaping-lane` |
| `/pitch` | `app-shell`, `pitch-document`, `pitch-decision` |
| `/betting-table` | `app-shell`, `betting-table` |
| `/cycle` | `app-shell`, `hill-ridge`, `appetite-burn`, `circuit-breaker`, `scope-ledger` |
| `/scope` | `app-shell`, `scope-hill`, `scope-tasks`, `scope-history` |
| `/settings` | `app-shell`, `cycle-settings`, `team-settings` |
| `/components` | `app-shell`, `ui`, `dashboard-layout`, `overlay-gallery`, `bet-index`, `attention-queue`, `cycle-shape`, `pitch-queue`, `shaping-lane`, `pitch-document`, `pitch-decision`, `betting-table`, `hill-ridge`, `appetite-burn`, `circuit-breaker`, `scope-ledger`, `scope-hill`, `scope-tasks`, `scope-history`, `cycle-settings`, `team-settings` |

## Components

| Name | What it renders |
| --- | --- |
| `app-shell` | Product shell composed through the theme-local dashboard-layout boundary: the full-width cycle bar, a 232px labelled rail, responsive disclosure, breadcrumb, command bar, page heading and footer. |
| `bet-index` | The home route's opening instrument: four bets enumerated with appetite wells, per-scope hill tracks and owners, with the cycle standing as the one oversized figure. |
| `attention-queue` | Derived attention list for stalled scopes, scopes still uphill late in the cycle, and uncommitted capacity on the next table. |
| `cycle-shape` | Three counted readings of where the work sits: on the hill, not started, shipped. |
| `pitch-queue` | Searchable, filterable, sortable pitch register with removable filter chips, a preserved no-match state, 25-row pagination, a per-row dropdown menu whose reversible actions raise a transient message with an undo, and an archive filter that takes the table past its page boundary. |
| `shaping-lane` | Pitches without a settled appetite, kept out of the betting table until they have one. |
| `pitch-document` | The pitch as a reading surface: problem, appetite at display size, a three-place breadboard, named rabbit holes and written no-gos. |
| `pitch-decision` | The bet decision: a dialog carrying team, start date and reason, a menu of reversible alternatives, a durable on-page receipt and an undo. |
| `betting-table` | The capacity decision surface: keyboard and pointer reorder with position announcements, per-row bet toggles that recompute committed team-weeks, an over-capacity block, a read-only observer projection and the decision log. |
| `hill-ridge` | The signature at full size: one hill curve breaking the page container, carrying a labelled marker for every scope in the cycle. |
| `scope-ledger` | Every scope with its inline hill track, exact position, task count, owner and last movement. |
| `appetite-burn` | Recharts figure: team-weeks spent against a fixed appetite per bet, with a dashed appetite outline, direct labels, a skeleton for the pre-mount hole, a plain-language summary and an exact data table. |
| `circuit-breaker` | Derived risk list with the irreversible break action behind a typed confirmation, a disclosure explaining the threshold in force, plus the stalled-scope reading. |
| `scope-hill` | The hill control: pointer drag and a full keyboard slider model over the same curve, with a recorded-move receipt. |
| `scope-tasks` | The scope's task list with live counts, stating that closing tasks does not move the hill. |
| `scope-history` | Dated hill moves including the backwards one, with the note and the person behind each. |
| `cycle-settings` | Cycle shape form with submit validation, a focused error summary linking each field, accepted, read-only and disabled treatments, notification switches and a durable saved receipt. Mounted beside the roster in a tab set on /settings. |
| `team-settings` | Roster table with access selects, seat arithmetic, and person removal behind a typed confirmation. |
| `overlay-gallery` | The overlay layer shown open: dialog, typed confirmation, popover, dropdown menu, tooltip, command palette, date picker and calendar, with their keyboard contract stated. |
| `ui/dialog` | Shared primitives: Dialog and ConfirmDialog over one modal layer — scrim, measure box and card — the latter holding its destructive action until the object's name is typed. |
| `ui/popover` | Shared primitive: a non-modal popover anchored to its trigger, clamped and flipped against the viewport, closing on Escape, an outside press and Tab leaving it. |
| `ui/tooltip` | Shared primitive: a tooltip that opens on hover and focus, dismisses on Escape, and is wired through aria-describedby. |
| `ui/command-palette` | Shared primitives: CommandPalette and the CommandBar trigger — a modal listbox on ui/dialog's layer, driven from one input through aria-activedescendant and opened with Command or Control K. |
| `ui/calendar` | Shared primitives: Calendar and DatePicker — a typeable date field beside the full date-grid keyboard model, with non-working days marked. |
| `ui/tabs` | Tab set: role=tablist with roving tabindex, Arrow Left and Right, Home and End, automatic activation, and a focusable panel wired both ways. Mounted on /settings. |
| `ui/disclosure` | Disclosure: a summary button carrying aria-expanded and aria-controls over a labelled region that Escape collapses from inside, returning focus to the summary. |
| `ui/progress` | Determinate progress bar with role=progressbar and aria-valuetext, used for elapsed time and spent appetite and never for a scope, which is what the hill is for. |
| `ui/skeleton` | The loading treatment: flat non-animated blocks hidden from assistive technology, paired with a status line that says what is arriving. |
| `ui/toast` | Transient message region: role=status or role=alert, dismissible, Escape clears the newest, and a message carrying an action never expires on a timer. |
| `ui/fields` | Shared form primitives: Field, Input, Textarea, Select, Checkbox, Toggle, FieldSet and ErrorSummary, carrying label, description, invalid, read-only, disabled and submitting treatments over a dedicated --field-border. |
| `ui/button` | Shared primitives: Button, ButtonLink and IconButton across primary, secondary, ghost and danger, with disabled and pending states from one buttonClasses helper. |
| `ui/badge` | Shared primitives: Badge, StateBadge, ShippedBadge, AppetiteChip, PriorityMark and Eyebrow — lifecycle by ring shape, priority by bar shape, never by colour alone. |
| `ui/panel` | Shared primitives: Panel with its sunken, card and raised surfaces, PanelHeader, PanelBody, PanelFooter and the designed EmptyState. |
| `ui/table` | Shared primitives: TableFrame with its own scroll container and caption, Th, Td and the removable FilterChip; the sortable head is ui/sort-head. |
| `ui/hill` | Shared primitives: HillTrack, HillRidge and OwnerMark — the signature curve computed from the scope fixture at three sizes, with text alternatives from the same data. |
| `ui/metric` | Shared primitives: HeroFigure for the one oversized number a view leads with, Metric for supporting figures, and AppetiteWell for a fixed track with time drawn inside it. |
| `ui/dashboard-layout` | Shared primitive: the shell boundary every route mounts inside, owning the rail, the sticky header, scroll ownership and the theme's one extra slot, cycleBar. |
| `ui/mode-toggle` | Shared primitive: the ModeToggle that switches light and dark on the theme scope and persists the choice. |
| `ui/brand` | Shared primitive: AppetiteMark, the hill reduced to a mark, and the one bespoke drawing this theme allows. |
| `ui/dropdown-menu` | Shared primitive: DropdownMenu with arrow keys, Home, End, 700ms type-ahead, roving tabindex, a check glyph on a menuitemcheckbox row, and a disabled item that keeps its focus so the sentence explaining it can be read. |
| `ui/sort-head` | Shared primitive: a sortable column head whose whole cell is the control, carrying aria-sort only where a comparator exists and a written sentence saying what activating it does next. |
| `ui/hint` | Shared primitive: a one-clause helper line with a named trigger beside it that opens the reasoning in the popover card, so a panel keeps one line on the page and the sentences one press away. |
## Design tokens

| Token | Light | Dark override |
| --- | --- | --- |
| `--background` | `#f3f4f7` | `#222326` |
| `--foreground` | `#222326` | `#fafafa` |
| `--card` | `#ffffff` | `#292a2e` |
| `--card-foreground` | `#222326` | `#fafafa` |
| `--surface-sunken` | `#e9ebf1` | `#1b1c1f` |
| `--surface-raised` | `#ffffff` | `#303136` |
| `--surface-overlay` | `#ffffff` | `#35363b` |
| `--overlay-border` | `#868992` | `#767980` |
| `--muted` | `#ebecf0` | `#303136` |
| `--muted-foreground` | `#60636c` | `#9fa1a8` |
| `--secondary` | `#ebecf0` | `#303136` |
| `--secondary-foreground` | `#222326` | `#fafafa` |
| `--secondary-hover` | `#dfe1e7` | `#35363b` |
| `--secondary-active` | `#d3d6de` | `#3a3b41` |
| `--border` | `#d0d3dc` | `#3a3b41` |
| `--border-strong` | `#7f838d` | `#83868e` |
| `--ring` | `#008585` | `#65d2d1` |
| `--shadow-color` | `#181a20` | `#000000` |
| `--scrim` | `#101116` | `#050608` |
| `--nav` | `#ebecf0` | `#18191b` |
| `--nav-foreground` | `#222326` | `#fafafa` |
| `--nav-muted` | `#60636c` | `#9fa1a8` |
| `--nav-hover` | `#e1e2e6` | `#232326` |
| `--nav-selected` | `#ffffff` | `#303136` |
| `--nav-selected-foreground` | `#005555` | `#65d2d1` |
| `--nav-border` | `#d0d3dc` | `#3a3b41` |
| `--primary` | `#058f8f` | `#058f8f` |
| `--primary-foreground` | `#001111` | `#001111` |
| `--primary-hover` | `#1e9a9a` | `#1e9a9a` |
| `--primary-active` | `#2ba0a0` | `#2ba0a0` |
| `--primary-soft` | `#d8f3f2` | `#103939` |
| `--primary-border` | `#2b8d8d` | `#428e8e` |
| `--primary-ink` | `#005d5d` | `#65d2d1` |
| `--accent` | `#7137b6` | `#be9df7` |
| `--accent-foreground` | `#f9f7fe` | `#191127` |
| `--accent-hover` | `#5f279e` | `#cfb4ff` |
| `--accent-active` | `#4c1b82` | `#decaff` |
| `--accent-soft` | `#f0e9fe` | `#382950` |
| `--accent-border` | `#8d62cd` | `#8a70b8` |
| `--field` | `#ffffff` | `#1c1d20` |
| `--field-border` | `#d0d3dc` | `#3a3b41` |
| `--control` | `#f6f7f8` | `#303136` |
| `--control-border` | `#d0d3dc` | `#43454b` |
| `--control-hover` | `#f0f1f4` | `#35363b` |
| `--control-active` | `#e5e6eb` | `#3a3b41` |
| `--selection` | `#d9eceb` | `#243c3b` |
| `--selection-foreground` | `#222326` | `#fafafa` |
| `--selection-border` | `#47807f` | `#5d9190` |
| `--link` | `#005d5d` | `#65d2d1` |
| `--link-hover` | `#003f3f` | `#97e9e8` |
| `--link-visited` | `#58437a` | `#c4acf2` |
| `--info` | `#0056bc` | `#7cb4fc` |
| `--info-foreground` | `#f7faff` | `#07162a` |
| `--info-soft` | `#e1eeff` | `#173355` |
| `--info-border` | `#3d7ece` | `#5682bb` |
| `--info-fill` | `#2463eb` | `#447aee` |
| `--positive` | `#0b6c3f` | `#6cd397` |
| `--positive-foreground` | `#f5fcf7` | `#021c0d` |
| `--positive-soft` | `#ddf6e5` | `#183b26` |
| `--positive-border` | `#498e65` | `#509069` |
| `--positive-fill` | `#019a5a` | `#2dc87a` |
| `--positive-hover` | `#237b52` | `#65c28d` |
| `--positive-active` | `#2d815a` | `#62ba87` |
| `--warning` | `#804f00` | `#f2ae59` |
| `--warning-foreground` | `#fff9f2` | `#231200` |
| `--warning-soft` | `#ffebd1` | `#432e14` |
| `--warning-border` | `#a86f21` | `#a37640` |
| `--warning-fill` | `#bd7606` | `#f6a523` |
| `--critical` | `#a2191b` | `#f6857a` |
| `--critical-foreground` | `#fff8f7` | `#270d0a` |
| `--critical-soft` | `#ffe7e4` | `#50221e` |
| `--critical-border` | `#c7534a` | `#bb635a` |
| `--critical-fill` | `#c92626` | `#da3e3e` |
| `--critical-hover` | `#ab3032` | `#e27c72` |
| `--critical-active` | `#b03c3d` | `#d7776f` |
| `--priority-none` | `#6b7280` | `#7a8190` |
| `--priority-low` | `#3c83f6` | `#5593f7` |
| `--priority-medium` | `#aa8004` | `#f6be13` |
| `--priority-high` | `#db6301` | `#fa832e` |
| `--radius-sm` | `0.25rem` | `0.25rem` |
| `--radius` | `0.375rem` | `0.375rem` |
| `--radius-lg` | `0.5rem` | `0.5rem` |
| `--radius-xl` | `0.75rem` | `0.75rem` |
| `--display-weight` | `600` | `550` |
| `--text-caption` | `0.75rem` | `0.75rem` |
| `--leading-caption` | `1.4` | `1.4` |
| `--text-small` | `0.875rem` | `0.875rem` |
| `--leading-small` | `1.45` | `1.45` |
| `--text-body` | `1rem` | `1rem` |
| `--leading-body` | `1.55` | `1.55` |
| `--text-lead` | `1.125rem` | `1.125rem` |
| `--leading-lead` | `1.6` | `1.6` |
| `--text-d1` | `1.5rem` | `1.5rem` |
| `--leading-d1` | `1.25` | `1.25` |
| `--text-d2` | `1.875rem` | `1.875rem` |
| `--leading-d2` | `1.2` | `1.2` |
| `--text-d3` | `clamp(2.125rem, 1.98rem + 0.62vw, 2.344rem)` | `clamp(2.125rem, 1.98rem + 0.62vw, 2.344rem)` |
| `--leading-d3` | `1.14` | `1.14` |
| `--text-d4` | `clamp(2.5rem, 2.2rem + 1.3vw, 2.93rem)` | `clamp(2.5rem, 2.2rem + 1.3vw, 2.93rem)` |
| `--leading-d4` | `1.06` | `1.06` |
| `--tracking-d1` | `-0.012em` | `-0.012em` |
| `--tracking-d2` | `-0.018em` | `-0.018em` |
| `--tracking-d3` | `-0.022em` | `-0.022em` |
| `--tracking-d4` | `-0.028em` | `-0.028em` |
| `--tracking-label` | `0.08em` | `0.08em` |
| `--font-display` | `var(--font-appetite-display), ui-sans-serif, system-ui, sans-serif` | `var(--font-appetite-display), ui-sans-serif, system-ui, sans-serif` |
| `--font-text` | `var(--font-appetite-text), ui-sans-serif, system-ui, sans-serif` | `var(--font-appetite-text), ui-sans-serif, system-ui, sans-serif` |
| `--font-sans` | `var(--font-text)` | `var(--font-text)` |
| `--font-mono` | `var(--font-appetite-mono), ui-monospace, monospace` | `var(--font-appetite-mono), ui-monospace, monospace` |
## Use it

- Registry: `bunx shadcn add https://tailthemes.com/r/appetite.json`
- MCP: [https://tailthemes.com/api/mcp](https://tailthemes.com/api/mcp)
- Download: [https://tailthemes.com/api/download/appetite](https://tailthemes.com/api/download/appetite)

## Links

- Product page: [https://tailthemes.com/themes/appetite](https://tailthemes.com/themes/appetite)
- Live preview: [https://tailthemes.com/preview/appetite](https://tailthemes.com/preview/appetite)
- Docs: [https://tailthemes.com/docs/appetite](https://tailthemes.com/docs/appetite)
- Manifest JSON: [https://tailthemes.com/api/themes/appetite](https://tailthemes.com/api/themes/appetite)
- Registry item: [https://tailthemes.com/r/appetite.json](https://tailthemes.com/r/appetite.json)
