con un clic
dashboard-patterns
Create dashboard pages and features following established patterns
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Create dashboard pages and features following established patterns
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
Use when a conversation is getting long, drifting, juggling multiple tasks, re-pasting the same files, or showing stale/confused context — and at the start of any new task. Triggers: long thread, context bloat, topic switch, repeated file uploads, 'why is it forgetting', degraded answers, finished one task and starting another.
Use when a user wants to deconstruct a complex problem, business challenge, product decision, strategy question, career crossroads, or stuck situation by stripping assumptions, identifying first principles, rebuilding options from foundational truths, and choosing one high-leverage action.
Audit role-based access control and permission drift across product surfaces.
Add a new feature to an existing @fabrk/* package following monorepo conventions
Build or rebuild the ADR index and dependency graph in AgentDB
Query AgentDB with semantic routing, hierarchical recall, causal graphs, and context synthesis
| name | dashboard-patterns |
| description | Create dashboard pages and features following established patterns |
| license | MIT |
| compatibility | Claude Code |
| metadata | {"author":"indx.sh","version":"1.0","project":"indx-web"} |
| allowed-tools | ["Read","Write","Edit","Glob"] |
Use when creating or modifying dashboard pages. Invoke this skill when:
All dashboard pages MUST use the UserDashboardTemplate:
import { UserDashboardTemplate } from '@/components/templates/user-dashboard-template';
export default function DashboardSavedPage() {
return (
<UserDashboardTemplate
title="Saved Items"
description="Your bookmarked rules and MCP servers"
user={user}
headerActions={<Button>> MANAGE</Button>}
>
{/* Dashboard content */}
</UserDashboardTemplate>
);
}
Display metrics at the top of dashboard:
import { KPICard } from '@/components/ui/kpi-card';
<div className="grid grid-cols-2 gap-4 md:grid-cols-4">
<KPICard
title="Total Views"
value={stats.views.toLocaleString()}
trend={{ value: 12, direction: 'up' }}
/>
<KPICard
title="Total Copies"
value={stats.copies.toLocaleString()}
trend={{ value: 5, direction: 'up' }}
/>
<KPICard
title="Rules"
value={stats.rules}
/>
<KPICard
title="MCP Servers"
value={stats.mcps}
/>
</div>
Use DataTable component with toolbar for lists:
import { DataTable } from '@/components/ui/data-table/data-table';
<DataTable
columns={columns}
data={items}
searchKey="title"
searchPlaceholder="Search saved items..."
filterColumn="type"
filterOptions={[
{ label: 'All', value: 'all' },
{ label: 'Rules', value: 'rule' },
{ label: 'MCP Servers', value: 'mcp' },
]}
pageSize={10}
/>
Always provide helpful empty states:
import { EmptyState } from '@/components/ui/empty-state';
{items.length === 0 ? (
<EmptyState
icon={<Bookmark className="h-12 w-12" />}
title="No Saved Items"
description="Items you save will appear here for quick access"
action={
<Button asChild>
<Link href="/rules">> BROWSE RULES</Link>
</Button>
}
/>
) : (
<DataTable ... />
)}
For tables with selection:
import { DataTableBulkActions } from '@/components/ui/data-table/data-table-bulk-actions';
<DataTableBulkActions
selectedCount={selectedRows.length}
onUnsave={() => handleBulkUnsave(selectedRows)}
onExport={() => handleExport(selectedRows)}
onDelete={() => handleBulkDelete(selectedRows)}
/>
'use client';
export default function DashboardSavedPage() {
const [items, setItems] = React.useState<SavedItem[]>([]);
const [isLoading, setIsLoading] = React.useState(true);
React.useEffect(() => {
async function fetchSaved() {
try {
const response = await fetch('/api/user/bookmarks');
const data = await response.json();
setItems(data.bookmarks);
} catch (error) {
console.error('Failed to fetch:', error);
} finally {
setIsLoading(false);
}
}
fetchSaved();
}, []);
if (isLoading) {
return <DashboardSkeleton />;
}
return (/* ... */);
}
// page.tsx (Server Component)
import { auth } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { DashboardSavedClient } from './client';
export default async function DashboardSavedPage() {
const session = await auth();
if (!session?.user) redirect('/login');
const bookmarks = await prisma.bookmark.findMany({
where: { userId: session.user.id },
include: { rule: true, mcpServer: true },
orderBy: { createdAt: 'desc' },
});
return <DashboardSavedClient items={bookmarks} />;
}
Always show loading skeletons:
import { Skeleton } from '@/components/ui/skeleton';
function DashboardSkeleton() {
return (
<div className="space-y-6">
{/* KPI Skeleton */}
<div className="grid grid-cols-2 gap-4 md:grid-cols-4">
{[...Array(4)].map((_, i) => (
<Skeleton key={i} className="h-24" />
))}
</div>
{/* Table Skeleton */}
<div className="space-y-2">
<Skeleton className="h-10" />
{[...Array(5)].map((_, i) => (
<Skeleton key={i} className="h-16" />
))}
</div>
</div>
);
}
space-y-6gap-4space-y-2// KPI cards
mode.color.bg.surface
mode.color.border.default
// Trends
mode.color.text.success // Positive trend
mode.color.text.danger // Negative trend
// Table
mode.color.bg.muted // Zebra striping
// Dashboard title
mode.typography.display.lg
// KPI values
mode.typography.headline.lg
// KPI labels
mode.typography.label.md
src/app/(platform)/dashboard/
├── page.tsx # Main dashboard (KPIs, recent activity)
├── saved/
│ └── page.tsx # Bookmarked items
├── submissions/
│ └── page.tsx # User's submitted content
├── history/
│ └── page.tsx # Recently viewed
└── analytics/
└── page.tsx # Detailed analytics/charts
src/app/api/user/
├── bookmarks/route.ts # GET, POST, DELETE
├── submissions/route.ts # GET
├── history/route.ts # GET
└── analytics/route.ts # GET (stats, charts data)
For analytics pages, use chart components:
import { LineChart } from '@/components/ui/line-chart';
import { BarChart } from '@/components/ui/bar-chart';
<LineChart
data={viewsData}
categories={['Views', 'Copies']}
index="date"
title="Activity Over Time"
/>