diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9005b5d..9bca006 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,14 +14,14 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: - version: 8 + version: 9.15.9 - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: "pnpm" - name: Install dependencies diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6f01eed..e577c70 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,28 +6,32 @@ Thank you for your interest in contributing to Agent Patterns! This document pro 1. Fork the repository 2. Clone your fork: `git clone https://github.com/harshmathurx/agent-patterns.git` -3. Install dependencies: `pnpm install` -4. Create a new branch: `git checkout -b feature/your-feature-name` +3. Enable Corepack: `corepack enable` +4. Install dependencies: `corepack pnpm install` +5. Create a new branch: `git checkout -b feature/your-feature-name` ## Development ### Running Locally ```bash +# Enable the pinned package manager +corepack enable + # Install dependencies -pnpm install +corepack pnpm install # Run playground -cd apps/playground && pnpm dev +cd apps/playground && corepack pnpm dev # Run tests -pnpm test +corepack pnpm test # Type check -pnpm typecheck +corepack pnpm typecheck # Lint -pnpm lint +corepack pnpm lint ``` ## Adding a New Pattern diff --git a/README.md b/README.md index b90e6e7..523b34e 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,21 @@ # Agent Patterns -![Agent Patterns Hero](https://via.placeholder.com/1200x400/1a1a1a/ffffff?text=Agent+Patterns+%7C+15+Copy-Paste+UI+Components+for+AI+Apps) +> shadcn-style UI patterns that agents can actually use correctly. -> Copy-paste UI patterns optimized for AI code generation. - -Beautiful, production-ready React components designed for LLM code generation. Each pattern has a Zod schema that AI models understand. No dependencies, just copy and paste. +Agent Patterns is 15 copy-paste agent UI patterns for React apps: dashboards, task queues, chat artifacts, forms, tables, timelines, and the Zod schemas agents need to generate valid props instead of hallucinated UI glue. --- ## πŸš€ Quick Start ```bash -# 1. Copy a pattern into your project -npx agent-patterns@latest add metric-card +# 1. Make sure this repo uses the pinned pnpm version +corepack enable + +# 2. Copy a pattern into your project +corepack pnpm dlx @agent-patterns/cli add metric-card -# 2. Use it in your code +# 3. Use it in your code import { MetricCard } from '@/patterns/metric-card/component' ``` -That's it. No npm install, no version conflicts, no build config. +That's it. Own the code. No black-box runtime dependency, no version conflicts, no build config. --- @@ -52,6 +53,18 @@ That's it. No npm install, no version conflicts, no build config. --- +## Stealable Examples + +Start with a complete surface instead of assembling patterns from scratch: + +- **Analytics dashboard** β€” metrics, chart, accounts table, and prioritized AI insights. +- **Agent inbox / task queue** β€” kanban triage, task detail, timeline, and human handoff. +- **AI chat with artifacts + actions** β€” chat messages, generated code, confirmation flows, and command actions. + +See [`docs/STEALABLE_EXAMPLES.md`](docs/STEALABLE_EXAMPLES.md) for copy-paste React examples. + +--- + ## πŸ€– Built for AI Code Generation Every pattern has an LLM-optimized Zod schema: @@ -79,11 +92,11 @@ const props = metricCardSchema.parse({ ## ✨ Why Agent Patterns? -### 1. **Zero Dependencies** -No npm install. No version conflicts. No build config. Just copy the component file and use it. +### 1. **Agent-native props** +Every pattern includes a Zod schema with field descriptions, variants, defaults, and validation boundaries. Agents get a constrained interface instead of guessing JSX. -### 2. **LLM-First Design** -Zod schemas with detailed descriptions that AI models understand. Your LLM generates valid props automatically. +### 2. **Prompt packs included** +Use the bundled system prompt and build prompts to make Cursor, Claude, ChatGPT, or v0 select the right pattern and emit valid props. ### 3. **Production Ready** Not toy examples. Real components with: @@ -122,60 +135,21 @@ Own your code. Modify freely. No black-box libraries. No "ejecting." --- -## πŸ—οΈ Example: Build a Dashboard in 60 Seconds +## Launch Kit -```typescript -import { StatsGrid } from '@/patterns/stats-grid/component' -import { Chart } from '@/patterns/chart/component' -import { DataTable } from '@/patterns/data-table/component' - -export default function Dashboard() { - return ( -
- {/* 4 Key Metrics */} - - - {/* Revenue Trend */} - - - {/* Transactions Table */} - -
- ) -} -``` +This repo is meant to work as a clean proof-of-work artifact: + +- one-line wedge: `shadcn-style UI patterns that agents can actually use correctly` +- resume bullet: [`docs/LAUNCH_KIT.md`](docs/LAUNCH_KIT.md#resume-bullet) +- 45-second demo script: [`docs/LAUNCH_KIT.md`](docs/LAUNCH_KIT.md#45-second-demo-script) +- launch copy draft: [`docs/LAUNCH_KIT.md`](docs/LAUNCH_KIT.md#launch-copy-draft) --- ## πŸ“š Documentation +- **[Stealable Examples](docs/STEALABLE_EXAMPLES.md)** β€” Analytics dashboard, agent inbox, and chat-with-artifacts examples +- **[Launch Kit](docs/LAUNCH_KIT.md)** β€” Resume bullet, demo script, and launch copy - **[Pattern Index](prompts/pattern-index.md)** β€” Complete schema reference for all 15 patterns - **[System Prompt](prompts/system-prompt.md)** β€” Use with Cursor, Claude, ChatGPT - **[Build Guides](prompts/)** β€” Example prompts for common layouts diff --git a/apps/playground/src/app/globals.css b/apps/playground/src/app/globals.css index 586874d..d36e21c 100644 --- a/apps/playground/src/app/globals.css +++ b/apps/playground/src/app/globals.css @@ -55,6 +55,7 @@ } body { @apply bg-background text-foreground; + font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; } } diff --git a/apps/playground/src/app/landing.tsx b/apps/playground/src/app/landing.tsx index 925981b..d45fbe3 100644 --- a/apps/playground/src/app/landing.tsx +++ b/apps/playground/src/app/landing.tsx @@ -6,6 +6,7 @@ import { HeroAnimation } from "@/components/hero-animation" import { PatternGallery } from "@/components/pattern-gallery" import { ThemeShowcase } from "@/components/theme-showcase" import { AIDemoZeroTokens } from "@/components/ai-demo-zero-tokens" +import { LaunchDemos } from "@/components/launch-demos" import Link from "next/link" export default function NewLandingPage() { @@ -44,13 +45,16 @@ export default function NewLandingPage() { Home + + Examples + Patterns Demo - + Playground @@ -58,7 +62,7 @@ export default function NewLandingPage() {
- Copy-paste UI patterns designed for LLM generation + shadcn-style UI patterns that agents can actually use correctly

@@ -91,19 +95,19 @@ export default function NewLandingPage() {

- Production-ready React components with LLM-optimized Zod schemas. - Build AI-powered UIs that work with any agent framework. + 15 copy-paste agent UI patterns for React apps: dashboards, task queues, + chat artifacts, forms, tables, timelines, and the schemas agents need to use them correctly.

- Browse Patterns β†’ + Steal the examples β†’ + {/* Launch Demos */} + + {/* Pattern Gallery */}
@@ -209,13 +216,13 @@ export default function NewLandingPage() {

Try the Playground β†’

- Built by developers, for developers. Open source and free to use. + Built for developers shipping agent interfaces. Open source and free to use.

diff --git a/apps/playground/src/app/layout.tsx b/apps/playground/src/app/layout.tsx index c6df792..886cf49 100644 --- a/apps/playground/src/app/layout.tsx +++ b/apps/playground/src/app/layout.tsx @@ -1,10 +1,7 @@ import type { Metadata } from "next" -import { Inter } from "next/font/google" import "./globals.css" import { ToastProvider } from "@/components/ui/toast" -const inter = Inter({ subsets: ["latin"] }) - export const metadata: Metadata = { title: "Agent Patterns - Playground", description: "Interactive playground for Agent Patterns", @@ -17,7 +14,7 @@ export default function RootLayout({ }) { return ( - + {children} diff --git a/apps/playground/src/components/launch-demos.tsx b/apps/playground/src/components/launch-demos.tsx new file mode 100644 index 0000000..ddaea59 --- /dev/null +++ b/apps/playground/src/components/launch-demos.tsx @@ -0,0 +1,120 @@ +const demos = [ + { + title: "Analytics dashboard", + promise: "KPI cards, charts, table rows, and AI insights in one copy-paste surface.", + patterns: ["MetricCard", "Chart", "DataTable", "InsightsList"], + preview: [ + { label: "Revenue", value: "$128.4K", meta: "+18%" }, + { label: "Pipeline", value: "$2.4M", meta: "42 deals" }, + { label: "Expansion", value: "31%", meta: "high confidence" }, + ], + code: `const dashboard = { + metrics: revenueMetrics, + chart: pipelineTrend, + table: accountRows, + insights: aiGeneratedInsights, +}`, + }, + { + title: "Agent inbox / task queue", + promise: "Turn agent work into an ops surface: triage, owners, status, timeline.", + patterns: ["KanbanBoard", "DetailCard", "Timeline", "AgentForm"], + preview: [ + { label: "New", value: "7", meta: "needs triage" }, + { label: "Running", value: "3", meta: "agent active" }, + { label: "Blocked", value: "1", meta: "human review" }, + ], + code: `const task = { + title: "Review failed webhook", + priority: "urgent", + owner: "ops-agent", + nextAction: "assign_human", +}`, + }, + { + title: "AI chat with artifacts + actions", + promise: "Chat is not enough. Render generated SQL, decisions, and risky actions beside it.", + patterns: ["ChatMessage", "CodeBlock", "ConfirmDialog", "CommandPalette"], + preview: [ + { label: "Artifact", value: "SQL", meta: "copyable" }, + { label: "Action", value: "Run", meta: "confirmed" }, + { label: "Trace", value: "4 steps", meta: "visible" }, + ], + code: `const artifact = { + type: "sql", + file: "churn-risk.sql", + action: "run_after_confirm", +}`, + }, +] + +export function LaunchDemos() { + return ( +
+
+
+

+ Stealable examples +

+

+ Start from a real agent UI, not a blank canvas. +

+

+ Three launch-ready compositions show how the 15 patterns combine into dashboards, + ops queues, and chat surfaces developers can copy into React apps. +

+
+ +
+ {demos.map((demo) => ( +
+
+

+ {demo.title} +

+

{demo.promise}

+
+ +
+ {demo.preview.map((item) => ( +
+
+

+ {item.label} +

+

{item.value}

+
+ + {item.meta} + +
+ ))} +
+ +
+ {demo.patterns.map((pattern) => ( + + {pattern} + + ))} +
+ +
+                {demo.code}
+              
+
+ ))} +
+
+
+ ) +} diff --git a/docs/LAUNCH_KIT.md b/docs/LAUNCH_KIT.md new file mode 100644 index 0000000..61ca980 --- /dev/null +++ b/docs/LAUNCH_KIT.md @@ -0,0 +1,40 @@ +# Launch Kit + +Agent Patterns is a proof-of-work OSS artifact, not a startup launch. The goal is to make the idea easy to understand, easy to steal from, and easy to cite on a resume. + +## One-line positioning + +> shadcn-style UI patterns that agents can actually use correctly. + +## Short description + +15 copy-paste agent UI patterns for React apps: dashboards, task queues, chat artifacts, forms, tables, timelines, and Zod schemas that keep LLM-generated props valid. + +## Resume bullet + +Built Agent Patterns, an open-source React pattern library for agentic UIs with 15 copy-paste components, Zod schemas, CLI tooling, and prompt packs for reliable LLM-generated interfaces. + +## 45-second demo script + +1. Open with the wedge: β€œAgents are good at text, bad at UI glue. Agent Patterns gives them constrained, copy-paste UI patterns.” +2. Show the landing page and the three stealable examples: analytics dashboard, agent inbox, chat with artifacts/actions. +3. Open a pattern directory and show the component, schema, example, and README living together. +4. Run the local checks: `corepack pnpm test -- --run` and `corepack pnpm build`. +5. Close with the portfolio line: β€œThis is not a startup. It is proof I can turn an AI-native product idea into a shippable OSS artifact.” + +## Launch loop + +- Record a 45-second screen capture of the landing page + examples + one pattern directory. +- Post a short X/LinkedIn launch note with the one-line wedge and repo link. +- Add the resume bullet under Projects / Open Source. +- Use the examples as screenshots in portfolio/resume material. + +## Launch copy draft + +Built Agent Patterns: shadcn-style UI patterns that agents can actually use correctly. + +It is 15 copy-paste React patterns for agentic apps: analytics dashboards, task queues, chat artifacts, forms, tables, timelines, and more. + +Each pattern ships with the component, example, README, and Zod schema so an LLM has a constrained interface instead of hallucinating props. + +Not a startup. Just a clean OSS proof-of-work artifact. diff --git a/docs/STEALABLE_EXAMPLES.md b/docs/STEALABLE_EXAMPLES.md new file mode 100644 index 0000000..49a6250 --- /dev/null +++ b/docs/STEALABLE_EXAMPLES.md @@ -0,0 +1,175 @@ +# Stealable Agent UI Examples + +These examples are intentionally small enough to paste into a React app, then expand with your own data and actions. + +## 1. Analytics Dashboard + +Use this when an agent needs to explain metrics, highlight risks, and hand off a table of records. + +```tsx +import { MetricCard } from "@/patterns/metric-card/component" +import { Chart } from "@/patterns/chart/component" +import { DataTable, type Column } from "@/patterns/data-table/component" +import { InsightsList } from "@/patterns/insights-list/component" + +type AccountRow = Record & { + account: string + plan: string + mrr: number + risk: string +} + +const columns: Column[] = [ + { key: "account", header: "Account", sortable: true }, + { key: "plan", header: "Plan", sortable: true }, + { key: "mrr", header: "MRR", accessor: (row) => `$${row.mrr.toLocaleString()}` }, + { key: "risk", header: "Risk" }, +] + +export function AnalyticsDashboardExample() { + return ( +
+
+ + + +
+ + + + + + +
+ ) +} +``` + +## 2. Agent Inbox / Task Queue + +Use this when background agents create work that humans need to triage, approve, or unblock. + +```tsx +import { KanbanBoard } from "@/patterns/kanban-board/component" +import { DetailCard } from "@/patterns/detail-card/component" +import { Timeline } from "@/patterns/timeline/component" + +export function AgentInboxExample() { + return ( +
+ { + console.log({ cardId, fromColumn, toColumn }) + }} + /> + +
+ + +
+
+ ) +} +``` + +## 3. AI Chat With Artifacts + Actions + +Use this when the chat assistant produces durable artifacts and high-risk actions. + +```tsx +import { useState } from "react" +import { ChatMessage } from "@/patterns/chat-message/component" +import { CodeBlock } from "@/patterns/code-block/component" +import { ConfirmDialog } from "@/patterns/confirm-dialog/component" + +export function ChatArtifactsExample() { + const [confirmOpen, setConfirmOpen] = useState(false) + + return ( +
+ + setConfirmOpen(true) }]} + /> + + 0.82\norder by churn_score desc;`} + showLineNumbers + copyable + /> + + setConfirmOpen(false)} + onCancel={() => setConfirmOpen(false)} + /> +
+ ) +} +``` diff --git a/package.json b/package.json index 0e1a289..3b47b2b 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,13 @@ "private": true, "description": "Open-source, copy-paste pattern library for LLM-generated UIs", "scripts": { - "build": "pnpm -r build", - "dev": "pnpm -r --parallel dev", - "test": "vitest", - "test:coverage": "vitest --coverage", + "build": "corepack pnpm -r build", + "dev": "corepack pnpm -r --parallel dev", + "test": "NODE_ENV=test vitest", + "test:coverage": "NODE_ENV=test vitest --coverage", "lint": "eslint .", "typecheck": "tsc --noEmit --strict", - "clean": "pnpm -r clean && rm -rf node_modules" + "clean": "corepack pnpm -r clean && rm -rf node_modules" }, "devDependencies": { "@testing-library/react": "^14.1.2", @@ -26,8 +26,8 @@ "vitest": "^1.2.0" }, "engines": { - "node": ">=18.0.0", - "pnpm": ">=8.0.0" - } + "node": ">=20.0.0", + "pnpm": ">=9.0.0" + }, + "packageManager": "pnpm@9.15.9" } - diff --git a/packages/cli/package.json b/packages/cli/package.json index 3caefa4..6d95033 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -11,8 +11,7 @@ "scripts": { "build": "tsc", "dev": "tsc --watch", - "clean": "rm -rf dist", - "prepare": "tsc" + "clean": "rm -rf dist" }, "dependencies": { "commander": "^11.1.0", diff --git a/packages/cli/src/commands/audit.ts b/packages/cli/src/commands/audit.ts index 21b8293..cdaca9e 100644 --- a/packages/cli/src/commands/audit.ts +++ b/packages/cli/src/commands/audit.ts @@ -159,7 +159,7 @@ export function printAuditReport(report: AuditReport, verbose: boolean = false): : report.overall.status === "partial" ? chalk.yellow : report.overall.status === "needs-improvement" - ? chalk.orange + ? chalk.hex("#f97316") : chalk.red console.log(chalk.bold("Overall Compliance:")) @@ -210,7 +210,7 @@ export function printAuditReport(report: AuditReport, verbose: boolean = false): : pattern.overallStatus === "partial" ? chalk.yellow : pattern.overallStatus === "needs-improvement" - ? chalk.orange + ? chalk.hex("#f97316") : chalk.red console.log(chalk.bold(` ${pattern.pattern}:`)) @@ -256,7 +256,7 @@ export function printAuditReport(report: AuditReport, verbose: boolean = false): : pattern.overallStatus === "partial" ? chalk.yellow : pattern.overallStatus === "needs-improvement" - ? chalk.orange + ? chalk.hex("#f97316") : chalk.red const statusIcon = @@ -290,7 +290,7 @@ export function printAuditReport(report: AuditReport, verbose: boolean = false): function getComplianceColor(compliance: number): (text: string) => string { if (compliance >= 90) return chalk.green if (compliance >= 70) return chalk.yellow - if (compliance >= 50) return chalk.orange + if (compliance >= 50) return chalk.hex("#f97316") return chalk.red } diff --git a/patterns/agent-form/component.tsx b/patterns/agent-form/component.tsx index fdb1710..aaa2371 100644 --- a/patterns/agent-form/component.tsx +++ b/patterns/agent-form/component.tsx @@ -10,7 +10,7 @@ export interface FormField { required?: boolean options?: { label: string; value: string }[] defaultValue?: string | number | boolean - validation?: z.ZodType + validation?: z.ZodType description?: string } @@ -20,7 +20,7 @@ export interface AgentFormProps extends Omit) => void | Promise submitLabel?: string - schema?: z.ZodObject + schema?: z.ZodObject showValidationErrors?: boolean } diff --git a/patterns/chart/component.tsx b/patterns/chart/component.tsx index 75549c7..84d169f 100644 --- a/patterns/chart/component.tsx +++ b/patterns/chart/component.tsx @@ -33,6 +33,16 @@ export interface ChartProps extends React.HTMLAttributes { colors?: string[] } +interface TooltipPayload { + name?: React.ReactNode + value?: React.ReactNode +} + +interface CustomTooltipProps { + active?: boolean + payload?: TooltipPayload[] +} + const DEFAULT_COLORS = [ "hsl(var(--primary))", "hsl(var(--chart-2))", @@ -66,13 +76,14 @@ export const Chart = React.forwardRef( })) // Custom tooltip - const CustomTooltip = ({ active, payload }: any) => { - if (active && payload && payload.length) { + const CustomTooltip = ({ active, payload }: CustomTooltipProps) => { + const firstItem = payload?.[0] + if (active && firstItem) { return (
-

{payload[0].name}

+

{firstItem.name}

- Value: {payload[0].value} + Value: {firstItem.value}

) diff --git a/patterns/code-block/component.tsx b/patterns/code-block/component.tsx index 8e0dfb3..d41fe44 100644 --- a/patterns/code-block/component.tsx +++ b/patterns/code-block/component.tsx @@ -39,7 +39,7 @@ export function CodeBlock({ setTimeout(() => setCopied(false), 2000) } - const languageColors = { + const languageColors: Record = { typescript: "text-blue-400", javascript: "text-yellow-400", python: "text-green-400", @@ -49,7 +49,7 @@ export function CodeBlock({ default: "text-purple-400", } - const languageColor = (languageColors as any)[language] || languageColors.default + const languageColor = languageColors[language] || languageColors.default return (
diff --git a/patterns/detail-card/component.tsx b/patterns/detail-card/component.tsx index ae4b4f8..d20573c 100644 --- a/patterns/detail-card/component.tsx +++ b/patterns/detail-card/component.tsx @@ -18,7 +18,7 @@ export interface DetailCardProps extends React.HTMLAttributes { fields: DetailField[] actions?: React.ReactNode editable?: boolean - onEdit?: (fields: Record) => void + onEdit?: (fields: Record) => void loading?: boolean } @@ -38,7 +38,7 @@ export const DetailCard = React.forwardRef( ref ) => { const [isEditing, setIsEditing] = React.useState(false) - const [editValues, setEditValues] = React.useState>({}) + const [editValues, setEditValues] = React.useState>({}) const [copiedField, setCopiedField] = React.useState(null) const handleCopy = async (text: string, label: string) => { @@ -53,7 +53,7 @@ export const DetailCard = React.forwardRef( const handleEditStart = () => { // Initialize edit values with current field values - const initialValues: Record = {} + const initialValues: Record = {} fields.forEach((field) => { if (typeof field.value === "string" || typeof field.value === "number") { initialValues[field.label] = field.value diff --git a/vitest.config.ts b/vitest.config.ts index c58aa96..6d9ed12 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -5,6 +5,7 @@ export default defineConfig({ test: { globals: true, environment: "jsdom", + setupFiles: ["./vitest.setup.ts"], coverage: { provider: "v8", reporter: ["text", "json", "html"], diff --git a/vitest.setup.ts b/vitest.setup.ts new file mode 100644 index 0000000..b9e7622 --- /dev/null +++ b/vitest.setup.ts @@ -0,0 +1 @@ +import "@testing-library/jest-dom/vitest"