Frontend Architecture
React 19 SPA with Vite 8, Tailwind CSS v4, TanStack React Query v5. 30+ pages across Resident, Official, and Guard modes. Social-media UX for residents, enterprise ERP for officials.
Stack
| Dependency | Version | Purpose |
|---|---|---|
| react + react-dom | 19.2 | UI framework |
| vite | 8.1 | Build tool, dev server (port 8888) |
| tailwindcss | 4.3 | Utility CSS (@tailwindcss/vite plugin) |
| typescript | 6.0 | Type safety |
| @tanstack/react-query | 5.101 | Server state, caching, mutations |
| react-router-dom | 7.18 | Client routing with nested layouts |
| react-hook-form | 7.81 | Form state management |
| zod | 4.4 | Form validation (via @hookform/resolvers) |
| motion | 12.42 | Animations (NOT framer-motion) |
| lucide-react | 1.23 | Icon library |
| class-variance-authority | 0.7 | Component variant styling |
| clsx + tailwind-merge | 2.1 / 3.6 | Conditional class merging |
| react-qr-code | 2.2 | QR code generation (UPI, visitor passes) |
Theme System
/* index.css — Tailwind v4 theme */
@import "tailwindcss";
@theme {
--font-heading: 'Outfit', sans-serif;
--font-body: 'Inter', sans-serif;
--color-brand: #10b981; /* emerald-500 */
--color-brand-dark: #059669; /* emerald-600 */
--color-brand-light: #d1fae5; /* emerald-100 */
--color-surface: #ffffff;
--color-surface-dark: #18181b;
}
/* Dark mode via .dark class on */
@custom-variant dark (&:where(.dark, .dark *));
Theme persisted in localStorage('societee_theme') with prefers-color-scheme system detection. ThemeContext provides theme, setTheme(), resolvedTheme.
Context Providers
| Context | Purpose |
|---|---|
AuthContext | User, mode (resident/official), roles, permissions, persona, switchMode() |
ThemeContext | Theme (light/dark/system), resolvedTheme, setTheme() |
QueryClient | TanStack React Query provider (staleTime: 5min, retry: 2) |
Custom Hooks
| Hook | Purpose |
|---|---|
useAuth() | Login, logout, user, mode, roles, isCommittee, hasPermission() |
useLogin() | Mutation hook for POST /auth/login |
useMe() | Query hook for GET /auth/me |
useSwitchPersona() | Mutation hook for POST /auth/switch-persona |
useLogout() | Mutation hook for POST /auth/logout |
Layout System
DashboardLayout
3-panel layout (sidebar + main + optional right panel). Role-based navigation. PersonaSwitcher (Resident ↔ Official pill toggle). Mobile bottom tabs. 11 official nav items.
GuardLayout
Lightweight top bar + 5-tab bottom nav (Gate, Visitors, Vehicles, SOS, Log). Minimal chrome, large touch targets. Separate from DashboardLayout.
Route Map
Public
/ → Landing (hero, features, pricing)
/login → Login (email + password)
/register → Register (society + admin details)
Resident Mode
/feed → Home Feed (posts, stories, quick stats)
/my-bills → My Bills (invoices, pay, history)
/my-complaints → My Complaints (create, track, chat)
/visitors → Visitors (pre-approve QR, history)
/community → Community (forum, events, marketplace)
/amenities → Amenity Booking (calendar, slots)
/letters → Letters & NOC (request, track)
/safety → Safety (alerts, emergency contacts)
/notifications → Notifications
/my-vehicles → My Vehicles (register, list)
/my-ledger → My Ledger (statement, balance)
/profile → Profile (sessions, password, MFA)
Official Mode
/official/dashboard → Dashboard (KPIs, charts, alerts)
/official/billing → Billing (invoices, defaulters, generate)
/official/accounting → Accounting (COA, journal, GST, TDS)
/official/payments → Payments (collection, reconciliation)
/official/reports → Reports (financial, operational, compliance)
/official/documents → Documents (vault, registers, letters)
/official/vendors → Vendors (directory, bills, approve)
/official/members → Members (directory, roles)
/official/facilities → Facilities (bookings, maintenance)
/official/security → Security (guards, blacklist, gate)
/official/settings → Settings (society, features, admin)
Guard Mode (nested under GuardLayout)
/guard/gate → GuardGate (shift, check-in/out, quick actions)
/guard/visitors → GuardVisitors (active list, entry form)
/guard/vehicles → GuardVehicles (read-only, exit)
/guard/sos → GuardSOS (emergency type, big red button)
/guard/log → GuardLog (shift timeline)
API Client
// frontend/src/lib/api.ts
class ApiClient {
private baseUrl = '/v1'; // Proxied to backend in dev
async get<T>(path: string): Promise<T>
async post<T>(path: string, body?: unknown): Promise<T>
async put<T>(path: string, body?: unknown): Promise<T>
async delete<T>(path: string): Promise<T>
async upload<T>(path: string, file: File, metadata?: Record<string, string>): Promise<T>
}
// Auth token injected via interceptor from localStorage
// Tenant ID injected from AuthContext
Vite Config
// frontend/vite.config.ts
export default defineConfig({
plugins: [react(), tailwindcss()],
server: {
port: 8888,
strictPort: true,
proxy: {
'/v1': { target: 'http://localhost:8787', changeOrigin: true }
}
}
})
Mode Switching
Frontend stores mode in localStorage('societee_mode') as 'resident' | 'official'. useAuth().switchMode() auto-selects the appropriate persona based on user roles. PersonaSwitcher renders a pill toggle in the sidebar header.
Design System
- Fonts: Outfit (headings), Inter (body)
- Cards: rounded-2xl, hover lift, gradient icon backgrounds
- Animations: motion/react for page transitions, micro-interactions
- Mobile: bottom tabs, swipe gestures, large touch targets
- Dark mode: full support via CSS custom properties + .dark class