Agentman desktop app design system AND component system — the portable styleguide for building or restyling an Electron/Next.js/React + Tailwind app in the Agentman house style (warm Burnt Peach brand over warm neutrals, dense information-first UI, shadcn/Radix primitives). Use this whenever the user is building UI, adding or designing a component (button, card, badge, input, select, dialog/modal, table, toast, layout/shell, sidebar, tabs, empty state, skeleton), choosing colors, picking spacing/radius/typography, setting up a tailwind.config, restyling a page, doing a design or component review, or asks 'what color/font/spacing should I use', 'how should this component work', 'make it match our style', 'is this on-brand', 'set up the design tokens or component library'. Apply it even when the user doesn't say 'styleguide' but is making any visual or component decision in an app meant to look like Agentman's. Ships copy-paste tailwind tokens, two color-registry helper files (status-tone, category-colors), a full visual reference, and a prescriptive component-system reference (primitive contracts, data-table pattern, app shell, feedback/overlays, enforcement).
# Agentman App Style Guide
A portable design system for building (or restyling) an Electron / Next.js / React app
with Tailwind in the Agentman house style. It is reverse-engineered from the production
MedMan desktop app — these are the tokens, scales, components, and patterns the real app
uses (or should use), not an aspirational spec.
It has two halves:
- **Visual system** — color, type, spacing, radius, elevation, motion (this file + `references/styleguide.md`).
- **Component system** — the primitive contracts, data-table pattern, app shell, feedback/overlays, and enforcement (`references/component-system.md`).
**Core identity:** a warm terracotta brand ("Burnt Peach", `#CB785D`) over **warm**
neutrals (linen / gunmetal), deliberately *not* cold slate-gray. Dense, information-first
layout — this is a tool, not a marketing landing page. Restraint over decoration. Built on
shadcn-style primitives (Radix + class-variance-authority).
## When to use this skill
Use it for any visual OR component decision in an Agentman-style app: setting up Tailwind
tokens, building/designing a component (button, card, badge, input, select, dialog, table,
toast, layout shell, tabs, empty state, skeleton), choosing a color for a status or category,
picking spacing/radius/elevation/type, restyling a page, or running a design/component review.
Don't wait for the user to say "styleguide" — if they're deciding how UI looks or how a
component behaves, this is the source of truth.
## How to apply it (the fast path)
1. **Tokens first.** Drop `assets/tailwind.colors.js` into `tailwind.config.js` under
`theme.extend.colors` → `primary-*` (Burnt Peach) + warm neutrals (`gunmetal`, `grey`,
`linen`, `cream`, `canvas`, `ghost`).
2. **Color decisions live in two files, never inline.** Copy `assets/status-tone.ts`
(status → semantic color) and `assets/category-colors.ts` (taxonomy → color). Every
badge/pill imports from these. A raw `text-purple-700` in a component is a smell.
3. **One primitive per UI role, and everyone goes through it.** A button is `<Button>`, not a
raw styled `<button>`; a status pill is `<StatusBadge>`, not bespoke spans. The primitive
is the only place a styling decision for that role is made. See `references/component-system.md`.
4. **Defaults.** Body text `text-sm`, resting weight `font-medium`, radius `rounded-lg`,
elevation `shadow-sm`, app bg `bg-canvas`, content on `bg-white` cards with `border-linen`.
5. **Read the references** for full detail before a non-trivial build or review:
`references/styleguide.md` (visual) and `references/component-system.md` (components).
## The visual system at a glance
### Color
- **Brand:** `primary-500` (#CB785D) for actions/links/focus; `primary-600` hover.
- **Text:** `text-gunmetal` (#383938, warm near-black) — never cold `slate-900`.
- **Surfaces:** `bg-canvas` (recessed ground) → white content card → `bg-linen`/`bg-cream`
sub-surfaces. Figure/ground, Linear-style.
- **Semantic (fixed meaning):** emerald = success, red = error, amber = warning, blue = info.
Defined once in `status-tone.ts`.
- **Category colors** (purple/violet/indigo/pink/sky): ONLY through `category-colors.ts`.
### Type (dense desktop scale)
- `text-sm` (14px) = default body/cells/labels. `text-xs` (12px) = metadata/badges.
- `text-lg`/`text-xl`/`text-2xl` for card/section/page titles.
- Resting weight `font-medium`; `font-semibold` headings; `font-bold` page titles only.
- Font: native system stack (no web font).
### Spacing / radius / elevation
- 4px base. Card padding `p-4`; form fields `space-y-4`; sections `space-y-6`.
- Radius: `rounded-md` (inputs), `rounded-lg` (cards/buttons, default), `rounded-xl`
(large cards, sparingly), `rounded-full` (badges). Never `rounded-2xl`+.
- Elevation: `shadow-sm` resting, `shadow-lg` popovers/dropdowns, `shadow-xl` modals.
### Motion
- `transition-colors duration-150` on hovers. Entrances ≤ 350ms, ease-out, once per mount.
- No hover scale/rotate, no infinite pulse on content, no animated gradients or blur blobs.
## The component system at a glance
Full contracts in `references/component-system.md`. The essentials:
- **One primitive per role.** Build on **Radix** (headless behavior/a11y) + **cva** (variants)
+ **`cn()`** (clsx + tailwind-merge) + Radix **`Slot`/`asChild`**. One icon library
(**lucide-react**). One toast helper (`showToast`).
- **Core primitives:** `Button` (primary/secondary/ghost/destructive/link × sm/md/icon),
`StatusBadge` (driven by `status-tone.ts`), `Card`, `Input`/`Textarea` + `Label`,
`Select`/`Combobox`, `Dialog`, `Tooltip`, `Checkbox`.
- **Data table:** one generic `AgentDataTable<TData>` renderer + a per-feature
`use<Feature>Table()` hook (TanStack v8). Stable `getRowId`, stable cell renderers,
persisted sort/filter/expansion, patch-single-row updates. Retire hand-rolled tables.
- **App shell:** compose every page as `AppLayout` → `Sidebar`/`SideDock` → `PageHeader` →
`PageTabs` → white content cards on `bg-canvas`. Pages don't reinvent chrome.
- **Feedback/overlays:** one `Toast`, one `Spinner`, one `Skeleton`, one `EmptyState`, an
`ErrorBoundary` per page. Flat `bg-black/40` scrims (no blur).
### Canonical recipes
```jsx
// Primary button (or use <Button variant="primary">)
<button className="bg-primary-500 hover:bg-primary-600 text-white font-medium px-4 py-2 rounded-lg transition-colors duration-150">Verify</button>
// Card
<div className="bg-white border border-linen rounded-lg p-4 shadow-sm">
<h3 className="text-lg font-semibold text-gunmetal mb-2">Coverage</h3>
<p className="text-sm text-grey">…</p>
</div>
// Status badge (driven by status-tone.ts)
import { statusTone, toneFor } from '@/utils/status-tone';
<span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full border text-xs font-medium ${statusTone(toneFor(status))}`}>{label}</span>
// Input
<input className="w-full h-9 px-3 rounded-md border border-linen text-sm text-gunmetal placeholder:text-grey focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500" />
```
## Anti-patterns (don't reproduce the drift)
Actual problems found auditing the live app — avoid them in any new app:
1. **Bypassed primitives.** Don't style raw `<button>` for actions (the app has 178 raw
buttons vs 13 using the primitive). Go through `<Button>`.
2. **Duplicate components.** One `StatusBadge`, not five; one table system, not 10+.
3. **Multiple neutral ramps.** No `slate-`/`gray-`/`neutral-`/`zinc-`. One warm neutral system.
4. **Two ramps for one meaning.** Pick `emerald` for success (not `green` *and* `emerald`).
5. **Inline category colors.** Route purple/indigo/etc. through `category-colors.ts`.
6. **Glassmorphism / gradients / over-rounding.** No `backdrop-blur`, `bg-gradient-to-*`, `rounded-2xl`+.
7. **Cold slate text.** Body is warm `gunmetal`, never `slate-900`/`charcoal`.
8. **Mixed icon libraries / decorative motion.** One icon set; no scale/rotate hovers or infinite pulses.
## Enforcement
Primitives alone don't hold the line (the app proves it). Add a CI grep/lint gate banning,
in feature/page source: raw `<button` (outside `ui/`), `slate-`/`gray-`/`neutral-`/`zinc-`,
`bg-gradient-to`, `backdrop-blur`, `rounded-2xl`/`rounded-3xl`, inline
`purple-/indigo-/violet-/pink-/sky-` outside the category map, a second `*StatusBadge*`, a
second icon library, or a hand-rolled `<table>` outside the shared table system. Full
checklist in `references/component-system.md` ("Enforcement") and `references/styleguide.md` §9.
## Bundled resources
- `references/styleguide.md` — the complete VISUAL system (color, type, spacing, layout, motion).
- `references/component-system.md` — the complete COMPONENT system (primitive contracts, data table, app shell, feedback/overlays, enforcement).
- `assets/tailwind.colors.js` — color block to paste into `tailwind.config.js`.
- `assets/status-tone.ts` — semantic status → color, single source of truth for status badges.
- `assets/category-colors.ts` — taxonomy/category → color registry (the only place these colors are decided).
**Principle:** one token system + one primitive per role; warm neutrals; semantic colors with
fixed meaning; category colors only through a registry; a generic table, one shell, one toast —
guarded by a CI gate. Restraint over decoration. Density over whitespace.
Try it now in your favorite AI, or set up MCP for persistent access.
Try Now
Or Set Up MCP