Build and Deploy a Client Portal With Claude Code

Build a secure client portal with private projects, updates, files, and requests, then deploy it live on Hostinger.

Roadmap & Resources

Plan Your Client Portal

Choose What Your Portal Includes

Open an empty folder — or your existing project — in Claude Code. The lists start with every common option: remove what you don't need, add anything missing, then copy the prompt.

Build Your Client Portal Interface

Choose what clients see and do and what you manage, and Claude Code builds the whole portal interface with realistic sample content.

Build the interface for a client portal for my business. This task builds the screens only, with realistic sample content. Sign-in and real data come later. Business: {{BUSINESS_TYPE}} Portal name: {{PORTAL_NAME}} Visual style: {{VISUAL_STYLE}} What clients can see: {{CLIENT_VIEW}} What clients can do: {{CLIENT_ACTIONS}} What I manage from my business dashboard: {{OWNER_MANAGES}} 1. INSPECT FIRST Inspect this folder before changing anything. - If it is empty, create a new React + Vite + TypeScript project here, with client-side routing and a simple, well-organised structure. - If a project already exists, keep its framework, styling and components, and add the portal to it. Do not rebuild, rename or restructure working code, and do not touch unrelated pages. Tell me which case applies, then continue. 2. SAVE THE PORTAL SCOPE Add a "Client portal" section to CLAUDE.md in the project root — create the file if it does not exist. Record the business, the portal name, the visual style, what clients can see, what clients can do, what I manage, and the project statuses you choose. Every later task reads this section, so keep it short and accurate. Never write keys or passwords into it. 3. BUILD ONLY WHAT I CHOSE Build exactly the features listed above. Do not add anything I did not list — no invoices, payments, chat, team members, notifications or calendar. If two choices conflict or one is unclear, ask me before building it. 4. THE CLIENT SIDE Build what one signed-in client sees: - a sign-in screen — the design only, it does not need to work yet - a home screen listing this client's own projects - a project page that brings together everything clients can see — only the items I listed - clear empty states, such as a project with no updates yet A client only ever sees their own projects. Design it that way from the start. 5. MY BUSINESS DASHBOARD Build a separate owner area for running the business day to day, covering only what I manage: - an overview of what needs my attention, such as new requests and projects due soon — no vanity metrics, fake statistics or charts - a client list, and a client page with that client's projects - a project list, and a project page where I manage everything I listed - the forms I will use, such as new client, new project and post an update The forms can stay local for now. Never pretend that something was saved. 6. PROJECT STATUSES Choose a short, fixed list of project statuses that fits this business — for example Planning → In progress → In review → Completed for an agency. No free-text statuses. 7. SAMPLE CONTENT Use realistic sample content for this business: two or three clients, a few projects at different statuses, and believable updates, file names, dates and requests. No lorem ipsum. Keep all sample content in ONE clearly named module, separate from the components, so real data can replace it later. 8. PREVIEW SWITCH Until real sign-in exists, add one small, clearly labelled switch between the client side and the business dashboard. Keep it in one place so it is easy to remove. 9. DESIGN Apply the visual style and the portal name. The portal must work well on phones, tablets and desktops — clients often open it on a phone. Keep it calm and practical: no marketing hero, no decorative gradients or glows, no fake analytics and no stock-photo filler. It should feel like a tool a real business uses every day. 10. RUN IT Start the development server and give me the local address. When finished, report: - whether you created a new project or extended an existing one - the client screens and the owner screens - the project statuses you chose - where the sample content lives - anything you did not build, and why

What kind of business is this portal for?

What is your portal called?

North Studio

Which visual style fits your brand?

What should clients see?

What can clients do?

What will you manage from your dashboard?

Claude Code saves your choices in the project's CLAUDE.md file, so every later prompt builds only what you picked.

Check the Portal Interface

Open the local address Claude Code gives you and use the preview switch to look at both sides:

The client side lists projects and opens a project page

The business dashboard shows your clients, their projects and your forms

Only the features you chose appear

The sample content fits your business

Both sides work at phone width

Ask Claude Code for any change now — the interface is easiest to adjust before real data arrives.

Expected result

You should now have a complete client-portal interface running locally with realistic sample content.

Add the Real Backend

Connect Supabase

If this project is already connected to the right Supabase project, reuse it — don't create a second one.

