# Creative Tim UI — Design & Usage Guide **Version 1.0.0** Creative Tim March 2026 > **Note:** > This document is primarily for AI agents and LLMs generating, reviewing, or modifying > UI code that uses the Creative Tim UI block library. Guidance is optimised for > automation and consistency. Humans may also find it useful as a reference. --- ## Abstract Creative Tim UI is a block library of 390+ React + Tailwind CSS components built on shadcn/ui. This guide covers the design philosophy behind every block, installation patterns, brand identity rules, Tailwind v4 constraints, and component conventions so AI-generated code stays consistent with the library — not just visually, but in the decisions it makes. --- ## Table of Contents 0. [Design Philosophy](#0-design-philosophy) 1. [Installing Blocks](#1-installing-blocks) 2. [PRO Blocks & API Key](#2-pro-blocks--api-key) 3. [Brand Identity](#3-brand-identity) 4. [Typography Rules](#4-typography-rules) 5. [Tailwind v4 Constraints](#5-tailwind-v4-constraints) 6. [Component Patterns](#6-component-patterns) 7. [Hydration Safety](#7-hydration-safety) 8. [Block Authoring Guide](#8-block-authoring-guide) --- ## 0. Design Philosophy Across 300+ products and categories, Creative Tim has applied the same discipline: identify what developers actually need, build that exceptionally well, and cut everything else. That discipline — research first, build only what's necessary, remove rather than add — is the foundation of every block in this library. **The five principles:** ### 0.1 The 95% Rule Build the common case exceptionally well. Do not reach for complex solutions to simple problems. A developer dropping in a block should not unwrap three layers of abstraction to change a label. ### 0.2 The "Light" Principle A block is done not when there's nothing left to add, but when there's nothing left to remove. No feature flags for things that can be changed in code. No helper components used only once. No animations on elements that don't need to communicate state. No extra wrappers that exist only to satisfy a mental model. ### 0.3 Research Before Rendering The first question is always: what problem does this solve for the person looking at the screen? Not what looks good in isolation. A pricing table reduces friction in a purchase decision. A dashboard surfaces the one number a person needs to act on. If the purpose isn't clear, the block isn't clear. ### 0.4 Standing on Foundations shadcn/ui's `Table`, `Card`, `Button`, `Badge`, `Dialog` are well-designed, accessible, and maintained. Do not rebuild them. Do not wrap them unnecessarily. The Creative Tim contribution is the **composition** — how primitives are assembled into something useful for real work. ### 0.5 Real Use, Not Demo Use The standard is: would a real team ship this to solve a real problem? Avoid visual complexity that doesn't carry information. A status badge that turns red when something is wrong is communication. A gradient that doesn't indicate anything is decoration. Only the first belongs. Full detail with code examples: `rules/brand-philosophy.md` --- --- ## 1. Installing Blocks ### 1.1 Creative Tim CLI The preferred method. Installs the block and all shadcn/ui primitive dependencies automatically. ```bash # Initialize project (auto-detects Next.js / Vite / Remix / Astro) npx @creative-tim/ui@latest init # Add a block npx @creative-tim/ui@latest add ``` **Package:** `@creative-tim/ui` (v0.4.x+) **Binaries:** `creative-tim-ui`, `creative-tim` (aliases for the same CLI) ```bash # All of these are equivalent: npx @creative-tim/ui@latest add hero-01 npx creative-tim-ui add hero-01 npx creative-tim add hero-01 ``` **Examples:** ```bash npx @creative-tim/ui@latest add hero-01 npx @creative-tim/ui@latest add ai-agent-activity-01 npx @creative-tim/ui@latest add agent-management-list-01 npx @creative-tim/ui@latest add pricing-01 ``` The CLI copies the component into `components/ui/` (or your configured components directory) and runs `npx shadcn@latest add` for each dependency. ### 1.2 shadcn CLI (Full URL) Use this when you prefer the shadcn workflow or when integrating with shadcn's registry tooling. ```bash npx shadcn@latest add https://www.creative-tim.com/ui/r/.json ``` **Examples:** ```bash npx shadcn@latest add https://www.creative-tim.com/ui/r/hero-01.json npx shadcn@latest add https://www.creative-tim.com/ui/r/testimonials-03.json ``` ### 1.3 Block Discovery Browse all blocks: - Website: https://www.creative-tim.com/ui - AI index: https://www.creative-tim.com/ui/llms.txt (grouped by category, machine-readable) Individual block JSON (for programmatic access): ``` https://www.creative-tim.com/ui/r/.json ``` --- ## 2. PRO Blocks & API Key PRO blocks require a `Creative-Tim-Api-Key` header when fetching the block JSON. Obtain a key at https://www.creative-tim.com/ui. ### 2.1 Environment Setup ```bash # .env.local (never commit this) CREATIVE_TIM_UI_API_KEY=pk_live_xxxxxxxxxxxxxxxx ``` ### 2.2 CLI Install with Key ```bash npx @creative-tim/ui@latest add --api-key $CREATIVE_TIM_UI_API_KEY ``` ### 2.3 Global Login (persists across sessions) ```bash npx @creative-tim/ui@latest login --api-key pk_live_xxxxxxxxxxxxxxxx ``` After login, all `add` commands automatically include the key — no `--api-key` flag needed. ### 2.4 Detecting PRO Blocks PRO blocks are marked on the website. In the registry JSON they include `"pro": true`. Free-tier blocks have no `pro` field. --- ## 3. Brand Identity ### 3.1 Primary Accent — Orange **Rule:** Use `orange` as the primary brand accent for interactive elements, icons, CTAs, and highlights. ```tsx // CORRECT — orange accent
JD OpenClaw ``` ```tsx // WRONG — violet/purple signals AI-generated defaults, not Creative Tim
...
... ``` **Why:** Purple/violet is the default accent in many AI coding tools. Any block using it looks auto-generated and inconsistent with the library. ### 3.2 Status Colors | State | Color | |-------|-------| | Active / Success | `emerald` | | Warning / Pending | `amber` | | Error / Stopped | `red` | | Info / In-Progress | `blue` | | Neutral / Inactive | `slate` | ### 3.3 Surface Colors - Card backgrounds: `bg-background` (default card) or `bg-muted/30` (subtle areas like sidebars) - Borders: use `border` (theme token) — never hardcode `border-gray-200` - Text hierarchy: `text-foreground` (primary), `text-muted-foreground` (secondary) --- ## 4. Typography Rules ### 4.1 `text-sm` for Readable Content **Rule:** Use `text-sm` for all body text that users need to read. ```tsx // CORRECT {agent.name}

