Skip to main content

Roadmap & Future Features

This page tracks planned enhancements, accepted feature requests, and future capabilities for CivicPulse.


πŸ”œ Planned β€” Next Sprint​

Camera Capture with GPS Injection​

Epic: Media
Priority: P1

Allow users to take a photo directly within the app (no gallery needed). GPS coordinates are captured at the exact moment of shutter-press β€” more accurate than EXIF metadata from the camera hardware.

Approach:

  • Custom camera UI using navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } })
  • Live GPS overlay on viewfinder via geolocation.watchPosition()
  • GPS injected as capturedGeo on the image object at capture time
  • Falls back to <input type="file" capture="environment"> on older browsers

Content Moderation β€” Phase 1 (Client-side NSFWJS)​

Epic: Safety
Priority: P0

Pre-upload image classification in the browser using TensorFlow.js + NSFWJS model (~7MB). Rejects images classified as Porn (>70%) or Sexy (>85%) before they ever leave the device.

Categories checked: Porn, Sexy, Hentai, Neutral, Drawing

Pros: Zero cost, zero latency, works offline, image never hits server
Cons: 7MB model on first load, can be fooled by edge cases


Content Moderation β€” Phase 2 (AWS Rekognition)​

Epic: Safety
Priority: P1

Backend moderation gate before S3 save. Every uploaded image passes through Rekognition.detectModerationLabels({ MinConfidence: 75 }). Returns structured labels with confidence scores.

Categories blocked: Explicit Nudity, Suggestive (high confidence), Rude Gestures, Drugs
Categories allowed with review: Graphic Violence (valid civic evidence), Visually Disturbing
Cost: ~$0.001 per image


Image Flagging β€” Phase 2 (Backend Persistence)​

Epic: Safety / Moderation
Priority: P1

Persist image flags to DynamoDB. Auto-blur after 2 flags. Admin moderation queue with Approve / Remove / Ban actions.

DynamoDB table: civicpulse-media-flags

PK: imageId
flags: [{ userId, reason, createdAt }]
flagCount: number
status: visible | blurred | removed

Issue Flagging β€” Phase 2 (Backend Persistence)​

Epic: Safety / Moderation
Priority: P1

Persist issue flags to DynamoDB. Auto-hide after 5 flags. Separate from image flagging. Admin queue shows full issue context for review.


Face & Licence Plate Blurring​

Epic: Privacy
Priority: P2

Automatically detect and blur faces and licence plates in uploaded civic images before storage.

  • AWS Rekognition DetectFaces β†’ blur bounding boxes
  • Rekognition DetectText β†’ detect and blur plate patterns
  • Applied as a post-upload async Lambda job

πŸ§ͺ Research Phase​

Duplicate Issue Detection (Geo + Image Hash + Text)​

Epic: Core
Priority: P2
Status: Parked β€” design complete, implementation deferred

The Problem​

Users frequently report the same physical issue from different angles, with different wording, or at slightly different times. This creates noise in the dataset and dilutes upvote signal.

Multi-Signal Scoring​

The system uses three independent signals combined into a weighted duplicate score:

duplicateScore =
geoProximityScore Γ— 0.55 // strongest β€” same physical location
+ imageHashScore Γ— 0.30 // medium β€” same photo or same scene
+ titleSimilarity Γ— 0.15 // weakest β€” same wording
ScoreAction shown to user
β‰₯ 0.85"This issue has almost certainly been reported β€” upvote instead?"
0.60–0.85"Very likely the same issue"
0.35–0.60"Possibly related"
< 0.35No duplicate warning shown

Signal 1 β€” Geo Proximity (Haversine Distance)​

When GPS is captured on the new issue, compute Haversine distance against all existing issues of the same category.

function haversineMetres(lat1, lng1, lat2, lng2) {
const R = 6371000;
const Ο†1 = lat1 * Math.PI/180, Ο†2 = lat2 * Math.PI/180;
const Δφ = (lat2-lat1) * Math.PI/180;
const Δλ = (lng2-lng1) * Math.PI/180;
const a = Math.sin(Δφ/2)**2 + Math.cos(Ο†1)*Math.cos(Ο†2)*Math.sin(Δλ/2)**2;
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
}

Configurable radius by category:

CategoryRadius
Road (pothole)50m
Traffic signal20m
Streetlight / Infrastructure30m
Waterlogging300m
Hygiene / Garbage100m
Healthcare / SystemicN/A

Signal 2 β€” Perceptual Image Hash (dHash)​

Compute a 64-bit perceptual hash of each uploaded image using the browser Canvas API (~5ms, no library needed). Compare Hamming distance against hashes of existing nearby issues.

Hamming distance 0–5   β†’ Virtually identical (same photo)
Hamming distance 6–10 β†’ Same scene, slight crop/resize
Hamming distance 11–20 β†’ Similar location, possibly same incident
Hamming distance 20+ β†’ Different image

The dHash is a dual-purpose computation β€” the same hash is used for both duplicate detection and the image blocklist (flagged/removed images are added to the blocklist, future uploads with Hamming < 8 are auto-rejected).

Signal 3 β€” Token-based Title Similarity (Jaccard)​

function jaccardSim(a, b) {
const ta = new Set(a.toLowerCase().split(/\s+/).filter(w => w.length > 3));
const tb = new Set(b.toLowerCase().split(/\s+/).filter(w => w.length > 3));
const intersection = [...ta].filter(w => tb.has(w)).length;
const union = new Set([...ta, ...tb]).size;
return union === 0 ? 0 : intersection / union;
}

UX β€” Duplicate Panel in New Issue Modal​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ⚠️ Similar issues found near you (Road Β· Mumbai) β”‚
│─────────────────────────────────────────────────────│
β”‚ ● Pothole causing accidents near Bandra 89 β–² β”‚
β”‚ 48m away Β· In Progress β”‚
β”‚ [πŸ“ 48m] [πŸ–Ό Image: 94%] [Aa Text: 61%] β”‚
β”‚ [View Issue] [↑ Upvote instead] β”‚
│─────────────────────────────────────────────────────│
β”‚ [My issue is different β†’] β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Implementation Plan​

PhaseWhatWhere
Phase 1Jaccard title match in NewModal, no backendFrontend
Phase 2Geo proximity check when GPS capturedFrontend + existing geo data
Phase 3dHash on upload + in-memory hash comparisonFrontend
Phase 4Backend /api/issues/similar with TF-IDFBackend
Phase 5Semantic embeddings (OpenAI / Bedrock)Backend

Backend Endpoint (Phase 4)​

POST /api/issues/similar
{
"title": "Deep crater on SV Road",
"city": "Mumbai",
"category": "road",
"geo": { "lat": 19.054, "lng": 72.842 }
}

β†’ Response:
[
{ "id": "ISS-003", "title": "Pothole causing accidents near Bandra",
"score": 0.82, "distance": 48, "imageMatch": 0.94 },
{ "id": "ISS-001", "title": "Waterlogging near Andheri Station",
"score": 0.21, "distance": 4200 }
]

πŸ“± Mobile App β€” React Native​

Epic: Mobile Priority: P1 Status: Planned

Overview​

A cross-platform iOS + Android app that brings CivicPulse to mobile-first users. The app shares all business logic and API contracts with the web platform β€” no separate backend needed.

Tech Stack​

