admin-dashboard
Admin & Developer Suite Development
This skill helps you extend the admin dashboard and build internal tools following the established patterns.
Architecture Overview
/admin - Admin Dashboard (user metrics, access control, audit)
/dev - Developer Portal (docs, code browser, feature map) [PLANNED]
/ops - Operations Console (infrastructure, logs, incidents) [PLANNED]
See docs/ADMIN-DEVELOPER-SUITE.md for the full design specification.
Current Admin Dashboard Structure
Location: src/app/admin/page.tsx
Existing Tabs
| Tab | Purpose | Data Source |
|---|---|---|
| Overview | Quick stats (users, check-ins, messages) | /api/admin/stats |
| Funnel | User engagement waterfall | /api/admin/stats |
| Page Views | Analytics by page path | /api/admin/stats |
| Users | User roster with activity | /api/admin/stats |
| Access Requests | Pending/approved/denied requests | /api/admin/access-requests |
| Allowed Emails | Email whitelist management | /api/admin/allowed-emails |
| Email Templates | Preview system emails | Local data |
Planned Tabs (from design)
| Tab | Purpose | Status |
|---|---|---|
| Production Health | API latency, Core Web Vitals | Pending |
| Error Tracking | HIPAA-safe error aggregation | Pending |
| External Services | Anthropic, DB, Push status | Pending |
| AI Analytics | Conversation metrics, tokens | Pending |
| Audit Logs | HIPAA compliance viewer | Pending |
Adding a New Admin Tab
1. Create the Tab Content Component
// In src/app/admin/page.tsx, add a new tab component
function ProductionHealthTab() {
const [metrics, setMetrics] = useState<APIMetrics | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchMetrics() {
const res = await fetch('/api/admin/metrics');
const data = await res.json();
setMetrics(data);
setLoading(false);
}
fetchMetrics();
}, []);
if (loading) return <div>Loading...</div>;
return (
<div className="space-y-6">
<div className="grid grid-cols-4 gap-4">
<StatCard label="Uptime" value={metrics.uptime} />
<StatCard label="Avg Latency" value={`${metrics.avgLatency}ms`} />
<StatCard label="Errors (24h)" value={metrics.errorCount} />
<StatCard label="Active Users" value={metrics.activeUsers} />
</div>
{/* More content */}
</div>
);
}
2. Add the Tab to the Tab List
const tabs = [
{ id: 'overview', label: 'Overview' },
{ id: 'health', label: 'Production Health' }, // NEW
{ id: 'funnel', label: 'Funnel' },
// ...
];
3. Add the Tab Content Renderer
function renderTabContent(tabId: string) {
switch (tabId) {
case 'overview':
return <OverviewTab stats={stats} />;
case 'health':
return <ProductionHealthTab />; // NEW
// ...
}
}
Creating Admin API Endpoints
Pattern: Admin Stats Endpoint
// src/app/api/admin/metrics/route.ts
import { requireAdmin } from '@/db/secure-db';
import { createRateLimiter } from '@/lib/rate-limit';
import { logAdminAction } from '@/lib/hipaa/audit';
const rateLimiter = createRateLimiter({
windowMs: 60000,
maxRequests: 60,
keyPrefix: 'admin:metrics'
});
export async function GET(request: Request) {
// 1. Check admin access
const admin = await requireAdmin();
if (!admin) {
return Response.json({ error: 'Forbidden' }, { status: 403 });
}
// 2. Apply rate limiting
const rateLimitResult = await rateLimiter.check(admin.id);
if (!rateLimitResult.allowed) {
return Response.json(
{ error: 'Rate limit exceeded' },
{ status: 429, headers: rateLimitResult.headers }
);
}
// 3. Log admin action
await logAdminAction(
admin.id,
AuditAction.ADMIN_STATS_VIEW,
'metrics',
null
);
// 4. Fetch and return data
const metrics = await getAPIMetrics();
return Response.json(metrics);
}
Key Patterns
StatCard Component
function StatCard({
label,
value,
trend,
status
}: {
label: string;
value: string | number;
trend?: 'up' | 'down' | 'neutral';
status?: 'good' | 'warning' | 'error';
}) {
return (
<div className="rounded-lg border bg-card p-4">
<div className="text-sm text-muted-foreground">{label}</div>
<div className="text-2xl font-bold">{value}</div>
{trend && <TrendIndicator direction={trend} />}
{status && <StatusBadge status={status} />}
</div>
);
}
Data Fetching Pattern
// Use SWR or React Query for real-time updates
import useSWR from 'swr';
function useAdminMetrics() {
const { data, error, isLoading } = useSWR(
'/api/admin/metrics',
fetcher,
{ refreshInterval: 30000 } // Refresh every 30s
);
return { metrics: data, error, isLoading };
}
HIPAA-Safe Error Display
// Never show user-specific error details
function ErrorList({ errors }: { errors: AggregatedError[] }) {
return (
<div>
{errors.map(error => (
<div key={error.hash}>
<span className="font-mono">{error.type}</span>
<span>{error.path}</span>
<span>{error.count} occurrences</span>
<span>{error.affectedUsers} users</span>
{/* NO user IDs, NO error messages with PHI */}
</div>
))}
</div>
);
}
Database Tables for Admin Features
Existing tables:
adminUsers- Admin role assignmentsallowedEmails- Email whitelistaccessRequests- Access request queueauditLog- HIPAA audit trailpageViews- Navigation analytics
Planned tables (from design):
api_metrics- API timing dataapp_errors- Aggregated errorsservice_health- External service statusconversation_analytics- AI chat metadataincidents- Incident tracking
Access Control
// Always use requireAdmin() for admin routes
import { requireAdmin } from '@/db/secure-db';
// For super-admin only features
const admin = await requireAdmin();
if (admin.role !== 'super_admin') {
return Response.json({ error: 'Super admin required' }, { status: 403 });
}
Testing Admin Features
// Mock admin authentication for tests
vi.mock('@/db/secure-db', () => ({
requireAdmin: vi.fn().mockResolvedValue({
id: 'test-admin',
role: 'admin'
})
}));
describe('Admin Metrics Endpoint', () => {
it('returns metrics for authenticated admin', async () => {
const response = await GET(mockRequest);
expect(response.status).toBe(200);
});
it('returns 403 for non-admin', async () => {
vi.mocked(requireAdmin).mockResolvedValueOnce(null);
const response = await GET(mockRequest);
expect(response.status).toBe(403);
});
});
Design Resources
- Full design spec:
docs/ADMIN-DEVELOPER-SUITE.md - Design system: Use existing components from
src/components/ui/ - Colors: Follow therapeutic palette (navy, teal, coral, cream)
More from curiositech/windags-skills
kleppmann-data-intensive
Comprehensive guide to designing reliable, scalable data systems covering databases, streaming, and consistency
3beautiful-cli-design
|
2next-move
>
1color-contrast-auditor
Detects and fixes color contrast violations using WCAG 2.1 guidelines and perceptual analysis. Expert in contrast ratio calculation, color blindness simulation, and providing accessible alternatives. Activate on "check contrast", "color accessibility", "WCAG audit", "readability check", "contrast ratio", "hard to read", "can't see text". NOT for general color theory (use color-theory-palette-harmony-expert), brand color selection (use web-design-expert), or non-visual accessibility (use ux-friction-analyzer).
1web-design-expert
Creates unique web designs with brand identity, color palettes, typography, and modern UI/UX patterns. Use for brand identity development, visual design systems, layout composition, and responsive web design. Activate on "web design", "brand identity", "color palette", "UI design", "visual design", "layout". NOT for typography details (use typography-expert), color theory deep-dives (use color-theory-expert), design system tokens (use design-system-creator), or code implementation without design direction.
1rust-tauri-development
Expert Tauri v2 developer for building desktop apps with Rust backend and web frontend. Activate on: Tauri app, Tauri v2, Rust desktop app, IPC commands, tauri::command, tauri.conf.json, Tauri plugin, WebviewWindow, system tray Tauri, Tauri multi-window. NOT for: Electron apps (use cross-platform-desktop), code signing/distribution (use rust-app-distribution), pure Rust CLI tools (use rust-expert).
1