Open Supabase

https://supabase.link/r4gdwhi

Create a new project if you don't have one Open the project's Connect panel Copy the Project URL and the Publishable key Ask Claude Code which environment variable names this project uses, then add both values locally

IMPORTANT

The browser app only needs the Project URL and the Publishable key. A Secret key belongs only in a trusted server environment, and only where one is genuinely needed — never in browser code and never committed to GitHub.

Create Your Test Accounts

Create four accounts: one for you with your real email address — it becomes the owner — and three test clients: Client A, Client B and Client C.

Supabase Authentication Users

Click Add user, then Create new user Enter the email address and a password Keep Auto Confirm User on, then create the user Repeat until all four accounts exist

Use email addresses you control for the test clients. Client C stays unconnected until you connect it from your business dashboard.

Add Sign-In and Real Data

Use this prompt in Claude Code. It gives you one SQL block to review and run.

Add the Real Backend

Add sign-in, the owner and client roles, and the tables for your chosen features, then replace the sample content with real data.

Turn the client portal into a real app with Supabase: real accounts, two roles and real data. Read the "Client portal" section of CLAUDE.md first. It lists what this portal includes — build only that. Inspect the project first. If it is already connected to Supabase, reuse that project and its client — do not create a second one. Use the current Supabase terms: the Project URL and the Publishable key. Never put a Secret or service-role key in browser code, and never print secret values. 1. ENVIRONMENT Read the Project URL and the Publishable key from environment variables, using this framework's naming. Tell me the exact names, list them in .env.example without values, and make sure .env is git-ignored. 2. SIGN-IN Add email and password sign-in, sign-out, and a sign-up screen clients use to create their account, with Supabase Auth. Protect every portal and dashboard route: a signed-out visitor goes to sign-in. Remove the preview switch. From now on, the signed-in account decides what appears. 3. TWO ROLES: OWNER AND CLIENT This portal has exactly two kinds of account: the owner (me) and clients. Do not build a general roles-and-permissions system. - Store the role in a profiles table keyed by the auth user id. Create a profile automatically for every new account, with the role client, and backfill profiles for the accounts that already exist. - Nobody can change their own role. Never decide the role from user_metadata, local storage, the URL or anything else the browser controls. - Make MY account the owner with ONE reviewed SQL statement — never through sign-up or the app. 4. CLIENTS AND ACCOUNTS A client is the business I work for; a client account is the login that belongs to it. - Connect each client to ONE account by the account's user id. Never match email addresses at runtime. - An account that is not connected to a client sees only a friendly "Your account is waiting for access" screen, and no data at all. 5. DATA MODEL Create the smallest set of tables for exactly the features in CLAUDE.md — for example clients, projects, milestones, updates, files, requests and comments, but only the ones it lists. - Store the project statuses from CLAUDE.md as constrained values. - Every row that belongs to a client carries its client id, directly or through its project. - Use generated ids, never names or emails, as identifiers. 6. FILES Only if CLAUDE.md includes files: create a PRIVATE Storage bucket — never a public one — and a files table for names and details. Store each file under a path that starts with its client id. Do not seed file rows without a real file; files arrive by upload later. 7. ACCESS RULES FROM THE START Turn on Row Level Security on every new table immediately, with no access for signed-out visitors. For now add only the read rules this task needs: the owner can read everything, and a connected client can read their own client record and the rows that belong to it. Use one trusted database check for "is this account the owner" and one for "which client is this account connected to". The next task completes and tests every rule. 8. REAL DATA Replace the sample content with real queries, and remove the sample-content module. Give me ONE reviewed SQL seed that recreates that sample content in Supabase and connects my test accounts by user id: Client A to one sample client, Client B to another. Leave Client C unconnected. Ask me for the four test accounts' email addresses — never their passwords. Show loading, empty and error states, and never show raw database errors. Give me: 1. The environment variable names 2. The tables and what each holds 3. How the owner role is stored and protected 4. How client accounts are connected 5. The read rules added now 6. ONE reviewed SQL block to run in the Supabase SQL Editor: the tables, the rules, the private bucket if needed, the profile backfill, the owner statement and the seed 7. Anything that blocks the next step Do not use destructive DROP statements. If a table with the same name already exists, warn me instead of replacing it. Do not connect the create and edit forms yet — they come after the access rules are complete.