LayerTechnology
FrameworkReact Native + Expo SDK 51
NavigationExpo Router (file-based, similar to Next.js)
StateSame Zustand/Context pattern as web
APIShared /api/* endpoints (same backend)
AuthGoogle Sign-In via expo-auth-session
Cameraexpo-camera β€” native viewfinder with GPS overlay
Pushexpo-notifications + existing VAPID backend
Offlineexpo-sqlite for local issue cache
Mapsreact-native-maps for issue heatmap
DistributionExpo Application Services (EAS) β†’ App Store + Play Store

Key Features (Mobile-first)​

  1. Native Camera β€” shoot from within the app, GPS injected at capture time
  2. Push Notifications β€” native OS notifications for issue updates and community replies
  3. Offline Mode β€” browse and draft reports without connectivity; auto-sync when back online
  4. Civic Score Widget β€” iOS/Android home screen widget showing your contribution score
  5. Nearby Issues Map β€” native map view showing issues clustered near the user
  6. Haptic Feedback β€” upvote, flag, submit actions use vibration feedback
  7. Biometric Auth β€” Face ID / Fingerprint login for returning users

Project Structure​

mobile/
β”œβ”€β”€ app/ # Expo Router file-based routes
β”‚ β”œβ”€β”€ (tabs)/
β”‚ β”‚ β”œβ”€β”€ index.tsx # Dashboard (same data as web)
β”‚ β”‚ β”œβ”€β”€ issues.tsx # Issues list with Near Me sort
β”‚ β”‚ β”œβ”€β”€ report.tsx # Report new issue (camera + form)
β”‚ β”‚ └── profile.tsx # Civic score + settings
β”‚ β”œβ”€β”€ issue/[id].tsx # Issue detail with chat
β”‚ └── _layout.tsx # Root layout + auth guard
β”œβ”€β”€ components/ # Shared UI components
β”œβ”€β”€ hooks/ # Shared hooks (useUserLocation, useFlags, etc.)
β”œβ”€β”€ api/ # API client (same endpoints as web)
└── app.json # Expo config

Shared Code Strategy​

Business logic in frontend/src/lib/ (pure JS/TS, no React imports) can be consumed by both web and mobile:

  • haversineMetres() β€” already portable
  • fmtDistance() β€” already portable
  • API client functions
  • Scoring algorithm

Implementation Phases​

PhaseMilestone
Phase 1Expo scaffold + auth + issue list + issue detail (read-only)
Phase 2Report new issue (form + camera + GPS + upload)
Phase 3Push notifications + offline mode
Phase 4Heatmap + nearby issues map
Phase 5Civic score widget + biometric auth
Phase 6App Store + Play Store submission

πŸ“² Growth & Marketing​

Social Media Validation Kit​

Epic: Growth Priority: P1 Status: TODO

Auto-generate shareable issue cards and viral mechanics so every report becomes a distribution channel.

Features:

  • Open Graph images: auto-generated per issue using Satori β€” title + category icon + upvote count + city + status badge. No headless Chrome.
  • One-click share: X/Twitter card, WhatsApp deep link, Instagram Stories image
  • Dynamic routes: GET /api/issues/:id/og-image returns PNG (cached 10min)
  • UTM tracking: every shared URL carries ?utm_source=civicpulse&utm_medium=share&utm_campaign=issue for campaign attribution

Backend: backend/services/shareService.js β€” Satori rendering + S3 cache Frontend: share sheet component with platform icons


Marketing Integrations​

Epic: Growth Priority: P2 Status: TODO

Instrument the funnel from landing β†’ sign-in β†’ first report β†’ returning user.

ToolPurposeWhere
Mailchimp / Loops.soWaitlist email capture on landing pageLanding CTA
PostHogProduct analytics alongside GA4 β€” funnel, retention, session recordingfrontend/src/analytics.js
HotjarHeatmaps on issue list + landing pageLoaded async
UTM paramsTrack campaign effectiveness for every inbound linkApp.tsx on mount

Privacy policy must be updated before enabling Hotjar session recording.


Referral & Viral Loop​

Epic: Growth Priority: P2 Status: TODO

Turn every reporter into a distribution channel.

  • Refer-a-friend link: unique ref code tied to civic score
  • City leaderboard badges: shareable PNG showing your rank β€” "#3 in Mumbai πŸ™οΈ"
  • Social proof on issue detail: "47 people in Mumbai upvoted this"
  • WhatsApp forward: pre-formatted message with issue URL + summary

Depends on: Social Media Validation Kit (row 65)


πŸ’‘ Backlog​

FeatureEpicPriorityNotes
PhotoDNA / NCMEC hash matchingSafetyP0 (compliance)Required if platform scales, for CSAM detection
Bulk issue import from CSVAdminP2For seeding city-specific data
Issue status API webhooksCoreP2Notify municipal systems on status change
Multi-language support (Hindi, Marathi, Tamil)UXP2i18n with react-intl
Offline support (PWA)UXP2Service worker caching for offline browsing
Municipal authority dashboardAdminP1Separate portal for government stakeholders
Issue assignment workflowCoreP1Assign to specific dept, track SLA
SMS notificationsNotificationsP2Twilio for non-smartphone users
Heatmap viewDiscoveryP2City-level issue density map
Civic score API (public)ScoringP2Open API for third-party civic apps
Mobile App (React Native + Expo)MobileP1See Mobile App section above for full spec