Admin panel that runs a driving school without spreadsheets

Admin panel that runs a driving school without spreadsheets

A learning platform with thousands of users, bilingual content, AI conversations, payments, and promotional campaigns cannot be managed through database queries and Telegram messages to developers. The client needed a proper admin panel — not a generic CRUD interface, but an operations center where the team can manage content, monitor users, analyze revenue, and run marketing campaigns without touching code. We built a full CMS and admin dashboard that covers every operational surface of the platform.

user profiles and ai observability

user detail view showing learning stats, payment timeline, and AI conversation history

The user management section alone goes deeper than most admin panels. Search by name, phone, or Telegram ID pulls up a detailed user profile: their learning statistics (questions answered, accuracy by topic, exam simulation history), complete payment history with subscription status timeline, AI chat logs (what they asked, what the assistant answered, which tools were invoked), and a full activity log. The AI chat viewer was specifically requested after the client noticed users occasionally reporting incorrect AI responses — having the full conversation with tool call traces lets the team verify exactly what happened and whether the issue was in the prompt, the tool response, or the model's interpretation. It's essentially an observability dashboard for every individual user's journey through the platform.

content across three surfaces

Content management covers three major areas: the question bank, the PDD (traffic rules) catalog, and the road signs database. Question editing supports full CRUD with media uploads — some questions include images of road situations, and occasionally short video clips. The upload pipeline validates file size and format on the client side, then runs server-side processing: images get resized to standard dimensions, and videos are checked for codec compatibility. The PDD editor works with the hierarchical chapter-and-point structure, preserving cross-references between points and handling bilingual content with the translation status workflow. Road signs management includes image upload with automatic thumbnail generation and category assignment. All three content areas support draft and published states, so editors can prepare updates without immediately pushing them to users.

analytics that drive decisions

analytics dashboard showing user retention chart, revenue breakdown, and top failed questions

The analytics dashboard was built with Recharts and pulls data from pre-aggregated tables that update on a schedule rather than running expensive queries on every page load. It covers the metrics the client actually makes decisions on: daily active users, subscription conversion rates, revenue by period, most-failed questions (which indicate either bad questions or poorly explained rules), AI consultant usage and cost, and user retention cohorts. The payment statistics section shows individual transactions with filtering by status, date range, and subscription tier — essential for resolving user complaints about "I paid but didn't get access," which inevitably happen with any payment system.

broadcasts, promocodes, and rate limits

Broadcast messaging and the promocode system serve the marketing side. Broadcasts let the team send messages to all users or filtered segments (active subscribers, expired users, users who haven't opened the app in 7 days) through the Telegram bot. The critical constraint here is Telegram's rate limiting — sending messages to 10,000+ users in a burst will get the bot temporarily blocked. We implemented a queued broadcast system: messages are dispatched in batches with configurable delays between them, with real-time progress tracking in the admin UI showing how many messages were sent, delivered, and failed. The promocode system supports percentage and fixed-amount discounts, usage limits (total and per-user), and expiration dates. Each promocode tracks redemptions with user attribution, so the marketing team can measure which channels drive actual conversions.

stack, speed, and lessons

The frontend is built on Next.js 16 with React 19, using Radix UI for accessible, composable components and Tailwind 4 for styling. Authentication runs through JWT tokens with bcrypt-hashed passwords — the admin panel is a separate system from the user-facing Telegram app, with its own auth flow and role-based permissions. File uploads use python-multipart on the backend with streaming to avoid memory issues on large media files. The trickiest performance challenge was the learning statistics aggregation: showing a table of all users sorted by activity or accuracy requires joining across multiple large tables. We solved this with materialized summary rows that update asynchronously, so the admin panel always loads fast even as the user base grows.

The takeaway from building this panel: an admin interface is only as useful as the decisions it enables. Early versions had every data point we could display, and the client's team ignored most of it. The dashboard became genuinely valuable once we sat down with the operations team and asked "what do you actually look at every morning?" — then built around those five or six metrics. The broadcast system, the AI chat viewer, and the failed-questions report get used daily. Half the other screens get used once a month. Knowing the difference before building would have saved a full sprint.

Stack

Frontend: Next.js 16, React 19, Tailwind CSS 4, Radix UI, Recharts

Backend: FastAPI, psycopg, python-jose (JWT), passlib/bcrypt, python-multipart

Database: PostgreSQL with pre-aggregated analytics tables

Features: role-based auth, queued broadcasts with rate limiting, media upload pipeline, promocode engine

2026, «VOSGLOS». All rights reserved.