Review the SQL, then run it in your Supabase project. It creates the tables, makes your account the owner, and connects Client A and Client B to two sample clients.

Supabase SQL Editor

Owner: sign in and see every sample client in the business dashboard

Client A: sign in and see only their own projects

Client C: sign in and see only the waiting screen

Refresh a page — you stay signed in and the data reloads

Expected result

Your owner account and a test client can sign in, and each loads real data from Supabase.

Make Every Client's Portal Private

Lock Down Every Client's Data

Make Every Client's Portal Private

Complete the access rules so each client reaches only their own projects, updates, files and requests, and only you reach the business dashboard.

Make every client's portal private. Read the "Client portal" section of CLAUDE.md first, and cover every feature it lists. The rule: a client can only ever reach their own client record and what belongs to it. It must hold no matter what the browser does — an edited URL, a changed id, a modified request, changed JavaScript, stored browser state or a direct call to Supabase with the Publishable key. The database decides, not the interface. A filter such as .eq('client_id', …) in the app is a convenience, never the protection. 1. OWNER ACCESS The owner's access comes from the trusted owner check in the database, never from a frontend check such as if (user.role === 'admin'). The owner can read and manage every client, project and related row. 2. CLIENT READS A connected client can read only their own client record, their own projects and the rows that belong to those projects. An unconnected or signed-out account can read nothing. 3. CLIENT WRITES Clients may create only what CLAUDE.md lets them do — such as requests, comments or file uploads — and only on their own projects. - The client id and the author come from the signed-in account, never from values the browser sends. - Clients cannot change statuses, progress, dates, other clients' rows or anything the owner manages. - Clients cannot edit or delete what the owner created. Everything else is owner-only. 4. TRUSTED CHECKS Keep the owner check and the "which client is this account" lookup as SECURITY DEFINER functions with a fixed search_path, and make sure neither can be used to read another account's data. No view or function may bypass these rules. 5. ACCOUNTS Nobody can change their own role or connect themselves to a client. Only the owner connects accounts. 6. PRIVATE FILES Only if CLAUDE.md includes files: - The bucket stays private. Never make it public to make downloads easier. - The owner can upload, read, replace and delete any client file. - A client can read only files under their own client id path. Only if clients can upload, they can add new files there — never replace or delete a file, and never write to another client's path. - Downloads use short-lived signed URLs that expire within a few minutes, created only for files the signed-in account may read. - Set a sensible file size limit, and check the type and size before upload. Give me: 1. Every rule, table by table: who can read, create, change and delete 2. The Storage rules 3. How signed URLs are created 4. ONE reviewed SQL block to run in the Supabase SQL Editor Never drop tables, columns or data. Replacing an earlier policy is fine — name each one you replace.

Review the SQL, then run it in the SQL Editor.

IMPORTANT

A hidden button or a filtered list is not privacy. The rules have to live in Supabase — otherwise anyone who changes one id in a link can open another client's projects and files.

Test Client A and Client B

Use two browsers — or a normal and a private window — so both clients stay signed in:

Client A: sign in and open one of their projects

Client B: sign in — none of Client A's projects appear

Client B: paste the address of Client A's project — nothing of Client A's appears

Client C: sign in — only the waiting screen appears

Prove Each Client's Data Is Private

Test the privacy rules directly in Supabase as Client A, Client B, an unconnected account and a signed-out visitor.

Prove that each client's data is private, directly at the Supabase level — not through the interface. Read the "Client portal" section of CLAUDE.md first, and test only the features it lists. Use a temporary LOCAL-ONLY script that uses the project's normal Supabase client with the Publishable key. Do NOT use the Secret or service-role key: it skips every access rule, so the test would prove nothing. Ask me to put the test accounts' passwords in local, uncommitted environment variables. Never commit passwords, never put them in source code and never print them. If the portal includes files and none exist yet, upload one small test file to a Client A project as the owner first, and delete it at the end. 1. AS CLIENT B, try to: - read Client A's client record, projects, milestones, updates, files and requests, including by their exact ids - create a request or comment on Client A's project - create a row that claims Client A's client id - change a project's status, progress or dates - change their own role, or connect their account to Client A - list, download, upload to, replace or delete anything under Client A's file path - create a signed URL for one of Client A's files Expected: refused — an error, no rows returned or zero rows changed. Re-read afterwards to confirm nothing changed. 2. AS CLIENT A: read their own projects and do one allowed client action. Expected: it works. 3. AS CLIENT C, who is not connected: read anything. Expected: nothing. 4. SIGNED OUT: repeat a few reads. Expected: nothing. 5. AS THE OWNER: read every client's projects. Expected: it works. Use test data only. Remove the script afterwards and do not commit it. Report expected versus actual for every test, then return exactly one: PORTAL PRIVATE or: NEEDS ATTENTION If NEEDS ATTENTION, give me the corrected SQL to run, and test again once I confirm it has run.

