DealPlate Admin Console
The operations surface for a live marketplace
Next.js App Router dashboard for running the DealPlate platform — restaurants, users, admins, promotions, reviews, subscriptions, and an audit trail of privileged actions.
7
Admin sections
App Router
Router
Firebase
Auth
Overview
Every marketplace needs somewhere for the operator to stand. The DealPlate console is that surface: a Next.js App Router application where platform administrators inspect and moderate the data the mobile app produces.
It's deliberately a separate client rather than a screen inside the app. Administration has different auth requirements, different risk, and a different device — squeezing it into the owner shell would have compromised all three.
Problem
The Flutter app gives owners control of their own restaurant and diners control of their own account. Neither can answer platform-level questions: which restaurants are live, which users are active, what a suspended account looks like, or who took a privileged action last Tuesday.
Without an operations surface, moderation means running SQL by hand against production — slow, unauditable, and a mistake waiting to happen.
Solution
A route-grouped dashboard where each administrative domain gets its own page under a shared layout, behind a dedicated login route.
Moderation is non-destructive by design. Suspending a restaurant sets a flag that hides it from consumers rather than deleting records, so an incorrect decision is reversible and history stays intact.
Privileged actions write to an audit log, which gets its own section in the console — the record of what operators did is treated as first-class data, not as server logs.
Features
Restaurant moderation
Review listed businesses and suspend ones that break the rules, hiding them from consumers without deleting their data.
User administration
Inspect accounts across roles, backed by last-seen tracking on the user record for activity visibility.
Admin management
A dedicated section for managing who holds administrative access.
Promotion oversight
Platform-wide view of live offers, independent of any single owner's dashboard.
Review moderation
Oversight of user-submitted ratings that roll up into public restaurant scores.
Subscription visibility
See which restaurants are on which plans and in what state.
Audit trail
A browsable record of privileged actions, so moderation decisions can be traced after the fact.
Shared pagination
A common pagination primitive in lib/, used across list views rather than reimplemented per page.
Tech Stack
Framework
- Next.js (App Router)
- React
- TypeScript
Routing
- Route groups
- Shared segment layout
Data
- Typed API client over the NestJS backend
Identity
- Firebase Auth
Typography
- Self-hosted Geist / Geist Mono
Architecture
A thin client. The console holds no business rules of its own — it authenticates, calls the same NestJS API the mobile app uses, and renders. All authorisation decisions stay server-side.
(dash) route group
Groups every authenticated admin section under one shared layout without adding a path segment.
App RouterLogin route
A separate unauthenticated entry point outside the dashboard group.
Firebase Authlib/api.ts
Single typed access point to the backend, so no page constructs requests ad hoc.
TypeScriptlib/pagination.tsx
Shared pagination component reused across every list view.
React
Folder Structure
- app/
- App Router root
- ├── login/
- Unauthenticated entry point
- ├── (dash)/
- Route group — shared layout for all admin sections
- │ ├── dashboard/
- Overview
- │ ├── restaurants/
- Listing moderation and suspension
- │ ├── users/ admins/
- Account and access administration
- │ ├── promotions/ reviews/
- Content oversight
- │ ├── subscriptions/
- Commercial state
- │ └── audit/
- Privileged action history
- ├── fonts/
- Self-hosted Geist and Geist Mono
- └── layout.tsx
- Root layout
- lib/
- api.ts (typed backend client), pagination.tsx (shared list paging)
API Flow
The console authenticates with Firebase like any other client and calls the same guarded API — it holds no privileged database access of its own.
Administrator signs in
The login route authenticates through Firebase, outside the (dash) group.
Requests go through lib/api.ts
One typed client attaches credentials, so no page builds requests by hand.
The API authorises the action
FirebaseAuthGuard verifies the token and the backend decides whether the caller may perform an admin action — the console is never trusted to make that call.
Privileged actions are recorded
Actions that change platform state write to AuditLog, which the console then reads back in its audit section.
Challenges
Deciding what moderation should mean
Deleting a restaurant is easy to implement and hard to undo. Suspension — a boolean on the restaurant record that hides it from consumers while preserving every relationship — keeps mistakes recoverable and keeps the audit trail meaningful.
Keeping authorisation out of the client
It's tempting to let an admin UI decide what an admin may do, since it already knows who is signed in. Every such decision stays on the API; the console only renders what it's allowed to fetch.
Two clients, one contract
The console and the Flutter app consume the same endpoints from different languages. Keeping a single typed API module rather than scattering fetch calls made backend changes something to update in one place.
Learnings
Route groups are the right tool for 'same layout, different auth posture' — the login route sitting outside (dash) keeps the boundary obvious in the file tree.
Reversible moderation beats destructive moderation; a suspended flag has been worth far more than a delete button.
An audit log is only useful if it's browsable by the people who need it, which means treating it as a product surface rather than a table.
Shared primitives like pagination pay for themselves by the third list view.
Future Improvements
Server-side role checks surfaced as UI affordances, so unavailable actions are hidden rather than attempted and rejected.
Bulk moderation for handling reported content in batches.
Richer platform analytics — growth, retention and redemption trends rather than current-state lists.
Exportable audit history for compliance and incident review.
Optimistic updates on moderation actions to make the console feel as responsive as it is consequential.