The community behind EventOxygen is one shared feed with several views. Every event has a community page; the Explore feed inside an event is that page's feed. Connections, messages and meetings are global to the person, not to the event.
Pages
Datatype community_page. The app looks up the page for the active event with GET /client/community/pages?type=event and scopes the feed to it. If no page exists for an event, the app falls back to the global feed, which is why an event with no page can show posts from everywhere.
| Operation | Route | Who |
|---|---|---|
| List / read pages | GET pages, GET pages/:pageId, GET pages/:pageId/members | Anyone |
| Create / edit | POST pages, PUT pages/:pageId | Signed-in customer or staff |
| Join / leave / invite | POST pages/:pageId/join, /leave, /invite | Signed-in |
| My pages | GET pages/mine | Signed-in |
A page keeps stats.postCount, incremented and decremented as posts come and go.
Announcements
Announcements are page broadcasts (pages/:pageId/announcements). Reading is public; creating requires page admin rights. They are the right channel for "the keynote moved to Hall B" because they are attached to the event's page rather than lost in the feed.
The announcements screen exists in the attendee app but nothing links to it yet. Announcements are still delivered as community_notification records of type announcement, so they appear in the Inbox → Notifications tab.
Stories
Twenty-four-hour stories (community_story) show in the bar at the top of the feed. A story has a caption (up to 500 characters), text content, background colour, stickers (text, emoji, mention, hashtag, location, poll, link), a default duration of 5 seconds, expiresAt, and can be kept as a highlight. Views and reactions are counted; status moves active → expired → removed.
Moderation
Posts carry status: active, flagged, removed, draft, with moderatedAt, moderatedBy and moderatedReason. Removing a post is a status change, not a deletion, so the audit trail survives.
Comments are soft-removed (status: removed) and the post's comment count is decremented. Only the author can delete their own comment from the app; staff moderate from the admin side.
Blocks (community_block) are per person and symmetric in effect: a message from either side of a block is refused with 403, and blocked people cannot send connection requests.
Reports (POST reports) let attendees flag a post, comment or person for review.
Hashtags and trending
Hashtags and mentions are extracted from post content automatically. Each hashtag record keeps usageCount and lastUsedAt, which is what GET hashtags/trending ranks on. Encourage a hashtag per track and the search screen's hashtag tab becomes a live programme feed.
Connections
Datatype community_connection, matched by email in both directions.
| Status | How it gets there |
|---|---|
pending | A request was sent. Only the target can respond; anyone else gets 403. |
accepted | The target accepted. Both people see each other under Connections. |
rejected | The target declined. A new request can be sent later. |
cancelled | The requester withdrew it. |
blocked | One side blocked the other; further requests are refused. |
A request is refused when the two are already connected, when one is already pending, when either has blocked the other, or when someone tries to connect with themselves. POST connections/accept-all accepts every pending request at once — useful for a speaker after a busy session.
Meetings
A meeting (community_meeting) starts proposed with every participant pending. It becomes confirmed only when all participants have accepted. Rescheduling resets everyone to pending and the meeting to proposed. The upcoming list shows confirmed meetings only, so a proposed meeting nobody accepted never clutters the day.
Group chats
community_group_chat and the groups/* routes exist on the server (create, list, messages, add and remove members), and the realtime gateway relays sendGroupMessage and groupTyping. The attendee app has no group-chat screen today; direct messages are the only conversation type it shows. Treat group chats as API-only until the app catches up.
Badges
GET badges lists the community badges an organization defines; GET badges/mine returns the ones a person has earned. Earning a badge produces a badge_earned notification.
Staff versus attendee surface
Staff have an admin mirror at /community/* (staff role required) covering connections, messages, meetings, blocks and reports with the same shapes as the /client/community/* routes. Posts, the feed, stories, bookmarks and pages are client-only: staff act on them as ordinary members through the client routes, or through Studio Manager.
| Capability | /client/community (attendee) | /community (staff) |
|---|---|---|
| Feed, posts, comments, reactions, polls | Yes | No |
| Stories, bookmarks, follow | Yes | No |
| Pages and announcements | Yes (page admin to post) | No |
| Connections, messages, meetings | Yes | Yes |
| Blocks, reports | Yes | Yes |