Continue when Claude Code reports PORTAL PRIVATE. If it reports NEEDS ATTENTION, run the corrected SQL it gives you and let it test again.

Expected result

Two different clients can sign in, but each sees only their own projects, files, updates, and requests.

Build the Business Dashboard

Manage Clients and Projects

Build the Business Dashboard

Create and manage clients, connect their accounts, and run every project from your own dashboard instead of Supabase.

Make my business dashboard fully working for clients and projects. I must never need the Supabase dashboard to run the business day to day. Read the "Client portal" section of CLAUDE.md first, and build only what it lists. Reuse the owner screens you already built. Every write goes through the access rules we just tested, so owner actions are enforced in the database. No Secret or service-role key in the app. 1. OWNER ONLY Only the owner account reaches the dashboard. Any other account sees a "no access" page, and the database refuses its requests anyway. 2. OVERVIEW Show what needs my attention: new client requests, projects due soon and recently updated projects. No vanity metrics, fake statistics or charts. 3. CLIENTS - Create a client and edit their details. - Connect a client account: I enter the email address the client signed up with, and an owner-only database function finds that CONFIRMED account and stores its user id. Never connect an unconfirmed account, and never connect one account to two clients. If no confirmed account exists yet, say so clearly. - Show whether each client is connected or still waiting for an account. - Disconnect an account, for example when a client relationship ends. It loses access immediately. - Open a client to see their details and active projects. - Delete a client only after a clear confirmation. It removes their projects and everything in them, including stored files. 4. PROJECTS - Create a project and assign it to a client. - Edit the name, description and dates. - Change the status, using the fixed statuses in CLAUDE.md. - Set progress — or derive it from milestones if CLAUDE.md includes them — and manage the milestones. - Mark a project completed. The client can still see the finished work. 5. FORMS Validate required fields, prevent double submission, show clear success and error messages, and never show raw database errors. Keep every screen usable on a tablet and a phone. When finished, report: - the owner routes - how the owner check works in the app and in the database - how an account is connected and disconnected - what each project field changes on the client side

Then sign in as the owner and check:

Create a new client

Connect Client C's account to it

Create a project for that client and set its status and dates

Client C: sign in and see the new project

Client A and Client B: still see only their own projects

Share Updates, Files and Requests

Share Updates, Files and Requests

Post updates, share private files and handle requests, and give each client one clear page for each project.

Finish the portal: the updates, files and requests I share with clients, and the client project page that brings everything together. Read the "Client portal" section of CLAUDE.md first. Build only the features it lists, and skip any part below that it does not include. Every read and write goes through the access rules we already tested. No Secret or service-role key in the app. 1. UPDATES I post an update on a project: a short message, shown with its date. The client sees the newest first. Only I can edit or delete an update. 2. FILES I upload files to a project, and I can delete them. If clients can upload, they can add files to their own projects too. - Upload into the private bucket under the client's path, and record each file in the files table. - Download through short-lived signed URLs. Never create public file links. - Show the name, size, date and who uploaded it. - Handle a failed or oversized upload with a clear message. 3. REQUESTS Keep requests lightweight — this is not a ticket system. A client sends a request about a project, with a subject and a message. I see new requests on the overview, can add one reply, and move each request Open → In progress → Done. The client sees the status and my reply. 4. COMMENTS If clients can comment, add a simple comment thread on each project, visible only to that client and me. 5. MILESTONES AND IMPORTANT DATES Show them on the project page if CLAUDE.md includes them. 6. THE CLIENT PROJECT PAGE Bring everything together on one clear project page: status, progress, milestones, important dates, the latest updates, files and requests — only what CLAUDE.md lists. Put the newest and most important information first, and make it work well on a phone. 7. CHANGES REACH THE RIGHT CLIENT When I change a project, that client sees the change the next time the page loads. Real-time updates are not needed. When finished, report: - what I can now share - what each client can see and do - how files are uploaded and downloaded - how requests move between Open, In progress and Done

