11 KiB
Sojorn Development TODO
Last Updated: February 7, 2026
🎯 High Priority — Feature Work
1. Finalize AI Moderation — Image & Video
Status: In Progress
Text moderation is live (OpenAI Moderation API). Image and video moderation not yet implemented.
- Add image moderation to post creation flow (send image to OpenAI or Vision API)
- Add video moderation via thumbnail extraction (grab first frame or key frame)
- Run extracted thumbnail through same image moderation pipeline
- Flag content that exceeds thresholds into
moderation_flagstable - Wire into existing Three Poisons scoring (Hate, Greed, Delusion)
- Add admin queue visibility for image/video flags
Backend: go-backend/internal/handlers/post_handler.go (CreatePost flow)
Key decision: Use OpenAI Vision API for images, ffmpeg thumbnail extraction for video on the server side
2. Quips — Complete Video Recorder & Editor Overhaul
Status: Needs major work
Current recorder is basic. Goal: TikTok/Instagram-level recording and editing experience.
- Multi-segment recording with pause/resume
- Speed control (0.5x, 1x, 2x, 3x)
- Filters and effects (color grading, beauty mode)
- Text overlays with timing and positioning
- Music/audio overlay from library or device
- Trim and reorder clips
- Transitions between segments
- Preview before posting
- Progress indicator during upload
- Thumbnail selection for posted quip
Frontend: sojorn_app/lib/screens/quips/create/
Packages to evaluate: camera, ffmpeg_kit_flutter, video_editor
3. Beacon Page Overhaul — Local Safety & Social Awareness
Status: Basic beacon system exists (post, vouch, report). Needs full redesign.
Vision: Citizen + Nextdoor but focused on social awareness over fear-mongering.
- Redesign beacon feed as a local safety dashboard
- Map view with clustered pins (incidents, community alerts, mutual aid)
- Beacon categories: Safety Alert, Community Need, Lost & Found, Event, Mutual Aid
- Verified/official source badges for local orgs
- "How to help" action items on each beacon (donate, volunteer, share)
- Tone guidelines — auto-moderate fear-bait and rage-bait language
- Neighborhood/radius filtering
- Push notifications for nearby beacons (opt-in)
- Confidence scoring visible to users (vouch/report ratio)
- Resolution status (active → resolved → archived)
Backend: go-backend/internal/handlers/post_handler.go (beacon endpoints)
Frontend: sojorn_app/lib/screens/beacons/
⚠️ Medium Priority — Core Features
4. User Profile Customization — Modular Widget System
Status: Basic profiles exist. Needs a modular, personalized approach.
Vision: New-age MySpace — users pick and arrange profile widgets to make it their own, without chaos.
Core Architecture:
- Profile is a grid/stack of draggable widgets the user can add, remove, and reorder
- Each widget is a self-contained component with a fixed max size and style boundary
- Widgets render inside a consistent design system (can't break the layout or go full HTML)
- Profile data stored as a JSON
profile_layoutcolumn: ordered list of widget types + config
Standard Fields (always present):
- Avatar + display name + handle (non-removable header)
- Bio (rich text, links, emoji)
- Pronouns field
- Location (optional, city-level)
Widget Catalog (user picks and arranges):
- Pinned Posts — Pin up to 3 posts to the top of your profile
- Music Widget — Currently listening / favorite track (Spotify/Apple Music embed or manual)
- Photo Grid — Mini gallery (3-6 featured photos from uploads)
- Social Links — Icons row for external links (site, GitHub, IG, etc.)
- Causes I Care About — Tag-style badges (environment, mutual aid, arts, etc.)
- Featured Friends — Highlight 3-6 people (like MySpace Top 8 but chill)
- Stats Widget — Post count, follower count, member since (opt-in)
- Quote Widget — A single styled quote / motto
- Beacon Activity — Recent community contributions
- Custom Text Block — Markdown-rendered freeform section
Theming (constrained but expressive):
- Accent color picker (applies to profile header, widget borders, link color)
- Light/dark/auto profile theme (independent of app theme)
- Banner image (behind header area)
- Profile badges (verified, early adopter, community helper — system-assigned)
Implementation:
- Backend:
profile_layout JSONBcolumn onprofilestable - Backend:
PUT /profile/layoutendpoint to save widget arrangement - Frontend:
ProfileWidgetRendererthat reads layout JSON and renders widget stack - Frontend:
ProfileEditorwith drag-to-reorder and add/remove widget catalog - Widget sandboxing — each widget has max height, no custom CSS/HTML injection
- Default layout for new users (bio + social links + pinned posts)
5. Blocking System
Status: Basic block exists. Import/export not implemented.
- Verify block prevents: seeing posts, DMs, mentions, search results, follow
- Block list management screen (view, unblock)
- Export block list as JSON/CSV
- Import block list from JSON/CSV
- Import block list from other platforms (Twitter/X format, Mastodon format)
- Blocked users cannot see your profile or posts
- Silent block (user doesn't know they're blocked)
Frontend: sojorn_app/lib/screens/profile/blocked_users_screen.dart
Backend: go-backend/internal/handlers/user_handler.go
6. E2EE Chat Stability & Sync
Status: X3DH implementation works but key sync across devices is fragile.
- Audit key recovery flow — ensure it reliably recovers from MAC errors
- Device-to-device key sync without storing plaintext on server
- QR code key verification between users
- "Encrypted with old keys" messages should offer re-request option
- Clean up
forceResetBrokenKeys()dead code insimple_e2ee_service.dart - Ensure cloud backup/restore cycle works end-to-end
- Add key fingerprint display in chat settings
- Rate limit key recovery to prevent loops
7. Repost / Boost Feature
Status: Not started.
A "repost" action that amplifies content to your followers without quote-posting.
- Repost button on posts (share to your followers' feeds)
- Repost count displayed on posts
- Reposted-by attribution in feed ("@user reposted")
- Undo repost
- Backend:
repoststable (user_id, post_id, created_at) - Feed algorithm weights reposts into feed ranking
8. Algorithm Refactor — Promote Good, Discourage Anger
Status: Basic algorithm exists in algorithm_config table. Needs philosophical overhaul.
Core principle: Show users what they love, not what they hate.
- Engagement scoring that weights positive interactions (save, repost, thoughtful reply) over rage-clicks
- De-rank content with high negative-reaction ratios
- "Cooling period" — delay viral anger content by 30min before amplifying
- Boost content tagged as good news, community, mutual aid, creativity
- User-controllable feed preferences ("show me more of X, less of Y")
- Diversity injection — prevent echo chambers by mixing in adjacent-interest content
- Transparency: show users why a post appeared in their feed
- Admin algorithm tuning panel (already built in admin dashboard)
- A/B testing framework for algorithm changes
🔧 Low Priority — Polish & Cleanup
9. Remaining Code TODOs
Small scattered items across the codebase:
sojorn_rich_text.dart— Implement profile navigation from @mentionspost_with_video_widget.dart— Implement post options menu (edit, delete, report)video_player_with_comments.dart— Implement "more options" buttonsojorn_swipeable_post.dart— Wire up allowChain setting when API supports itreading_post_card.dart— Implement share functionality
10. Legacy Cleanup
- Delete
go-backend/cmd/supabase-migrate/directory (dead migration tool) - Update 2 stale Supabase comments in
go-backend/internal/middleware/auth.go - Remove
forceResetBrokenKeys()fromsimple_e2ee_service.dart
✅ Completed
Core Platform (shipped)
- ✅ Go backend — 100% migrated from Supabase
- ✅ User auth (JWT, refresh tokens, email verification)
- ✅ Posts (create, edit, delete, visibility, chains)
- ✅ Comments (threaded, with replies)
- ✅ Feed algorithm (basic version)
- ✅ Image/video uploads to Cloudflare R2
- ✅ Follow/unfollow system
- ✅ Search (users, posts, hashtags)
- ✅ Categories and user settings
- ✅ Chain posts
- ✅ Beacon voting (vouch, report, remove vote)
- ✅ E2EE chat (X3DH, key backup/restore)
- ✅ Push notifications (FCM)
- ✅ Quips (basic video recording and feed)
Admin & Moderation (shipped)
- ✅ Admin panel (Next.js dashboard, users, posts, moderation queue, appeals)
- ✅ OpenAI text moderation (auto-flag on post/comment creation)
- ✅ Three Poisons scoring (Hate, Greed, Delusion)
- ✅ Ban/suspend system with content jailing
- ✅ Email notifications (ban, suspend, restore, content removal)
- ✅ Moderation queue with dismiss/action/ban workflows
- ✅ User violation tracking and history
- ✅ IP-based ban evasion detection
Infrastructure (shipped)
- ✅ PostgreSQL with full schema
- ✅ Cloudflare R2 media storage
- ✅ Nginx reverse proxy + SSL/TLS
- ✅ Systemd service management
- ✅ GeoIP for location features
- ✅ Automated deploy scripts
NSFW Moderation System (Feb 7, 2026)
- ✅ AI moderation prompt: Cinemax nudity rule, violence 1-10 scale (≤5 allowed)
- ✅ Three-outcome moderation: clean / nsfw (auto-label + warn) / flag (remove + appeal email)
- ✅ DB:
nsfw_blur_enabledcolumn onuser_settings - ✅ Backend:
is_nsfw/nsfw_reasonreturned from ALL post queries (feed, profile, detail, saved, liked, chain, focus context) - ✅ Backend: NSFW posts excluded from search, discover, trending, hashtag pages
- ✅ Backend: NSFW in feed limited to own posts + followed users only
- ✅ Backend:
nsfw_warningandcontent_removednotification types + appeal email - ✅ Backend: user self-labeling (
is_nsfwin CreatePost) - ✅ Flutter: NSFW opt-in toggle + blur toggle in settings (hidden behind expandable at bottom)
- ✅ Flutter: 18+ confirmation dialog for enabling NSFW (moderation rules, not a free-for-all)
- ✅ Flutter: 18+ confirmation dialog for disabling blur (disturbing content warning)
- ✅ Flutter: 6-click path to enable (profile → settings → expand → toggle → confirm → enable)
- ✅ Flutter: blur enforced everywhere — post card, threaded conversation, parent preview, replies
- ✅ Flutter: NSFW self-label toggle in compose toolbar
- ✅ Flutter:
publishPostAPI sendsis_nsfw/nsfw_reason
Recent Fixes (Feb 2026)
- ✅ Notification badge count clears on archive
- ✅ Notification UI → full page (was slide-up dialog)
- ✅ Moderation queue constraint fix (dismissed/actioned statuses)
- ✅ Debug print cleanup (190+ statements removed)
- ✅ Run scripts cleanup (run_dev, run_web, run_web_chrome)