{description}

{agent.lastActive} ``` ```tsx // WRONG — text-xs for readable body content is too small {agent.name}

{description}

``` ### 4.2 `text-xs` Only for Tiny/Supplementary Elements `text-xs` is acceptable for: - Avatar initials (`AvatarFallback`) - `font-mono` timestamps and IDs - Badge/pill labels (priority, status) - Sidebar group headers (`uppercase tracking-wider`) - Action buttons with h-6 or h-7 (`className="h-6 px-2 text-xs"`) ### 4.3 Never Use Arbitrary Font Sizes ```tsx // WRONG ...

...

...
``` --- ## 5. Tailwind v4 Constraints ### 5.1 No Arbitrary Values Tailwind v4 uses a continuous numeric scale. Arbitrary bracket values are not allowed. ```tsx // WRONG — arbitrary values
``` ```tsx // CORRECT — use the numeric scale
// h-96 = 384px, w-72 = 288px
// 384px — close enough, or max-w-xs / max-w-md
// gap-3.5 = 14px, p-4 = 16px ``` ### 5.2 Numeric Scale Reference ``` h-6 = 24px h-8 = 32px h-10 = 40px h-12 = 48px h-16 = 64px h-20 = 80px h-24 = 96px h-32 = 128px h-48 = 192px h-64 = 256px h-80 = 320px h-96 = 384px gap-1 = 4px gap-2 = 8px gap-3 = 12px gap-4 = 16px gap-5 = 20px gap-6 = 24px p-2 = 8px p-3 = 12px p-4 = 16px p-5 = 20px p-6 = 24px ``` ### 5.3 Use Semantic Width Utilities ```tsx // CORRECT
// 384px
// 448px
// 512px
// 576px
// 672px
// sidebar = 256px
// kanban column = 288px ``` ### 5.4 Responsive Breakpoints Only ```tsx // CORRECT
// WRONG — custom media query
``` --- ## 6. Component Patterns ### 6.1 Card Structure Use `Card > CardHeader + CardContent` for content grouping. ```tsx import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" Section Title {/* content */} ``` ### 6.2 KPI / Stat Cards — py-0 KPI cards use `py-0` on CardContent to let the parent padding control vertical rhythm. ```tsx // CORRECT

