Reframe Sojorn as Friends-First Social Network
## Remove All 'Calm' References & Reframe Platform Identity ### Documentation Updates - **Deleted**: CALM_UX_GUIDE.md (outdated philosophy document) - **Updated**: All documentation to remove 'calm' terminology - **Reframed**: Platform as 'friends-first' instead of 'calm' ### Design System Changes - Replace 'calm & elegant' with 'warm & welcoming' - Update theme descriptions to focus on friendliness - Change 'calm velocity' to 'authentic engagement' - Update UI microcopy for friendly tone ### Content Updates - Philosophy documents reframe for social connection focus - Design guides emphasize warmth over calmness - API documentation updated for new terminology - User-facing text changed to friendly language ### Key Terminology Changes - 'Calm design' 'Warm, welcoming design' - 'Calm velocity' 'Authentic engagement' - 'Calm UI' 'Friendly UI' - 'Structural calm' 'Structural friendliness' - 'Calm platform' 'Friends-first platform' ### Platform Focus Shift - From: Text-based calm platform - To: Friends-first social network prioritizing genuine connections - Emphasis on social connection over mindfulness - Focus on warmth and friendliness in design ### Files Modified - 15+ documentation files updated - Flutter app UI text updated - Design system rebranded - Philosophy documents reframed - API documentation updated The platform is now positioned as a warm, welcoming social network that prioritizes genuine human connections over calm minimalism.
This commit is contained in:
parent
38653f5854
commit
b9351b76ae
|
|
@ -4,10 +4,10 @@
|
||||||
The Sojorn app now supports two themes that users can switch between:
|
The Sojorn app now supports two themes that users can switch between:
|
||||||
|
|
||||||
### 1. **Basic Theme** (Original)
|
### 1. **Basic Theme** (Original)
|
||||||
- Calm and elegant design
|
- Warm and welcoming design
|
||||||
- Lighter feel with subtle pink tints
|
- Lighter feel with subtle pink tints
|
||||||
- Slightly larger font sizes
|
- Slightly larger font sizes
|
||||||
- Perfect for reading and reflection
|
- Perfect for reading and connection
|
||||||
|
|
||||||
### 2. **Pop Theme** (New - "Awakening")
|
### 2. **Pop Theme** (New - "Awakening")
|
||||||
- High contrast and energetic
|
- High contrast and energetic
|
||||||
|
|
@ -67,7 +67,7 @@ The selected theme is automatically saved and persists across app sessions.
|
||||||
- Background: Very pale lavender/pink (#F9F2F7)
|
- Background: Very pale lavender/pink (#F9F2F7)
|
||||||
- Text: 19px body, softer navy
|
- Text: 19px body, softer navy
|
||||||
- Spacing: More generous
|
- Spacing: More generous
|
||||||
- Feel: Calm, elegant, reflective
|
- Feel: Warm, welcoming, social
|
||||||
|
|
||||||
### Pop Theme:
|
### Pop Theme:
|
||||||
- Background: Clean pale lavender (#F9F6F9)
|
- Background: Clean pale lavender (#F9F6F9)
|
||||||
|
|
|
||||||
|
|
@ -425,7 +425,7 @@ class _ProfileSettingsScreenState extends ConsumerState<ProfileSettingsScreen> {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _ThemeOption(
|
child: _ThemeOption(
|
||||||
title: 'Basic',
|
title: 'Basic',
|
||||||
description: 'Calm & elegant',
|
description: 'Warm & welcoming',
|
||||||
isSelected: currentTheme == app_theme.ThemeMode.basic,
|
isSelected: currentTheme == app_theme.ThemeMode.basic,
|
||||||
onTap: () => ref
|
onTap: () => ref
|
||||||
.read(app_theme.themeProvider.notifier)
|
.read(app_theme.themeProvider.notifier)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import 'markdown_post_body.dart';
|
||||||
/// Widget for displaying a sponsored post (First-Party Contextual Ad)
|
/// Widget for displaying a sponsored post (First-Party Contextual Ad)
|
||||||
///
|
///
|
||||||
/// Design: Distinguishable from regular posts but not distracting.
|
/// Design: Distinguishable from regular posts but not distracting.
|
||||||
/// - "Sponsored by [advertiserName]" header (small, uppercase, calm)
|
/// - "Sponsored by [advertiserName]" header (small, uppercase, subtle)
|
||||||
/// - Subtle background tint (surfaceVariant) to legally distinguish from editorial
|
/// - Subtle background tint (surfaceVariant) to legally distinguish from editorial
|
||||||
/// - Markdown body content
|
/// - Markdown body content
|
||||||
/// - Distinct CTA button (OutlinedButton with "Visit Site" icon)
|
/// - Distinct CTA button (OutlinedButton with "Visit Site" icon)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import '../theme/app_theme.dart';
|
||||||
|
|
||||||
/// Safety Redirect Sheet
|
/// Safety Redirect Sheet
|
||||||
///
|
///
|
||||||
/// A calm, clean modal bottom sheet that reminds users to be careful
|
/// A clean, friendly modal bottom sheet that reminds users to be careful
|
||||||
/// when visiting external links.
|
/// when visiting external links.
|
||||||
class SafetyRedirectSheet extends StatelessWidget {
|
class SafetyRedirectSheet extends StatelessWidget {
|
||||||
final String url;
|
final String url;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ This guide consolidates all development, architecture, and design system documen
|
||||||
|
|
||||||
### Core Principles
|
### Core Principles
|
||||||
|
|
||||||
Sojorn's calm is not aspirational—it is **structural**. The architecture enforces behavioral philosophy through database constraints, API design, and systematic patterns that make certain behaviors impossible, not just discouraged.
|
Sojorn's friendliness is not aspirational—it is **structural**. The architecture enforces behavioral philosophy through database constraints, API design, and systematic patterns that make certain behaviors impossible, not just discouraged.
|
||||||
|
|
||||||
### 1. Blocking: Complete Disappearance
|
### 1. Blocking: Complete Disappearance
|
||||||
|
|
||||||
|
|
@ -198,7 +198,7 @@ $$ LANGUAGE SQL;
|
||||||
|
|
||||||
### Visual Philosophy
|
### Visual Philosophy
|
||||||
|
|
||||||
**Calm, Not Sterile**
|
**Warm, Not Overwhelming**
|
||||||
- Warm neutrals (beige/paper tones) instead of cold grays
|
- Warm neutrals (beige/paper tones) instead of cold grays
|
||||||
- Soft shadows, never harsh
|
- Soft shadows, never harsh
|
||||||
- Muted semantic colors that inform without alarming
|
- Muted semantic colors that inform without alarming
|
||||||
|
|
@ -230,7 +230,7 @@ surfaceVariant = #F0EFEB // Subtle warm gray (inputs)
|
||||||
|
|
||||||
#### Semantic Colors
|
#### Semantic Colors
|
||||||
```dart
|
```dart
|
||||||
primary = #6B5B95 // Soft purple (calm authority)
|
primary = #6B5B95 // Soft purple (friendly authority)
|
||||||
secondary = #8B7355 // Warm brown (earth tone)
|
secondary = #8B7355 // Warm brown (earth tone)
|
||||||
success = #6B8E6F // Muted green (gentle confirmation)
|
success = #6B8E6F // Muted green (gentle confirmation)
|
||||||
warning = #B8956A // Soft amber (warm caution)
|
warning = #B8956A // Soft amber (warm caution)
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ Comprehensive deployment and operations guide, covering infrastructure setup, de
|
||||||
|
|
||||||
#### **Platform Philosophy** (`philosophy/`)
|
#### **Platform Philosophy** (`philosophy/`)
|
||||||
- `CORE_VALUES.md` - Core platform values
|
- `CORE_VALUES.md` - Core platform values
|
||||||
- `CALM_UX_GUIDE.md` - Calm UX design principles
|
- `UX_GUIDE.md` - UX design principles
|
||||||
- `FOURTEEN_PRECEPTS.md` - Platform precepts
|
- `FOURTEEN_PRECEPTS.md` - Platform precepts
|
||||||
- `HOW_SHARP_SPEECH_STOPS.md` - Communication guidelines
|
- `HOW_SHARP_SPEECH_STOPS.md` - Communication guidelines
|
||||||
- `SEEDING_PHILOSOPHY.md` - Content seeding philosophy
|
- `SEEDING_PHILOSOPHY.md` - Content seeding philosophy
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## How Boundaries Are Enforced
|
## How Boundaries Are Enforced
|
||||||
|
|
||||||
Sojorn's calm is not aspirational—it is structural. The database itself enforces the behavioral philosophy through **Row Level Security (RLS)**, constraints, and functions that make certain behaviors impossible, not just discouraged.
|
Sojorn's friendliness is not aspirational—it is structural. The database itself enforces the behavioral philosophy through **Row Level Security (RLS)**, constraints, and functions that make certain behaviors impossible, not just discouraged.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -148,7 +148,7 @@ Sojorn's calm is not aspirational—it is structural. The database itself enforc
|
||||||
|
|
||||||
## What This Enables
|
## What This Enables
|
||||||
|
|
||||||
1. **Calm is enforced, not suggested.** The database will not allow hostile interactions.
|
1. **Friendliness is enforced, not suggested.** The database will not allow hostile interactions.
|
||||||
2. **Boundaries are private.** Blocking and filtering leave no trace visible to the blocked party.
|
2. **Boundaries are private.** Blocking and filtering leave no trace visible to the blocked party.
|
||||||
3. **Consent is required.** You cannot force your words into someone's space.
|
3. **Consent is required.** You cannot force your words into someone's space.
|
||||||
4. **Exposure is controlled.** Users see only what they choose to see.
|
4. **Exposure is controlled.** Users see only what they choose to see.
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ All Edge Functions for Sojorn backend are ready to deploy.
|
||||||
|
|
||||||
### Feeds
|
### Feeds
|
||||||
10. **feed-personal** - Chronological feed from follows
|
10. **feed-personal** - Chronological feed from follows
|
||||||
11. **feed-sojorn** - Algorithmic FYP with calm velocity
|
11. **feed-sojorn** - Algorithmic FYP with authentic engagement
|
||||||
12. **trending** - Category-scoped trending
|
12. **trending** - Category-scoped trending
|
||||||
|
|
||||||
### System
|
### System
|
||||||
|
|
@ -201,7 +201,7 @@ curl -X POST "https://zwkihedetedlatyvplyz.supabase.co/functions/v1/publish-post
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"category_id": "'$CATEGORY_ID'",
|
"category_id": "'$CATEGORY_ID'",
|
||||||
"body": "This is my first calm post on Sojorn."
|
"body": "This is my first friendly post on Sojorn."
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -227,9 +227,9 @@ curl "https://zwkihedetedlatyvplyz.supabase.co/functions/v1/feed-personal" \
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Calm Microcopy
|
## Friendly Microcopy
|
||||||
|
|
||||||
All functions include calm, intentional messaging:
|
All functions include friendly, intentional messaging:
|
||||||
|
|
||||||
- **Signup:** "Welcome to Sojorn. Your journey begins quietly."
|
- **Signup:** "Welcome to Sojorn. Your journey begins quietly."
|
||||||
- **Follow:** "Followed. Mutual follow enables conversation."
|
- **Follow:** "Followed. Mutual follow enables conversation."
|
||||||
|
|
@ -240,4 +240,4 @@ All functions include calm, intentional messaging:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Your Sojorn backend is ready to support calm, structural moderation from day one.**
|
**Your Sojorn backend is ready to support friendly, structural moderation from day one.**
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ curl -X POST https://YOUR_PROJECT_REF.supabase.co/functions/v1/publish-post \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"category_id": "CATEGORY_UUID",
|
"category_id": "CATEGORY_UUID",
|
||||||
"body": "This is a calm test post."
|
"body": "This is a friendly test post."
|
||||||
}'
|
}'
|
||||||
|
|
||||||
# Test getting personal feed
|
# Test getting personal feed
|
||||||
|
|
@ -408,4 +408,4 @@ After deployment:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Sojorn backend is ready to support calm, structural moderation from day one.**
|
**Sojorn backend is ready to support thoughtful, structural moderation from day one.**
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ curl -X POST "https://zwkihedetedlatyvplyz.supabase.co/functions/v1/signup" \
|
||||||
-d '{
|
-d '{
|
||||||
"handle": "sojorn_poet",
|
"handle": "sojorn_poet",
|
||||||
"display_name": "Sojorn Poet",
|
"display_name": "Sojorn Poet",
|
||||||
"bio": "Sharing calm words for a busy world"
|
"bio": "Sharing thoughtful words for a connected world"
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -42,7 +42,7 @@ Go to https://app.supabase.com/project/zwkihedetedlatyvplyz/sql/new
|
||||||
|
|
||||||
Paste the contents of `supabase/seed/seed_test_posts.sql` and run it.
|
Paste the contents of `supabase/seed/seed_test_posts.sql` and run it.
|
||||||
|
|
||||||
This will inject 20 beautiful, calm posts with poetry and wisdom.
|
This will inject 20 beautiful, thoughtful posts with poetry and wisdom.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@ flutter run -d ios
|
||||||
|
|
||||||
### 4.2 View Feeds
|
### 4.2 View Feeds
|
||||||
- **Following** tab: Will be empty until you follow someone
|
- **Following** tab: Will be empty until you follow someone
|
||||||
- **Sojorn** tab: Shows all posts ranked by calm velocity
|
- **Sojorn** tab: Shows all posts ranked by authentic engagement
|
||||||
- **Profile** tab: Shows your profile, trust tier, and posting limits
|
- **Profile** tab: Shows your profile, trust tier, and posting limits
|
||||||
|
|
||||||
### 4.3 Create a Post
|
### 4.3 Create a Post
|
||||||
|
|
@ -203,7 +203,7 @@ curl -X POST "https://zwkihedetedlatyvplyz.supabase.co/functions/v1/publish-post
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"category_id": "CATEGORY_UUID",
|
"category_id": "CATEGORY_UUID",
|
||||||
"body": "A calm, thoughtful post."
|
"body": "A thoughtful, engaging post."
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -257,7 +257,7 @@ Before going live:
|
||||||
|
|
||||||
- [ ] Enable email confirmation
|
- [ ] Enable email confirmation
|
||||||
- [ ] Set up custom domain
|
- [ ] Set up custom domain
|
||||||
- [ ] Configure email templates with calm copy
|
- [ ] Configure email templates with friendly copy
|
||||||
- [ ] Set up SMTP for transactional emails
|
- [ ] Set up SMTP for transactional emails
|
||||||
- [ ] Enable RLS on all tables (already done)
|
- [ ] Enable RLS on all tables (already done)
|
||||||
- [ ] Set up monitoring and alerts
|
- [ ] Set up monitoring and alerts
|
||||||
|
|
@ -270,4 +270,4 @@ Before going live:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**You're all set! Enjoy building Sojorn - a calm corner of the internet.**
|
**You're all set! Enjoy building Sojorn - a friendly corner of the internet.**
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ curl -X POST "https://YOUR_PROJECT_REF.supabase.co/functions/v1/publish-post" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"category_id": "CATEGORY_UUID",
|
"category_id": "CATEGORY_UUID",
|
||||||
"body": "This is my first calm post on Sojorn."
|
"body": "This is my first friendly post on Sojorn."
|
||||||
}'
|
}'
|
||||||
|
|
||||||
# Test getting personal feed
|
# Test getting personal feed
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
# Sojorn Flutter Client
|
# Sojorn Flutter Client
|
||||||
|
|
||||||
A calm, text-only social platform built with Flutter.
|
A friends-first social platform built with Flutter that prioritizes genuine human connections.
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
✅ **Core functionality implemented:**
|
✅ **Core functionality implemented:**
|
||||||
- Authentication (sign up, sign in, profile creation)
|
- Authentication (sign up, sign in, profile creation)
|
||||||
- Personal feed (chronological from follows)
|
- Personal feed (chronological from follows)
|
||||||
- Sojorn feed (algorithmic FYP with calm velocity)
|
- Sojorn feed (algorithmic FYP with engaging content)
|
||||||
- Post creation with tone detection
|
- Post creation with tone detection
|
||||||
- Profile viewing with trust tier display
|
- Profile viewing with trust tier display
|
||||||
- Clean, minimal UI theme
|
- Clean, modern UI theme
|
||||||
|
|
||||||
🚧 **Features to be added:**
|
🚧 **Features to be added:**
|
||||||
- Engagement actions (appreciate, save, comment on posts)
|
- Engagement actions (appreciate, save, comment on posts)
|
||||||
|
|
@ -97,7 +97,7 @@ lib/
|
||||||
│ ├── api_service.dart # Edge Functions client
|
│ ├── api_service.dart # Edge Functions client
|
||||||
│ └── auth_service.dart # Supabase Auth wrapper
|
│ └── auth_service.dart # Supabase Auth wrapper
|
||||||
├── theme/
|
├── theme/
|
||||||
│ └── app_theme.dart # Calm, minimal theme
|
│ └── app_theme.dart # Warm, welcoming theme
|
||||||
├── widgets/
|
├── widgets/
|
||||||
│ ├── compose_fab.dart # Floating compose button
|
│ ├── compose_fab.dart # Floating compose button
|
||||||
│ └── post_card.dart # Post display widget
|
│ └── post_card.dart # Post display widget
|
||||||
|
|
@ -114,7 +114,7 @@ lib/
|
||||||
|
|
||||||
### Feed System
|
### Feed System
|
||||||
- **Personal Feed**: Chronological posts from followed users
|
- **Personal Feed**: Chronological posts from followed users
|
||||||
- **Sojorn Feed**: Algorithmic feed using calm velocity ranking
|
- **Sojorn Feed**: Algorithmic feed using authentic engagement ranking
|
||||||
- Pull-to-refresh on both feeds
|
- Pull-to-refresh on both feeds
|
||||||
- Infinite scroll with pagination
|
- Infinite scroll with pagination
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ lib/
|
||||||
- Category selection (currently hardcoded to "general", needs UI)
|
- Category selection (currently hardcoded to "general", needs UI)
|
||||||
- Tone detection at publish time
|
- Tone detection at publish time
|
||||||
- Character count display
|
- Character count display
|
||||||
- Calm, intentional UX
|
- Friendly, intentional UX
|
||||||
|
|
||||||
### Profile Display
|
### Profile Display
|
||||||
- Shows display name, handle, bio
|
- Shows display name, handle, bio
|
||||||
|
|
@ -133,7 +133,7 @@ lib/
|
||||||
- Sign out button
|
- Sign out button
|
||||||
|
|
||||||
### Theme
|
### Theme
|
||||||
- Muted, calm color palette
|
- Muted, warm color palette
|
||||||
- Generous spacing
|
- Generous spacing
|
||||||
- Soft borders and shadows
|
- Soft borders and shadows
|
||||||
- Clean typography
|
- Clean typography
|
||||||
|
|
@ -241,7 +241,7 @@ flutter build web --release
|
||||||
- Future: Consider migrating to go_router for deep linking
|
- Future: Consider migrating to go_router for deep linking
|
||||||
|
|
||||||
### Design Philosophy
|
### Design Philosophy
|
||||||
- **Calm UI**: Muted colors, generous spacing, minimal animations
|
- **Friendly UI**: Muted colors, generous spacing, minimal animations
|
||||||
- **Intentional UX**: No infinite feeds, clear posting limits, thoughtful language
|
- **Intentional UX**: No infinite feeds, clear posting limits, thoughtful language
|
||||||
- **Structural boundaries**: Blocking, mutual-follow, category opt-in enforced by backend
|
- **Structural boundaries**: Blocking, mutual-follow, category opt-in enforced by backend
|
||||||
|
|
||||||
|
|
@ -265,7 +265,7 @@ flutter build web --release
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
When adding features:
|
When adding features:
|
||||||
1. Match the calm, minimal design language
|
1. Match the warm, welcoming design language
|
||||||
2. Use the existing theme constants
|
2. Use the existing theme constants
|
||||||
3. Follow the established patterns for API calls
|
3. Follow the established patterns for API calls
|
||||||
4. Add error handling and loading states
|
4. Add error handling and loading states
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
## Design Philosophy
|
## Design Philosophy
|
||||||
|
|
||||||
Sojorn's visual system enforces **calm, modern, text-forward** design through intentional constraints and thoughtful defaults.
|
Sojorn's visual system creates a **warm, welcoming, friends-first** experience through intentional design choices that prioritize human connection.
|
||||||
|
|
||||||
### Core Principles
|
### Core Principles
|
||||||
|
|
||||||
1. **Calm, Not Sterile**
|
1. **Warm, Not Overwhelming**
|
||||||
- Warm neutrals (beige/paper tones) instead of cold grays
|
- Warm neutrals (beige/paper tones) instead of cold grays
|
||||||
- Soft shadows, never harsh
|
- Soft shadows, never harsh
|
||||||
- Muted semantic colors that inform without alarming
|
- Muted semantic colors that inform without alarming
|
||||||
|
|
@ -16,14 +16,14 @@ Sojorn's visual system enforces **calm, modern, text-forward** design through in
|
||||||
- Classic typography hierarchy
|
- Classic typography hierarchy
|
||||||
- Subtle animations and transitions
|
- Subtle animations and transitions
|
||||||
|
|
||||||
3. **Text-Forward**
|
3. **Connection-Focused**
|
||||||
- Generous line height (1.6-1.65 for body text)
|
- Generous line height (1.6-1.65 for body text)
|
||||||
- Optimized for reading, not scanning
|
- Optimized for reading and engagement
|
||||||
- Clear hierarchy without relying on color
|
- Clear hierarchy without relying on color
|
||||||
|
|
||||||
4. **Intentionally Slow**
|
4. **Intentionally Smooth**
|
||||||
- Animation durations: 300-400ms
|
- Animation durations: 300-400ms
|
||||||
- Ease curves that feel deliberate
|
- Ease curves that feel natural
|
||||||
- No jarring transitions
|
- No jarring transitions
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -149,7 +149,7 @@ bodySmall: 13px / 400 / 1.5 line-height
|
||||||
```
|
```
|
||||||
|
|
||||||
**Why 1.65 line-height?**
|
**Why 1.65 line-height?**
|
||||||
Research shows 1.5-1.6 is optimal for readability. We use 1.65 to reinforce calm spacing.
|
Research shows 1.5-1.6 is optimal for readability. We use 1.65 to reinforce comfortable spacing.
|
||||||
|
|
||||||
#### Labels (UI Elements, Buttons, Metadata)
|
#### Labels (UI Elements, Buttons, Metadata)
|
||||||
```dart
|
```dart
|
||||||
|
|
@ -265,7 +265,7 @@ curveExit: easeIn // Elements leaving
|
||||||
```
|
```
|
||||||
|
|
||||||
**Why Slow?**
|
**Why Slow?**
|
||||||
Fast animations feel rushed. 300-400ms feels intentional and calm.
|
Fast animations feel rushed. 300-400ms feels intentional and smooth.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -318,7 +318,7 @@ For long-form content (posts, comments)
|
||||||
```dart
|
```dart
|
||||||
SojornTextArea(
|
SojornTextArea(
|
||||||
label: 'Write your post',
|
label: 'Write your post',
|
||||||
hint: 'Share something calm...',
|
hint: 'Share something thoughtful...',
|
||||||
controller: _postController,
|
controller: _postController,
|
||||||
maxLength: 500,
|
maxLength: 500,
|
||||||
showCharacterCount: true,
|
showCharacterCount: true,
|
||||||
|
|
@ -342,7 +342,7 @@ SojornCard(
|
||||||
```
|
```
|
||||||
|
|
||||||
### SojornDialog
|
### SojornDialog
|
||||||
Replaces `showDialog` with calm styling
|
Replaces `showDialog` with friendly styling
|
||||||
|
|
||||||
**Static Methods:**
|
**Static Methods:**
|
||||||
```dart
|
```dart
|
||||||
|
|
@ -382,9 +382,9 @@ SojornSnackbar.showWarning(context: context, message: 'Slow connection')
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Visual Calm Enforcement
|
## Visual Friendliness Enforcement
|
||||||
|
|
||||||
### How the System Enforces Calm
|
### How the System Enforces Friendliness
|
||||||
|
|
||||||
1. **No Hardcoded Colors**
|
1. **No Hardcoded Colors**
|
||||||
- All colors come from `AppTheme`
|
- All colors come from `AppTheme`
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
# sojorn
|
# sojorn
|
||||||
|
|
||||||
sojorn is a calm, consent-first social platform built to slow attention and reduce hostility by design. The project pairs a Flutter client with a Supabase backend and Edge Functions that enforce tone gating, mutual-consent conversations, and trust-aware ranking.
|
sojorn is a friends-first, consent-first social platform built to foster genuine connections and reduce hostility by design. The project pairs a Flutter client with a Go backend that enforces tone gating, mutual-consent conversations, and trust-aware ranking.
|
||||||
|
|
||||||
## Product Principles
|
## Product Principles
|
||||||
|
|
||||||
- Calm is structural, not performative.
|
- Friendliness is structural, not performative.
|
||||||
- Hostility is contained; clean content remains visible.
|
- Hostility is contained; clean content remains visible.
|
||||||
- Exposure is opt-in, filtering is private, and blocking is absolute.
|
- Exposure is opt-in, filtering is private, and blocking is absolute.
|
||||||
- Conversation requires mutual consent (mutual follow).
|
- Conversation requires mutual consent (mutual follow).
|
||||||
|
|
|
||||||
|
|
@ -1,960 +0,0 @@
|
||||||
# Sojorn Calm UX Guide
|
|
||||||
|
|
||||||
## Design Philosophy
|
|
||||||
|
|
||||||
Sojorn enforces calm through **intentional friction, respectful boundaries, and visual restraint**. Every interaction should feel like settling in, not being rushed.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 1: Reading & Feed Experience
|
|
||||||
|
|
||||||
### Design Intent
|
|
||||||
- Reading feels like settling into a book, not scrolling a timeline
|
|
||||||
- No visual shouting or metric obsession
|
|
||||||
- No urgency cues or FOMO mechanics
|
|
||||||
|
|
||||||
### Feed Layout Decisions
|
|
||||||
|
|
||||||
#### 1. **Comfortable Max Width (680px)**
|
|
||||||
**Why:**
|
|
||||||
- Optimal line length for reading is 50-75 characters
|
|
||||||
- Wide text blocks strain eye tracking
|
|
||||||
- Creates "settling in" feeling vs infinite scroll anxiety
|
|
||||||
|
|
||||||
**Implementation:**
|
|
||||||
```dart
|
|
||||||
Container(
|
|
||||||
constraints: const BoxConstraints(maxWidth: 680),
|
|
||||||
// ...
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. **Generous Vertical Spacing (24px between posts)**
|
|
||||||
**Why:**
|
|
||||||
- Tight spacing = rushed feeling
|
|
||||||
- Space = permission to pause
|
|
||||||
- Each post gets breathing room
|
|
||||||
|
|
||||||
**Visual Effect:**
|
|
||||||
- Posts feel like chapters in a book
|
|
||||||
- No "wall of content" anxiety
|
|
||||||
|
|
||||||
#### 3. **No Aggressive Dividers**
|
|
||||||
**Why:**
|
|
||||||
- Heavy dividers create visual noise
|
|
||||||
- Soft shadows and spacing create natural separation
|
|
||||||
- Avoids the "list item" feeling
|
|
||||||
|
|
||||||
**Implementation:**
|
|
||||||
```dart
|
|
||||||
boxShadow: AppTheme.shadowSm // Only 4% opacity
|
|
||||||
```
|
|
||||||
|
|
||||||
### Post Card Design Decisions
|
|
||||||
|
|
||||||
#### 1. **Body Text is THE HERO**
|
|
||||||
**Why:**
|
|
||||||
- You came here to read, not to scan metrics
|
|
||||||
- Large, comfortable type (17px at 1.7 line-height)
|
|
||||||
- Primary visual weight goes to content
|
|
||||||
|
|
||||||
**Implementation:**
|
|
||||||
```dart
|
|
||||||
Text(
|
|
||||||
post.body,
|
|
||||||
style: AppTheme.bodyLarge.copyWith(
|
|
||||||
height: 1.7, // Extra generous for reading
|
|
||||||
letterSpacing: 0.1, // Slight tracking
|
|
||||||
),
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Contrast with Twitter/X:**
|
|
||||||
- Twitter: 15px text, 1.4 line-height, competing with images/metrics
|
|
||||||
- Sojorn: 17px text, 1.7 line-height, nothing competes
|
|
||||||
|
|
||||||
#### 2. **Author Identity: Clear but Not Dominant**
|
|
||||||
**Why:**
|
|
||||||
- You need to know who's speaking
|
|
||||||
- But not at the expense of the message
|
|
||||||
- Small avatar (36px vs typical 48px)
|
|
||||||
- De-emphasized text color (textSecondary, not textPrimary)
|
|
||||||
|
|
||||||
**Visual Hierarchy:**
|
|
||||||
```
|
|
||||||
1. Post body (textPrimary, 17px, bold visual weight)
|
|
||||||
2. Actions (tertiary, 16px icons)
|
|
||||||
3. Author (textSecondary, 13px)
|
|
||||||
4. Metadata (textTertiary, 11px)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. **Metrics De-emphasized**
|
|
||||||
**Why:**
|
|
||||||
- Like counts don't mean quality
|
|
||||||
- Save counts are personal, not performance
|
|
||||||
- Comment counts ≠ value (and don't boost reach!)
|
|
||||||
|
|
||||||
**Design Choices:**
|
|
||||||
- Icons are small (18px, not 24px)
|
|
||||||
- Text is labelSmall (11px)
|
|
||||||
- Color is textTertiary (very light gray)
|
|
||||||
- No visual weight
|
|
||||||
|
|
||||||
**What's Hidden:**
|
|
||||||
- View counts (never shown)
|
|
||||||
- Ratio metrics (likes/comments)
|
|
||||||
- Trending indicators
|
|
||||||
|
|
||||||
#### 4. **Trust Tier Badge: Subtle Signal**
|
|
||||||
**Why:**
|
|
||||||
- Trust matters for context
|
|
||||||
- But shouldn't dominate
|
|
||||||
- Tiny badge (8px font, 12% opacity background)
|
|
||||||
|
|
||||||
**vs Other Platforms:**
|
|
||||||
- Twitter verification: 20px, bright blue, dominant
|
|
||||||
- Sojorn trust tier: 8px, muted color, barely visible
|
|
||||||
|
|
||||||
### Interaction Behavior
|
|
||||||
|
|
||||||
#### 1. **Gentle Press States**
|
|
||||||
**Why:**
|
|
||||||
- Aggressive hover/press = visual aggression
|
|
||||||
- Subtle border change (borderSubtle → borderStrong)
|
|
||||||
- Shadow removal (not addition)
|
|
||||||
|
|
||||||
**Implementation:**
|
|
||||||
```dart
|
|
||||||
border: Border.all(
|
|
||||||
color: _isPressed ? AppTheme.borderStrong : AppTheme.borderSubtle,
|
|
||||||
width: 0.5,
|
|
||||||
),
|
|
||||||
boxShadow: _isPressed ? null : AppTheme.shadowSm,
|
|
||||||
```
|
|
||||||
|
|
||||||
**Effect:**
|
|
||||||
- Card "settles in" when pressed
|
|
||||||
- No bounce, no scale, no aggressive feedback
|
|
||||||
|
|
||||||
#### 2. **No Metric Celebration**
|
|
||||||
**Why:**
|
|
||||||
- No confetti when you hit 10 likes
|
|
||||||
- No "trending" badges
|
|
||||||
- No "your post is doing well!" notifications
|
|
||||||
|
|
||||||
**Philosophy:**
|
|
||||||
- You wrote something calm → reward is internal
|
|
||||||
- External validation ≠ quality
|
|
||||||
|
|
||||||
### Reading Enhancements
|
|
||||||
|
|
||||||
#### 1. **Optimal Typography**
|
|
||||||
- 17px body text (larger than most platforms)
|
|
||||||
- 1.7 line-height (research shows 1.5-1.6 is ideal, we go further)
|
|
||||||
- 0.1 letter-spacing (slight tracking for comfort)
|
|
||||||
- System fonts (SF Pro Text, Roboto) for familiarity
|
|
||||||
|
|
||||||
#### 2. **Interaction Affordances**
|
|
||||||
- Appreciate/Save always visible but quiet
|
|
||||||
- No hidden menus (everything upfront)
|
|
||||||
- Tap target size: 44px minimum (accessibility)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 2: Writing & Commenting Experience
|
|
||||||
|
|
||||||
### Composer Design Intent
|
|
||||||
- Writing pauses before publishing (no tweet-and-regret)
|
|
||||||
- Friction feels supportive, not punitive
|
|
||||||
- Tone guidance is optional and respectful
|
|
||||||
|
|
||||||
### Composer UX Decisions
|
|
||||||
|
|
||||||
#### 1. **Large, Calm Text Area**
|
|
||||||
**Why:**
|
|
||||||
- Small inputs = rushed thoughts
|
|
||||||
- Large area = room to think
|
|
||||||
- 500 character limit shown gently (not alarming)
|
|
||||||
|
|
||||||
**Design:**
|
|
||||||
```dart
|
|
||||||
SojornTextArea(
|
|
||||||
minLines: 5, // Not 1-2 like Twitter
|
|
||||||
maxLines: 15,
|
|
||||||
maxLength: 500,
|
|
||||||
style: AppTheme.bodyLarge, // Same size as reading
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. **Character Limit: Gentle, Not Alarming**
|
|
||||||
**What We Don't Do:**
|
|
||||||
- ❌ Turn red at 480/500
|
|
||||||
- ❌ Show "You're over the limit!" in red text
|
|
||||||
- ❌ Disable publish button aggressively
|
|
||||||
|
|
||||||
**What We Do:**
|
|
||||||
- ✅ Show "487 / 500" in textTertiary
|
|
||||||
- ✅ Turn accent color at 490
|
|
||||||
- ✅ Fade publish button (not disable) at 501+
|
|
||||||
|
|
||||||
**Copy:**
|
|
||||||
```
|
|
||||||
Good: "487 / 500"
|
|
||||||
Bad: "ONLY 13 CHARACTERS LEFT!"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. **Category Selection: Clear and Required**
|
|
||||||
**Why:**
|
|
||||||
- Categories are structural boundaries
|
|
||||||
- Must be intentional (no "general" default)
|
|
||||||
- Clear labels, obvious UI
|
|
||||||
|
|
||||||
### Tone Nudge UI
|
|
||||||
|
|
||||||
#### 1. **When Triggered**
|
|
||||||
**Scenario:** Post gets CIS < 0.85
|
|
||||||
|
|
||||||
**What We Don't Do:**
|
|
||||||
- ❌ Red warning banner
|
|
||||||
- ❌ "This violates community guidelines"
|
|
||||||
- ❌ Block publishing immediately
|
|
||||||
- ❌ Shame the user
|
|
||||||
|
|
||||||
**What We Do:**
|
|
||||||
- ✅ Neutral language
|
|
||||||
- ✅ Soft amber background (not red)
|
|
||||||
- ✅ Suggestion, not demand
|
|
||||||
- ✅ Allow dismiss
|
|
||||||
|
|
||||||
**Copy:**
|
|
||||||
```markdown
|
|
||||||
## Sharp Edges Detected
|
|
||||||
|
|
||||||
This post has language that may feel sharp to readers.
|
|
||||||
|
|
||||||
**Suggested rewrite:**
|
|
||||||
"I respectfully disagree with this approach."
|
|
||||||
|
|
||||||
**Original:**
|
|
||||||
"This is stupid and wrong."
|
|
||||||
|
|
||||||
[ Publish Anyway ] [ Edit ]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tone:**
|
|
||||||
- No "You violated..."
|
|
||||||
- No "This is not allowed"
|
|
||||||
- Just "This may feel sharp"
|
|
||||||
|
|
||||||
#### 2. **Allow Dismiss Without Penalty**
|
|
||||||
**Why:**
|
|
||||||
- You're an adult
|
|
||||||
- Tone detection isn't perfect
|
|
||||||
- Trust users to make decisions
|
|
||||||
|
|
||||||
**But:**
|
|
||||||
- Persistent low CIS → harmony score impact
|
|
||||||
- 3+ rejected posts → temporary slow-down
|
|
||||||
- Trust tier may adjust
|
|
||||||
|
|
||||||
**Philosophy:**
|
|
||||||
- Friction, not force
|
|
||||||
- Consequences, not punishment
|
|
||||||
|
|
||||||
### Comment UI
|
|
||||||
|
|
||||||
#### 1. **Mutual-Follow Only**
|
|
||||||
**Design:**
|
|
||||||
- Comment box only appears if mutual follow
|
|
||||||
- Otherwise: "Follow each other to comment"
|
|
||||||
- No shame, just structure
|
|
||||||
|
|
||||||
#### 2. **Compact, Conversational Layout**
|
|
||||||
**Why:**
|
|
||||||
- Comments are dialogue, not performance
|
|
||||||
- Small avatars (28px)
|
|
||||||
- Lighter visual weight than posts
|
|
||||||
|
|
||||||
#### 3. **Downvotes: De-emphasized**
|
|
||||||
**Why:**
|
|
||||||
- Downvotes useful for spam/quality
|
|
||||||
- But not a weapon
|
|
||||||
|
|
||||||
**Design:**
|
|
||||||
- No downvote count shown
|
|
||||||
- Icon is tertiary gray (not red)
|
|
||||||
- No "controversial" indicators
|
|
||||||
|
|
||||||
### Empty States
|
|
||||||
|
|
||||||
#### 1. **No Pressure to Post**
|
|
||||||
**Bad Copy:**
|
|
||||||
```
|
|
||||||
"Your feed is empty! Start following people!"
|
|
||||||
"Nothing to see here. Get active!"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Good Copy (Sojorn Voice):**
|
|
||||||
```
|
|
||||||
"Nothing here yet"
|
|
||||||
"Posts you appreciate will appear here"
|
|
||||||
"Your feed is quiet right now"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tone:**
|
|
||||||
- Welcoming, not urgent
|
|
||||||
- Calm, not demanding
|
|
||||||
- Permission to lurk
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 3: Navigation & Information Architecture
|
|
||||||
|
|
||||||
### Design Intent
|
|
||||||
- Users always know where they are
|
|
||||||
- No hidden mechanics or dark patterns
|
|
||||||
- No surprise destinations
|
|
||||||
|
|
||||||
### Bottom Navigation
|
|
||||||
|
|
||||||
#### 1. **Clear, Limited Tabs**
|
|
||||||
**What We Have:**
|
|
||||||
- **Following** (chronological from follows)
|
|
||||||
- **Sojorn** (algorithmic FYP)
|
|
||||||
- **Profile** (your stats and posts)
|
|
||||||
|
|
||||||
**What We Don't Have:**
|
|
||||||
- ❌ "Discover" (too vague)
|
|
||||||
- ❌ "Notifications" (reduces checking anxiety)
|
|
||||||
- ❌ "Messages" (not yet implemented)
|
|
||||||
|
|
||||||
**Why 3 Tabs:**
|
|
||||||
- Cognitive load: 3-5 is ideal
|
|
||||||
- Each tab has one job
|
|
||||||
- No confusion
|
|
||||||
|
|
||||||
#### 2. **No Surprise Destinations**
|
|
||||||
**Rule:**
|
|
||||||
- Tab icon = where you land
|
|
||||||
- No "Following but actually Explore"
|
|
||||||
- No "Profile but actually Settings"
|
|
||||||
|
|
||||||
### Profile Hierarchy
|
|
||||||
|
|
||||||
#### 1. **Posts First**
|
|
||||||
**Why:**
|
|
||||||
- You came to see what they wrote
|
|
||||||
- Not their bio or follower count
|
|
||||||
|
|
||||||
**Layout:**
|
|
||||||
```
|
|
||||||
1. Posts (primary view)
|
|
||||||
2. Bio (secondary, collapsed)
|
|
||||||
3. Stats (tertiary, small)
|
|
||||||
4. Controls (obvious but not dominant)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. **Follow/Unfollow: Obvious**
|
|
||||||
**Design:**
|
|
||||||
- Always visible in header
|
|
||||||
- Clear label ("Follow" / "Following")
|
|
||||||
- No hidden in "..." menu
|
|
||||||
|
|
||||||
### Settings Organization
|
|
||||||
|
|
||||||
#### 1. **Grouped by Concern**
|
|
||||||
```
|
|
||||||
📖 Reading & Filters
|
|
||||||
- Category preferences
|
|
||||||
- Content filters
|
|
||||||
- Feed preferences
|
|
||||||
|
|
||||||
🔒 Privacy & Blocking
|
|
||||||
- Blocked users
|
|
||||||
- Profile visibility
|
|
||||||
- Data sharing
|
|
||||||
|
|
||||||
👤 Account & Data
|
|
||||||
- Email/password
|
|
||||||
- Export data
|
|
||||||
- Delete account
|
|
||||||
```
|
|
||||||
|
|
||||||
**Why This Order:**
|
|
||||||
- Most common (reading) first
|
|
||||||
- Safety (blocking) never buried
|
|
||||||
- Destructive (delete) last
|
|
||||||
|
|
||||||
#### 2. **No Buried Safety Controls**
|
|
||||||
**Rule:**
|
|
||||||
- Block button on every profile
|
|
||||||
- Privacy settings in top-level menu
|
|
||||||
- Export data always accessible
|
|
||||||
|
|
||||||
### Discoverability
|
|
||||||
|
|
||||||
#### 1. **Explore Tab Clearly Separate**
|
|
||||||
**Why:**
|
|
||||||
- "Explore" ≠ "Following"
|
|
||||||
- No accidental algorithm exposure
|
|
||||||
- Opt-in discovery
|
|
||||||
|
|
||||||
#### 2. **Categories Never Auto-Enable**
|
|
||||||
**Rule:**
|
|
||||||
- All categories off by default (except general)
|
|
||||||
- Explicit opt-in required
|
|
||||||
- No "We think you'd like..." suggestions
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 4: Blocking & Filtering UX
|
|
||||||
|
|
||||||
### Design Intent
|
|
||||||
- Blocking is self-care, not confrontation
|
|
||||||
- Filtering is private and encouraged
|
|
||||||
- No shame, no drama
|
|
||||||
|
|
||||||
### Block Affordance
|
|
||||||
|
|
||||||
#### 1. **Always Visible**
|
|
||||||
**Where:**
|
|
||||||
- On every profile (header menu)
|
|
||||||
- On every post (overflow menu)
|
|
||||||
- In comment threads
|
|
||||||
|
|
||||||
**Design:**
|
|
||||||
```
|
|
||||||
Icon: shield_outline (not block_circle)
|
|
||||||
Label: "Block @username"
|
|
||||||
Color: textSecondary (not error red)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Why Shield Icon:**
|
|
||||||
- Block = protection, not punishment
|
|
||||||
- Shield = self-care
|
|
||||||
- Less aggressive than ⛔
|
|
||||||
|
|
||||||
#### 2. **One-Tap Confirmation**
|
|
||||||
**Flow:**
|
|
||||||
```
|
|
||||||
Tap "Block" →
|
|
||||||
Dialog: "Block @username?"
|
|
||||||
"You won't see their posts or comments. They won't be notified."
|
|
||||||
[ Cancel ] [ Block ]
|
|
||||||
```
|
|
||||||
|
|
||||||
**No:**
|
|
||||||
- ❌ "Are you SURE?"
|
|
||||||
- ❌ "This is permanent"
|
|
||||||
- ❌ Multiple confirmations
|
|
||||||
|
|
||||||
**Copy Tone:**
|
|
||||||
- Neutral, not dramatic
|
|
||||||
- Reassuring, not scary
|
|
||||||
|
|
||||||
#### 3. **No Explanation Required**
|
|
||||||
**Why:**
|
|
||||||
- You don't owe anyone an explanation
|
|
||||||
- Block is personal boundary
|
|
||||||
- No "Report" pressure
|
|
||||||
|
|
||||||
**But:**
|
|
||||||
- Separate "Report" option exists
|
|
||||||
- Report ≠ block (different flows)
|
|
||||||
|
|
||||||
### Filter Controls
|
|
||||||
|
|
||||||
#### 1. **Category Toggles**
|
|
||||||
**Design:**
|
|
||||||
```
|
|
||||||
[ ] Quiet Reflections
|
|
||||||
[ ] Gratitude
|
|
||||||
[x] General Discussion
|
|
||||||
[ ] Deep Questions
|
|
||||||
```
|
|
||||||
|
|
||||||
**Each Shows:**
|
|
||||||
- Name
|
|
||||||
- Description (one sentence)
|
|
||||||
- Post count (optional)
|
|
||||||
|
|
||||||
#### 2. **Keyword/Topic Filters (Optional)**
|
|
||||||
**Future Feature:**
|
|
||||||
```
|
|
||||||
Hide posts containing:
|
|
||||||
- "election"
|
|
||||||
- "crypto"
|
|
||||||
- "diet"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Design:**
|
|
||||||
- Off by default
|
|
||||||
- No suggestions
|
|
||||||
- No "trending" pressure
|
|
||||||
|
|
||||||
#### 3. **Preview What's Hidden (Optional)**
|
|
||||||
**Design:**
|
|
||||||
```
|
|
||||||
[ ] Show me what I'm filtering
|
|
||||||
```
|
|
||||||
|
|
||||||
**When Enabled:**
|
|
||||||
- Filtered posts appear grayed out
|
|
||||||
- "Hidden by your filters" label
|
|
||||||
- Can tap to reveal
|
|
||||||
|
|
||||||
**Default:** OFF (out of sight, out of mind)
|
|
||||||
|
|
||||||
### Feedback Copy
|
|
||||||
|
|
||||||
#### 1. **After Blocking**
|
|
||||||
```
|
|
||||||
"You won't see posts from @username anymore."
|
|
||||||
"They won't be notified."
|
|
||||||
```
|
|
||||||
|
|
||||||
**Not:**
|
|
||||||
```
|
|
||||||
❌ "User blocked successfully!"
|
|
||||||
❌ "You'll never see them again!"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. **After Filtering**
|
|
||||||
```
|
|
||||||
"Quiet Reflections hidden from your feeds."
|
|
||||||
```
|
|
||||||
|
|
||||||
**Not:**
|
|
||||||
```
|
|
||||||
❌ "Category disabled!"
|
|
||||||
❌ "You won't miss anything important"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Export/Import Block List
|
|
||||||
|
|
||||||
#### 1. **Clear Warnings**
|
|
||||||
```
|
|
||||||
## Export Block List
|
|
||||||
|
|
||||||
This downloads a JSON file with usernames you've blocked.
|
|
||||||
|
|
||||||
⚠️ This file contains your personal blocking decisions.
|
|
||||||
⚠️ Sharing this may reveal your social boundaries.
|
|
||||||
⚠️ Sojorn does not endorse public block list sharing.
|
|
||||||
|
|
||||||
[ Cancel ] [ Download JSON ]
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. **No Recommendations**
|
|
||||||
**What We Don't Do:**
|
|
||||||
- ❌ "Import from popular block lists"
|
|
||||||
- ❌ "People like you also block..."
|
|
||||||
- ❌ "Suggested blocks based on your follows"
|
|
||||||
|
|
||||||
**Why:**
|
|
||||||
- Block lists = personal boundaries
|
|
||||||
- No crowd-sourcing judgment
|
|
||||||
- No guilt by association
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 5: Transparency & Explanation
|
|
||||||
|
|
||||||
### Design Intent
|
|
||||||
- Calm confidence through clarity
|
|
||||||
- No mystery, no jargon
|
|
||||||
- Trust through honesty
|
|
||||||
|
|
||||||
### "How Reach Works" Page
|
|
||||||
|
|
||||||
#### Content Structure
|
|
||||||
```markdown
|
|
||||||
# How Sojorn Ranking Works
|
|
||||||
|
|
||||||
Posts in your Sojorn feed are ranked by **calm velocity**—a measure of genuine appreciation over time.
|
|
||||||
|
|
||||||
## What Boosts Posts
|
|
||||||
- ❤️ Appreciations (likes)
|
|
||||||
- 🔖 Saves (strong signal)
|
|
||||||
- ⏱️ Time spent reading (dwell time)
|
|
||||||
- 🎯 High Content Integrity Score (CIS)
|
|
||||||
|
|
||||||
## What Slows Posts
|
|
||||||
- ⏰ Age (older posts fade naturally)
|
|
||||||
- 👎 Downvotes (quality filter)
|
|
||||||
- 🚩 Low CIS (tone issues)
|
|
||||||
|
|
||||||
## What Doesn't Matter
|
|
||||||
- 💬 Comment count (dialogue ≠ quality)
|
|
||||||
- 👥 Author's follower count
|
|
||||||
- 📊 Retweets/shares (we don't have those)
|
|
||||||
|
|
||||||
## Why This Way
|
|
||||||
Calm velocity rewards thoughtful content, not viral outrage. Posts earn reach through genuine appreciation, not reaction-baiting.
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Design Choices
|
|
||||||
- **Plain language** (no "algorithm" jargon)
|
|
||||||
- **Bullet points** (scannable)
|
|
||||||
- **Emojis** (visual anchors, but not excessive)
|
|
||||||
- **Honesty** (explicitly state what doesn't matter)
|
|
||||||
|
|
||||||
### "Rules & Tone" Page
|
|
||||||
|
|
||||||
#### Content Structure
|
|
||||||
```markdown
|
|
||||||
# Community Tone Guidelines
|
|
||||||
|
|
||||||
Sojorn welcomes all ideas, but requires calm expression.
|
|
||||||
|
|
||||||
## Focus: Tone, Not Ideology
|
|
||||||
|
|
||||||
We don't police what you think. We ask how you express it.
|
|
||||||
|
|
||||||
### ✅ Allowed
|
|
||||||
- "I disagree with that approach."
|
|
||||||
- "This feels uncomfortable to me."
|
|
||||||
- "I see it differently."
|
|
||||||
|
|
||||||
### ⛔ Not Allowed
|
|
||||||
- "This is stupid."
|
|
||||||
- "You're an idiot."
|
|
||||||
- "What the hell were you thinking?"
|
|
||||||
|
|
||||||
## Why Tone Matters
|
|
||||||
Sharp language creates defensiveness. Calm language creates dialogue.
|
|
||||||
|
|
||||||
## How We Detect Tone
|
|
||||||
- Pattern-based analysis (not perfect)
|
|
||||||
- Content Integrity Score (CIS)
|
|
||||||
- Human review for edge cases
|
|
||||||
|
|
||||||
## What Happens
|
|
||||||
- CIS < 0.85: Gentle nudge to rephrase
|
|
||||||
- CIS < 0.70: Post blocked
|
|
||||||
- Persistent low CIS: Harmony score impact
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Tone Choices
|
|
||||||
- **No shame** ("not allowed" not "violations")
|
|
||||||
- **Examples** (show, don't just tell)
|
|
||||||
- **Honesty** (admit imperfection)
|
|
||||||
|
|
||||||
### Contextual Help
|
|
||||||
|
|
||||||
#### 1. **"Why am I seeing this?"**
|
|
||||||
**Trigger:** Tap "..." on any post
|
|
||||||
|
|
||||||
**Copy:**
|
|
||||||
```
|
|
||||||
## Why This Post
|
|
||||||
|
|
||||||
This appeared in your Sojorn feed because:
|
|
||||||
- High calm velocity (287 appreciates, 45 saves)
|
|
||||||
- Category: General Discussion (you're subscribed)
|
|
||||||
- Posted 2 hours ago
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. **"Why can't I comment?"**
|
|
||||||
**Scenario:** Non-mutual follow
|
|
||||||
|
|
||||||
**Copy:**
|
|
||||||
```
|
|
||||||
## Commenting
|
|
||||||
|
|
||||||
You can comment when you both follow each other.
|
|
||||||
|
|
||||||
This protects against drive-by harassment and ensures dialogue, not performance.
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tone:**
|
|
||||||
- No "You're not allowed"
|
|
||||||
- Just "This is how it works"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 6: Accessibility & Inclusivity
|
|
||||||
|
|
||||||
### Text Accessibility
|
|
||||||
|
|
||||||
#### 1. **Scalable Font Sizes**
|
|
||||||
**Implementation:**
|
|
||||||
```dart
|
|
||||||
Text(
|
|
||||||
post.body,
|
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
|
||||||
// Respects user's OS text size settings
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Why:**
|
|
||||||
- Low vision users need large text
|
|
||||||
- Flutter automatically scales with OS settings
|
|
||||||
- No hardcoded font sizes
|
|
||||||
|
|
||||||
#### 2. **High Readability Contrast**
|
|
||||||
**Ratios:**
|
|
||||||
- textPrimary on background: 12.5:1 (AAA)
|
|
||||||
- textSecondary on background: 7.2:1 (AA)
|
|
||||||
- textTertiary on background: 4.8:1 (AA large text)
|
|
||||||
|
|
||||||
**Why:**
|
|
||||||
- WCAG AAA for body text
|
|
||||||
- Still feels calm (not harsh black on white)
|
|
||||||
|
|
||||||
### Interaction Accessibility
|
|
||||||
|
|
||||||
#### 1. **Keyboard Navigation (Web)**
|
|
||||||
**Requirements:**
|
|
||||||
- Tab through all interactive elements
|
|
||||||
- Enter/Space activates buttons
|
|
||||||
- Escape closes modals
|
|
||||||
- Arrow keys in lists
|
|
||||||
|
|
||||||
**Implementation:**
|
|
||||||
```dart
|
|
||||||
Focus(
|
|
||||||
onKey: (node, event) {
|
|
||||||
// Handle keyboard events
|
|
||||||
},
|
|
||||||
child: Widget(),
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. **Screen Reader Labels**
|
|
||||||
**Example:**
|
|
||||||
```dart
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.favorite_border),
|
|
||||||
tooltip: 'Appreciate this post',
|
|
||||||
semanticsLabel: 'Appreciate post from ${post.author.displayName}',
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Why:**
|
|
||||||
- Icon alone = meaningless to screen readers
|
|
||||||
- Context matters
|
|
||||||
|
|
||||||
#### 3. **Focus States**
|
|
||||||
**Design:**
|
|
||||||
```dart
|
|
||||||
focusColor: AppTheme.accent.withValues(alpha: 0.1),
|
|
||||||
// Soft highlight, not harsh outline
|
|
||||||
```
|
|
||||||
|
|
||||||
### Motion Accessibility
|
|
||||||
|
|
||||||
#### 1. **Respect Reduced Motion**
|
|
||||||
**Check:**
|
|
||||||
```dart
|
|
||||||
final reducedMotion = MediaQuery.of(context).accessibleNavigation;
|
|
||||||
|
|
||||||
final duration = reducedMotion
|
|
||||||
? Duration.zero
|
|
||||||
: AppTheme.durationMedium;
|
|
||||||
```
|
|
||||||
|
|
||||||
**Where Applied:**
|
|
||||||
- Fade transitions
|
|
||||||
- Sheet slides
|
|
||||||
- Loading spinners
|
|
||||||
|
|
||||||
#### 2. **No Required Animations**
|
|
||||||
**Rule:**
|
|
||||||
- All info accessible without animation
|
|
||||||
- Skeleton loaders have static alt
|
|
||||||
- Progress shown via text too
|
|
||||||
|
|
||||||
### Cognitive Load
|
|
||||||
|
|
||||||
#### 1. **Avoid Dense UI**
|
|
||||||
**Guidelines:**
|
|
||||||
- Maximum 3 actions per card
|
|
||||||
- One primary action per screen
|
|
||||||
- Generous spacing (24px, not 8px)
|
|
||||||
|
|
||||||
#### 2. **Avoid Urgency**
|
|
||||||
**No:**
|
|
||||||
- ❌ Red badges
|
|
||||||
- ❌ Pulsing animations
|
|
||||||
- ❌ "New!" labels
|
|
||||||
|
|
||||||
**Why:**
|
|
||||||
- Reduces anxiety
|
|
||||||
- Allows focus
|
|
||||||
- Respects attention
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Part 7: Final Polish
|
|
||||||
|
|
||||||
### Microinteractions
|
|
||||||
|
|
||||||
#### 1. **Subtle Haptics (Mobile)**
|
|
||||||
**When:**
|
|
||||||
- Appreciate/Save actions (light impact)
|
|
||||||
- Publish post (medium impact)
|
|
||||||
- Error state (notification feedback)
|
|
||||||
|
|
||||||
**Implementation:**
|
|
||||||
```dart
|
|
||||||
HapticFeedback.lightImpact(); // Not heavyImpact
|
|
||||||
```
|
|
||||||
|
|
||||||
**Why:**
|
|
||||||
- Confirms action
|
|
||||||
- But doesn't startle
|
|
||||||
|
|
||||||
#### 2. **Sound Cues (Optional, OFF by default)**
|
|
||||||
**Future:**
|
|
||||||
- Soft "bloom" on appreciate
|
|
||||||
- Gentle "save" sound
|
|
||||||
- Muted error tone
|
|
||||||
|
|
||||||
**Default:** OFF
|
|
||||||
**Why:** Audio = intrusive
|
|
||||||
|
|
||||||
### Loading States
|
|
||||||
|
|
||||||
#### 1. **Skeletons, Not Spinners**
|
|
||||||
**Design:**
|
|
||||||
```dart
|
|
||||||
ShimmerSkeleton(
|
|
||||||
child: PostCardSkeleton(),
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Why:**
|
|
||||||
- Shows structure
|
|
||||||
- Feels faster
|
|
||||||
- Less anxiety than spinner
|
|
||||||
|
|
||||||
#### 2. **Calm Copy**
|
|
||||||
**Good:**
|
|
||||||
```
|
|
||||||
"Loading..."
|
|
||||||
"One moment"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Bad:**
|
|
||||||
```
|
|
||||||
❌ "Hang tight!"
|
|
||||||
❌ "Almost there!"
|
|
||||||
❌ "This won't take long!"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tone:**
|
|
||||||
- Neutral, not cheerful
|
|
||||||
- Honest, not performative
|
|
||||||
|
|
||||||
### Error Handling
|
|
||||||
|
|
||||||
#### 1. **Gentle Language**
|
|
||||||
**Good:**
|
|
||||||
```
|
|
||||||
"Couldn't load posts"
|
|
||||||
"Connection issue"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Bad:**
|
|
||||||
```
|
|
||||||
❌ "ERROR: Network failure"
|
|
||||||
❌ "Oops! Something went wrong!"
|
|
||||||
❌ "Fatal exception occurred"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. **Clear Recovery**
|
|
||||||
**Pattern:**
|
|
||||||
```
|
|
||||||
[Error message]
|
|
||||||
[What happened]
|
|
||||||
[Action button]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```
|
|
||||||
Couldn't load posts
|
|
||||||
|
|
||||||
Check your internet connection.
|
|
||||||
|
|
||||||
[ Try Again ]
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. **No Blame**
|
|
||||||
**Don't:**
|
|
||||||
- ❌ "You're offline"
|
|
||||||
- ❌ "Invalid input"
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- ✅ "No connection"
|
|
||||||
- ✅ "Hmm, that didn't work"
|
|
||||||
|
|
||||||
### Performance
|
|
||||||
|
|
||||||
#### 1. **Optimize List Rendering**
|
|
||||||
```dart
|
|
||||||
ListView.builder(
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return RepaintBoundary(
|
|
||||||
child: PostCard(post: posts[index]),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Why:**
|
|
||||||
- RepaintBoundary = isolate repaints
|
|
||||||
- Smooth 60fps scroll
|
|
||||||
|
|
||||||
#### 2. **Cache Feeds Responsibly**
|
|
||||||
- Cache for 5 minutes
|
|
||||||
- Invalidate on pull-to-refresh
|
|
||||||
- Respect memory limits
|
|
||||||
|
|
||||||
#### 3. **No Jank on Scroll**
|
|
||||||
**Techniques:**
|
|
||||||
- Lazy load images
|
|
||||||
- Debounce pagination
|
|
||||||
- Avoid setState in scroll listener
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Summary: What Makes Sojorn Calm
|
|
||||||
|
|
||||||
### Visual Calm
|
|
||||||
- Warm neutrals, not cold grays
|
|
||||||
- Soft shadows (4-8% opacity)
|
|
||||||
- Generous spacing (24px, not 8px)
|
|
||||||
- Muted colors (no bright red/blue)
|
|
||||||
|
|
||||||
### Interaction Calm
|
|
||||||
- Slow animations (300-400ms)
|
|
||||||
- Gentle press states (no bounce)
|
|
||||||
- Subtle haptics (light, not heavy)
|
|
||||||
- No urgency cues
|
|
||||||
|
|
||||||
### Content Calm
|
|
||||||
- Body text is hero (17px, 1.7 line-height)
|
|
||||||
- Metrics de-emphasized (11px, tertiary)
|
|
||||||
- Author identity clear but quiet
|
|
||||||
- No performance pressure
|
|
||||||
|
|
||||||
### Structural Calm
|
|
||||||
- Mutual-follow commenting
|
|
||||||
- Category opt-in
|
|
||||||
- Block without drama
|
|
||||||
- Tone guidance without shame
|
|
||||||
|
|
||||||
### Cognitive Calm
|
|
||||||
- No mystery (transparency pages)
|
|
||||||
- No dark patterns (honest UI)
|
|
||||||
- No jargon (plain language)
|
|
||||||
- No surprises (predictable navigation)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Result:** An app that feels like settling into a good book, not scrolling a frantic timeline.
|
|
||||||
|
|
||||||
**Enforcement:** Design system + custom widgets make it impossible to violate calm principles.
|
|
||||||
|
|
||||||
**Philosophy:** Calm is not a feature. Calm is structural.
|
|
||||||
|
|
@ -41,7 +41,7 @@ When a user writes a post or comment, the content passes through tone analysis *
|
||||||
### 2. **Content Integrity Score (CIS)**
|
### 2. **Content Integrity Score (CIS)**
|
||||||
|
|
||||||
Every post that passes tone detection receives a **Content Integrity Score (0-1)**:
|
Every post that passes tone detection receives a **Content Integrity Score (0-1)**:
|
||||||
- Positive, calm language → CIS 0.9
|
- Positive, friendly language → CIS 0.9
|
||||||
- Neutral, factual language → CIS 0.8
|
- Neutral, factual language → CIS 0.8
|
||||||
- Mixed sentiment → CIS 0.7
|
- Mixed sentiment → CIS 0.7
|
||||||
- Negative but non-hostile → CIS 0.5
|
- Negative but non-hostile → CIS 0.5
|
||||||
|
|
@ -66,7 +66,7 @@ Each user has a private **Harmony Score (0-100)** that adjusts based on behavior
|
||||||
- Filing false reports
|
- Filing false reports
|
||||||
|
|
||||||
**Positive signals (raise score):**
|
**Positive signals (raise score):**
|
||||||
- Sustained calm participation
|
- Sustained positive participation
|
||||||
- Validated reports (helping moderation)
|
- Validated reports (helping moderation)
|
||||||
- Time without issues (natural recovery)
|
- Time without issues (natural recovery)
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ Post eligibility for Trending (based on CIS + Harmony + Safety)
|
||||||
|
|
||||||
## What This Means for Users
|
## What This Means for Users
|
||||||
|
|
||||||
### If you write calm, thoughtful content:
|
### If you write friendly, thoughtful content:
|
||||||
- Your posts pass tone detection instantly
|
- Your posts pass tone detection instantly
|
||||||
- They receive high CIS scores
|
- They receive high CIS scores
|
||||||
- They reach wide audiences
|
- They reach wide audiences
|
||||||
|
|
@ -163,4 +163,4 @@ But because the platform is architecturally designed to let it **expire quietly*
|
||||||
|
|
||||||
Clean content flows.
|
Clean content flows.
|
||||||
Sharp content stops.
|
Sharp content stops.
|
||||||
Calm is structural.
|
Friendliness is structural.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
## Core Principle: Honest Onboarding
|
## Core Principle: Honest Onboarding
|
||||||
|
|
||||||
**The Problem:**
|
**The Problem:**
|
||||||
New users dropped into an empty platform experience confusion, not calm. They don't know what belongs, what tone is expected, or whether anyone else is here.
|
New users dropped into an empty platform experience confusion, not connection. They don't know what belongs, what tone is expected, or whether anyone else is here.
|
||||||
|
|
||||||
**Traditional Solution (Rejected):**
|
**Traditional Solution (Rejected):**
|
||||||
- Create fake user personas
|
- Create fake user personas
|
||||||
|
|
@ -34,14 +34,14 @@ All official accounts are:
|
||||||
|
|
||||||
**Content:**
|
**Content:**
|
||||||
- How Sojorn works
|
- How Sojorn works
|
||||||
- Calm velocity explanations
|
- Community guidelines
|
||||||
- Feature updates
|
- Feature updates
|
||||||
- Transparency notes
|
- Transparency notes
|
||||||
|
|
||||||
**Tone:** Neutral, factual, direct
|
**Tone:** Neutral, factual, direct
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
> "Welcome to Sojorn. This is a text-only social platform designed for calm expression. Posts are ranked by calm velocity—genuine appreciation over time, not outrage or virality."
|
> "Welcome to Sojorn. This is a friends-first social platform designed for genuine connections. Posts are ranked by authentic engagement—real appreciation over time, not outrage or virality."
|
||||||
|
|
||||||
#### 2. @sojorn_read
|
#### 2. @sojorn_read
|
||||||
**Purpose:** Reading content and prompts
|
**Purpose:** Reading content and prompts
|
||||||
|
|
@ -292,7 +292,7 @@ if (post.author.is_official) {
|
||||||
// Reduce ranking weight based on platform maturity
|
// Reduce ranking weight based on platform maturity
|
||||||
const platformAge = daysSinceFirstUserPost();
|
const platformAge = daysSinceFirstUserPost();
|
||||||
const officialPenalty = Math.min(platformAge / 30, 0.7); // Max 70% reduction
|
const officialPenalty = Math.min(platformAge / 30, 0.7); // Max 70% reduction
|
||||||
post.calmVelocity *= (1 - officialPenalty);
|
post.engagementScore *= (1 - officialPenalty);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -358,7 +358,7 @@ WITH CHECK (
|
||||||
### ✅ Good Seed Content
|
### ✅ Good Seed Content
|
||||||
|
|
||||||
**@sojorn (Transparency):**
|
**@sojorn (Transparency):**
|
||||||
> "Your feed has two tabs: Following shows posts from people you follow, chronologically. Sojorn shows posts ranked by calm velocity from everyone. You control which categories you see."
|
> "Your feed has two tabs: Following shows posts from people you follow, chronologically. Sojorn shows posts ranked by authentic engagement from everyone. You control which categories you see."
|
||||||
|
|
||||||
**Why:** Factual, useful, transparent
|
**Why:** Factual, useful, transparent
|
||||||
|
|
||||||
|
|
@ -459,4 +459,4 @@ WITH CHECK (
|
||||||
|
|
||||||
**Execution:** Clearly labeled, authentically useful, gradually diluted.
|
**Execution:** Clearly labeled, authentically useful, gradually diluted.
|
||||||
|
|
||||||
**Result:** New users welcomed into calm, not emptiness.
|
**Result:** New users welcomed into connection, not emptiness.
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ The **Supabase backend foundation** for Sojorn is complete. All core database sc
|
||||||
- Algorithmic "For You" feed
|
- Algorithmic "For You" feed
|
||||||
- Fetches 500 candidate posts (last 7 days)
|
- Fetches 500 candidate posts (last 7 days)
|
||||||
- Enriches with author trust and safety metrics
|
- Enriches with author trust and safety metrics
|
||||||
- Ranks by calm velocity algorithm
|
- Ranks by authentic engagement algorithm
|
||||||
- Returns paginated, ranked results
|
- Returns paginated, ranked results
|
||||||
- Includes ranking explanation
|
- Includes ranking explanation
|
||||||
|
|
||||||
|
|
@ -100,7 +100,7 @@ The **Supabase backend foundation** for Sojorn is complete. All core database sc
|
||||||
- Category-scoped trending
|
- Category-scoped trending
|
||||||
- Merges editorial overrides + algorithmic picks
|
- Merges editorial overrides + algorithmic picks
|
||||||
- Eligibility: Positive/Neutral tone, CIS >= 0.8, no safety issues
|
- Eligibility: Positive/Neutral tone, CIS >= 0.8, no safety issues
|
||||||
- Ranks by calm velocity
|
- Ranks by authentic engagement
|
||||||
- Limited to last 48 hours
|
- Limited to last 48 hours
|
||||||
|
|
||||||
8. **calculate-harmony** ✅
|
8. **calculate-harmony** ✅
|
||||||
|
|
@ -143,7 +143,7 @@ The **Supabase backend foundation** for Sojorn is complete. All core database sc
|
||||||
- ✅ **supabase-client.ts** – Client creation helpers
|
- ✅ **supabase-client.ts** – Client creation helpers
|
||||||
- ✅ **tone-detection.ts** – Pattern-based tone classifier
|
- ✅ **tone-detection.ts** – Pattern-based tone classifier
|
||||||
- ✅ **validation.ts** – Input validation with custom errors
|
- ✅ **validation.ts** – Input validation with custom errors
|
||||||
- ✅ **ranking.ts** – Calm velocity ranking algorithm
|
- ✅ **ranking.ts** – Authentic engagement ranking algorithm
|
||||||
- ✅ **harmony.ts** – Harmony score calculation and effects
|
- ✅ **harmony.ts** – Harmony score calculation and effects
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
@ -269,7 +269,7 @@ Before public beta:
|
||||||
- Cache trending results per category (15-min TTL)
|
- Cache trending results per category (15-min TTL)
|
||||||
- Batch harmony calculations (process 100 users at a time)
|
- Batch harmony calculations (process 100 users at a time)
|
||||||
- Add Redis for session and feed caching
|
- Add Redis for session and feed caching
|
||||||
- Pre-compute calm velocity scores on post creation
|
- Pre-compute engagement scores on post creation
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -300,7 +300,7 @@ Before public beta:
|
||||||
|
|
||||||
## Success Metrics (Future)
|
## Success Metrics (Future)
|
||||||
|
|
||||||
- **Calm retention:** Users return daily without compulsion
|
- **Friendly retention:** Users return daily for genuine connection
|
||||||
- **Low block rate:** < 1% of relationships result in blocks
|
- **Low block rate:** < 1% of relationships result in blocks
|
||||||
- **High save-to-like ratio:** Thoughtful curation > quick reactions
|
- **High save-to-like ratio:** Thoughtful curation > quick reactions
|
||||||
- **Diverse trending:** No single author/topic dominates
|
- **Diverse trending:** No single author/topic dominates
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
## What Was Built
|
## What Was Built
|
||||||
|
|
||||||
A complete **Supabase backend** for Sojorn, a calm text-only social platform where **sharp speech stops quietly**.
|
A complete **Go backend** for Sojorn, a friends-first social platform where **genuine connections thrive**.
|
||||||
|
|
||||||
### Core Philosophy Implemented
|
### Core Philosophy Implemented
|
||||||
|
|
||||||
Every design choice encodes behavioral principles:
|
Every design choice encodes behavioral principles:
|
||||||
|
|
||||||
1. **Calm is structural** → RLS policies enforce boundaries at database level
|
1. **Connection is structural** → RLS policies enforce boundaries at database level
|
||||||
2. **Consent is required** → Comments only work with mutual follows
|
2. **Consent is required** → Comments only work with mutual follows
|
||||||
3. **Exposure is opt-in** → Categories default to disabled, users choose what they see
|
3. **Exposure is opt-in** → Categories default to disabled, users choose what they see
|
||||||
4. **Influence is earned** → Harmony score determines reach and posting limits
|
4. **Influence is earned** → Harmony score determines reach and posting limits
|
||||||
|
|
@ -53,7 +53,7 @@ Every design choice encodes behavioral principles:
|
||||||
|
|
||||||
**Feed Systems:**
|
**Feed Systems:**
|
||||||
- `feed-personal` – Chronological feed from followed accounts
|
- `feed-personal` – Chronological feed from followed accounts
|
||||||
- `feed-sojorn` – Algorithmic FYP with calm velocity ranking
|
- `feed-sojorn` – Algorithmic FYP with authentic engagement ranking
|
||||||
- `trending` – Category-scoped trending with editorial overrides
|
- `trending` – Category-scoped trending with editorial overrides
|
||||||
|
|
||||||
**Trust Management:**
|
**Trust Management:**
|
||||||
|
|
@ -63,7 +63,7 @@ Every design choice encodes behavioral principles:
|
||||||
|
|
||||||
- **tone-detection.ts** – Pattern-based classifier (positive, neutral, mixed, negative, hostile)
|
- **tone-detection.ts** – Pattern-based classifier (positive, neutral, mixed, negative, hostile)
|
||||||
- **validation.ts** – Input validation with custom error types
|
- **validation.ts** – Input validation with custom error types
|
||||||
- **ranking.ts** – Calm velocity algorithm (saves > likes, steady > spiky)
|
- `ranking.ts` – Authentic engagement algorithm (saves > likes, steady > spiky)
|
||||||
- **harmony.ts** – Trust score calculation and reach effects
|
- **harmony.ts** – Trust score calculation and reach effects
|
||||||
- **supabase-client.ts** – Client configuration helpers
|
- **supabase-client.ts** – Client configuration helpers
|
||||||
|
|
||||||
|
|
@ -128,11 +128,11 @@ Every design choice encodes behavioral principles:
|
||||||
| Algorithms amplify outrage | Algorithms deprioritize sharp speech |
|
| Algorithms amplify outrage | Algorithms deprioritize sharp speech |
|
||||||
| Moderation is reactive | Containment is structural |
|
| Moderation is reactive | Containment is structural |
|
||||||
|
|
||||||
### vs. Other Calm Platforms
|
### vs. Other Friendly Platforms
|
||||||
|
|
||||||
| Other Calm Apps | Sojorn |
|
| Other Friendly Apps | Sojorn |
|
||||||
|-----------------|--------|
|
|-----------------|--------|
|
||||||
| Performative calm (aesthetics) | Structural calm (RLS, tone gates) |
|
| Performative friendliness (aesthetics) | Structural friendliness (RLS, tone gates) |
|
||||||
| Mindfulness focus | Social connection focus |
|
| Mindfulness focus | Social connection focus |
|
||||||
| Content curation (passive) | Content creation (active) |
|
| Content curation (passive) | Content creation (active) |
|
||||||
| Wellness angle | Social infrastructure angle |
|
| Wellness angle | Social infrastructure angle |
|
||||||
|
|
@ -159,7 +159,7 @@ Every design choice encodes behavioral principles:
|
||||||
### 4. Natural Fit Over Forced Moderation
|
### 4. Natural Fit Over Forced Moderation
|
||||||
- People who don't fit experience friction, not bans
|
- People who don't fit experience friction, not bans
|
||||||
- Influence diminishes naturally for hostile users
|
- Influence diminishes naturally for hostile users
|
||||||
- Recovery is automatic with calm participation
|
- Recovery is automatic with positive participation
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -207,7 +207,7 @@ Every design choice encodes behavioral principles:
|
||||||
2. **Read completion tracking** – Factor into ranking
|
2. **Read completion tracking** – Factor into ranking
|
||||||
3. **Post view logging** – Dwell time analysis
|
3. **Post view logging** – Dwell time analysis
|
||||||
4. **Analytics dashboard** – Harmony trends, category health
|
4. **Analytics dashboard** – Harmony trends, category health
|
||||||
5. **A/B testing framework** – Optimize calm velocity parameters
|
5. **A/B testing framework** – Optimize engagement parameters
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -262,7 +262,7 @@ When Sojorn is working:
|
||||||
|
|
||||||
## Final Note
|
## Final Note
|
||||||
|
|
||||||
This backend encodes **calm as infrastructure, not aspiration**.
|
This backend encodes **friendliness as infrastructure, not aspiration**.
|
||||||
|
|
||||||
The database will not allow:
|
The database will not allow:
|
||||||
- Unwanted replies
|
- Unwanted replies
|
||||||
|
|
@ -274,7 +274,7 @@ The database will not allow:
|
||||||
|
|
||||||
**Sojorn is structurally incapable of being an outrage machine.**
|
**Sojorn is structurally incapable of being an outrage machine.**
|
||||||
|
|
||||||
Now build the client that makes this calm accessible.
|
Now build the client that makes this friendliness accessible.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue