Blocks are UI components with integrated business logic. Unlike Atoms (pure UI) or Templates (layouts), Blocks include:
| Category | shadcn/ui Equivalent | Description |
|---|---|---|
| UI | shadcn/ui primitives | Radix-based, minimal |
| Atoms | UI Components | 2+ primitives combined |
| Templates | Blocks | Full-page layouts |
| Blocks | Beyond shadcn | UI + Business Logic |
Blocks are sourced from open source (60-80% complete) and adapted to our stack:
Open Source Repo
│
▼
┌─────────────────┐
│ /block add │ ← Fetch from source
└────────┬────────┘
│
▼
┌─────────────────┐
│ Transform │ ← Import paths, styling conventions
└────────┬────────┘
│
▼
┌─────────────────┐
│ Adapt Stack │ ← Auth.js, Prisma/Neon, mirror-pattern
└────────┬────────┘
│
▼
┌─────────────────┐
│ Integrate │ ← Route + Component directories
└────────┬────────┘
│
▼
┌─────────────────┐
│ Validate │ ← TypeScript, i18n, RTL, Audit
└─────────────────┘
/block Command# Add a new block from source
/block github:tanstack/table
/block shadcn:sidebar-07
/block magicui:shimmer-button
# Manage existing blocks
/block list # List all blocks
/block refactor table # Refactor block
/block audit table # Quality audit (100-point)
/block update table # Update from sourceEach block follows the mirror-pattern:
src/app/[lang]/(root)/blocks/{name}/
├── page.tsx # Route entry point
src/components/root/block/{name}/
├── content.tsx # Main composition
├── config.ts # Configuration
├── types.ts # TypeScript types
├── actions.ts # Server actions
├── validation.ts # Zod schemas
└── README.md # Documentation
When mining blocks, we adapt:
| External | Our Stack |
|---|---|
| Clerk, Auth0 | Auth.js (NextAuth v5) |
| MongoDB, Supabase | Prisma + Neon |
| hex/rgb colors | OKLCH theme variables |
| ml/mr margins | ms/me logical properties |
| Block | Description | Route |
|---|---|---|
| Data Table | Advanced table with filtering, sorting, pagination | /blocks/table |
| Block | Description | Route |
|---|---|---|
| Auth | Login, register, forgot password flows | /blocks/auth |
| Block | Description | Route |
|---|---|---|
| Invoice | Invoice generation and management | /blocks/invoice |
Each block is scored on:
| Category | Points | Criteria |
|---|---|---|
| Architecture | 20 | Mirror-pattern, separation of concerns |
| Code Quality | 20 | No any types, error handling |
| Styling | 15 | OKLCH tokens, RTL-compatible |
| i18n | 15 | Strings extracted, Arabic translations |
| Accessibility | 10 | Semantic HTML, ARIA labels |
| Performance | 10 | No blocking renders, lazy loading |
| Security | 5 | Input sanitization, CSRF |
| Documentation | 5 | README, props documented |
Grades:
| Category | Icon | Description |
|---|---|---|
data | Table | Data tables, grids, listings |
auth | Lock | Authentication flows |
payment | CreditCard | Stripe, billing, invoices |
dashboard | LayoutDashboard | Analytics, charts, metrics |
forms | FormInput | Complex form patterns |
marketing | Megaphone | Landing page sections |
# Add block from GitHub
/block github:example/invoice-generator
# The block-processor will:
# 1. Fetch block files
# 2. Transform imports
# 3. Adapt to Auth.js + Prisma
# 4. Create mirror-pattern structure
# 5. Add i18n support
# 6. Run initial audit// src/app/[lang]/(root)/blocks/my-block/page.tsx
import { getDictionary } from "@/components/local/dictionaries"
import type { Locale } from "@/components/local/config"
import MyBlockContent from "@/components/root/block/my-block/content"
interface PageProps {
params: Promise<{ lang: Locale }>
}
export default async function MyBlockPage({ params }: PageProps) {
const { lang } = await params
const dictionary = await getDictionary(lang)
return <MyBlockContent dictionary={dictionary} lang={lang} />
}// src/components/root/block/my-block/content.tsx
import type { getDictionary } from "@/components/local/dictionaries"
import type { Locale } from "@/components/local/config"
interface MyBlockContentProps {
dictionary: Awaited<ReturnType<typeof getDictionary>>
lang: Locale
}
export default function MyBlockContent({ dictionary, lang }: MyBlockContentProps) {
return (
<div dir={lang === 'ar' ? 'rtl' : 'ltr'}>
{/* Block content */}
</div>
)
}// src/components/root/block/my-block/config.ts
export const myBlockConfig = {
id: "my-block",
name: "My Block",
description: "Description of what this block does",
category: "forms",
version: "1.0.0",
}// ~/.claude/memory/block.json
{
"blocks": [
{
"id": "my-block",
"name": "My Block",
"source": "internal",
"route": "/blocks/my-block",
"component": "src/components/root/block/my-block",
"category": "forms",
"status": "active"
}
]
}Use /block refactor <name> to improve existing blocks:
/block refactor tableThis will:
any)Blocks should reuse existing codebase infrastructure:
// Use existing Auth.js integration
import { currentUser } from "@/lib/auth"
import { useCurrentUser } from "@/components/auth/use-current-user"// Use existing Prisma client
import { db } from "@/lib/db"
// Follow multi-file schema pattern
// prisma/models/invoice.prisma// Use existing shadcn/ui components
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
// Use existing atoms
import { StatCard } from "@/components/atom/stat-card"// Use existing templates for layouts
import Sidebar01 from "@/components/template/sidebar-01"
import Header01 from "@/components/template/header-01"Always create both route and component directories:
app/[lang]/(root)/blocks/{name}/components/root/block/{name}/Extract all user-facing strings from the start:
// Good
<h1>{dictionary.blocks.invoice.title}</h1>
// Bad
<h1>Invoice Generator</h1>Use logical properties:
// Good
className="ms-4 me-2 text-start"
// Bad
className="ml-4 mr-2 text-left"No any types, full TypeScript coverage:
// Good
interface InvoiceItem {
id: string
description: string
quantity: number
price: number
}
// Bad
const items: any[] = []Use server actions for mutations:
// src/components/root/block/invoice/actions.ts
"use server"
import { db } from "@/lib/db"
import { currentUser } from "@/lib/auth"
export async function createInvoice(data: InvoiceFormData) {
const user = await currentUser()
if (!user) throw new Error("Unauthorized")
return db.invoice.create({ data: { ...data, userId: user.id } })
}Block metadata is stored in ~/.claude/memory/block.json:
{
"blocks": [
{
"id": "table",
"name": "Data Table",
"source": "internal:tablecn",
"route": "/blocks/table",
"component": "src/components/tablecn",
"category": "data",
"status": "active",
"auditScore": 85,
"stack": { "auth": false, "prisma": true, "i18n": true }
}
],
"categories": { "data": { "icon": "Table", "count": 1 } },
"preferences": { "defaultAuth": "authjs", "defaultDB": "prisma-neon" }
}On This Page
BlocksWhat are Blocks?Component HierarchyMining WorkflowUsing/block CommandBlock StructureStack AdaptationAvailable BlocksData BlocksAuthentication BlocksPayment BlocksQuality Audit (100 points)Block CategoriesCreating a New BlockFrom External SourceManual CreationRefactoring BlocksReusing InfrastructureAuthenticationDatabaseUI ComponentsTemplatesBest Practices1. Mirror-Pattern Structure2. i18n First3. RTL Support4. Type Safety5. Server ActionsMemory & RegistryRelated Documentation