{
  "slug": "restrained-saas-dashboard",
  "name": "Restrained SaaS Dashboard",
  "tagline": "Dense, calm and aligned. The look of a product people use every day.",
  "version": "07e55d2",
  "url": "https://dontmakeitugly.com/packs/restrained-saas-dashboard",
  "markdownUrl": "https://dontmakeitugly.com/packs/restrained-saas-dashboard.md",
  "designMdUrl": "https://dontmakeitugly.com/packs/restrained-saas-dashboard/DESIGN.md",
  "files": [
    {
      "path": "DESIGN.md",
      "content": "---\nversion: alpha\nname: Restrained SaaS Dashboard\ndescription: A quiet, dense product interface for software with numbers in it. Greys do the work; one blue does the pointing.\ncolors:\n  paper: \"#fafafa\"\n  surface: \"#ffffff\"\n  surface-2: \"#f4f4f5\"\n  ink: \"#0a0a0a\"\n  ink-2: \"#525252\"\n  ink-3: \"#737373\"\n  line: \"#e5e5e5\"\n  line-strong: \"#d4d4d4\"\n  primary: \"#2563eb\"\n  primary-soft: \"#eff6ff\"\n  on-primary: \"#ffffff\"\n  positive: \"#15803d\"\n  positive-soft: \"#f0fdf4\"\n  negative: \"#b91c1c\"\n  negative-soft: \"#fef2f2\"\n  warning: \"#b45309\"\n  warning-soft: \"#fffbeb\"\n  chart-1: \"#2563eb\"\n  chart-2: \"#0a0a0a\"\n  chart-3: \"#a3a3a3\"\n  chart-4: \"#d4d4d4\"\ntypography:\n  title:\n    fontFamily: Geist\n    fontSize: 24px\n    fontWeight: 600\n    lineHeight: 1.2\n    letterSpacing: -0.02em\n  heading:\n    fontFamily: Geist\n    fontSize: 16px\n    fontWeight: 600\n    lineHeight: 1.4\n  body:\n    fontFamily: Geist\n    fontSize: 14px\n    fontWeight: 400\n    lineHeight: 1.5\n  caption:\n    fontFamily: Geist\n    fontSize: 12px\n    fontWeight: 500\n    lineHeight: 1.4\n    letterSpacing: 0.01em\n  number:\n    fontFamily: JetBrains Mono\n    fontSize: 14px\n    fontWeight: 500\n    lineHeight: 1.4\n    fontFeature: \"tnum\"\n  metric:\n    fontFamily: JetBrains Mono\n    fontSize: 28px\n    fontWeight: 500\n    lineHeight: 1.1\n    letterSpacing: -0.02em\n    fontFeature: \"tnum\"\nrounded:\n  sm: 4px\n  md: 6px\n  lg: 8px\n  full: 9999px\nspacing:\n  base: 4px\n  xs: 4px\n  sm: 8px\n  md: 12px\n  lg: 16px\n  xl: 24px\n  2xl: 32px\n  3xl: 48px\n  sidebar: 240px\n  gutter: 24px\ncomponents:\n  button-primary:\n    backgroundColor: \"{colors.primary}\"\n    textColor: \"{colors.on-primary}\"\n    typography: \"{typography.body}\"\n    rounded: \"{rounded.md}\"\n    padding: \"{spacing.md}\"\n    height: 32px\n  button-secondary:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.ink}\"\n    typography: \"{typography.body}\"\n    rounded: \"{rounded.md}\"\n    padding: \"{spacing.md}\"\n    height: 32px\n  card:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.ink}\"\n    rounded: \"{rounded.lg}\"\n    padding: \"{spacing.lg}\"\n  stat:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.ink}\"\n    typography: \"{typography.metric}\"\n    rounded: \"{rounded.lg}\"\n    padding: \"{spacing.lg}\"\n  table-header:\n    backgroundColor: \"{colors.surface-2}\"\n    textColor: \"{colors.ink-2}\"\n    typography: \"{typography.caption}\"\n    height: 36px\n  table-cell:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.ink}\"\n    typography: \"{typography.body}\"\n    height: 40px\n  badge:\n    backgroundColor: \"{colors.surface-2}\"\n    textColor: \"{colors.ink-2}\"\n    typography: \"{typography.caption}\"\n    rounded: \"{rounded.full}\"\n    padding: \"{spacing.xs}\"\n  input:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.ink}\"\n    typography: \"{typography.body}\"\n    rounded: \"{rounded.md}\"\n    padding: \"{spacing.sm}\"\n    height: 32px\n---\n\n# Restrained SaaS Dashboard\n\n## Overview\n\nA product interface for software that shows people numbers: analytics, billing, admin, ops. The feeling to aim for is the one Linear, Vercel and Stripe share: dense but calm, everything aligned, nothing shouting. The user is at this screen every day, so it should get out of the way.\n\nIf in doubt, remove something. Dashboards go wrong by addition: one more card, one more colour, one more chart type.\n\n## Colors\n\nAlmost everything is grey. The palette has one accent and three status colours, and each of them has exactly one job.\n\n- **Paper (#fafafa) and Surface (#ffffff):** the app background and the panels on it. That single step is the only elevation.\n- **Ink (#0a0a0a), Ink 2 (#525252), Ink 3 (#737373):** primary text, secondary text, labels and table headers.\n- **Line (#e5e5e5):** every border, divider and table rule. Line strong is for inputs and focused edges.\n- **Primary (#2563eb):** the one blue. Primary buttons, active navigation, links, focus rings, the first chart series. If two things on a screen are blue, one of them is wrong.\n- **Positive, Negative, Warning:** deltas, status badges, validation. Never decorative, never as backgrounds larger than a badge.\n- **Chart series:** blue, ink, mid grey, light grey, in that order. A chart with more than four series needs a different chart.\n\nDark mode is out of scope for this contract. If you add one, derive it from Radix Colors' grey scale so the steps match.\n\n## Typography\n\nOne family for words, one for numbers.\n\n- **Geist** for all text. Titles at 24px semibold with tight tracking; section headings at 16px semibold; body at 14px; captions and table headers at 12px medium with a hint of tracking.\n- **JetBrains Mono** with tabular figures for anything numeric that sits in a column or changes over time: metrics, table numbers, timestamps, IDs. Right-align numbers in tables.\n- Body is 14px, not 16px. This is a tool, not an article. Never go below 12px.\n\n## Layout\n\nA fixed 240px sidebar and a fluid content area with 24px padding. The content sits on a 4px base scale; components use 8, 12, 16 and 24. Sections separate with 32px, pages with 48px.\n\nGroup related metrics in one row of stat cards, at most four. Below that, one primary chart, then the table. Filters and date ranges sit in a single toolbar above the content, right-aligned, never in a sidebar of their own.\n\n## Elevation & Depth\n\nFlat. Cards are surface-on-paper with a 1px line border and no shadow. Popovers and menus get one soft shadow (0 4px 12px at 8% ink) because they float; nothing else does. No gradients anywhere, including chart fills, which are solid at low opacity.\n\n## Shapes\n\nSmall and consistent: 4px on badges and checkboxes, 6px on buttons and inputs, 8px on cards and panels. Pills only for status badges. Avatars are the only circles.\n\n## Components\n\n- **Buttons:** 32px tall. Primary is blue with white text, one per view. Secondary is surface with a line border. Destructive uses negative text on a secondary shape, never a red fill.\n- **Stat card:** label in caption grey, the number in mono at 28px, a delta in positive or negative with an arrow. No sparkline unless there is room for the axis.\n- **Table:** 36px header row in surface-2 with caption text in ink 2, 40px body rows, hairline rules only between rows, numbers right-aligned in mono. Sticky header. Row hover is surface-2.\n- **Charts:** Tremor defaults with the series colours above, a single grid axis, no legend when the title already says what the line is.\n- **Badges:** pill, surface-2 background, caption text. Status variants use the soft colours with their solid partner as text.\n- **Inputs:** 32px, line-strong border, primary ring on focus. Labels above, help text below in ink-3.\n- **Empty state:** a short sentence and one secondary action. No illustration.\n\n## Do's and Don'ts\n\n- Do use only Geist and JetBrains Mono. Numbers that align are the whole point of the mono face.\n- Do keep every colour inside the palette. When a status needs a colour, use the soft/solid pair, never a new one.\n- Do keep contrast at WCAG AA: 4.5:1 for text, 3:1 for icons and borders that carry meaning.\n- Do respect `prefers-reduced-motion`; number animations and chart transitions collapse to instant.\n- Don't use gradients, glows or glassmorphism anywhere, including chart fills and hero cards.\n- Don't put a card inside a card. If content needs grouping inside a panel, use a divider.\n- Don't add a rainbow of chart colours. Four series, then rethink the chart.\n- Don't use blue for anything that is not interactive.\n",
      "overwrite": "never"
    },
    {
      "path": "dmiu.config.json",
      "content": "{\n  \"pack\": \"restrained-saas-dashboard\",\n  \"designMd\": \"DESIGN.md\",\n  \"baseUrl\": \"http://localhost:3000\",\n  \"routes\": [\n    \"/\",\n    \"/dashboard\"\n  ],\n  \"viewports\": [\n    {\n      \"width\": 1280,\n      \"height\": 800\n    },\n    {\n      \"width\": 390,\n      \"height\": 844\n    }\n  ],\n  \"tolerance\": {\n    \"color\": 6,\n    \"spacing\": 1\n  },\n  \"forbidGradients\": true,\n  \"ignore\": [],\n  \"baselines\": {\n    \"dir\": \".dmiu/baselines\",\n    \"threshold\": 0.02\n  }\n}\n",
      "overwrite": "never"
    },
    {
      "path": ".dmiu/references/README.md",
      "content": "# Reference screens for Restrained SaaS Dashboard\n\nThese are third-party sites we point at, not assets to copy. Take the principle, not the pixels.\n\n## Vercel Geist\n\nhttps://vercel.com/geist/introduction\n\nHow a developer-tool interface stays quiet: one accent, hairline structure, dense but readable type.\n\nLook at: the grey scale and how little colour there is\n\nPreview: https://dontmakeitugly.com/previews/geist-design-system.jpg\n\n## Tremor\n\nhttps://tremor.so\n\nCharts and KPI blocks with sensible defaults. This is what the stat row and primary chart should feel like.\n\nLook at: chart palette, axis restraint, stat card hierarchy\n\nPreview: https://dontmakeitugly.com/previews/tremor.jpg\n\n## Origin UI\n\nhttps://originui.com\n\nPractical product components: tables, filters, inputs, badges. Less flashy than landing-page kits, which is the point.\n\nLook at: table density, badge sizing, form spacing\n\nPreview: https://dontmakeitugly.com/previews/origin-ui.jpg\n",
      "overwrite": "always"
    }
  ],
  "agentsSnippet": "<!-- BEGIN:dontmakeitugly -->\n## Design contract (Restrained SaaS Dashboard)\n\nThis project uses a DESIGN.md contract from Don't Make It Ugly. Before writing or changing any UI:\n\n1. Read `DESIGN.md`. Use only its fonts, colours, spacing scale and radii. If something you need isn't there, ask before inventing it.\n2. Read `.dmiu/references/README.md` for the reference screens and what to take from each.\n3. When you finish a UI change, start the dev server and run `npx dontmakeitugly check`. Read `.dmiu/report.md` and fix every error before you say you're done.\n4. Never edit `DESIGN.md` to make a check pass. Change the code.\n\nCurated resources for this pack (each page says how an agent can use it):\n\n- Tremor: https://dontmakeitugly.com/resources/tremor.md\n- Origin UI: https://dontmakeitugly.com/resources/origin-ui.md\n- NumberFlow: https://dontmakeitugly.com/resources/number-flow.md\n- Vercel Geist: https://dontmakeitugly.com/resources/geist-design-system.md\n- Radix Colors: https://dontmakeitugly.com/resources/radix-colors.md\n- Web Interface Guidelines: https://dontmakeitugly.com/resources/vercel-web-interface-guidelines.md\n- shadcn MCP server: https://dontmakeitugly.com/resources/shadcn-mcp.md\n- Playwright MCP: https://dontmakeitugly.com/resources/playwright-mcp.md\n<!-- END:dontmakeitugly -->",
  "references": [
    {
      "resource": "geist-design-system",
      "name": "Vercel Geist",
      "caption": "How a developer-tool interface stays quiet: one accent, hairline structure, dense but readable type.",
      "focus": "the grey scale and how little colour there is",
      "url": "https://vercel.com/geist/introduction",
      "image": "https://dontmakeitugly.com/previews/geist-design-system.jpg"
    },
    {
      "resource": "tremor",
      "name": "Tremor",
      "caption": "Charts and KPI blocks with sensible defaults. This is what the stat row and primary chart should feel like.",
      "focus": "chart palette, axis restraint, stat card hierarchy",
      "url": "https://tremor.so",
      "image": "https://dontmakeitugly.com/previews/tremor.jpg"
    },
    {
      "resource": "origin-ui",
      "name": "Origin UI",
      "caption": "Practical product components: tables, filters, inputs, badges. Less flashy than landing-page kits, which is the point.",
      "focus": "table density, badge sizing, form spacing",
      "url": "https://originui.com",
      "image": "https://dontmakeitugly.com/previews/origin-ui.jpg"
    }
  ],
  "resources": [
    {
      "slug": "tremor",
      "name": "Tremor",
      "tagline": "Copy-paste React components for dashboards and charts.",
      "url": "https://tremor.so",
      "markdownUrl": "https://dontmakeitugly.com/resources/tremor.md",
      "agentPrompt": "Use Tremor as a design and implementation reference for this project.\n\nWhat it is: Copy-paste React components for dashboards and charts.\n\nWebsite: https://tremor.so\nDocumentation: https://tremor.so/docs/getting-started/installation\nGitHub: https://github.com/tremorlabs/tremor\n\nUse it specifically for:\n- SaaS dashboards\n- analytics pages\n- charts\n- admin panels\n\nHow you can access it: Docs, GitHub, Copy/paste.\nWorks with: React, Next.js, Tailwind CSS.\nLicense: Apache-2.0. Respect it.\n\nStudy the relevant design and implementation patterns, but adapt them to this project's existing architecture, visual language, accessibility requirements and conventions. Do not blindly copy the entire resource."
    },
    {
      "slug": "origin-ui",
      "name": "Origin UI",
      "tagline": "Hundreds of polished, practical components built on shadcn/ui conventions.",
      "url": "https://originui.com",
      "markdownUrl": "https://dontmakeitugly.com/resources/origin-ui.md",
      "agentPrompt": "Use Origin UI as a design and implementation reference for this project.\n\nWhat it is: Hundreds of polished, practical components built on shadcn/ui conventions.\n\nWebsite: https://originui.com\nGitHub: https://github.com/origin-space/originui\n\nUse it specifically for:\n- app interfaces\n- forms and inputs\n- tables\n- settings pages\n\nHow you can access it: Public website, GitHub, CLI, Copy/paste.\nWorks with: React, Next.js, Tailwind CSS.\nLicense: MIT. Respect it.\n\nRead the documentation before writing code, and use the current version's API. Install it properly rather than re-implementing it. Adapt the defaults to this project's existing design tokens, typography, spacing and accessibility requirements. Do not blindly copy the entire resource."
    },
    {
      "slug": "number-flow",
      "name": "NumberFlow",
      "tagline": "Animated number transitions that make counters, prices and stats feel expensive.",
      "url": "https://number-flow.barvian.me",
      "markdownUrl": "https://dontmakeitugly.com/resources/number-flow.md",
      "installCommand": "npm install @number-flow/react",
      "agentPrompt": "Use NumberFlow as a design and implementation reference for this project.\n\nWhat it is: Animated number transitions that make counters, prices and stats feel expensive.\n\nWebsite: https://number-flow.barvian.me\nGitHub: https://github.com/barvian/number-flow\nnpm: https://www.npmjs.com/package/@number-flow/react\nInstall: npm install @number-flow/react\n\nUse it specifically for:\n- pricing toggles\n- stat counters\n- dashboards\n- small delightful details\n\nHow you can access it: Docs, GitHub, npm.\nWorks with: React, Vue, Svelte.\nLicense: MIT. Respect it.\n\nRead the documentation before writing code, and use the current version's API. Install it properly rather than re-implementing it. Adapt the defaults to this project's existing design tokens, typography, spacing and accessibility requirements. Do not blindly copy the entire resource."
    },
    {
      "slug": "geist-design-system",
      "name": "Vercel Geist",
      "tagline": "Vercel's design system: the reference for the modern developer-tool look.",
      "url": "https://vercel.com/geist/introduction",
      "markdownUrl": "https://dontmakeitugly.com/resources/geist-design-system.md",
      "agentPrompt": "Use Vercel Geist as a design and implementation reference for this project.\n\nWhat it is: Vercel's design system: the reference for the modern developer-tool look.\n\nWebsite: https://vercel.com/geist/introduction\n\nUse it specifically for:\n- developer tools\n- dark mode colour scales\n- minimal product UI\n\nHow you can access it: Docs, Public website.\nWorks with: React, Next.js.\n\nStudy the relevant design and implementation patterns, but adapt them to this project's existing architecture, visual language, accessibility requirements and conventions. Do not blindly copy the entire resource."
    },
    {
      "slug": "radix-colors",
      "name": "Radix Colors",
      "tagline": "Colour scales designed for real UI, with light and dark modes that actually match.",
      "url": "https://www.radix-ui.com/colors",
      "markdownUrl": "https://dontmakeitugly.com/resources/radix-colors.md",
      "installCommand": "npm install @radix-ui/colors",
      "agentPrompt": "Use Radix Colors as a design and implementation reference for this project.\n\nWhat it is: Colour scales designed for real UI, with light and dark modes that actually match.\n\nWebsite: https://www.radix-ui.com/colors\nDocumentation: https://www.radix-ui.com/colors/docs/overview/installation\nGitHub: https://github.com/radix-ui/colors\nnpm: https://www.npmjs.com/package/@radix-ui/colors\nInstall: npm install @radix-ui/colors\n\nUse it specifically for:\n- colour systems\n- dark mode\n- accessible palettes\n- design tokens\n\nHow you can access it: Docs, GitHub, npm.\nWorks with: Framework agnostic, Tailwind CSS.\nLicense: MIT. Respect it.\n\nRead the documentation before writing code, and use the current version's API. Install it properly rather than re-implementing it. Adapt the defaults to this project's existing design tokens, typography, spacing and accessibility requirements. Do not blindly copy the entire resource."
    },
    {
      "slug": "vercel-web-interface-guidelines",
      "name": "Web Interface Guidelines",
      "tagline": "A concise, agent-readable checklist of what a well-built web interface must get right.",
      "url": "https://github.com/vercel-labs/web-interface-guidelines",
      "markdownUrl": "https://dontmakeitugly.com/resources/vercel-web-interface-guidelines.md",
      "agentPrompt": "Use Web Interface Guidelines as a design and implementation reference for this project.\n\nWhat it is: A concise, agent-readable checklist of what a well-built web interface must get right.\n\nWebsite: https://github.com/vercel-labs/web-interface-guidelines\nGitHub: https://github.com/vercel-labs/web-interface-guidelines\n\nUse it specifically for:\n- agent rules files\n- design reviews\n- accessibility basics\n- polish\n\nHow you can access it: GitHub, Copy/paste, CLI.\nWorks with: Framework agnostic.\nLicense: MIT. Respect it.\n\nRead the documentation before writing code, and use the current version's API. Install it properly rather than re-implementing it. Adapt the defaults to this project's existing design tokens, typography, spacing and accessibility requirements. Do not blindly copy the entire resource."
    },
    {
      "slug": "shadcn-mcp",
      "name": "shadcn MCP server",
      "tagline": "Let your agent browse, search and install components from any shadcn registry.",
      "url": "https://ui.shadcn.com/docs/mcp",
      "markdownUrl": "https://dontmakeitugly.com/resources/shadcn-mcp.md",
      "installCommand": "npx shadcn@latest mcp init --client claude",
      "agentPrompt": "Set up and use shadcn MCP server in this project.\n\nWhat it is: Let your agent browse, search and install components from any shadcn registry.\n\nWebsite: https://ui.shadcn.com/docs/mcp\nGitHub: https://github.com/shadcn-ui/ui\nInstall: npx shadcn@latest mcp init --client claude\n\nUse it specifically for:\n- installing components via agent\n- browsing registries\n- shadcn projects\n\nHow you can access it: MCP, CLI, Docs, GitHub.\nWorks with: React, Next.js, Tailwind CSS.\nLicense: MIT. Respect it.\n\nFollow the official setup instructions above. Once available, use it when it is relevant to the task rather than by default, and tell me what it changed."
    },
    {
      "slug": "playwright-mcp",
      "name": "Playwright MCP",
      "tagline": "Give your agent a browser so it can see and test what it built.",
      "url": "https://github.com/microsoft/playwright-mcp",
      "markdownUrl": "https://dontmakeitugly.com/resources/playwright-mcp.md",
      "installCommand": "claude mcp add playwright -- npx @playwright/mcp@latest",
      "agentPrompt": "Set up and use Playwright MCP in this project.\n\nWhat it is: Give your agent a browser so it can see and test what it built.\n\nWebsite: https://github.com/microsoft/playwright-mcp\nGitHub: https://github.com/microsoft/playwright-mcp\nInstall: claude mcp add playwright -- npx @playwright/mcp@latest\n\nUse it specifically for:\n- visual QA by the agent\n- responsive checks\n- accessibility tree inspection\n- iterating on design\n\nHow you can access it: MCP, GitHub, npm, Docs.\nWorks with: Framework agnostic.\nLicense: Apache-2.0. Respect it.\n\nFollow the official setup instructions above. Once available, use it when it is relevant to the task rather than by default, and tell me what it changed."
    }
  ],
  "check": {
    "routes": [
      "/",
      "/dashboard"
    ],
    "colorTolerance": 6,
    "spacingTolerance": 1,
    "forbidGradients": true
  }
}
