Jon McGee
← All projects

Web app · Sep 2026 · Preview only

PCI Compliance Tracker

A web app we built at work to stay on top of PCI compliance. Every morning it answers one question: who do I need to contact?

Preview only. This one isn't open for use.

What it is

Merchants who take cards have to complete a PCI compliance questionnaire, and it expires after a year. Keeping track of who is current, who is about to lapse and who has already lapsed was a pile of spreadsheets. This app replaces that with one dashboard built around a single question: who do I need to contact?

It tracks merchants across three card processors in one place. The preview here uses invented businesses and numbers, because the real app holds private records.

Walkthrough

  1. Start on the dashboardCounts at the top show expired, urgent, expiring soon, compliant, non-compliant and missing-info merchants. Below them, tabs list exactly who is in each group, most urgent first.
  2. Narrow it downFilter by processor, hide inactive accounts where PCI does not apply, or show only people nobody has contacted in two weeks.
  3. Open a merchantSee their details, edit them, add follow-up notes and a follow-up date, and view the reminder history. When a merchant finishes their questionnaire, Mark PCI completed sets the new expiration to one calendar year later.
  4. Log the contactRecord that you called or emailed, and when. The dashboard shows how long since each merchant was last contacted, so nobody gets forgotten.
  5. Import a spreadsheetDrop in an Excel or CSV export from a processor. A preview lets you map the columns first. It matches by merchant ID, updates what changed, never creates duplicates, never deletes anything, and never erases data with a blank cell.
  6. Let the reminders runOnce a day the app sends a single digest email: who expires in 10 days, who expires today, and everyone currently expired. It will not send twice and retries on failure.

How status works

Status comes from the expiration date alone, because a processor's own text goes stale the moment a merchant finishes. With the default settings, more than 30 days left is Compliant, 30 days or fewer is Expiring Soon, 10 days or fewer is Urgent, and a date in the past is Expired. A merchant with no date is Missing Info, unless the processor reports them as non-compliant. Both thresholds can be changed in Settings.

Every status badge pairs a color with an icon and a word, so color is never the only signal.

Reports and housekeeping

  • Reports chart status by processor, how long expired merchants have been expired, upcoming expirations over the next six months and a trend over time.
  • Data quality flags merchants with no contact info or no PCI date, anyone missing from the latest processor file, emails that do not look valid, business names shared by several merchant IDs and processor conflicts from recent imports. Each list can be exported.
  • Merchants is a full table with search, sorting, a column chooser, saved views and Excel or CSV export.
  • Settings covers light, dark or system theme, accent color, thresholds, reminder options, a full backup and the team list.

Security and how it's built

  • Sign-in is by email and password plus an access list with admin and member roles. There is no public sign-up.
  • Every database table has row-level security, and secret keys only ever live on the server.
  • An admin-only access log records who did what in a tamper-evident way.
  • It runs on Next.js 16 and Supabase, with Resend for email and a Vercel cron job for the daily digest. The logic is covered by unit tests, a database security test suite and end-to-end tests.