Then test with the owner account and Client A. Skip any check for a feature your portal doesn't include.

Owner: post an update on a Client A project

Owner: upload a file to the same project

Client A: see the update and download the file

Client A: send a request

Owner: reply to the request and mark it Done

Client B: none of it appears

Expected result

When you update a project, the right client sees the change — and no other client does.

Test the Complete Client Experience

Test the Owner and Client Experience

Use the owner account and Client A in two browsers. Skip any check for a feature your portal doesn't include.

Owner: sign in and land on the business dashboard

Owner: the overview shows new requests and projects due soon

Owner: create a client and edit their details

Owner: the client list shows who is connected and who is still waiting

Owner: create a project for Client A

Owner: change its status, progress and dates

Owner: post an update on it

Owner: upload a file to it

Owner: answer a request and mark it Done

Client A: sign in and see only their own projects

Client A: the new project shows the right status, progress and dates

Client A: read the latest update

Client A: download the file

Client A: upload a file or add a comment, if your portal allows it

Client A: send a request, then see your reply and the Done status

Client A: a completed project still shows the finished work

Test Privacy and Everyday Use

Now sign in as Client B and Client C, then run the everyday checks:

Client B: none of Client A's projects, files, updates or requests appear

Client B: opening a Client A project link shows nothing of Client A's

Client B: changing an id in the address bar reveals nothing

Client B: the business dashboard is refused, even by typing its address

Owner: disconnect Client C — after a refresh, Client C sees only the waiting screen

Signed out: every portal and dashboard page asks you to sign in

A copied file download link stops working after a few minutes

Everything you saved is still there after a refresh

The client side works well on a phone

The business dashboard is usable on a tablet and a phone

A client with no projects yet sees a clear empty state

Errors show a clear message, such as an upload that's too large

Sign out, then press Back — no private page reappears

The portal name, style and project statuses match what you chose

Fix What Failed

List the checks that failed, and Claude Code fixes only those real problems without redesigning the portal.

I tested the whole client portal by hand. Read the "Client portal" section of CLAUDE.md first. These checks failed: {{FAILED_CHECKS}} 1. FIX WHAT FAILED Find the real cause of each failure and fix it at its source. Keep every fix as small as possible — no redesign, no new features and no rewrites of working code. 2. CHECK PRIVACY AGAIN After any change that touches data, access rules or files, run the Client A and Client B privacy tests again at the Supabase level, with the Publishable key — never the Secret or service-role key. 3. CLEAN UP Make sure no preview switch, test-only script, hard-coded sample content or debug logging of client data is left in the app. Return exactly one: PORTAL READY or: NEEDS ATTENTION If NEEDS ATTENTION, list only what still fails.

Which checks failed?

Client A could not download the file. The dashboard overview is hard to use on a phone...

Expected result

The owner and multiple clients can use the portal safely without seeing or changing each other's private data.

Deploy the Client Portal to Hostinger

Prepare and Deploy the Portal

Prepare the Portal for Production

Build the portal for production, remove development leftovers, keep secrets out, and make every page survive a refresh on Hostinger.

Prepare this client portal for production on Hostinger, as a Node.js Web App deployed from GitHub. Read the "Client portal" section of CLAUDE.md first. Do not add features, and never print secret values. 1. BUILD Run the production build and fix anything that fails. 2. REMOVE DEVELOPMENT CODE Remove anything left from development: sample content, the preview switch, test-only scripts, debug logging and any hard-coded test account. 3. NO SECRETS IN THE APP Search the source code and the built files. Only the Supabase Project URL and Publishable key may appear — no Secret or service-role key and no passwords. Make sure .env is git-ignored and never committed, and that .env.example lists the variable names without values. 4. ENVIRONMENT VARIABLES List the exact environment variable names Hostinger needs, and whether this framework needs them at build time. 5. LIVE ADDRESSES Nothing may point at localhost in production. Build every sign-in, sign-up and email-confirmation redirect from the live address, never a hard-coded URL. 6. PAGE REFRESH The portal uses client-side routes, such as a project page. Refreshing or directly opening any route on Hostinger must load the app, not a 404. Set this up the way Hostinger's Node.js Web App serves this framework — for example a small production server with a fallback to the app. 7. HOSTINGER SETTINGS Tell me what to confirm on Hostinger's deploy screen: the framework, build command, output directory, Node version and, if one is needed, the entry file. Do not commit or push — I will review first. Report: - the build result - what you removed - the environment variable names - how page refresh is handled - the Hostinger settings - anything that blocks deployment

