Community: in-app feed, comments and profiles

Everything is driven from Community in the sidebar, once you have picked the app concerned. Each community belongs to one app and one only.

Enabling it

Customise → General → Community enabled.

Enabling does three things at once, so you do not have to guess them:

  1. the feed becomes visible in the SDK
  2. a default group is created
  3. the Community product is enabled on your App ID

While it is off, the SDK shows a waiting screen and no content is served. That is the default: nobody wants an empty feed appearing in a production app on deployment day.


Groups

The tabs of your feed. A post belongs to exactly one group, which keeps the tabs readable and the counters honest.

SettingEffect
Name, emoji, descriptionWhat the member sees
Who can post"Everyone" or "The team only"
ArchiveHidden in the app, its posts stay in the database

"The team only" turns the group into a noticeboard: members read and comment, they do not post. That is the mechanism behind welcome groups of the "About…" kind.

The default group receives posts with no explicit group. It can be neither deleted nor archived - otherwise those posts would have nowhere to go. A group can only be deleted when empty; otherwise, archive it.


Posts

The table of everything published, by your team as well as by members. Filterable by group, status and full-text search.

Posting

A studio post carries the "team" badge and does not go through moderation: you do not have to pass your own filter. The configured maximum length applies to members, not to your announcements.

Options: pin to the top of the group, show or hide the team badge, schedule.

Scheduling

Set a future date: the post goes out automatically at that time (to the minute). A future date always implies scheduling, even if you ask to "publish now" - otherwise a post dated tomorrow would appear at the top of the feed today.

Creating in bulk

Up to 50 posts at once, to seed a community or roll out an editorial calendar. One block per post, the shared options at the top.

It is all or nothing: if one entry is rejected, none is created. A half published series would be more painful to recover from than a clean failure, because you would first have to work out where it stopped.

Statuses

StatusMeaning
PublishedVisible in the feed
Awaiting reviewHeld by moderation, visible only to its author
ScheduledWill go out at its date
DraftWill not go out until you decide
RemovedRemoved by moderation, kept for audit

Deleting or removing

Two different acts:

  • Delete (Posts table) erases permanently, with comments and reactions. For content that should never have existed - personal data published by mistake, an erasure request.
  • Remove (moderation queue) sets it to "Removed" and logs the decision. That is the act for sanctioning.

Members

Everyone who has opened the community. A profile is created the first time the feed opens, with no sign-up.

Editable inline:

  • Role - member, moderator, admin
  • Team badge - shows a badge under the nickname in the feed

You can edit neither the nickname nor the bio of a member. Moderating content is legitimate; rewriting someone's identity is not. Sanctions go through the Decision button, which logs them.


Moderation

Queue

Reports from members, enriched with an excerpt of the content concerned, its author and the number of reports on the same target - enough to decide without opening three screens.

A member reports a piece of content only once: otherwise the counter that triggers automatic hiding would be trivial to manipulate.

Decisions

A single route for every action, which guarantees that no decision escapes the log.

On content:

ActionEffect
Leave onlineDismisses the reports, the content stays
RemoveHidden for everyone, kept for audit
RestoreUndoes a removal

On a profile:

ActionEffect
WarnLogged, no visible effect
Shadow banThe member posts and sees their content, nobody else does. Never notified
BanRead only
Lift the sanctionBack to normal
Erase the profileNickname, bio and avatar erased (GDPR). Posts remain, signed with the name of the time

Ban and shadow ban accept a duration; with no duration, the sanction is permanent. A temporary sanction is lifted automatically when the member returns.

The shadow ban is the only tool that does not announce itself. A banned member knows it and goes to complain elsewhere; a shadow banned member keeps talking into the void. Reserve it for cases where the noise is the problem.

Modes

Customise → Moderation.

ModeBehaviour
OffEverything is published. Reports still arrive
AutomaticEvery piece of content is evaluated before publication
ManualNothing is published without approval. Only sustainable at low volume

In automatic mode, two thresholds between 0 and 1:

  • above the review threshold, the content goes to the queue instead of being published;
  • above the rejection threshold, it is rejected outright and the author knows.

Banned words are compared on whole words, ignoring case and accents. A match rejects the content without calling the classifier.

Automatic hiding after N reports sets the content aside pending arbitration. That is what lets the community defend itself overnight. Zero disables it.

If the classifier fails, the content is published. A community that rejects everything because a provider is down is broken in a far more visible way than an hour of unfiltered content. Reports remain the safety net.

Log

