All projects
Owned · 2026

Tower Optical Dashboard

Next.js · Supabase · PostgreSQL · Google Pub/Sub · Chart.js · Vercel

What it is

The analytics & operations portal for Tower Optical, a coin-operated/tap-to-pay binocular-viewer company I acquired in 2025 that has been in business since 1933. The viewers are tap-to-pay-enabled as of July 2026, and this is where the people who run them find out whether they are earning and whether anything is broken. Admin & staff watch the whole fleet; venue partners see only their own sites, in aggregate.

Analytics, the view that answers both halves of the question at once — a KPI row across the top, transactions broken out by location below, and a gross-versus-net-to-Tower toggle above both.

What it does

Analytics leads with the fleet: a KPI row, transactions by location, and per-site badges for anything needing attention, filtered by site and date range and switchable between gross card authorizations and net to Tower. Machine health is the triage view: what is offline, what is low on battery, what needs replacing. Each machine has its own page with cell-signal and battery telemetry, its device identity, and its location on a map. Ask AI takes plain-English questions against the same data. Incomplete days are flagged and left out of averages, test transactions are filtered and marked, and an idle machine reads "no activity" rather than a silent zero.

Machine health is the triage view: counts across the top, then a card per site naming exactly which unit is offline, low on battery, or waiting on a replacement.
One machine, in depth: current device status above 30 days of cell-signal and battery telemetry. The identity panel below this, which carries the unit's payment-terminal identifiers, is deliberately excluded from the capture.
Ask AI, shown empty — this is the interface before anything is asked, not a transcript. No API key is configured in this environment, so there is no exchange to show; the four chips are the app's own built-in suggestions.

Revenue Sharing is the money side, and the one screen where being wrong costs real dollars. The viewers sit on someone else's property, so most sites take a cut of what their machines earn, and this page is where that cut gets calculated, sent and paid. Terms are stored per site rather than assumed — each site's percentage, whether a park fee applies and whether it comes out before or after the split, its tax rates, where the money is wired, and for some sites a tiered rate that steps up past an annual threshold. Sites still taking coins get a manual cash box that folds into the split fee-free.

Revenue Sharing for a month, gross through to each partner's cut. Figures are blurred here; the percentages, the deduction order and the per-site statement state are the parts worth showing.

Payment runs through the Brex API against Tower's own checking account, so a remittance finishes inside the dashboard rather than in a banking tab: pick the month, send each venue its statement, then send the money — either an ACH transfer or a paper check that Brex prints and mails. Partners' bank details sit in Brex rather than in Tower's database.

How it's built

Next.js on Vercel over Supabase Postgres, with partner isolation enforced in the database, not in the interface. Chart.js draws the charts, including a custom plugin that moves colliding bar labels out of each other's way. The brand typeface is self-hosted, and light and dark are two hand-tuned token sets rather than an inversion.