Customization

Last updated on 2026-05-31

The Trading Dashboard Kit is designed to be customized for your trading platform or investment product. 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 teal theme uses oklch hue 160. Change the hue to rebrand the entire kit:

:root {
  /* Change from teal (hue 160) to indigo (hue 270) */
  --primary: oklch(0.45 0.2 270);
  --primary-foreground: oklch(0.98 0 0);
  --accent: oklch(0.94 0.02 270);
  --accent-foreground: oklch(0.35 0.15 270);
  --ring: oklch(0.55 0.18 270);
}

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

All 39 screens automatically inherit the new colors -- buttons, badges, links, charts, sidebar accents, order form actions, and focus rings all update at once.

Changing Typography

Configure fonts in app/layout.tsx:

import { Inter, DM_Sans, JetBrains_Mono } from "next/font/google";

const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });
const dmSans = DM_Sans({ subsets: ["latin"], variable: "--font-dm-sans" });
const jetbrainsMono = JetBrains_Mono({ subsets: ["latin"], variable: "--font-jetbrains" });

Swap these for any Google Font or local font files. The CSS variables --font-sans, --font-heading, and --font-mono control body text, headings, and code/numbers respectively.

Replacing Seed Data

All mock data lives in data/seed.ts and data/seed-social.ts. Replace with your data source:

Market Data API (e.g., Alpha Vantage, Polygon.io)

import { getQuote } from "@/lib/market-data"

export default async function DashboardPage() {
  const portfolio = await getPortfolio()
  const indices = await getMarketIndices()
  return <Dashboard portfolio={portfolio} indices={indices} />
}

Brokerage API (e.g., Alpaca, Interactive Brokers)

// app/api/portfolio/route.ts
export async function GET() {
  const res = await fetch("https://paper-api.alpaca.markets/v2/positions", {
    headers: {
      "APCA-API-KEY-ID": process.env.ALPACA_KEY_ID!,
      "APCA-API-SECRET-KEY": process.env.ALPACA_SECRET_KEY!,
    },
  })
  const positions = await res.json()
  return Response.json(positions)
}

Database (Prisma, Drizzle)

import { db } from "@/lib/db"

const positions = await db.position.findMany({
  where: { portfolioId: user.portfolioId },
  orderBy: { marketValue: "desc" },
  include: { stock: true },
})

WebSocket for Real-Time Data

// hooks/use-market-stream.ts
import { useEffect, useState } from "react"

export function useMarketStream(tickers: string[]) {
  const [quotes, setQuotes] = useState<Record<string, Quote>>({})

  useEffect(() => {
    const ws = new WebSocket(process.env.NEXT_PUBLIC_WS_URL!)
    ws.onopen = () => ws.send(JSON.stringify({ action: "subscribe", tickers }))
    ws.onmessage = (event) => {
      const data = JSON.parse(event.data)
      setQuotes(prev => ({ ...prev, [data.ticker]: data }))
    }
    return () => ws.close()
  }, [tickers])

  return quotes
}

Extending Components

Use the cn() utility (from lib/utils.ts) to add custom classes without conflicts:

import { Button } from "@/components/ui/button"

<Button className="rounded-full shadow-lg" size="lg">
  Place Order
</Button>

Adding Component Variants

Components use class-variance-authority for variant management:

const badgeVariants = cva("...", {
  variants: {
    variant: {
      default: "...",
      bullish: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200",
      bearish: "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200",
      neutral: "bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200",
    },
  },
})

Customizing the Sidebar

Edit components/layout/sidebar.tsx to add or remove navigation items:

const navItems = [
  { label: "Dashboard", href: "/", icon: LayoutDashboard },
  { label: "Watchlist", href: "/watchlist", icon: Eye },
  { label: "Portfolio", href: "/portfolio", icon: Briefcase },
  { label: "Trading", href: "/trading/order-entry", icon: ArrowLeftRight },
  { label: "Markets", href: "/markets/screener", icon: Globe },
  { label: "Research", href: "/research/detail", icon: Search },
  { label: "Social", href: "/social/feed", icon: Users },
  { label: "Analytics", href: "/analytics/pnl", icon: BarChart3 },
  { label: "Settings", href: "/settings", icon: Settings },
  // Remove items you don't need
  // Add items for new trading pages
]

