Requests Live
Community Q&A. Users post requests for help, services, or items. Two discussion modes — private 1-to-1 supporter chats (default) or public many-to-many community discussions.
1. Overview
A consumer posts a request ("Need a plumber in Gadag", "Looking for organic vegetables", "Has anyone tried this restaurant?"). Other users respond. Two modes:
- Private (default): up to 3 supporters, each gets their own 1-to-1 thread with the requester
- Public: one shared discussion thread, anyone can join, no cap
The mode is set at post-time via a toggle in the create form. After creation it can't be changed.
2. User journey
Posting
- Requests tab → "+ Post"
- Title + description (voice input supported in 12 Indian languages via Sarvam AI)
- Category (35 options: Driver, Plumber, Mechanic, etc., searchable, custom entries allowed)
- Toggles: Public discussion (Y/N), Anonymous (Y/N)
- Optional phone (hidden if anonymous)
- Submit → notifies nearby service providers + community members
Responding (private mode)
- Browse requests → tap one
- Tap "I Can Help" → creates a 1-to-1 thread with the requester
- Chat in real-time
- Up to 3 helpers per request
Joining (public mode)
- Browse requests → tap one with PUBLIC badge
- Tap "Open Discussion" / "Join Discussion" → enters the shared thread
- See messages from all participants in chronological order
- Anyone can post; messages can be edited within 15 min (mobile only at the moment)
Owner actions
- View threads (or shared discussion)
- Mark Complete (closes the request)
- Delete
3. Web ↔ Mobile parity
| Capability | Web | Mobile |
|---|---|---|
| Post request | ✅ With public/private toggle | ✅ Same toggle |
| Browse with category filter | ✅ | ✅ |
| "My Requests" filter | ✅ | ✅ |
| "I Helped" filter | ✅ | ✅ |
| Public/Private filter pills | ❌ Not yet | ✅ |
| PUBLIC badge on cards | ✅ Added 2026-04-17 | ✅ |
| "Open Discussion" CTA | ✅ Added 2026-04-17 | ✅ |
| Edit/delete own messages | ❌ | ✅ (15-min window) |
| Member count on public threads | ❌ Just shows "Public Discussion" | ✅ "Public Discussion · N members" |
4. Key components
Web
src/app/(consumer)/requests/page.tsx— list view + grid card + detail modal + create modal + thread chat (single file, ~1850 lines)
Mobile
mobile/app/(tabs)/requests.tsx— list + detail + chat + post flow (single file, ~3500 lines)
Shared
src/app/api/requests/**— CRUD + threads + messages
5. APIs
| Endpoint | Method | Purpose |
|---|---|---|
/api/requests | GET | List with filters (category, mine=true, helped=true, status) |
/api/requests | POST | Create. Body includes discussionType: "public" | "private" |
/api/requests/[id] | GET, PATCH, DELETE | Single request — owner can update status / delete |
/api/requests/[id]/threads | GET, POST | List threads (public mode → returns single shared thread; private mode → list of supporter threads, max 3) |
/api/requests/[id]/threads/[threadId]/messages | GET, POST | Chat messages |
/api/requests/[id]/threads/[threadId]/messages/[messageId] | PATCH, DELETE | Edit / soft-delete (sender only, 15-min window for public) |
6. Database touchpoints
Request—discussionType∈"private" \| "public"(default"private"),status,consumerId,category,phone,isAnonymous, geolocationRequestThread— for private mode there's one row per supporter (max 3); for public mode there's exactly one row (supporterIdis set to the request owner as a schema compromise — UI never surfaces it)RequestMessage— chat.editedAt,isEdited,isDeletedfields support edit/delete
7. Business logic
Private vs Public branching (the gnarly bit)
The /api/requests/[id]/threads POST endpoint detects mode and takes different branches:
private→ creates a new thread for the supporter (rejects ifMAX_THREADS_PER_REQUEST=3reached, rejects owner)public→ idempotent lookup-or-create of the single shared thread, no owner rejection, no max-threads check
/api/requests/[id]/threads/[threadId]/messages GET/POST gates the 403 on !isPublic so anyone can read/post in public threads.
This was bug #1 in the 2026-04-15 mobile fixes — the original endpoint unconditionally rejected the owner with "you cannot support your own request", which broke "Open Discussion" for the requester.
Anti-spam measures
- Self-support prevention (private mode): owner can't open a thread on their own request
- Phone optional, hidden when
isAnonymous - 35 categories with controlled vocabulary; custom categories tracked separately
- Auto-message: tapping "I Can Help" creates the thread with a first message — no empty threads
Public-thread member count
Computed on read by counting distinct consumerId in RequestMessage for that thread, plus the request owner. Mobile displays it; web doesn't (yet).
8. Feature flags / env vars
- None gating this feature.
- Voice input requires
SARVAM_API_KEY.
9. Tests
tests/web-mobile-parity-requests.test.ts— 9 tests locking the public-discussion UI parity (added 2026-04-17 after the bug)tests/public-discussion.test.ts— public-mode branching (currently fails on import due to missing GIPHY route — pre-existing, unrelated)tests/mobile-bugs-2026-04-15.test.ts— 4 mobile bug fixes including the public-mode threads endpoint
10. Known gotchas
RequestThread.supporterIdis set to the OWNER for public-mode threads — schema compromise to avoid a migration. The public UI never reads this field, so it's invisible. Don't be surprised if you seethread.supporterId === request.consumerIdon public threads.- Web doesn't have edit/delete for messages. Mobile does (with a 15-min window). Don't write a feature that depends on web-side edit until we add it.
- Voice input is best-effort. If the user records but Sarvam fails, the form still submits with whatever text was typed. Don't block submit on STT.
- Public discussions don't show in "My Requests" filter unless you posted them. The filter is purely owner-based, not member-based.
11. Related
- CHANGELOG: 2026-04-15 mobile bug fixes, 2026-04-17 web-mobile parity
- Notifications — push to owner on new message; broadcast to category-matched providers on new request
- Glossary — Discussion types, Public Discussion definition