Push the project to GitHub with Claude Code or your normal GitHub workflow. If it already has a repository, use it.

Deploy on Hostinger

Recommended plan: Business

USED IN TUTORIAL

https://www.hostg.xyz/SHK1P

Hostinger Websites Add Website Node.js Web App

Choose Import Git repository Connect GitHub and select the portal's repository Confirm the framework and build settings Claude Code gave you Add the environment variables with your project's exact names Click Deploy and wait for the result

IMPORTANT

Add the Supabase Project URL and Publishable key under the names your project already uses. Private server keys stay private — never rename one to a VITE_ or NEXT_PUBLIC_ variable to make the deployment work.

Fix a Failed Website or Web App Deployment with AI

Use this if the Hostinger deployment fails.

/video/fix-a-failed-website-or-web-app-deployment-with-ai

Set Up Production Sign-In

Clients can only sign in on your live address once Supabase knows it, and they need real confirmation emails.

1. Add your live address

Set the Site URL to your live Hostinger address and add it to the Redirect URLs.

Supabase Authentication URL Configuration

2. Keep Confirm email on

Open Email and make sure Confirm email is on. You only connect confirmed accounts, so this is what proves a client owns their email address.

Supabase Authentication Sign In / Providers

3. Send emails from your own domain

Supabase's built-in email only reaches your own team's addresses, two emails an hour, so real clients would never receive their confirmation email. Choose a provider such as Resend, Postmark, Amazon SES or Brevo, verify your domain there and create SMTP credentials. Then turn on Enable Custom SMTP and enter the sender email, sender name, host, port, username and password.

Supabase Authentication Emails SMTP Settings

Keep SMTP credentials in Supabase

Your SMTP password lets anyone send email as your domain. Enter it only in Supabase's SMTP settings — never in the app, an environment file, the repository or a Claude Code conversation.

Test the Live Portal

Open your live address and check:

The portal opens on your Hostinger address

Owner: sign in and see the business dashboard

Owner: refresh a dashboard page — it reloads without an error

New client: sign up with a real email address and confirm it from the inbox

Owner: connect that account to a client and give it a project

Client: sign in and see only their own project

Client: see your newest update and download a shared file

Client B: still sees none of that client's data

Sign out — private pages ask you to sign in again

The portal works on a phone

Verify the Live Client Portal

Check the deployment, production sign-in, the business dashboard and client privacy on the live portal.

Perform a focused production check of this client portal, now live on Hostinger. Read the "Client portal" section of CLAUDE.md first. Do not add features and never print secret values. Do not claim to inspect Hostinger or Supabase settings you cannot see — ask me for the live address, and ask me to confirm specific settings. 1. DEPLOYMENT - the deployment succeeded from the intended repository and branch - the required environment variables are set - no secret files are in the repository 2. SIGN-IN - the Supabase Site URL and Redirect URLs use the live address - Confirm email is on, and custom SMTP sends the confirmation emails - sign-in, sign-out and email-confirmation links use the live address, never localhost - refreshing a protected page keeps the session and never shows a 404 3. OWNER - only the owner reaches the business dashboard - the owner can connect a confirmed account to a client 4. PRIVACY - run the Client A and Client B privacy tests against the production Supabase project, with the Publishable key — never the Secret or service-role key - the file bucket is private, and downloads use short-lived signed URLs Return exactly one: PORTAL LIVE or: NEEDS ATTENTION If PORTAL LIVE, summarize the live address, sign-in, the business dashboard, client privacy and files. If NEEDS ATTENTION, list only launch blockers.

Before real clients join

Delete the test clients from your business dashboard, then delete the Client A, B and C accounts in Supabase. Keep your own owner account.

Supabase Authentication Users

Expected result

Your client portal is live on Hostinger, with private client accounts, real project data, secure files, and a protected business dashboard.