sojorn/_legacy/supabase/BEACON_SYSTEM_EXPLAINED.md
Patrick Britton 3c4680bdd7 Initial commit: Complete threaded conversation system with inline replies
**Major Features Added:**
- **Inline Reply System**: Replace compose screen with inline reply boxes
- **Thread Navigation**: Parent/child navigation with jump functionality
- **Chain Flow UI**: Reply counts, expand/collapse animations, visual hierarchy
- **Enhanced Animations**: Smooth transitions, hover effects, micro-interactions

 **Frontend Changes:**
- **ThreadedCommentWidget**: Complete rewrite with animations and navigation
- **ThreadNode Model**: Added parent references and descendant counting
- **ThreadedConversationScreen**: Integrated navigation handlers
- **PostDetailScreen**: Replaced with threaded conversation view
- **ComposeScreen**: Added reply indicators and context
- **PostActions**: Fixed visibility checks for chain buttons

 **Backend Changes:**
- **API Route**: Added /posts/:id/thread endpoint
- **Post Repository**: Include allow_chain and visibility fields in feed
- **Thread Handler**: Support for fetching post chains

 **UI/UX Improvements:**
- **Reply Context**: Clear indication when replying to specific posts
- **Character Counting**: 500 character limit with live counter
- **Visual Hierarchy**: Depth-based indentation and styling
- **Smooth Animations**: SizeTransition, FadeTransition, hover states
- **Chain Navigation**: Parent/child buttons with visual feedback

 **Technical Enhancements:**
- **Animation Controllers**: Proper lifecycle management
- **State Management**: Clean separation of concerns
- **Navigation Callbacks**: Reusable navigation system
- **Error Handling**: Graceful fallbacks and user feedback

This creates a Reddit-style threaded conversation experience with smooth
animations, inline replies, and intuitive navigation between posts in a chain.
2026-01-30 07:40:19 -06:00

5.5 KiB

Beacon System Architecture

Overview

Sojorn has two separate posting systems that share the same database but create slightly different content:

  1. Regular Posts (compose_screen.dart) - Standard social media posts
  2. Beacon Posts (create-beacon_sheet.dart) - GPS-tagged safety alerts

How It Works

Database Structure

Both systems create records in the posts table, but with different flags:

Field Regular Post Beacon Post
is_beacon FALSE TRUE
beacon_type NULL 'police', 'checkpoint', 'taskForce', 'hazard', 'safety', or 'community'
location NULL GPS coordinates (PostGIS POINT)
confidence_score NULL 0.5 - 1.0 (starts at 50-80% based on user trust)
is_active_beacon NULL TRUE (becomes FALSE when pruned)
allow_chain User choice Always FALSE

User Opt-In System

Critical Feature: Beacon posts are OPT-IN ONLY for feeds.

profiles.beacon_enabled Column

  • Default: FALSE (opted out)
  • When FALSE: User NEVER sees beacon posts in their Following or Sojorn feeds
  • When TRUE: User sees beacon posts mixed in with regular posts
  • Beacon Map: ALWAYS visible regardless of this setting

Why Opt-In?

Some users don't want safety alerts mixed into their social feed. The opt-in system allows:

  • Casual users: Just social content
  • Community safety advocates: Social content + beacons
  • Everyone: Can still view the Beacon Network map anytime

Feed Filtering Logic

feed-personal (Following Feed)

// Check user's beacon preference
const { data: profile } = await supabase
  .from("profiles")
  .select("beacon_enabled")
  .eq("id", user.id)
  .single();

const beaconEnabled = profile?.beacon_enabled || false;

// Build query
let postsQuery = supabase.from("posts").select(...);

// Filter out beacons if user has NOT opted in
if (!beaconEnabled) {
  postsQuery = postsQuery.eq("is_beacon", false);
}

feed-sojorn (Algorithmic Feed)

Same logic - beacons are filtered unless beacon_enabled = TRUE.

Beacon Creation Flow

  1. User opens Beacon Network tab
  2. Taps map to drop beacon
  3. Fills out CreateBeaconSheet:
    • Type (police, checkpoint, etc.)
    • Title
    • Description
    • Optional photo
  4. Submits → Edge function create-beacon
  5. Creates a POST in the posts table with:
    • is_beacon = TRUE
    • beacon_type = <selected_type>
    • location = GPS point
    • category_id = "Beacon Alerts" category
    • confidence_score based on user's trust score
    • allow_chain = FALSE

Regular Post Creation Flow

  1. User taps "New Post" button
  2. Fills out ComposeScreen:
    • Community selection
    • Body text
    • Optional photo
    • Toggle for chain responses
  3. Submits → Edge function publish-post
  4. Creates a POST in the posts table with:
    • is_beacon = FALSE
    • No GPS data
    • User-selected category
    • User's chain preference

Key Differences

Feature Regular Post Beacon Post
Purpose Social sharing Safety alerts
GPS Data No Required
Visible On Feeds (if user follows author) Beacon map + feeds (if user opted in)
Category User selects Always "Beacon Alerts"
Chaining User choice Disabled
Confidence Score No Yes (trust-based)
Voting No Yes (vouch/report)
Auto-Pruning No Yes (low confidence + old = disabled)

User Experience Scenarios

Scenario 1: User With Beacons Disabled (Default)

Following Feed: ✓ Regular posts from people they follow
Sojorn Feed:    ✓ Algorithmic regular posts
Beacon Map:     ✓ All active beacons in area

Scenario 2: User With Beacons Enabled

Following Feed: ✓ Regular posts + beacons from people they follow
Sojorn Feed:    ✓ Algorithmic regular posts + beacons
Beacon Map:     ✓ All active beacons in area

Scenario 3: User Creates Beacon

  1. Beacon appears on map IMMEDIATELY for ALL users
  2. Beacon appears in creator's feed (if they have beacons enabled)
  3. Beacon appears in OTHER users' feeds (if they follow creator AND have beacons enabled)

Migration Required

To enable this system, run:

-- Add beacon_enabled column to profiles
ALTER TABLE profiles ADD COLUMN IF NOT EXISTS beacon_enabled BOOLEAN NOT NULL DEFAULT FALSE;

-- Add index for fast filtering
CREATE INDEX IF NOT EXISTS idx_profiles_beacon_enabled ON profiles(beacon_enabled) WHERE beacon_enabled = TRUE;

Or apply the migration file:

# Via Supabase Dashboard SQL Editor
# Paste contents of: supabase/migrations/add_beacon_opt_in.sql

Edge Functions Updated

  1. feed-personal - Now filters beacons based on user preference
  2. feed-sojorn - Now filters beacons based on user preference
  3. create-beacon - Creates beacon posts correctly
  4. publish-post - Creates regular posts correctly

Frontend Components

  • ComposeScreen - Regular post composer
  • CreateBeaconSheet - Beacon post composer
  • 🔲 Settings Screen - TODO: Add toggle for beacon_enabled preference
  • BeaconScreen - Shows beacons on map (always visible)
  • FeedPersonalScreen - Filtered feed
  • FeedSojornScreen - Filtered feed

Next Steps

  1. Apply database migration (add_beacon_opt_in.sql)
  2. Deploy updated edge functions
  3. Add UI toggle in user settings for beacon opt-in
  4. Test both posting flows
  5. Verify feed filtering works correctly