The Community module turns any AppMint tenant into a social platform. It's the layer that lets your customers (not staff) follow each other, post content, run group chats, join interest pages, and earn badges. Everything is multi-tenant — every record carries the orgid boundary like the rest of AppEngine.
Two surfaces
Community ships two REST controllers plus one WebSocket gateway:
| Surface | Path | Principal | Purpose |
|---|---|---|---|
| Customer-facing | /client/community/* | Customer (or public for read) | Pages, posts, stories, feed, follows, bookmarks, groups, badges |
| Staff/admin | /community/* | User | Connection requests, DMs, meetings, blocks, reports |
| Realtime | ws://api/community-chat | Customer JWT | Live DMs, group chat, presence, typing |
The split keeps the customer API ergonomic (single token, one prefix) while admin tooling remains under the staff role gate.
Concepts
| Concept | Owns |
|---|---|
| Page | A community space. Has type, category, members, owner, announcements |
| Post | A feed entry — text, media, poll, share. Belongs to a page or a user |
| Comment | A reply tree under a post |
| Reaction | Like, love, etc. on a post, comment, story or message |
| Story | Ephemeral media — auto-expires after 24h |
| Follow | One-way subscription. Person follows person, person follows page |
| Connection | Two-way handshake. Connection requests resolve to an active connection |
| Block | One person blocks another. Blocks suppress feed visibility and DMs |
| Report | Member-submitted moderation report against content or a user |
| DM thread | Direct message conversation between two emails |
| Group chat | Multi-member chat room with member roles |
| Bookmark | Saved pointer to any target (post, page, comment) under an optional collection |
| Announcement | Page-admin-authored broadcast pinned to a page |
| Badge | Awardable marker on a member's profile |
| Notification | In-app activity record, with unread flag |
What's in each page
- Pages and profiles — community pages, member profiles, public read endpoints.
- Posts and feed — creating posts, reading the feed, comments, reactions, polls, shares.
- Stories — 24-hour ephemeral content.
- Follows and connections — one-way follows and two-way connection handshakes.
- Direct messaging — DM REST + WS gateway.
- Group chat — rooms, members, broadcast over WS.
- Moderation and blocking — block users, report content, moderation hooks.
Identity
Community uses Customer principals — the end users of your platform, not your staff. A customer signs in via POST /profile/customer/signin, which mints a JWT used both for REST and the WebSocket handshake. Email is the canonical identifier inside Community: feeds, follows, threads and group memberships are keyed off customer.data.email.
Public reads
Many endpoints are decorated @PublicRoute() so unauthenticated visitors can browse a community: list pages, get a page, read the feed, fetch trending hashtags, view stories. Anything mutating — creating a post, following someone, sending a DM — requires the customer JWT.
# Public — anyone can read the feed
curl https://appengine.appmint.io/client/community/feed \
-H "orgid: my-org"
# Authenticated — must sign in first
curl https://appengine.appmint.io/client/community/posts \
-H "orgid: my-org" \
-H "Authorization: Bearer <customer-jwt>" \
-H "Content-Type: application/json" \
-d '{ "content": { "text": "hello" } }'
How it fits
- DMs and group chat live here — distinct from the staff
ChatModule(which powers customer-support inboxes and AI escalation). - Notifications are written by community services and surfaced via
/client/community/notifications. Email/SMS fan-out is handled by the Sync notification queue, not by Community itself. - Pages and posts are first-class collections (
community_page,community_post, etc.), so they can be queried via the generic/data/{collection}API and segmented by Dynamic Query.
Community is opt-in. If you're building a pure SaaS or e-commerce app, you can leave the module disabled and there's no surface to clean up.