DEV Community

Cover image for Building a SaaS Dashboard UI from Scratch (With Code)
Pixel Mosaic
Pixel Mosaic

Posted on

Building a SaaS Dashboard UI from Scratch (With Code)

Modern SaaS products live and die by their dashboards. A clean, responsive, and intuitive UI can dramatically improve user experience, retention, and perceived value.

In this guide, we’ll build a SaaS dashboard UI from scratch using React + Tailwind CSS, focusing on structure, scalability, and clean design.


Tech Stack

  • React (Vite or Next.js)
  • Tailwind CSS
  • Recharts (for charts)
  • Lucide Icons

Project Structure

src/
 ├── components/
 │   ├── Sidebar.jsx
 │   ├── Header.jsx
 │   ├── StatCard.jsx
 │   ├── ChartCard.jsx
 │   └── Table.jsx
 ├── pages/
 │   └── Dashboard.jsx
 └── App.jsx
Enter fullscreen mode Exit fullscreen mode

Step 1: App Layout

We start with a basic layout: Sidebar + Main Content

// App.jsx
import Dashboard from "./pages/Dashboard";

export default function App() {
  return (
    <div className="flex h-screen bg-gray-100">
      <Dashboard />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Sidebar

// components/Sidebar.jsx
import { Home, BarChart2, Settings } from "lucide-react";

export default function Sidebar() {
  return (
    <div className="w-64 bg-white shadow-lg p-5">
      <h1 className="text-xl font-bold mb-8">SaaSify</h1>

      <nav className="space-y-4">
        <a className="flex items-center gap-2 text-gray-700 hover:text-black">
          <Home size={18} /> Dashboard
        </a>
        <a className="flex items-center gap-2 text-gray-700 hover:text-black">
          <BarChart2 size={18} /> Analytics
        </a>
        <a className="flex items-center gap-2 text-gray-700 hover:text-black">
          <Settings size={18} /> Settings
        </a>
      </nav>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Header

// components/Header.jsx
export default function Header() {
  return (
    <div className="flex justify-between items-center mb-6">
      <h2 className="text-2xl font-semibold">Dashboard</h2>

      <input
        type="text"
        placeholder="Search..."
        className="px-4 py-2 border rounded-lg"
      />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Stat Cards

// components/StatCard.jsx
export default function StatCard({ title, value }) {
  return (
    <div className="bg-white p-5 rounded-2xl shadow">
      <h3 className="text-gray-500">{title}</h3>
      <p className="text-2xl font-bold mt-2">{value}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Chart Component

// components/ChartCard.jsx
import {
  LineChart,
  Line,
  XAxis,
  Tooltip,
  ResponsiveContainer,
} from "recharts";

const data = [
  { name: "Jan", users: 400 },
  { name: "Feb", users: 800 },
  { name: "Mar", users: 650 },
  { name: "Apr", users: 900 },
];

export default function ChartCard() {
  return (
    <div className="bg-white p-5 rounded-2xl shadow">
      <h3 className="mb-4 font-semibold">User Growth</h3>

      <ResponsiveContainer width="100%" height={250}>
        <LineChart data={data}>
          <XAxis dataKey="name" />
          <Tooltip />
          <Line type="monotone" dataKey="users" />
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 6: Table

// components/Table.jsx
const users = [
  { name: "John Doe", email: "john@example.com", plan: "Pro" },
  { name: "Jane Smith", email: "jane@example.com", plan: "Basic" },
];

export default function Table() {
  return (
    <div className="bg-white p-5 rounded-2xl shadow">
      <h3 className="mb-4 font-semibold">Recent Users</h3>

      <table className="w-full text-left">
        <thead>
          <tr className="text-gray-500">
            <th>Name</th>
            <th>Email</th>
            <th>Plan</th>
          </tr>
        </thead>
        <tbody>
          {users.map((user, i) => (
            <tr key={i} className="border-t">
              <td className="py-2">{user.name}</td>
              <td>{user.email}</td>
              <td>{user.plan}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 7: Dashboard Page

// pages/Dashboard.jsx
import Sidebar from "../components/Sidebar";
import Header from "../components/Header";
import StatCard from "../components/StatCard";
import ChartCard from "../components/ChartCard";
import Table from "../components/Table";

export default function Dashboard() {
  return (
    <>
      <Sidebar />

      <div className="flex-1 p-6 overflow-y-auto">
        <Header />

        <div className="grid grid-cols-3 gap-6 mb-6">
          <StatCard title="Revenue" value="$12,400" />
          <StatCard title="Users" value="1,230" />
          <StatCard title="Conversion Rate" value="3.2%" />
        </div>

        <div className="grid grid-cols-2 gap-6 mb-6">
          <ChartCard />
          <Table />
        </div>
      </div>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Design Tips for SaaS Dashboards

  • Use consistent spacing (8px system)
  • Prefer soft shadows & rounded corners
  • Limit color palette (2–3 primary colors)
  • Highlight key metrics with contrast
  • Keep navigation predictable

Bonus Improvements

  • Add dark mode
  • Add authentication pages
  • Connect to real APIs
  • Add filters & date ranges
  • Make it fully responsive

Final Thoughts

Building a SaaS dashboard isn’t about stuffing features—it’s about clarity and usability. Start simple, focus on hierarchy, and iterate based on real user feedback.

If you’re planning to scale this:

  • Introduce a design system
  • Use component libraries (like shadcn/ui)
  • Split logic using hooks/services

Top comments (0)