Freelance DevRole
Client WorkType
1 Wk → OngoingTimeline
+25%Sales Lift

THE PROBLEM

Management had no idea what the team was actually doing

A solar sales org tracked rep performance through an Excel sheet. Most people didn't fill it in. The ones who did spent 10 minutes and still got it wrong. Management had zero real-time visibility — they'd ask for weekly reports and get back whatever people could remember. I built a replacement in a week as a side project. Then everyone started using it.

THE PROCESS

How I approached it

The design constraint was adoption. If it took more than a minute to use, it wouldn't get used. I started from the rep's perspective: phone in hand at the end of a long day, low patience, wants to be done. Everything else — the leaderboard, the manager dashboard, the Google Sheets sync — was secondary to that 30-second interaction.

Engineering Perspective

"Points aren't stored anywhere. They're calculated fresh from raw activity counts every time you load the leaderboard. That sounds like extra work until you realize the scoring rules changed twice while people were already using the app. Because nothing was hardcoded, historical data recalculated automatically both times. No migration scripts. No stale numbers. No angry reps wondering why their score from last month looks wrong. The right way to build this was to never store derived data in the first place."

DATA LIFECYCLE

1. Authenticated Ingestion

Strict Google OAuth flow checks domain allowlists. Role-based middleware ensures field reps and office coordinators access the correct reporting endpoints.

2. Dynamic Upsertion

Submitting a report triggers a conflict-aware PostgreSQL upsert. Points are strictly a computed derivative of raw activity, maintaining a single source of truth.

3. Sheets Syncing

Parallel execution paths push relevant lead statuses to an external Google Sheet using stored refresh tokens via the Google API.

4. Dashboard Hydration

React components map raw data into heatmap grids, 30-day trend lines, and tie-aware rank leaderboards instantly.

KEY DECISIONS

Why I built it this way

What we gainedWhy a PWA instead of a native app

Field reps work on phones. That's the only requirement that matters. Building a native app for an internal tool means App Store approvals, release cycles, and maintenance overhead nobody needs. A PWA installs from the browser, works offline-capable, and ships like a website.

What we gainedWhy Google Sheets instead of migrating

The team already had lead data in Google Sheets. That habit wasn't going away. Fighting it would mean a migration nobody wanted and a tool nobody trusted. So I plugged into their existing sheets instead. Reps manage leads from the app. Data writes back to the spreadsheet they already knew.

What we gainedWhy dynamic point calculation

Points aren't saved anywhere — they're computed from raw activity counts every time they're needed. Storing derived values is a trap: the moment the scoring rules change, your historical data is wrong. The rules did change, twice. Because points are always recalculated on the fly, every change applied retroactively with zero effort.

What we gainedWhy domain-restricted Google OAuth

Internal tool. Company emails only. Google OAuth with an email-domain allowlist means no password management, no reset flow, no account security headaches. Someone leaves the company — access stops working the moment IT revokes their account.

THE SOLUTION

Log your day in 30 seconds. See the leaderboard. Done.

RepTrack is a PWA. Reps open it on their phone, pick their work mode — field, home, or off — enter their activity counts, and close it. 30 seconds on a bad day. Every activity converts to points through a weighted scoring system. The leaderboard updates in real time. Reps see where they stand. Managers filter by team and time period and see live rankings without asking anyone for a report. No more weekly emails. The numbers are always current.

TECHNICAL ARCHITECTURE

CLIENT INTERFACE
Next.js PWA
Tailwind CSS + shadcn/ui
SERVER INFRASTRUCTURE
Next.js 15 App Router
VercelBetter AuthDrizzle ORM
PRIMARY DATABASE
PostgreSQL
Profiles, KPI Reports, Org Hierarchy
EXTERNAL INTEGRATION
Google Sheets API
Legacy Lead Bidirectional Sync

RESULTS

+25%Sales in 3 Months
30 secDaily Report Time
100%PWA Adoption
LiveLeaderboard Updates

The business owner finally had visibility into team performance. Within 3 months, sales grew 25% — not because of the app, but because of the conversations the data made possible.

LEARNINGS

What Worked

  • — Shipping in a week forced focus on the one thing that mattered: the 30-second report flow.
  • — Integrating with Google Sheets respected existing habits instead of demanding a migration nobody wanted.

What I'd Do Differently

  • — The point scoring rules changed twice in production. I'd define the formula in a config object from day one — I got lucky that dynamic calculation made retroactive changes painless.
  • — I built the leaderboard before confirming reps actually wanted to see each other's scores. It worked out, but I should have asked first.
Next.js 15Drizzle ORMPostgreSQLGoogle APIsVercel