Every decision, human and automatic, with its reason. Never edited, never purged: it is what lets you answer "why was this member banned?" six months later.


Statistics

Every counter is shown with its value over the previous period of the same length. "240 posts" says nothing; "240 against 180" says everything.

Audience

Members, new members, active members, active per day, opens.

"Active members" counts distinct people who opened the community, not the number of opens.

Contribution

Posts, comments, reactions, views, and the participation rate: the share of active members who post or comment.

It is the metric that separates a community from a wall of announcements. An audience that climbs with a rate that collapses describes a community people watch without taking part in.

Views are unique per member: scrolling back over a post does not inflate the counter.

Health

Pending reports, reports over the period, removed content, banned members. These metrics are inverted on display - a rise is shown in red.

Retention

The share of each weekly cohort still active N weeks later. The colour intensity carries the information: you read a sagging curve at a glance.

It is the only indicator that says whether the community holds. An activity curve can climb purely because you are acquiring, while every cohort evaporates.

Leaderboards

Top contributors and most viewed posts, over the period and not cumulative. A leaderboard frozen on totals would reward the old-timers forever and hide who is carrying the community this month.


Customising

Four tabs, each saved independently: setting moderation does not overwrite the theme.

TabContents
GeneralEnabling, features, translation
AppearanceColour, font, size, corner radius, light/dark theme, preview
ContentMaximum lengths, images per post, lines before "see more", flood protection
ModerationMode, thresholds, automatic hiding, rules, banned words

Every change is picked up by the SDK on the next open, with no resubmission of the app.

Using your own font

In Appearance, choose "Custom" and enter the PostScript name of a font already bundled in your app - not the file name.

bash
# Find the PostScript name of a font file
mdls -name com_apple_ats_name_postscript MyFont.ttf

If the SDK cannot find the font, it silently falls back to the system font: a missing font must not make the feed unreadable.

This setting is iOS only: on Android, "custom" and "rounded" fall back to the system default. Bundling a typeface in the SDK would weigh on every integrating app, including the ones that do not want it.

Instant translation

Content is translated into the reader's device language. The first reader of a language pays for the call to the translator, the following ones read the cache - that is what makes the feature sustainable.

The member can always go back to the original text.


Embedding the feed in your app

The feed is rendered natively by the SDK. Your app provides an entry point - a tab, a button - and the SDK draws the rest. Two prerequisites:

  1. The SDK is installed and AppwinCore.configure is called at launch (AppwinCore.instance.configure in Dart).
  2. The community is enabled, as described at the top of this page. Without that, the SDK renders a waiting screen and the calls get a 403.

SwiftUI - in a tab

swift
import AppwinCommunity

TabView {
  HomeView()
    .tabItem { Label("Home", systemImage: "house") }

  AppwinCommunity.communityView()
    .tabItem { Label("Community", systemImage: "bubble.left.and.bubble.right") }
}

UIKit

swift
let communityVC = AppwinCommunity.communityViewController()
communityVC.tabBarItem = UITabBarItem(
  title: "Community",
  image: UIImage(systemName: "bubble.left.and.bubble.right"),
  tag: 1
)
tabBarController.viewControllers = [homeVC, communityVC, profileVC]

Modal

swift
AppwinCommunity.presentCommunity()

What the member can do

Depending on what is enabled in the dashboard:

  • read the feed, filter by group, pull to refresh
  • post, edit and delete their own content
  • comment, reply to a comment (one level only)
  • react to posts and comments
  • view profiles, edit their own, go back to anonymous
  • report a post, a comment or a profile
  • read in their own language if translation is on

Each of these has a switch on the studio side. A feature that is turned off disappears from the interface; it is not greyed out.


Localisation

The SDK's labels are resolved in your app's resources, not in the module's. You can therefore translate or reword any label without waiting for a release from us.

Add an AppwinCommunity.strings to your project:

Plain text
"community.new_post" = "Share something";
"community.like" = "Like";
"community.comments" = "Reactions";

The keys are listed in CommunityStrings.swift.

With no resource provided, the SDK uses its English defaults - never a raw key on screen. Two uses:

  • translating into a language we do not ship yet
  • rewording a label that does not match your tone

Troubleshooting

SymptomLikely cause
"Coming soon" screenCommunity disabled in the dashboard
403 on every callCommunity product not enabled on the App ID - re-enable it from Customise
Empty feed with no errorNo posts; publish from the dashboard to seed it
The feed does not scroll (Flutter)A parent widget intercepts the gesture
Native error screenconfigure not called before the view is shown
iOS build failsDeployment target below iOS 16

Next