AI-visibility dashboard
An AI-visibility dashboard for Mulberry Marketing Communications
A client dashboard for an agency partner, where the database, not the page, decides who can see which client's audit results.
How it fits together
Inputs
Audit runs
Results from the scored audit engine arrive through an ingest script and an internal API that requires a secret header.
n8n
Agency staff and their clients
People sign in with a magic link. There are no passwords to store or reset.
Engine
Client dashboard
Scores, check results, and history for each client site, by role.
Next.js
Row-level security as the boundary
The app connects as a restricted role, and each request carries the user's id into its transaction, so policies scope every client table through membership.
- PostgreSQL
Viewer, editor, and admin
Each person has one role, and only administrators can manage clients and who belongs to them.
Refresh on request
A user can ask for a fresh audit, limited to one per site per day and recorded before the call goes out.
Outputs
Client-ready reporting
Each client sees only its own sites and results.
Audit log
Every tool run and approval is recorded, and the app's database role cannot delete history.
Guardrails
- One client can never read another client's data
- Internal endpoints reject calls without the shared secret
- No stored passwords
The problem
Mulberry Marketing Communications, a B2B marketing agency, wanted to offer AI-visibility audits to its own clients. That needed a place where each client could see its results and nobody else's, with access managed in one place.
What I built
- A Next.js dashboard with magic-link sign-in, database sessions, and viewer, editor, and admin roles.
- A Postgres schema where row-level security, not application code, decides which rows a signed-in person can read or change.
- An ingest path for audit runs and an internal API guarded by a secret header.
- A rate-limited refresh request and an append-only record of every tool run and approval.
How I built it
I built it under a technical partnership with Mulberry. The dashboard runs on Next.js and PostgreSQL, and the scores come from the same scored audit engine described on this site. The tenant boundary lives in the database so that a bug in a page cannot leak one client's results to another.
What it shows
I put access rules where they cannot be skipped, and I build multi-client products that a partner can put in front of its own customers.