Build a Full-Stack SaaS Dashboard
Build a production-ready SaaS dashboard with authentication, role-based access, charts, and real-time data. The kind of project that gets you hired or funded.
- Planning the dashboard architecture
- Authentication and project setup
- API routes and seed data
- Dashboard UI with charts and KPIs
- Role-based access control
- Deployment and production configuration
- Real-time updates with Server-Sent Events
- Performance optimization
- Data export and reporting
- Iteration and continuous improvement
Planning the dashboard architecture
A SaaS dashboard is the nerve center of a software business. It is where users see their data, manage their account, and get value from your product. Building one teaches you every major web development concept: authentication, authorization, data modeling, API design, state management, and deployment. We will build a project analytics dashboard — imagine a simplified version of Vercel's or Stripe's dashboard. Users sign up, connect their projects, and see metrics like page views, API calls, error rates, and uptime. The dashboard has three user roles: viewer who can see data, editor who can modify settings, and admin who can manage team members. Start by planning the data model. Ask Claude Code: Help me design a database schema for a SaaS analytics dashboard. I need users with roles, organizations that users belong to, projects within organizations, and metrics data including page views, API calls, and errors with timestamps. Use PostgreSQL-compatible types and show the schema as SQL CREATE TABLE statements. Claude Code will produce a relational schema with proper foreign keys, indexes, and constraints. Review the schema before proceeding — the data model is the foundation everything else builds on. A bad schema creates problems that are expensive to fix later. Check that every table has a primary key, relationships use foreign keys, frequently queried columns have indexes, and timestamp columns use timezone-aware types.
Authentication and project setup
Create the project: `mkdir ~/projects/saas-dashboard && cd ~/projects/saas-dashboard && git init && claude`. Tell Claude Code: Create a Next.js 14 App Router project with TypeScript, Tailwind CSS, and the following: NextAuth.js for authentication with GitHub and email providers, Prisma ORM with PostgreSQL, and a dashboard layout with a sidebar navigation. Set up the Prisma schema based on the data model we designed. Create a login page, a registration page, and a protected dashboard route that requires authentication. Claude Code will scaffold a professional project structure. For the database, use a free PostgreSQL instance from Neon at neon.tech or Supabase at supabase.com. Both offer generous free tiers. Copy the connection string and add it to .env as DATABASE_URL. Run the Prisma commands: `npx prisma db push` creates the database tables from your schema. `npx prisma generate` generates the TypeScript client for type-safe database queries. `npx prisma studio` opens a visual database editor in your browser for inspecting data during development. Test authentication by running `npm run dev`, navigating to the login page, and signing in with GitHub. You will need to create a GitHub OAuth app in your GitHub developer settings — tell Claude Code to walk you through this process. After signing in, you should be redirected to the dashboard. Check the database with Prisma Studio and verify your user record was created.
API routes and seed data
The dashboard needs API routes to fetch and manipulate data. Ask Claude Code: Create API routes for the dashboard including GET /api/projects to list user projects, POST /api/projects to create a new project, GET /api/projects/[id]/metrics to get metrics for a project with date range filtering, and PUT /api/projects/[id]/settings to update project settings. All routes should verify authentication, check that the user has access to the requested project, and return proper error responses with correct HTTP status codes. Use Prisma for all database queries. Claude Code will create route handlers in the App Router convention with authentication checks, input validation, and error handling. Each route follows the same pattern: verify the session exists, validate the input parameters, query the database, and return the response with appropriate status codes. For the metrics endpoint, Claude Code should implement date range filtering using query parameters like from and to dates. Also ask Claude Code to create a seed script: Create a seed script at prisma/seed.ts that generates realistic sample data with 3 projects and 90 days of metrics data. Randomize the page view counts, API call counts, and error counts to look realistic with some daily variation. Add a seed command to package.json. Run `npm run seed` to populate the database. This sample data makes development much more productive because you can see how charts and tables look with real-looking data instead of staring at empty states.
Dashboard UI with charts and KPIs
Now build the visual dashboard. Ask Claude Code: Build the main dashboard page at /dashboard. It should show a header with the user name and organization, a sidebar with navigation links for Overview, Projects, Settings, and Team, an overview page with 4 KPI cards showing Total Page Views, API Calls, Error Rate, and Uptime percentage, a line chart showing page views over the last 30 days, a bar chart showing API calls by project, and a table of recent errors with timestamp, project, and error message. Use Recharts for the charts and fetch data from the API routes we created. Claude Code will install recharts and build the dashboard components. For the KPI cards, specify that each should show the current value, the change compared to the previous period as a percentage like +12.5%, and a small sparkline showing the trend. For the charts ask Claude Code to add a gradient fill under the line chart, tooltips on hover showing the exact value and date, and the ability to toggle between 7-day, 30-day, and 90-day views. The bar chart should show each project as a different color with a legend. Add professional touches: loading skeletons that match the layout of each component — skeleton cards for KPIs, a skeleton rectangle for charts, and skeleton rows for the table. Use Tailwind's animate-pulse class for the shimmer effect. Test the dashboard with your seed data. You should see realistic charts and metrics. Verify that date range changes update the charts and the error table is sortable by clicking column headers.
Role-based access control
Not every user should see everything. Implement role-based access control. Ask Claude Code: Add role-based access control to the dashboard. The roles are viewer who can see dashboards and metrics but cannot modify anything, editor who can modify project settings and create new projects, and admin who can manage team members, invite users, and change roles. Create a middleware that checks the user role before allowing access to protected routes. Add a team management page at /dashboard/team that only admins can access. Claude Code will implement RBAC at multiple levels: middleware for page-level access where the team page returns 403 for non-admins, API route checks for action-level access where only editors and admins can POST to /api/projects, and UI-level conditional rendering where non-admins do not see the Team link in the sidebar navigation. The UI should not just hide elements — it should also explain restrictions. If a viewer navigates directly to a restricted URL, they should see a message explaining that they need editor or admin access and suggesting they contact their organization admin. Ask Claude Code to also create an invite system where admins can enter an email address and role to send an invitation. The invited user receives a link, signs up, and is automatically added to the organization with the specified role. Store pending invitations in the database with an expiry date. Test by creating accounts with different roles and verifying that each role can only access and modify what it should.
Deployment and production configuration
Deploy the dashboard to Vercel. First, ensure your environment variables are production-ready. You need DATABASE_URL pointing to your Neon or Supabase production database, NEXTAUTH_SECRET generated with `openssl rand -base64 32`, NEXTAUTH_URL set to your production URL, and GitHub OAuth credentials created as a separate OAuth app for production with the production callback URL. Push to GitHub and connect to Vercel. Add all environment variables in the Vercel dashboard and deploy. Add `prisma generate` to your build script so it runs during deployment: set the build command to `prisma generate && next build`. Run database migrations on the production database. After deployment, verify the complete flow: login works, data loads correctly, charts render with the seeded data, and role-based access is enforced. Ask Claude Code to add a health check endpoint at /api/health that returns the application version, database connection status, and uptime. This endpoint is useful for monitoring and for load balancers that need to verify the application is running. For error tracking in production, consider integrating Sentry which offers a free tier. Tell Claude Code to install the Sentry SDK and configure it for Next.js to capture all unhandled errors in both server and client components. This gives you visibility into production issues before users report them.
Real-time updates with Server-Sent Events
A static dashboard that only updates on page refresh is functional but not impressive. Add real-time updates to make the dashboard feel alive. Ask Claude Code: Add real-time metric updates to the dashboard using Server-Sent Events. When new metrics are recorded, the KPI cards and charts should update without a page refresh. Create an SSE endpoint at /api/metrics/stream that sends updates every 10 seconds. The client should connect to this stream and update the UI smoothly with animated number transitions. Server-Sent Events are simpler than WebSockets and work well for one-directional data flow from server to client. The client connects with an EventSource object, and the server pushes JSON updates through the open connection. Claude Code will create the SSE endpoint and a custom React hook called something like useMetricStream that connects to it and updates component state as new data arrives. For the animated transitions ask Claude Code to animate KPI numbers from the old value to the new value over 500 milliseconds. If the value increased, briefly flash the card border green. If it decreased, flash it red. For the charts, when new data arrives, smoothly extend the line with an animation instead of re-rendering the entire chart component. Test by opening the dashboard and watching the numbers update automatically. The real-time feel transforms the dashboard from a reporting tool into a monitoring tool. This feature alone makes the project feel like a premium product worth showcasing in a portfolio.
Performance optimization
A dashboard that loads slowly is a dashboard nobody uses. Ask Claude Code: Audit the dashboard for performance issues. Check for unnecessary re-renders in React components, large bundle sizes, unoptimized database queries including N+1 problems, missing database indexes, and opportunities for code splitting. Fix everything you find. Claude Code will analyse the codebase and likely find several issues. Common fixes include: adding React.memo to chart components that re-render on every parent state change, using dynamic imports for heavy libraries like recharts with `const Chart = dynamic(() => import('../components/Chart'), { ssr: false })`, adding database indexes on frequently filtered columns like project_id and created_at, and replacing multiple sequential database queries with Prisma includes or joins. Measure before and after with real numbers. Ask Claude Code to add response time logging to the API routes so you can identify the slowest endpoints. For the frontend, open Chrome DevTools, go to the Lighthouse tab, and run an audit. Target a First Contentful Paint under 1.5 seconds, Time to Interactive under 3 seconds, and a Lighthouse performance score above 90. Ask Claude Code to address any specific Lighthouse recommendations. Also check the bundle size: `npx next build` shows the size of each page. If any page is over 200KB, investigate what is making it large and whether code splitting or lazy loading can help.
Data export and reporting
Business users need to get data out of your dashboard and into their workflows. Ask Claude Code: Add a data export feature. Users should be able to export their metrics data as CSV or PDF. The CSV export includes all raw data points with proper headers. The PDF export is a formatted report with the KPI summary, charts rendered as images, and a data table. Add an Export button to the dashboard header with a dropdown for format selection. For CSV generation, Claude Code will create a server-side endpoint that queries the database and streams the CSV as a download. For PDF generation, it will use a library like @react-pdf/renderer to create a formatted document programmatically. Next, add scheduled reports: ask Claude Code to create a scheduled reports feature where users configure a weekly or monthly email report that includes the same content as the PDF export. Store the schedule configuration in the database and use Vercel Cron or a similar service to trigger report generation and email delivery. The email should use well-designed HTML with inline styles because email clients do not support external CSS. Test by triggering a report manually and verifying the CSV opens correctly in Excel, the PDF looks professional with proper formatting, and the email renders properly across Gmail, Outlook, and Apple Mail. These export features transform your dashboard from a viewing tool into a business intelligence platform that delivers value even when users are not logged in.
Iteration and continuous improvement
Your dashboard is deployed, functional, and performant. Now iterate based on how real users would interact with it. Here are common improvement patterns and how to implement them with Claude Code. Navigation improvement: build a command palette triggered by Cmd+K that lets users quickly navigate to any page, search for projects, or trigger actions like Export or Invite Team Member. Use the cmdk library for this. Data management: add pagination to the errors table showing 20 items per page and the projects list showing 10 per page. Add filters for date range, project, and error severity. Mobile experience: redesign the dashboard for mobile viewports. Replace the sidebar with a bottom tab bar. Stack KPI cards vertically. Make charts horizontally scrollable. Onboarding: add an empty state for new users that walks them through creating their first project, connecting data, and understanding the dashboard layout. Accessibility: ensure all interactive elements are keyboard navigable, charts have text alternatives, and color is not the only way to convey information. Each iteration follows the same Claude Code workflow: describe the change clearly, let Claude Code implement it, test the result, commit, and deploy. The dashboard will evolve from a basic metrics viewer into a sophisticated business tool through this process of continuous iteration. This is exactly how real SaaS products are built — not in one heroic effort, but through steady improvement driven by user needs and feedback.
Building AI-Powered Products
This guide is hands-on and practical. The full curriculum covers the conceptual foundations in depth with structured lessons and quizzes.
Go to lesson