How to Build an Admin Dashboard with Next.js in 2026

typescript dev.to

Why Dashboards Matter for SaaS

Every SaaS product eventually needs an admin dashboard. Whether it's monitoring revenue, tracking active users, or managing customer accounts, dashboards are where data becomes actionable. A well-built dashboard is often the difference between a product that feels professional and one that feels like a prototype.

Yet dashboards are notoriously time-consuming to build from scratch. You need charts that work, tables that sort and filter, a sidebar that collapses on mobile, stat cards that update in real time, and a layout that stays coherent at every screen size. Get any one of these wrong and the whole thing falls apart.

In 2026, Next.js 16 with Tailwind CSS v4 is the strongest foundation for building admin dashboards. Here's how to approach it.

Key Components of a Modern Dashboard

Stat Cards

Stat cards are the first thing users see — a row of KPI tiles showing the numbers that matter most: total revenue, active users, conversion rate, churn. A good stat card includes the current value, a comparison to the previous period, and a trend indicator (up/down arrow with color coding).

\`tsx
interface StatCardProps {
label: string;
value: string;
change: number;
changeLabel: string;
}

export function StatCard({ label, value, change, changeLabel }: StatCardProps) {
const isPositive = change >= 0;
return (


{label}


{value}



{isPositive ? "+" : ""}{change}% {changeLabel}



);
}
`\

Keep stat cards in a 2x2 or 4-column grid on desktop, stacking to a single column on mobile.

Charts

Charts are where most dashboard projects get complicated. You need to choose a library, understand its API, and make it work with your data format.

Choosing a Charting Library: Recharts vs Chart.js vs Tremor

Recharts is the most popular choice for React dashboards. It's built on SVG, composable, and integrates naturally with React's component model. The API is declarative and easy to read.

\`tsx
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from "recharts";

export function RevenueChart({ data }: { data: { date: string; revenue: number }[] }) {
return (








);
}
`\

Chart.js (via react-chartjs-2) is battle-tested and has more chart types, but the API is more imperative and less idiomatic in React. Good for teams coming from a non-React background.

Tremor provides pre-built dashboard components including charts, stat cards, and tables. It's the fastest path to a working dashboard, but less flexible for custom designs.

For most SaaS dashboards, Recharts is the right choice. It's flexible, actively maintained, and the community is large.

Data Tables

Tables are the most common dashboard component and the easiest to get wrong. A production-grade data table needs:

  • Sortable columns (click header to sort, click again to reverse)
  • Pagination (server-side for large datasets, client-side for small ones)
  • Search and filter
  • Row selection for bulk actions
  • Responsive behavior (horizontal scroll or card view on mobile)

Build your table as a generic component that accepts column definitions and row data. This makes it reusable across different sections of the dashboard.

Sidebar

The sidebar is the backbone of your dashboard navigation. In 2026, the standard pattern is:

  • Desktop: Fixed sidebar, 240px wide, with icons and labels
  • Tablet: Collapsible sidebar, icons-only mode
  • Mobile: Off-canvas drawer, triggered by a hamburger menu

\`tsx
"use client";

import { useState } from "react";

export function Sidebar() {
const [collapsed, setCollapsed] = useState(false);

return (

setCollapsed(!collapsed)}>
{collapsed ? "Expand" : "Collapse"}

{/* nav items */}

);
}
`\

Store the collapsed state in localStorage\ so it persists across page loads.

Data Architecture: The Single Data File Pattern

The cleanest approach for dashboard data is a single data file that exports everything the dashboard needs. This keeps your mock data organized and makes it easy to swap in a real API later.

\`ts
// data/dashboard.ts
export const stats = [
{ label: "Total Revenue", value: "$48,295", change: 12.5, changeLabel: "vs last month" },
{ label: "Active Users", value: "2,847", change: 8.2, changeLabel: "vs last month" },
{ label: "Conversion Rate", value: "3.4%", change: -0.6, changeLabel: "vs last month" },
{ label: "Churn Rate", value: "1.2%", change: -0.3, changeLabel: "vs last month" },
];

export const revenueData = [
{ date: "Jan", revenue: 32000 },
{ date: "Feb", revenue: 38000 },
// ...
];

export const recentOrders = [
{ id: "ORD-001", customer: "Alice Johnson", amount: "$299", status: "Paid" },
// ...
];
`\

This pattern works for templates, prototypes, and early-stage products. When you're ready to connect a real API, replace the imports with fetch\ calls — the components don't need to change.

Dark Mode Implementation

Dashboard users are almost universally power users who prefer dark mode. Implement it with CSS variables so the switch is instant and doesn't cause a flash of wrong theme.

\`css
/* globals.css */
@import "tailwindcss";

@theme inline {
--color-background: #ffffff;
--color-foreground: #0f172a;
--color-card: #f8fafc;
--color-border: #e2e8f0;
}

.dark {
--color-background: #0f172a;
--color-foreground: #f8fafc;
--color-card: #1e293b;
--color-border: #334155;
}
`\

Store the preference in localStorage\ and apply the .dark\ class to <html>\ before the first paint to avoid flicker:

\tsx
// app/layout.tsx — inline script runs before React hydrates
const themeScript = \

const theme = localStorage.getItem("theme") ?? "dark";
document.documentElement.classList.toggle("dark", theme === "dark");
`;

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (




{children}

);
}
`\

Responsive Sidebar Patterns

The sidebar needs fundamentally different behavior at different breakpoints:

Large screens (lg+): Persistent sidebar. The main content shifts right when the sidebar is open. Use CSS Grid or Flexbox with a fixed-width sidebar column.

Medium screens (md): Icon-only sidebar. Keep navigation accessible without consuming too much horizontal space.

Small screens (sm and below): Off-canvas drawer. The sidebar slides in from the left over the content. A backdrop overlay closes it when tapped.

\`tsx
// Use Tailwind's responsive prefixes to handle this declaratively

{children}

`\

Getting Started Fast

Building a production-quality admin dashboard from scratch takes weeks. You need to get every component right, handle responsive behavior at every breakpoint, wire up dark mode, and make sure charts look good in both themes.

Craftly's Dashboard template ($39) ships with all of this pre-built: stat cards, Recharts integration, a sortable data table, responsive sidebar with collapse state, and full dark mode. The single data file pattern means you can customize the content without touching the component code.

In the meantime, the patterns above give you everything you need to build your own. Start with the layout and sidebar — get those right and the rest of the components slot in cleanly.

A great admin dashboard isn't about the number of charts or the complexity of the data. It's about making the right numbers immediately visible and actionable. Focus on that, and the technical decisions become clearer.

Browse Craftly's template collection for production-ready Next.js templates built with these patterns from the ground up.


Originally published on Craftly.

Check out our premium templates:

Built with Next.js 16, TypeScript, and Tailwind CSS v4.

Source: dev.to

arrow_back Back to Tutorials