Total Agents

42

// WRONG — default py causes too much padding in stat grids ``` ### 6.3 Sidebar Navigation Standard sidebar width is `w-64` (256px), with `bg-muted/30 border-r`. ```tsx ``` ### 6.4 ScrollArea for Overflow Any list that may overflow its container must use `ScrollArea`. ```tsx import { ScrollArea } from "@/components/ui/scroll-area"
{items.map((item) => )}
``` ### 6.5 Badge Variants ```tsx // Status badge (with dot)
Active
// Type badge OpenClaw ``` ### 6.6 Avoid Inline Styles ```tsx // WRONG
// CORRECT
``` --- ## 7. Hydration Safety ### 7.1 Never Use Date in useState Initializer `new Date()`, `Date.now()`, and `toLocaleTimeString()` return different values on the server vs. the client, causing React hydration errors. ```tsx // WRONG — causes "Hydration failed" error const [events, setEvents] = useState(() => [ { id: "1", timestamp: new Date().toLocaleTimeString() }, ]) // WRONG — locale-dependent const [time, setTime] = useState(new Date().toLocaleTimeString()) ``` ```tsx // CORRECT — static strings for initial SSR state const INITIAL_TIMESTAMPS = ["10:30:00", "10:30:04", "10:30:08"] const [events, setEvents] = useState(() => INITIAL_DATA.slice(0, 3).map((e, i) => ({ ...e, id: `init-${i}`, timestamp: INITIAL_TIMESTAMPS[i], })) ) // Live timestamps only inside useEffect / setInterval (client-only) function nowTimeString() { const d = new Date() return [d.getHours(), d.getMinutes(), d.getSeconds()] .map((n) => String(n).padStart(2, "0")) .join(":") } useEffect(() => { const interval = setInterval(() => { setEvents((prev) => [ ...prev, { id: `evt-${Date.now()}`, timestamp: nowTimeString(), ... } ]) }, 2000) return () => clearInterval(interval) }, []) ``` ### 7.2 suppressHydrationWarning for Intentional Mismatches If a mismatch is truly intentional (e.g. a live clock that intentionally differs): ```tsx ``` --- ## 8. Block Authoring Guide ### 8.1 File Structure Every block consists of two files: 1. `registry/creative-tim/blocks/.tsx` — the component 2. `registry/creative-tim/blocks//page.tsx` — the page wrapper The page wrapper simply renders the block: ```tsx import BlockName from "@/registry/creative-tim/blocks/" export default function Page() { return } ``` ### 8.2 Registry Entry Add to `registry/registry-blocks.ts`: ```ts { name: "my-block-01", type: "registry:block", categories: ["my-category"], meta: { isFree: true, label: "My Block", createdAt: "2026-03-14", }, registryDependencies: ["button", "card", "badge"], // SHORT NAMES ONLY files: [ { path: "registry/creative-tim/blocks/my-block-01.tsx", type: "registry:component", }, { path: "registry/creative-tim/blocks/my-block-01/page.tsx", type: "registry:page", target: "app/blocks/my-block-01/page.tsx", }, ], } ``` **IMPORTANT:** `registryDependencies` must use **short names** (`"button"`, `"card"`, `"badge"`) — never full URLs. ### 8.3 After Adding Blocks Rebuild the registry: ```bash pnpm --filter www registry:build ``` This regenerates `public/r/*.json`, `__index__.tsx`, and `__blocks__.json` (which powers `llms.txt`). ### 8.4 Import Paths in Blocks Use the registry alias, not relative paths: ```tsx import { Button } from "@/registry/creative-tim/ui/button" import { Card, CardContent } from "@/registry/creative-tim/ui/card" ``` ### 8.5 Block Checklist Before submitting a new block: - [ ] No `violet` or `purple` colors — use `orange` for brand accent - [ ] All readable text uses `text-sm` minimum - [ ] No arbitrary Tailwind values (`[10px]`, `[85%]`, etc.) - [ ] KPI/stat `CardContent` uses `px-4 py-0` - [ ] No `new Date()` in `useState` initializers - [ ] No inline `style={{}}` attributes - [ ] `registryDependencies` uses short names - [ ] `registry:build` completes without errors