Fresh journey mockup, premium component system only. Governed by build/place-pages/master-plan/ — each screen implements its council decision sheet verbatim (✅ rulings only; ⏳/🚫 absent by design). C13-amended / DECISIONS #8: ONE language per screen — the app renders a single locale via i18n (12 locales); frames are English, plus one hi-locale reference frame. Currently: S1 Entry + Set-your-place (5 states + locale check), S2 Intro (the carousel is dead — land on the page, a ~40% sheet does the talking; 3 states + locale check) and S3 Adaptive landing + place header (THE HEADER DIET — top bar → counted ladder → Today strip → sticky tabs, ≈230px vs 510px; identity blocks move into Overview; 5 states + locale check) and S4 Overview tab content (identity blocks first; ONE builder/consumer reorder at 60%; ONE consolidated builder card; directory trust anatomy — checkmark only on claimed, no party on administrative roles, no dead call chips; hybrid local places + POI sheet; 4 states + locale check). Later screens land here as their councils rule.
Owner 2026-06-14 (discovery pass): a "Trending near Bheldi" rail leads the tab — a geo-scored mix of the most-active circles + channels across village→block→district (uses the trending backend already built), rich cards with a member-avatar stack (faces = life + social proof), an activity pulse (🔥 Hot / Growing), a level chip, and inline Join/Open. It surfaces what's alive beyond a 3-circle village without leaving the tab. Cards stay 2G-safe — avatar stacks, NO cover images. The lists below gain the same avatar-stack treatment. · Implements C11 last-activity on EVERY circle card — a 47-member dead circle must never look identical to a live one (rural: join→dead→never returns) · C12 the JOINED row is whole-card tappable → ENTERS the circle, subtle chevron (today the Joined button is disabled and there's no way in — comprehension bug); joined floats first (0-cost app sort) · B9 both gating variants on screen: member card carries the last-post teaser, non-member cards show count-only "4 posts this week" / "Active this week" · C13 section label "in Bheldi", never "near you"; localized type badges ≥10.5px · A5 🚫 auto/official place circle — official-CREATED channels get the Official badge + first ordering instead; channel header = announcement framing, "broadcast" banned · C15 keep: inline Join, member count, circles before channels, single REST call (no 20× hydration) · D16 open create entry at bottom, no Seva gate. App-only 🔨: C11 ChannelInfo.lastActivity field absent (M) — channels order by size until it ships · F20 hasMore computed server-side but NOT exposed — 10+10 pagination replaces today's 20+20 silent truncation. G metric: weekly join-or-create per visited place ≥15% in 60d.
Cold start fires at <3 local circles (invariant: effectiveCount=max(affiliated,discovered) flips it off at 3 organic regionIds-tagged circles). A4 residents banner answers the unasked WhatsApp question with PERMANENCE framing — "stays with the village, doesn't die with a group number"; 🔨 banner hidden when the place has 0 on-app users (currently always shown) · A2 🔨 suggestion chips become SERVER-canonical — app currently ignores state.suggestedToCreate and hardcodes its own list; "Bheldi ke log" added to the seed list; region-aware topic order server-side · A3 ONE primary CTA "Start a group for Bheldi" — channel creation demoted to a small secondary link, 🚫 equal-weight dual buttons (paralysis); the Buy & Sell chip skips the picker straight to Circle creation · A1 LABELED nearby section "Nearby — in Garkha Block": own header, max 5, NEVER mixed into the local list (one parent-region query, S) — rural discovery wins, the explicit parent label answers the false-social-proof objection; 🚫 bare "see what's active nearby" link · A6 memberCount 0 → "New" chip, never "0 members" (Law #7).
Implements D17 Circle/Channel picker — Circle PRE-SELECTED on chip flows; comprehension subtitles localized for a rural first-timer (hi: "सभी लिख सकते हैं, मिलकर बात करें" / channel = you write, neighbours read); "admin" never renders in hi — mukhiya/pramukh framing (the word "admin" reads as liability, not honor); "Founding Steward" title localized · D18 initialName + initialDescription pre-filled from the chip topic (halves blank fields); place-prefix names kept, server slugs stay stable; the Buy & Sell chip SKIPS this picker straight to Circle creation (A3) · D16 OPEN creation for circles AND channels — NO Seva gate ever: the cold-start flywheel depends on a zero-Seva first visitor founding the first group; Seva is the REWARD, never the key — founder beat "★ +20 Seva" (already built), DECISIONS #10: Seva, never "karma". Moderation lever if needed later = steward approval on AFFILIATION, not creation.
You're the Founding Steward — the first to start a group that stays with the village, not one phone number.
+20 Seva earnedImplements C14 empty-but-joined circle STAYS LISTED with a "No recent posts" sub-label — never silently dropped (⏳ unread pills deferred: circles = S via existing pipeline stage not wired, channels = L via chat infra; Join conversion is the goal now) · F20 2G kit: skeleton shimmer ROWS on load — a lone spinner reads as 8–12s of nothing and bounces; error state gets an explicit RETRY (today errors fall through to the cold-start banner — a lie); optimistic Join = instant swap to Joined + revert on error, never a spinner on the button. App-only 🔨: F20 limit 20+20 → 10+10 with hasMore pagination (computed server-side, NOT exposed — silent truncation past 20) · verify groups compound index {groupType, isDeleted, regionIds} via explain() before district scale · q:60 imgproxy hint on avatars.
Implements B9 activity signal ON the community card, content gated: a MEMBER sees the last-post teaser + timestamp; a NON-member sees count only ("4 posts this week") — activity visible, content gated → join incentive (lastPostCreatedAt already in the payload, ~0 cost) · B7 CIRCLE POSTS NEVER REACH THE PLACE FEED — unanimous ruling: the WhatsApp mental model is ironclad, posted "in the circle" ≠ "to the village"; one betrayal = never posts in a circle again; S6's !circleId filters stand · B8 channels are the exception (broadcast = public is the author's intent): labeled channel cards in the place feed = design ACCEPTED, ⏳ BUILD AT S14 (additive groupId query, same mechanism as events-in-feed); feed-tab digest row also revisits at S14 · 🔴 B10 P0 SECURITY (standing, pre-dates S8): getPostV2 has NO circle-membership check — private-circle posts readable by ANY authed user with the postId (posts.service.ts:4220; settings.isPrivate never enforced) — 🔨 enforce isPrivate at getPostV2 (M); and CIRCLE_POSTS_IN_TIMELINE flag does NOT cover the DB fallback (posts.repo.ts:3938 hardcodes the exclusion) — both paths move together if ever flipped.
DECISIONS #8: ONE language per screen via i18n — this frame renders S8·A end-to-end in hi. E19 🔨 P0 i18n sweep: EVERY communities_* key in hi.i18n.json is untranslated English today — a Hindi-set phone sees English across this whole tab — plus hardcoded EN strings not even keyed (_StartCommunityBlock RichText, _ResidentsBanner, _TrustNote, picker subtitles); banned in hi: "broadcast", "admin" (→मुखिया/प्रमुख), "steward karma" (→सेवा) · C13 type badges localized — समूह (Samuh) for circles, ख़बर (Khabar) for channels, ≥10.5px ("CIRCLE" 9px uppercase is invisible on a Redmi); section label "भेल्दी में", never "near you"; channel header = announcement framing घोषणाएँ · joined sub "जुड़े हुए", activity lines "इस हफ़्ते सक्रिय" / "इस हफ़्ते 4 पोस्ट" (B9 gating identical), create entry "भेल्दी के लिए समूह शुरू करें". Numerals, handles and the brand "Nyburs" stay Latin. Layout, components and ordering identical to S8·A.
Journey position: S1 confirm → LAND on the home-village page + intro sheet (S2 — the carousel gate is dead per S2·A1/A2; adaptive landing starts from the SECOND session) → S3+. All frames render inline in the Place branch (root tab, no back chevron). One language per screen (C13-amended / DECISIONS #8): en frames + one hi-locale translation check per screen (S1·F, S2·D). S1 app-only rulings (A2 key scoping, A3 far-GPS soft confirm, A4 gpsAccuracy + 3/30d rate-limit, E21 timeout→retry, F28 events) ship in set_your_place.page.dart + nybursapi. S2 app-only rulings: A3 PlaceIntroRoute/PlaceIntroExtra deleted — the sheet lives in place-page logic reading the loaded PlaceDetail, placeIntroSeen + double-show guard, ~1.2s rise · D13 funnel events · D14 kill criterion (D1-return uplift ≥ +4pp or the intro is removed) · D15 post-first-contribution share card — part of the S2 design set, designed & built with the profile/share wave · E16 interim carousel bugs die with the carousel. C12's ⏳ rename is RESOLVED by DECISIONS #10: points = "Seva" — UI renders "★ +N Seva" / "Seva score" ("सेवा" in hi); "karma" survives only as internal code identifiers. S3 (header diet) app-only/build-phase rulings cited in captions: A3 first-arrival = client skips the landing call when placeIntroSeen unset + lazy ladder after paint (zero API change) · D12 auto-follow home wired as an UpdatePinnedRegions side-effect of confirmHomePlace · E15 invalidatePlaceDetail also busts places#landing#<id> (15-min banner lag), 10-min remount refresh gate, isFollowedByViewer pre-warm/fold, landing cache key gains a userId prefix BEFORE any personal cell ships (cross-user leak), open-issues count added to the landing payload · E16 personal-delta cells (Seva delta / issue-moved / per-rung rank) are deferred — the ③ Today slot is DESIGNED for them · F17/F18 mechanical-AA + i18n batches: ≥11px sublabels, kPlaceWarn light variant, chip maxWidth/ellipsis/scroll-to-active wiring, home icon on active chip, "1 contributor" singular, onAppCount stats gate ≥3, Material icons for stats, hide the "Nearby" stub tab, 44px back-chevron, "Page completeness" → "{place} info" (hi: jaankari), live "karma" string → Seva. Banner mechanics: "Go to" = pushReplacement; orientation state capped at 3 impressions in the first 2 weeks. S4 (Overview tab content) app-only/build-phase rulings cited in captions: A1 identity blocks structurally relocate from pre-tab slivers into the Overview tab + sticky TabBar via SliverPersistentHeader · B6 expose verifiedCivic in DTOs (the checkmark currently renders on ALL rows — must become claimed-only) · B8 _ContactChip currently has NO onTap — wire the locked Call·WhatsApp·Copy sheet · B10 attribution = batched revision join on directoryTemplate (M); the ⏳ confirm-counts mechanism ("6 logon ne sahi maana") + confirm-gated call = slot designed, built later · B11 new REPORT contribution kind (S) · B14 election-staleness refresh mechanics ride the election runbook · B16 POI lat/lng is currently silently dropped — plumb it (S) for distance + open-in-maps · D ledger: onAppCount display DEPENDS on the primaryLocation sync flag (currently OFF — everything reads 0; launch-blocking) + ≥3 gate, emoji stats → icons, "1 contributors" singular, helpChipMeta missing keys (popularPlace/co/civil_surgeon/chief_secretary/dgp/panchayat_secretary = invisible chips), hardcoded-strings batch (hero fallback, completeness card, "Add a place", empty states, "karma" in _LeaderRow → Seva ×2), placeText3 ≥11px/text-2, party+seat 320px overflow guards, breadcrumb › RTL, rank width, _SectionLabel merge, canRevert role-gate, kPlaceWarn light #D9641B, "View all" 44px tap targets, steward card tap + role label. The S4·A/S4·B/S4·E tall frames render the FULL Overview scroll in one device frame — in app the same content scrolls under the sticky tab bar.