A mothers group. A cycle club. A tech meetup. Communities bring shared-interest groups onto MiFamilias — built on the same trust foundations as family bubbles, with every guardrail enforced server-side. Each diagram below maps to real handlers, entities, and routes in the codebase.
Communities are launching with our beta-tester families only. Every community in the beta is hand-verified, and we tune the guardrails with real groups before opening the doors wider. Trust first, scale second.
Someone forwarded the group WhatsApp link… and a 12-year-old just joined.
MiFamilias already has two trust shapes: the closed family bubble (mutual, consensus-vouched) and the celebrity broadcast (one-way, public). Communities slot between them — and they depend on family bubbles: you can only enter a community because your family already vouched you into a real, active family. Fake accounts have nowhere to come from.
flowchart LR
subgraph T1["fa:fa-house-chimney Family Bubble"]
A["Mutual trust
consensus vouching
guardian consent for minors"]
end
subgraph T2["fa:fa-people-group Community (new)"]
B["Shared interest
verified adults only
open feed, moderated"]
end
subgraph T3["fa:fa-star Celebrity"]
C["One-way broadcast
public followers"]
end
A ==>|"family membership is
a REQUIREMENT to enter"| B
A -.->|"follows"| C
style A fill:#14262a,stroke:#34d399,color:#e8f4f0
style B fill:#0e3b2e,stroke:#4ade80,stroke-width:2px,color:#e8f4f0
style C fill:#14262a,stroke:#8aa6a0,color:#8aa6a0
The family-anchor rule: an active member of a family with more than 2 members — real verified people who vouched each other in. The existing trust pyramid does the anti-fraud work for us.
Community access is never stored as a flag — it's recomputed from the live profile
on every request by communityPermissionService.
Edit your date of birth, lose your verification, leave your family: access ends immediately.
flowchart TD
U["fa:fa-user Any request touching
communities"] --> G1{"Account active?"}
G1 -->|no| X["fa:fa-ban 403 — with the exact
unmet requirements listed"]
G1 -->|yes| G2{"Date of birth on file
AND 18+?"}
G2 -->|"no / missing DOB"| X
G2 -->|yes| G3{"Age verified?"}
G3 -->|no| X
G3 -->|yes| G4{"Active member of a family
with >2 members?"}
G4 -->|no| X
G4 -->|yes| V["fa:fa-circle-check COMMUNITY VIEWER
browse · join · post"]
V --> G5{"Strong verification?
(document / video check)"}
G5 -->|no| V2["viewer only"]
G5 -->|yes| CR["fa:fa-shield-halved COMMUNITY CREATOR
create · own · run"]
style U fill:#14262a,stroke:#34d399,color:#e8f4f0
style X fill:#2a1416,stroke:#f87171,color:#fecaca
style V fill:#0e3b2e,stroke:#34d399,color:#e8f4f0
style V2 fill:#14262a,stroke:#8aa6a0,color:#8aa6a0
style CR fill:#0e3b2e,stroke:#4ade80,stroke-width:2px,color:#e8f4f0
The same checklist powers the in-app help modal via GET /communities/permissions — users see exactly which requirement they're missing, with met/unmet ticks.
Sensitive communities (e.g. parenting groups) can set the verified age gate: joining then requires the strong, identity-checked verification — the creator bar — for every member.
In WhatsApp, the link is the door. Here, every redemption runs the full permission gate server-side — a forwarded link in the hands of a child is inert.
sequenceDiagram
participant M as Minor (forwarded link)
participant A as Verified adult
participant API as POST /communities/join/:token
participant G as Permission gates
M->>API: redeem invite token
API->>G: viewer permission?
G-->>API: refused — under 18
API-->>M: 403 — "not eligible" + requirement checklist
Note over M,API: No entry. No preview. No member list.
The link reveals nothing.
A->>API: redeem same token
API->>G: viewer permission?
G-->>API: passed — verified adult, family-anchored
API->>G: community age gate (declared / verified)?
G-->>API: passed
API-->>A: welcome — active member
Invites expire (max 30 days), carry usage limits, and are revocable. Banned members can never redeem one — status: banned is permanent.
Communities reuse the platform's existing moderation stack — and tighten it. Family feeds warn about profanity; communities block it. And every post waits out a cooling-off window before anyone else can see it.
flowchart LR
P(["fa:fa-pen Member writes
a post"]) --> F1{"fa:fa-filter Profanity check
(blocker, not warner)"}
F1 -->|"moderate / severe"| R1["fa:fa-ban Rejected —
edit and retry"]
F1 -->|clean| F2{"fa:fa-image Image scanning
same pipeline as
family posts"}
F2 -->|violation| R2["fa:fa-ban Rejected"]
F2 -->|pass| F3["fa:fa-hourglass-half Cooling-off window
(default 5 min, owner-set)
status: scheduled"]
F3 -->|"author can delete —
nobody ever saw it"| D["fa:fa-trash Gone"]
F3 -->|"window passes"| L["fa:fa-circle-check Live in the feed"]
L --> F4{"fa:fa-flag Reports"}
F4 -->|"3+ unique reports"| H["fa:fa-eye-slash Auto-hidden,
moderator review"]
F4 -->|none| L
style P fill:#14262a,stroke:#34d399,color:#e8f4f0
style F1 fill:#14262a,stroke:#34d399,color:#e8f4f0
style F2 fill:#14262a,stroke:#34d399,color:#e8f4f0
style F3 fill:#0e3b2e,stroke:#4ade80,stroke-width:2px,color:#e8f4f0
style F4 fill:#14262a,stroke:#34d399,color:#e8f4f0
style R1 fill:#2a1416,stroke:#f87171,color:#fecaca
style R2 fill:#2a1416,stroke:#f87171,color:#fecaca
style D fill:#14262a,stroke:#8aa6a0,color:#8aa6a0
style H fill:#2a1416,stroke:#f87171,color:#fecaca
style L fill:#0e3b2e,stroke:#34d399,color:#e8f4f0
The cooling-off window is the anti-troll heartbeat: heat-of-the-moment posts can be pulled by their author before a single other member sees them. Owners tune it from 0–60 minutes.
Moderation is unilateral here — owners and moderators remove or ban instantly. Families need consensus to remove a member; loose groups need fast tools instead.
Grooming, scams and harassment happen in private messages, invisible to the group. MiFamilias has no user-to-user DMs anywhere on the platform, and communities don't add one. There is no private place for a bad actor to take a conversation.
flowchart TD
M["fa:fa-user A community member
can see about you:"] --> Y1["fa:fa-check Auto-generated handle
(e.g. SwiftFalcon42)"]
M --> Y2["fa:fa-check Chosen avatar icon
(never your photo)"]
M --> Y3["fa:fa-check Your posts & comments
(visible to ALL members
+ moderators)"]
M --> N1["fa:fa-xmark Phone number"]
M --> N2["fa:fa-xmark Email address"]
M --> N3["fa:fa-xmark Location / presence"]
M --> N4["fa:fa-xmark Private messages —
the feature does not exist"]
style M fill:#14262a,stroke:#34d399,color:#e8f4f0
style Y1 fill:#0e3b2e,stroke:#34d399,color:#e8f4f0
style Y2 fill:#0e3b2e,stroke:#34d399,color:#e8f4f0
style Y3 fill:#0e3b2e,stroke:#34d399,color:#e8f4f0
style N1 fill:#2a1416,stroke:#f87171,color:#fecaca
style N2 fill:#2a1416,stroke:#f87171,color:#fecaca
style N3 fill:#2a1416,stroke:#f87171,color:#fecaca
style N4 fill:#2a1416,stroke:#f87171,color:#fecaca
Phone sharing stays family-scoped (setPhoneSharing per family) and never gains a community scope. The family feed's tap-to-contact is stripped from community feeds.
Communities plug straight into the user-activated advertising engine. Joining a community is the strongest interest signal there is — so we treat it the same way we treat every signal: as a reason to ask, never to profile.
flowchart LR
J(["fa:fa-people-group You join
Brisbane Cycle Club"]) --> Q{{"fa:fa-bell One question:
"Want cycling offers
while you're a member?""}}
Q -->|"Yes — you pick
the duration"| W["fa:fa-circle-check Interest window opens
ads labeled
'Because you asked'"]
Q -->|"No thanks"| Z["fa:fa-xmark Nothing stored.
Joining alone never
changes your ads"]
W --> S["fa:fa-rectangle-ad Community suggestion
cards may fill ad slots:
'Sponsored community' label,
unmissable"]
S -.-> X["Never shown to minors.
Never your own communities.
Sponsors get NO member data
and NO messaging channel."]
style J fill:#14262a,stroke:#34d399,color:#e8f4f0
style Q fill:#0e3b2e,stroke:#4ade80,stroke-width:2px,color:#e8f4f0
style W fill:#0e3b2e,stroke:#34d399,color:#e8f4f0
style Z fill:#14262a,stroke:#8aa6a0,color:#8aa6a0
style S fill:#14262a,stroke:#34d399,color:#e8f4f0
style X fill:#14262a,stroke:#8aa6a0,color:#8aa6a0
Leave the community and a community-sourced interest window ends with it. Guardian ad controls and the existing opt-out machinery apply unchanged.