Each item takes a label, href, and a Lucide icon component. Active state highlighting is handled automatically based on the current pathname.

Customizing the Header

Edit components/layout/app-header.tsx to modify quick actions in the top bar:

  • Search input -- triggers the command palette
  • Notification bell -- links to notifications
  • Theme toggle -- switches between light and dark mode
  • User menu -- dropdown with profile, settings, and sign out

Remove or reorder these actions to fit your trading platform workflow.

Adding New Trading Pages

  1. Create a new route in app/(app)/your-page/page.tsx
  2. The page automatically inherits the app layout (sidebar, header)
  3. Add a sidebar link in components/layout/sidebar.tsx
// app/(app)/alerts/page.tsx
export default function AlertsPage() {
  return (
    <div className="space-y-6">
      <h1 className="font-heading text-2xl font-bold">Price Alerts</h1>
      {/* Your content */}
    </div>
  )
}

Integrating Market Data Providers

Alpha Vantage

// app/api/quotes/route.ts
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const symbol = searchParams.get("symbol")

  const res = await fetch(
    `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${symbol}&apikey=${process.env.ALPHA_VANTAGE_KEY}`
  )
  const data = await res.json()
  return Response.json(data["Global Quote"])
}

Polygon.io

// app/api/quotes/[ticker]/route.ts
export async function GET(request: Request, { params }: { params: { ticker: string } }) {
  const res = await fetch(
    `https://api.polygon.io/v2/aggs/ticker/${params.ticker}/prev?apiKey=${process.env.POLYGON_API_KEY}`
  )
  const data = await res.json()
  return Response.json(data.results[0])
}

Finnhub

// app/api/quotes/[ticker]/route.ts
export async function GET(request: Request, { params }: { params: { ticker: string } }) {
  const res = await fetch(
    `https://finnhub.io/api/v1/quote?symbol=${params.ticker}&token=${process.env.FINNHUB_API_KEY}`
  )
  return Response.json(await res.json())
}

Integrating Brokerage APIs

Alpaca (Paper Trading)

// app/api/orders/route.ts
const ALPACA_BASE = "https://paper-api.alpaca.markets/v2"

export async function POST(request: Request) {
  const body = await request.json()
  const res = await fetch(`${ALPACA_BASE}/orders`, {
    method: "POST",
    headers: {
      "APCA-API-KEY-ID": process.env.ALPACA_KEY_ID!,
      "APCA-API-SECRET-KEY": process.env.ALPACA_SECRET_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      symbol: body.ticker,
      qty: body.quantity,
      side: body.side,
      type: body.type,
      time_in_force: body.timeInForce,
      limit_price: body.limitPrice,
    }),
  })
  return Response.json(await res.json())
}

Interactive Brokers (Client Portal API)

// app/api/ibkr/orders/route.ts
export async function POST(request: Request) {
  const body = await request.json()
  const res = await fetch(`${process.env.IBKR_BASE_URL}/v1/api/iserver/account/${process.env.IBKR_ACCOUNT_ID}/orders`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      orders: [{
        conid: body.contractId,
        orderType: body.type.toUpperCase(),
        side: body.side.toUpperCase(),
        quantity: body.quantity,
        price: body.limitPrice,
        tif: body.timeInForce.toUpperCase(),
      }],
    }),
  })
  return Response.json(await res.json())
}

Removing Unused Features

Delete directories you don't need:

  • Don't need social trading? Delete app/(app)/social/ and components/social/ and data/seed-social.ts
  • Don't need backtesting? Delete app/(app)/analytics/backtesting/ and related components in components/analytics/
  • Don't need options? Delete app/(app)/trading/options/ and components/trading/options-chain-table.tsx
  • Don't need research? Delete app/(app)/research/ and components/research/
  • Don't need settings? Delete app/(app)/settings/ and components/settings/
  • 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 the new-york style with CSS variables enabled.