In production since Dec 2025
Tailor-made CRM for an operation with 120k+ customers
Management system built from scratch: intake funnel, support, team and economy across 10 decision areas, with period deltas and permission-gated access.
- Period
- Dec 2025 — ongoing
- Role
- Solo
- 120k+
- signups in the funnel
- 10
- dashboard areas
- 228 days
- in production, no downtime
#Context
This is a tailor-made CRM — the problem is the same one any fast-growing company has, except here the customer is a player. A GTA:RP server with thousands of players is a business: it has customer intake, support, staff, an internal economy and competitors. And it produces data all the time — signups, screening, characters, support cases, penalties, financial movement. The problem is that this data is born inside the game system, built to run the match, not to run the business. In practice management decided by gut feeling: nobody could answer "how many of the people who signed up this month actually played?" without pulling a technical person off whatever they were doing. I built the panel that turns that raw data into a tool the whole team uses on its own.
#What the product does
The intake funnel is the main screen — and the most valuable one. Joining the server takes a sequence of steps, from first contact to an actual first session, and the panel shows how many people survive each one. That's what reveals where the marketing budget is being lost: bringing in a thousand people a month means nothing if most drop out before they ever play. With the funnel on screen, management stops arguing about "we need more marketing" and starts arguing about which specific step is turning people away.
Eight analytics areas, each answering a question management used to ask without having an answer:
- Overview — the intake funnel, support volume by problem type, penalties issued and active subscriptions. The screen you open a meeting with.
- Acquisition — where do players come from? Marketing channels ranked by signups in the period, with daily history. Shows which media spend is actually bringing people in, and which is just spending.
- Retention — do they stay? How many people were online each day and how many crossed the playtime milestones. Separates the spike of a one-off event from growth that holds.
- Players — the individual record, queried in real time with search. This is the screen support opens when someone complains, to see that person's situation without having to ask a technician for help.
- Organizations — the size of each in-game group and public-service coverage as a calls-made versus calls-answered ratio. Exposes which area is understaffed for its demand.
- Staff — per-member productivity: cases closed, reviews completed and hours dedicated, separating time worked from time the same person spends playing for fun. No more evaluating by impression.
- Economy — how much money is circulating in the game and the average per player, filtered to people who actually played in recent days. The distinction matters: counting balances parked in abandoned accounts inflates the figure and hides real inflation.
- Vehicles — fleet composition by model, to size up what's in excess and what's missing.
Two administration areas, so the panel doesn't depend on me: management creates its own team accounts and adjusts what each person can see, and registers the monitored servers, with player counts for now, yesterday and on average.
Every number comes with a comparison. No metric shows up alone: next to it sits the change against the same previous interval, up or down. Beyond the today / yesterday / 7-day / 30-day shortcuts, you can pick a specific date range — the week of an event, the month of a campaign, the period before and after a major change — and see exactly what it moved.
History preserved across seasons. The server wipes its base when a new season starts. The panel isolates the previous season instead of discarding it, so management can still compare today's performance against last cycle's — precisely the data that disappears when no tool is keeping it.
#Architecture
#Technical decisions
The game system already has all of this. Why did it need a separate panel?
Because the game system answers 'how things are now', never 'how they were'. When a player gets approved, their record is updated and the previous number stops existing. In practice: nobody can say whether the last server update improved or hurt player intake, because no record of the before was kept. The panel stores one snapshot of the business per day. That's what makes it possible to answer 'up or down versus last month' — and it's that comparison, not the standalone number, that justifies spending on marketing, an event or more staff.
Why wasn't it enough to give database access to whoever can write queries?
That's how it worked before, and it was expensive on three fronts. Security: whoever gets database access also gets every player's full record — email, phone number, ID document. No coordinator needs that to know how many people signed up this week. Operational risk: every heavy query competes with the live game server, and a sloppy report at peak hours degrades the experience of people currently playing. And trust in the numbers: everyone calculated their own way, so two departments would walk into a meeting with different values for the same question, and the meeting turned into an argument about whose spreadsheet was right. The panel solves all three at once — one calculation rule, heavy work running once a day outside critical hours, and each person seeing only their slice.
Does the panel show yesterday's data or right now?
Both, and the choice follows the type of question. Trends — intake funnel, retention, acquisition — come from the daily snapshot, because what matters there is the comparison against the previous period. Point lookups — one player's record, the economy balance, how many people are online right now — go straight to the source in real time, because whoever opens a profile wants this minute's state, not yesterday's. Every screen makes clear which case it is: where there's a lag, the last-update time sits at the top, so nobody decides thinking they're looking at real time.
How does the whole team use the panel without everyone seeing everything?
Each person gets access only to the areas their job needs, and viewing is separated from changing: you can grant someone who monitors signups the ability to look without editing. Whoever handles new-player screening doesn't see the economy; whoever analyses acquisition doesn't open records with personal data. The block isn't just an item disappearing from the menu — the protection lives on the server, so going around the interface doesn't help. In practice that's what made it possible to open the tool to the entire team instead of keeping it with two or three trusted people.
What if a day's collection fails? Does the panel stop?
No. Collection is automatic and daily, but machines go down, networks drop and a day can be missing. Instead of showing an error and blocking the analysis, the panel compares against the closest available day and says so on screen: 'comparing against data from 28 days ago'. That's a product choice — for a management decision, an approximate number that declares itself is worth far more than a blank screen. The manager keeps deciding, knowing exactly what the comparison is against.
#Data volume
The operation the panel consolidates daily:
- 120k+ signups at the top of the intake funnel.
- 80k+ characters created.
- 50k+ support cases classified by type.
- 7 marketing channels tracked, from the public listing to friend referrals.
- 228 days of continuous operation since the project started, backing every comparison and every trend in the panel.
#Outcome
- In production since December 2025, continuously maintained — the panel survived a full server season wipe without losing the previous history.
- Management tracks intake, marketing, retention and economy on consolidated, comparable numbers, without depending on a technical person to produce a report.
- The tool is used by the entire team, not by two or three people: each role sees its own slice, and player personal data stays restricted to whoever needs it to handle a case.
Stack
- Next.js
- TypeScript
- React
- MySQL
- better-auth
- Recharts
- Tailwind CSS