ワンクリックで
dashboard-patterns
>-
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
>-
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Route complex requests to the right specialist agent or chain of agents. This skill acts as the central brain of an agent swarm — it analyses what the user needs, determines which specialist domain(s) are required, and coordinates parallel or sequential agent execution. Use this skill when a request spans multiple domains (e.g., "research competitors and create a pitch deck"), when you need to decide which specialist should handle an ambiguous request, or when a task requires a multi-step pipeline across different skills. Triggers on: multi-step requests, cross-domain tasks, "coordinate", "plan this out", "I need help with multiple things", or any complex request that touches more than one specialist area. Also triggers when the user seems unsure which tool or approach to use.
>-
Hybrid DAG execution primitive combining deterministic and agentic nodes with hard iteration caps
">"
Act as a brand ambassador — create authentic, platform-specific social media content that embodies a brand's identity and connects with audiences. Use this skill whenever the user asks to "create social media content for a brand", "act as a brand ambassador", "write ambassador posts", "promote [brand] on social media", "create influencer-style content", "write authentic brand content", "social media ambassador", or any request involving representing a brand through social content. Also triggers on "ambassador voice", "brand promotion posts", "influencer content", "authentic brand posts", "UGC-style content", or when someone wants social media content that sounds like a real person recommending a brand rather than corporate marketing copy. Even if the user just says "help me promote [brand]" or "I need content for [brand]'s social channels" — use this skill.
>-
| id | dashboard-patterns |
| name | dashboard-patterns |
| type | skill |
| version | 1.0.0 |
| created | 20/03/2026 |
| modified | 20/03/2026 |
| status | active |
| metadata | {"author":"NodeJS-Starter-V1","version":"1.0.0","locale":"en-AU"} |
| description | >- |
| context | fork |
Codifies the project's existing dashboard architecture: the Status Command Centre component library, backend analytics APIs, and the Scientific Luxury design rules that govern every data surface. Enforces timeline layout, spectral colours, physics-based animations, and Australian locale formatting.
Codifies real-time dashboard patterns for NodeJS-Starter-V1 including the Status Command Centre component library, timeline/orbital layouts, Supabase Realtime integration, spectral colour mapping, and Scientific Luxury design enforcement for all data visualisation surfaces.
metrics-collector instead)email-template instead)structured-logging instead)scientific-luxury instead)grid-cols-2/grid-cols-4 layouts. Use vertical timelines, horizontal data strips, and orbital arrangements.Location: apps/web/components/status-command-centre/
| Category | Components |
|---|---|
| Main | StatusCommandCentre (full/compact/minimal variants) |
| Data Display | DataStrip (horizontal metrics), MetricTile (stat tile with trends) |
| Visualisation | ProgressOrb, ProgressRing, StatusPulse, StatusBadge |
| Activity | AgentNode, AgentActivityCard, ActivityTimeline, AgentThinkingIndicator |
| Utility | NotificationStream, ElapsedTimer |
| Hooks | useElapsedTime, useCountdown, useStatusTransitions, useStatusColourTransition |
| Utils | formatElapsedAU, formatTimestampAU, formatDateAU, getAustralianTimezone |
| Page | Location | Data Source |
|---|---|---|
| Agent Dashboard | apps/web/app/(dashboard)/agents/page.tsx | /api/agents/stats, /api/agents/list |
| Analytics Dashboard | apps/web/app/dashboard-analytics/page.tsx | /api/analytics/metrics/overview |
| Status Command Centre | Embedded component | Supabase Realtime (agent_runs table) |
| Route | Location | Returns |
|---|---|---|
/analytics/metrics/overview | apps/backend/src/api/routes/analytics.py | Runs, success rate, cost, tokens |
/analytics/metrics/agents | Same file | Per-agent performance breakdown |
/analytics/metrics/costs | Same file | Cost by model, token breakdown |
/api/agents/stats | apps/backend/src/api/routes/agent_dashboard.py | Aggregate agent statistics |
/api/agents/{id}/health | Same file | AgentHealthReport model |
/api/agents/performance/trends | Same file | Time-series trend data |
// REJECTED — violates Scientific Luxury and Timeline law
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
<Card>...</Card>
<Card>...</Card>
</div>
The StatusCommandCentre implements a vertical timeline spine with agent nodes:
<div className="relative pl-4">
{/* Vertical Timeline Spine */}
<motion.div
initial={{ scaleY: 0 }}
animate={{ scaleY: 1 }}
transition={{ delay: 0.3, duration: 0.8, ease: [0.19, 1, 0.22, 1] }}
className="absolute top-0 bottom-0 left-8 w-px origin-top
bg-gradient-to-b from-white/10 via-white/5 to-transparent"
/>
{/* Agent Nodes along the spine */}
<div className="space-y-8">
{runs.map((run, index) => (
<AgentNode key={run.id} run={run} index={index} />
))}
</div>
</div>
Replace metric grids with DataStrip — inline horizontal layout with spectral-coloured values:
<DataStrip
metrics={[
{ label: 'Total', value: runs.length },
{ label: 'Active', value: activeRuns.length, variant: 'info' },
{ label: 'Completed', value: completedRuns.length, variant: 'success' },
{ label: 'Failed', value: failedRuns.length, variant: 'error' },
]}
/>
DataStrip uses JetBrains Mono for values, text-[10px] tracking-widest uppercase for labels, pipe separators between metrics, and spectral glow on non-zero highlighted values.
Every AgentRunStatus maps to a spectral colour defined in constants.ts:
| Status | Colour | HSL | Animation |
|---|---|---|---|
pending | Slate | hsl(220 14% 46%) | Pulse (idle) |
in_progress | Blue | hsl(217 91% 60%) | Spin (active) |
awaiting_verification | Amber | hsl(38 92% 50%) | Pulse (active) |
verification_in_progress | Amber | hsl(38 92% 50%) | Spin (active) |
verification_passed | Green | hsl(142 76% 36%) | None (idle) |
verification_failed | Red | hsl(0 84% 60%) | Pulse (urgent) |
completed | Emerald | #00FF88 | None (idle) |
failed | Red | #FF4444 | Pulse (urgent) |
blocked | Slate | Muted | None (idle) |
escalated_to_human | Magenta | #FF00FF | Pulse (urgent) |
Access via getStatusConfig(status) from constants.ts. Each config includes colour (primary, glow, background), icon, animation, and intensity.
DataStrip variants use simplified spectral colours: info=#00F5FF, success=#00FF88, warning=#FFB800, error=#FF4444.
All animations use Framer Motion. CSS transitions are BANNED.
Components animate in sequence with delay offsets:
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 * index, ease: [0.19, 1, 0.22, 1] }}
>
Status indicators use breathing animation for active states:
<motion.span
className="h-1.5 w-1.5 rounded-full"
style={{ backgroundColor: config.colour.primary }}
animate={{ opacity: [1, 0.4, 1], scale: [1, 1.2, 1] }}
transition={{ duration: 2, repeat: Infinity, ease: 'easeInOut' }}
/>
Active agents trigger a radial gradient background glow:
{activeRuns.length > 0 && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 0.1 }}
className="pointer-events-none absolute inset-0"
style={{ background: 'radial-gradient(ellipse at 20% 10%, hsl(217 91% 60% / 0.15) 0%, transparent 50%)' }}
/>
)}
Use useStatusTransitions hook to detect state changes and apply transition animations (success ripple, error shake).
Use Next.js Server Components for initial data fetch with cache: 'no-store':
async function fetchAgentStats() {
const backendUrl = process.env.BACKEND_URL || 'http://localhost:8000';
const res = await fetch(`${backendUrl}/api/agents/stats`, { cache: 'no-store' });
if (!res.ok) return FALLBACK_STATS;
return res.json();
}
Always provide fallback data so the page renders even when the backend is unavailable.
For non-realtime pages, poll at 30-second intervals:
useEffect(() => {
fetchMetrics();
const interval = setInterval(fetchMetrics, 30_000);
return () => clearInterval(interval);
}, []);
For the Status Command Centre, subscribe to agent_runs table changes:
const channel = supabase
.channel('agent-runs')
.on('postgres_changes', { event: '*', schema: 'public', table: 'agent_runs' },
(payload: RealtimePayload) => {
if (payload.eventType === 'INSERT') addRun(payload.new);
if (payload.eventType === 'UPDATE') updateRun(payload.new);
})
.subscribe();
Types RealtimeEvent, RealtimePayload, and ConnectionStatus are defined in types.ts.
Always display connection state using the ConnectionIndicator component:
Every dashboard page must show a skeleton that matches the final layout structure:
function LoadingSkeleton() {
return (
<div className="space-y-8">
<motion.div
className="h-10 w-64 rounded-sm bg-white/5"
animate={{ opacity: [0.5, 1, 0.5] }}
transition={{ duration: 1.5, repeat: Infinity }}
/>
{/* More skeleton elements matching the real layout */}
</div>
);
}
Rules: Use bg-white/5 for skeleton blocks, rounded-sm only, breathing opacity animation, staggered delays per element.
When no data is available, show a centred empty state with a breathing orb:
<div className="flex flex-col items-center justify-center py-20">
<motion.div
className="h-3 w-3 rounded-full bg-white/20"
animate={{ scale: [1, 1.5, 1], opacity: [0.5, 1, 0.5] }}
transition={{ duration: 2, repeat: Infinity, ease: 'easeInOut' }}
/>
<h3 className="text-xl font-light text-white">No Active Agents</h3>
<p className="font-mono text-xs text-white/40">Description text.</p>
</div>
Every dashboard page follows this structure:
// 1. Server Component wrapper (data fetch)
export default async function DashboardPage() {
const data = await fetchData();
return (
<div className="relative min-h-screen bg-[#050505]">
{/* Header */}
<header className="border-b border-white/[0.06] px-8 py-6">
<p className="text-[10px] tracking-[0.3em] text-white/30 uppercase">Category Label</p>
<h1 className="text-4xl font-extralight tracking-tight text-white">Page Title</h1>
<DataStrip metrics={[...]} />
</header>
{/* Content — timeline or orbital, never grid */}
<Suspense fallback={<LoadingSkeleton />}>
<DashboardContent data={data} />
</Suspense>
{/* Footer */}
<footer className="px-8 py-4">
<p className="font-mono text-[10px] text-white/20">
{new Date().toLocaleDateString('en-AU')}
</p>
</footer>
</div>
);
}
| Need | Component | Import From |
|---|---|---|
| Inline metrics row | DataStrip | status-command-centre |
| Single stat with trend | MetricTile | status-command-centre |
| Agent execution status | AgentNode | status-command-centre |
| Circular progress | ProgressOrb or ProgressRing | status-command-centre |
| Status dot | StatusPulse | status-command-centre |
| Status label | StatusBadge | status-command-centre |
| Step timeline | ActivityTimeline | status-command-centre |
| Notification sidebar | NotificationStream | status-command-centre |
| Elapsed time counter | ElapsedTimer | status-command-centre |
| Anti-Pattern | Why It Fails | Correct Approach |
|---|---|---|
grid-cols-2 / grid-cols-4 metric cards | Violates Scientific Luxury layout rules | DataStrip or timeline layout |
Standard <Card> with rounded-lg | Wrong corners, wrong aesthetic | rounded-sm border-[0.5px] border-white/[0.06] |
CSS transition: all 0.3s linear | Banned by Bezier (Council of Logic) | Framer Motion with physics-based easing |
| White/light background dashboards | Violates OLED black requirement | bg-[#050505] always |
| No loading skeleton | Layout shift on data load | Skeleton matching final layout structure |
| No connection indicator | Users cannot tell if data is live | ConnectionIndicator in every realtime page |
| Hardcoded status colours | Drift from spectral palette | getStatusConfig(status).colour |
setInterval without cleanup | Memory leak on unmount | useEffect with clearInterval in cleanup |
bg-[#050505])DataStrip for summary metrics (not metric grid)border-[0.5px] border-white/[0.06])rounded-sm only (no rounded-lg, rounded-xl)metrics-collector MetricsRegistry for data sourceSTATUS_CONFIG constantsformatDateAU, formatTimestampAU)status-command-centre/types.ts[AGENT_ACTIVATED]: Dashboard Patterns
[PHASE]: {Design | Implementation | Review}
[STATUS]: {in_progress | complete}
{dashboard analysis or implementation guidance}
[NEXT_ACTION]: {what to do next}
constants.tsMetricsRegistry provides the data layer (counters, gauges, histograms)DataStrip and MetricTile componentsAgentRunStatus (10 states) maps directly to STATUS_CONFIG colour/animation entriesuseStatusTransitions hook handles state change animationsdashboard_loaded, dashboard_error eventsDataStrip or MetricTileformatDateAU() utilityformatTimeAU() and getAustralianTimezone()total_cost_usd converted to AUD for display