Circles
Overview
Circles are private, small-group spaces within CommonPlace that allow users to share content with a specific subset of their friends. Unlike public posting, circle posts are only visible to members of the selected circle(s). This feature supports the platform's emphasis on human-scale social contexts by enabling more intimate sharing without broadcasting to everyone.
There are two types of circles: static circles where members are explicitly invited, and dynamic circles where membership is determined by view rules (such as relationship types). Circles support full lifecycle management including creation, member invitation, role management (admin/member), and deletion. Each circle maintains its own feed pacing state so users can catch up on a per-circle basis.
Circles integrate deeply with the post system through audience controls. When creating a post, users can select "Circles" as the audience and choose one or more circles to share with. The feed supports filtering by individual circles, and new post counts per circle are displayed in the filter dropdown.
Relevant Invariants
- Invariant #7: "Human-Scale Social Contexts" -- Circles are intentionally small groups of mutual friends, not broadcast channels.
- Invariant #14: "Privacy Is Infrastructure" -- Circle posts are only visible to circle members through RLS policies.
- Invariant #19: "Complexity Must Be Earned" -- Circle creation is rate-limited, and new accounts face additional restrictions.
User Experience
User Flow
- Creating a circle: Navigate to the Circles page and click "Create Circle". Provide a name and optional description. For dynamic circles, define view rules instead of inviting members.
- Inviting friends: Within a circle, use the invite modal to select friends to invite. Blocked users are automatically excluded from the available friends list.
- Accepting an invite: Invited users see pending invitations and can accept or decline.
- Posting to a circle: When composing a post, select "Circles" as the audience and choose target circles.
- Viewing circle posts: Filter the main feed by a specific circle, or visit the circle's detail page.
- Managing members: Admins can invite, remove, promote/demote members, and update circle details.
- Leaving or deleting: Members can leave; admins can delete the circle.
Technical Implementation
Key Files
| File | Purpose |
|---|---|
src/hooks/useCircles.js | Main hooks: useCircles (list all), useCircle (single circle management), useAvailableFriends (invite candidates), useCirclePosts (circle feed) |
src/hooks/useCircleFeedState.js | Per-circle feed pacing: useCircleFeedState, useCircleNewPostCount, useMarkCircleChecked, useAllCirclesNewPostCounts |
src/components/circles/CreateCircleModal.jsx | Modal for creating a new static circle |
src/components/circles/CreateDynamicCircleModal.jsx | Modal for creating a dynamic circle with view rules |
src/components/circles/CreateCircleChooser.jsx | Chooser between static and dynamic circle creation |
src/components/circles/InviteFriendModal.jsx | Modal for inviting friends to a circle |
src/components/circles/CharterEditor.jsx | Editor for circle charters (guidelines) |
src/components/circles/CharterDisplay.jsx | Display component for circle charters |
useCircles() Hook
Fetches all circles the current user belongs to, separating them into active memberships and pending invites. For each circle, it fetches the member count.
Returns:
myCircles-- Active circle memberships with member count, user role, and circle detailspendingInvites-- Circles the user has been invited to but not yet acceptedcreateCircle(name, description)-- Creates a static circle via thecreate_circleRPC function (SECURITY DEFINER). Rate-limited.createDynamicCircle(name, description, rules)-- Creates a dynamic circle with view rulesacceptInvite(circleId)/declineInvite(circleId)-- Handle invitations
useCircle(circleId) Hook
Manages a single circle with full CRUD operations.
Returns:
circle,members,pendingInvites,viewRules,userMembership- Derived:
isAdmin,isMember,isInvited,isDynamic,memberCount,isOnlyAdmin - Actions:
updateCircle,inviteFriend,cancelInvite,removeMember,updateMemberRole,leaveCircle,deleteCircle,updateViewRules
useAvailableFriends(circleId) Hook
Fetches friends who can be invited to a circle. Excludes users who are already members/invited and users who are blocked in either direction.
useCirclePosts(circleId) Hook
Fetches posts shared to a specific circle with pagination (20 per page). Uses an RPC function get_circle_posts_excluding_blocked to filter out posts from blocked users, with a fallback to a direct query if the RPC function is not available.
Database Tables
| Table | Purpose |
|---|---|
circles | Circle definitions: name, description, circle_type (static/dynamic), created_by |
circle_members | Membership records: circle_id, user_id, role (admin/member), status (member/invited), invited_by, responded_at |
circle_view_rules | View rules for dynamic circles: rule_type, rule_values, mutual_only |
post_circles | Associates posts with circles (many-to-many) |
circle_feed_state | Per-user, per-circle feed pacing state |
circle_shares | Records of posts shared to circles (for the share-to-circle feature) |
Rate Limiting
Circle creation uses tier-aware rate limiting via useTierAwareRateLimit. New accounts face additional restrictions and cannot create circles until their account matures. Circle invitations are also rate-limited.
Edge Cases
| Scenario | Behavior |
|---|---|
| New account tries to create circle | Blocked with isNewAccountRestriction flag and descriptive error message |
| Last admin tries to leave | isOnlyAdmin flag is set; UI should warn before allowing |
| Blocked user in available friends | Automatically excluded by useAvailableFriends which checks blocks in both directions |
| Circle deleted | All associated circle_members and post_circles records are cascade deleted |
| Post shared to multiple circles | Multiple post_circles records are created; post appears in each circle's feed |
| Dynamic circle with view rules | Membership is determined by rules rather than explicit invites; rules can be updated by admin |
Related
- Feed -- Feed supports per-circle filtering and shows new post counts per circle
- Friends -- Only friends can be invited to circles
- Posts -- Posts can target circles as their audience
Last updated: 2026-02-07