Skip to main content

Admin Console — Overview

The admin console is the operator-facing side of CivicPulse India. Where the public site is where citizens report civic issues (potholes, garbage, unsafe streets, etc.) and track them, the admin console is where CivicPulse staff and city partners moderate that content, configure how the platform behaves, and administer the platform itself.

It is a separate React application (apps/admin) from the public citizen site (apps/web) — a different codebase, a different deploy, and a different authentication system. It talks to the same backend API, under an /admin-namespaced set of routes, but an admin session cookie is not a citizen session cookie and the two cannot be used interchangeably.

The console is intentionally not styled like the editorial public site. It's a dense, utilitarian operator UI: a persistent left sidebar, data tables with filters and bulk actions, detail drawers, review queues, and configuration forms — built for people who use it for hours at a stretch, not for casual browsing.

Who uses it

Every admin account has exactly one role (AdminRole in packages/db/src/schema/admin.ts). The backend defines the machinery to enforce it per-route — a @Roles() decorator and a RolesGuard in apps/api/src/admin-auth/roles.decorator.ts — but as of this writing @Roles() is not actually applied to any controller anywhere in the codebase, so today every authenticated admin (regardless of role) can call every admin endpoint; only the frontend hides UI a role shouldn't see. Role enforcement is a real gap, not a design choice — worth closing before this console handles production traffic. There are four roles:

RoleLabel in the UIWhat it can do
super_adminSuper AdminFull access across all cities and sections, RBAC and system ops.
city_adminCity AdminFull access scoped to your assigned city.
reviewerReviewerModeration queues only — feed, flags and applications.
auditorAuditorRead-only access, including the audit log.

These descriptions are pulled directly from the product itself (the role card in the sidebar), not paraphrased — they're the authoritative statement of what each role is for.

Scoping is enforced by a cityScope column on the admin's account: null means all cities (only meaningful for super_admin); a non-null array of city IDs scopes a city_admin, reviewer, or auditor to specific cities. CivicPulse is multi-tenant across Indian cities (Mumbai is live as of this writing, with more cities in rollout), and a global city switcher in the console's chrome scopes most screens to a single city at a time.

The spec calls for two-factor authentication on admin accounts as part of the access-control model. As of this writing, admin login is email + password only (an argon2-verified, cookie-based session service) — 2FA is not yet implemented in the codebase.

Tech stack

  • React 18 with React Router 6, built with Vite — a client-rendered single-page app, not server-rendered.
  • TypeScript throughout. apps/admin does not depend on @civicpulse/db — it locally redeclares the AdminRole union type (apps/admin/src/types.ts) to match the backend's, rather than importing it; only the backend (apps/api) imports AdminRole from @civicpulse/db.
  • CSS Modules for styling, with no CSS-in-JS and no inline styles beyond one narrow, sanctioned exception: cssVars() (apps/admin/src/lib/cssVars.ts) for passing dynamic values through as CSS custom properties via style={cssVars({...})}, used in 24 components including Sidebar.tsx — every component with visual output otherwise ships a co-located *.module.css file.
  • Route-level code splitting: every top-level section is a React.lazy()-loaded page, so the console only downloads the code for the section an admin is actually viewing.
  • Session auth against the NestJS API using an httpOnly cookie; the admin's role and city scope travel with every request and are re-checked server-side (the UI hiding a button is a courtesy, not the security boundary).

Map of sections

The sidebar groups the console's sections into five clusters. This is the real, current navigation structure — sections without a page built yet are called out explicitly rather than glossed over.

Overview

  • Dashboard — a per-city at-a-glance view: open issues, SLA breaches, escalations, resolution rate, intake backlog, and pending queues, meant as the first screen an admin lands on.

Moderation

  • Feed Review — the triage and moderation heart of the console: reviewing incoming reports, correcting auto-routing, moderating issues and comments, and handling flagged content.
  • Integrations — managing the multi-channel intake connections (WhatsApp, Instagram, X, the platform itself), their health, and the outbound notification templates sent back to citizens.

Platform Setup

  • Configuration — policy-level settings: feature flags, SLA and escalation timing, scoring weights, and the taxonomy of categories/statuses/priorities that the rest of the platform runs on.
  • Geography & Reference — the reference data that routing depends on: cities, wards, ward boundaries, and pincode-to-ward mappings.
  • Officials & Accountability — the directory of offices and officials that issues are routed to, the responsibility chains that define escalation order, and the computed accountability scores.

People

  • Reporters — reviewing applications from citizens who want verified-reporter status, and managing existing reporters.
  • Admins & Access — administering admin accounts themselves: roles, city scoping, and access control for the console.

System

  • Notifications — outbound broadcast messaging and announcements to citizens.
  • Analytics & Reports — aggregate reporting across issues, wards, officials, and channels.
  • System / Ops — operational surfaces for the platform, including the audit log.

One section from the design spec, Events (moderation of community clean-ups, plantation drives, and similar NGO/citizen-run events), appears as an entry in the sidebar but has no page wired up yet — clicking it currently shows a "lands in a later milestone" notice rather than navigating anywhere. It's listed here for completeness but isn't part of the working console as of this writing, so it isn't covered as a section in the rest of this documentation.

How this documentation is organized

This overview is the landing page for the Admin Console section of the docs. The pages that follow it go deeper, in order:

  • Spec — the original design brief for the console: product context, roles, and the full section-by-section information architecture it was built against.
  • Implementation Plan — how that spec was broken down into a buildable sequence of milestones.
  • Build Log — a record of what was actually built, milestone by milestone, against that plan.

Read this page for orientation; read those for the detail on any specific section or decision.