Customization

Last updated on 2026-04-05

The NeuralDesk AI Ops Dashboard is designed to be customized for your AI operations platform. All components use design tokens and Tailwind CSS utilities, making brand adaptation straightforward.

Changing Colors

Update CSS custom properties in app/globals.css. The default purple/violet theme uses oklch hue 285. Change the hue to rebrand the entire kit:

:root {
  /* Change from purple (hue 285) to cyan (hue 195) */
  --primary: oklch(0.45 0.2 195);
  --primary-foreground: oklch(0.98 0 0);
  --accent: oklch(0.94 0.02 195);
  --accent-foreground: oklch(0.35 0.15 195);
  --ring: oklch(0.55 0.18 195);
}

.dark {
  --primary: oklch(0.7 0.18 195);
  --primary-foreground: oklch(0.15 0.02 195);
}

All 13 screens automatically inherit the new colors -- buttons, badges, stat cards, charts, sidebar, status indicators, and focus rings all update at once.

Adding Model Providers

The model registry supports any LLM provider. Add new providers by extending the seed data and type definitions:

// types/index.ts
export type ModelProvider = "openai" | "anthropic" | "google" | "meta" | "mistral" | "cohere" | "your-provider"

// data/seed.ts
export const models: Model[] = [
  // ... existing models
  {
    id: "your-model-v1",
    name: "Your Custom Model v1",
    provider: "your-provider",
    type: "chat",
    status: "deployed",
    version: "1.0.0",
    costPerInputToken: 0.000003,
    costPerOutputToken: 0.000015,
    avgLatency: 180,
    // ...
  },
]

Provider logos and colors are configured in the model components. Add your provider's branding in components/models/model-status-badge.tsx.

Modifying Prompt Templates

Customize prompt templates in the seed data or connect to your template storage:

// data/seed.ts
export const promptTemplates: PromptTemplate[] = [
  {
    id: "custom-template",
    name: "Customer Support Agent",
    category: "system",
    content: `You are a helpful customer support agent for {{company_name}}.

Your responsibilities:
- Answer questions about {{product_name}}
- Escalate billing issues to the billing team
- Always be polite and professional

Context: {{context}}`,
    variables: ["company_name", "product_name", "context"],
    model: "gpt-4o",
    // ...
  },
]

Template variables use the {{variable_name}} syntax and are automatically detected by the playground editor.

Connecting to Real LLM APIs

Replace seed data with actual API calls to LLM providers. The kit is designed for easy backend integration:

OpenAI

// app/api/chat/route.ts
import OpenAI from "openai"

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })

export async function POST(req: Request) {
  const { model, messages, temperature, maxTokens } = await req.json()

  const response = await openai.chat.completions.create({
    model,
    messages,
    temperature,
    max_tokens: maxTokens,
  })

  return Response.json({
    content: response.choices[0].message.content,
    usage: response.usage,
    model: response.model,
  })
}

Anthropic

// app/api/chat/route.ts
import Anthropic from "@anthropic-ai/sdk"

const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY })

export async function POST(req: Request) {
  const { model, messages, temperature, maxTokens } = await req.json()

  const response = await anthropic.messages.create({
    model,
    messages,
    temperature,
    max_tokens: maxTokens,
  })

  return Response.json({
    content: response.content[0].text,
    usage: {
      input_tokens: response.usage.input_tokens,
      output_tokens: response.usage.output_tokens,
    },
    model: response.model,
  })
}

Multi-Provider Router

// lib/llm-router.ts
export async function routeToProvider(provider: string, params: LLMParams) {
  switch (provider) {
    case "openai":
      return callOpenAI(params)
    case "anthropic":
      return callAnthropic(params)
    case "google":
      return callGemini(params)
    default:
      throw new Error(`Unknown provider: ${provider}`)
  }
}

Custom Dashboards

Add new dashboard widgets by creating components in components/dashboard/:

// components/dashboard/model-health-widget.tsx
"use client"

import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"

interface ModelHealthWidgetProps {
  models: ModelHealth[]
}

export function ModelHealthWidget({ models }: ModelHealthWidgetProps) {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Model Health</CardTitle>
      </CardHeader>
      <CardContent>
        {models.map((model) => (
          <div key={model.id} className="flex items-center justify-between py-2">
            <span className="text-sm font-medium">{model.name}</span>
            <span className={`text-sm ${model.healthy ? "text-green-600" : "text-destructive"}`}>
              {model.healthy ? "Healthy" : "Degraded"}
            </span>
          </div>
        ))}
      </CardContent>
    </Card>
  )
}

Then add the widget to the dashboard page:

// app/(app)/dashboard/page.tsx
import { ModelHealthWidget } from "@/components/dashboard/model-health-widget"

<ModelHealthWidget models={modelHealthData} />

Customizing the Sidebar

Edit components/layout/app-sidebar.tsx to add or remove navigation items. The sidebar is organized into sections:

const sections = [
  {
    title: "Overview",
    items: [
      { label: "Dashboard", href: "/dashboard", icon: LayoutDashboard },
    ],
  },
  {
    title: "Operations",
    items: [
      { label: "Models", href: "/models", icon: Bot },
      { label: "Prompts", href: "/prompts", icon: MessageSquare },
      { label: "Usage", href: "/usage", icon: BarChart3 },
      { label: "Logs", href: "/logs", icon: ScrollText },
      { label: "Errors", href: "/errors", icon: AlertTriangle },
    ],
  },
  {
    title: "Testing",
    items: [
      { label: "Playground", href: "/playground", icon: Play },
    ],
  },
  {
    title: "Admin",
    items: [
      { label: "Team", href: "/team", icon: Users },
      { label: "Settings", href: "/settings", icon: Settings },
    ],
  },
]

Removing Unused Features

Delete directories you don't need:

  • Don't need the playground? Delete app/(app)/playground/ and components/playground/
  • Don't need error tracking? Delete app/(app)/errors/ and components/errors/
  • Don't need team management? Delete app/(app)/team/ and components/team/
  • Run pnpm build to verify no broken imports

Using shadcn/ui CLI

Add new components alongside the kit:

npx shadcn@latest add <component-name>

Components install to components/ui/ and integrate seamlessly with the existing design tokens. The kit uses shadcn/ui v4 with @base-ui/react.