sojorn/sojorn_docs/DEVELOPMENT_COMPREHENSIVE.md
Patrick Britton b9351b76ae 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.
2026-01-30 09:49:36 -06:00

726 lines
21 KiB
Markdown

# Development & Architecture Comprehensive Guide
## Overview
This guide consolidates all development, architecture, and design system documentation for the Sojorn platform, covering the philosophical foundations, technical architecture, and implementation patterns.
---
## Architecture Philosophy
### Core Principles
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
**Principle**: When you block someone, they disappear from your world and you from theirs.
**Implementation**:
- Database function: `has_block_between(user_a, user_b)` checks bidirectional blocks
- API middleware prevents blocked users from:
- Seeing each other's profiles
- Seeing each other's posts
- Seeing each other's follows
- Interacting in any way
**Effect**: No notifications, no traces, no conflict. The system enforces separation silently.
### 2. Consent: Conversation Requires Mutual Follow
**Principle**: You cannot reply to someone unless you mutually follow each other.
**Implementation**:
- Database function: `is_mutual_follow(user_a, user_b)` verifies bidirectional following
- Comment creation requires mutual follow relationship
- API endpoints enforce conversation gating
**Effect**: Unwanted replies are impossible. Conversation is opt-in by structure.
### 3. Exposure: Opt-In by Default
**Principle**: Users choose what content they see. Filtering is private and encouraged.
**Implementation**:
- All categories except `general` have `default_off = true`
- Users must explicitly enable categories to see posts
- Feed algorithms respect user preferences
**Effect**: Users control their content exposure without social pressure.
---
## Technical Architecture
### System Overview
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Flutter App │ │ Go Backend │ │ PostgreSQL │
│ │ │ │ │ │
│ - UI/UX │◄──►│ - REST API │◄──►│ - Data Store │
│ - State Mgmt │ │ - Business Logic│ │ - Constraints │
│ - Navigation │ │ - Validation │ │ - Functions │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Local Storage │ │ File System │ │ Extensions │
│ │ │ │ │ │
│ - Secure Storage│ │ - Uploads │ │ - PostGIS │
│ - Cache │ │ - Logs │ │ - pg_trgm │
│ - Preferences │ │ - Temp Files │ │ - uuid-ossp │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### Backend Architecture
#### Layer Structure
```
┌─────────────────────────────────────────┐
│ API Layer │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Gin │ │ Middleware │ │
│ │ Router │ │ - Auth │ │
│ │ │ │ - CORS │ │
│ │ │ │ - Rate Limit │ │
│ └─────────────┘ └─────────────────┘ │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ Service Layer │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Business │ │ External │ │
│ │ Logic │ │ Services │ │
│ │ │ │ - FCM │ │
│ │ │ │ - R2 Storage │ │
│ └─────────────┘ └─────────────────┘ │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ Repository Layer │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Data │ │ Database │ │
│ │ Access │ │ - PostgreSQL │ │
│ │ │ │ - Migrations │ │
│ │ │ │ - Queries │ │
│ └─────────────┘ └─────────────────┘ │
└─────────────────────────────────────────┘
```
#### Key Components
**1. Authentication & Authorization**
- JWT-based authentication with refresh tokens
- Role-based access control
- Session management with secure cookies
**2. Data Validation**
- Structured request/response models
- Input sanitization and validation
- Error handling with proper HTTP status codes
**3. Business Logic Services**
- User management and relationships
- Content moderation and filtering
- Notification and messaging systems
**4. External Integrations**
- Firebase Cloud Messaging
- Cloudflare R2 storage
- Email services
### Database Architecture
#### Core Schema Design
**Identity & Relationships**
```sql
profiles (users, identity, settings)
├── follows (mutual relationships)
├── blocks (complete separation)
└── user_category_settings (content preferences)
```
**Content & Engagement**
```sql
posts (content, metadata)
├── post_metrics (engagement data)
├── post_likes (boosts only)
├── post_saves (private bookmarks)
└── comments (mutual-follow-only)
```
**Moderation & Trust**
```sql
reports (community moderation)
├── trust_state (harmony scoring)
└── audit_log (transparency trail)
```
#### Database Functions
**Relationship Checking**
```sql
-- Bidirectional blocking
CREATE OR REPLACE FUNCTION has_block_between(user_a UUID, user_b UUID)
RETURNS BOOLEAN AS $$
SELECT EXISTS (
SELECT 1 FROM blocks
WHERE (blocker_id = user_a AND blocked_id = user_b)
OR (blocker_id = user_b AND blocked_id = user_a)
);
$$ LANGUAGE SQL;
-- Mutual follow verification
CREATE OR REPLACE FUNCTION is_mutual_follow(user_a UUID, user_b UUID)
RETURNS BOOLEAN AS $$
SELECT EXISTS (
SELECT 1 FROM follows f1
JOIN follows f2 ON f1.follower_id = f2.following_id
AND f1.following_id = f2.follower_id
WHERE f1.follower_id = user_a AND f1.following_id = user_b
);
$$ LANGUAGE SQL;
```
**Rate Limiting**
```sql
-- Posting rate limits
CREATE OR REPLACE FUNCTION can_post(user_id UUID)
RETURNS BOOLEAN AS $$
SELECT get_post_rate_limit(user_id) > 0;
$$ LANGUAGE SQL;
```
---
## Design System
### Visual Philosophy
**Warm, Not Overwhelming**
- Warm neutrals (beige/paper tones) instead of cold grays
- Soft shadows, never harsh
- Muted semantic colors that inform without alarming
**Modern, Not Trendy**
- Timeless color palette
- Classic typography hierarchy
- Subtle animations and transitions
**Text-Forward**
- Generous line height (1.6-1.65 for body text)
- Optimized for reading, not scanning
- Clear hierarchy without relying on color
**Intentionally Slow**
- Animation durations: 300-400ms
- Ease curves that feel deliberate
- No jarring transitions
### Color System
#### Background Palette
```dart
background = #F8F7F4 // Warm off-white (like paper)
surface = #FFFFFD // Barely warm white
surfaceElevated = #FFFFFF // Pure white for cards
surfaceVariant = #F0EFEB // Subtle warm gray (inputs)
```
#### Semantic Colors
```dart
primary = #6B5B95 // Soft purple (friendly authority)
secondary = #8B7355 // Warm brown (earth tone)
success = #6B8E6F // Muted green (gentle confirmation)
warning = #B8956A // Soft amber (warm caution)
error = #B86B6B // Muted rose (gentle error)
```
#### Border System
```dart
borderSubtle = #E8E6E1 // Barely visible dividers
border = #D8D6D1 // Default borders
borderStrong = #C8C6C1 // Emphasized borders
```
### Typography
#### Font Hierarchy
```dart
// Display
displayLarge = 32px / 48px / 300
displayMedium = 28px / 42px / 300
displaySmall = 24px / 36px / 300
// Headings
headlineLarge = 20px / 30px / 400
headlineMedium = 18px / 27px / 400
headlineSmall = 16px / 24px / 500
// Body
bodyLarge = 16px / 26px / 400
bodyMedium = 14px / 22px / 400
bodySmall = 12px / 20px / 400
// Labels
labelLarge = 14px / 20px / 500
labelMedium = 12px / 16px / 500
labelSmall = 10px / 14px / 500
```
#### Typography Principles
- **Line Height**: 1.6-1.65 for body text (optimized for reading)
- **Font Weight**: Conservative use (300-500, rarely 700)
- **Letter Spacing**: Subtle adjustments for readability
- **Color**: Primary use of gray scale, semantic colors sparingly
### Component System
#### Buttons
```dart
// Primary Button
ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(primary),
foregroundColor: MaterialStateProperty.all<Color>(surface),
elevation: MaterialStateProperty.all<double>(2),
padding: MaterialStateProperty.all<EdgeInsets>(
EdgeInsets.symmetric(horizontal: 24, vertical: 16)
),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))
)
)
// Secondary Button
ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(surfaceVariant),
foregroundColor: MaterialStateProperty.all<Color>(primary),
elevation: MaterialStateProperty.all<double>(1),
// ... same padding and shape
)
```
#### Cards
```dart
Card(
elevation: 3,
shadowColor: Colors.black.withOpacity(0.1),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12)
),
child: Padding(
padding: EdgeInsets.all(16),
child: // content
)
)
```
#### Input Fields
```dart
InputDecoration(
filled: true,
fillColor: surfaceVariant,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: border)
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: primary, width: 2)
),
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12)
)
```
---
## Development Patterns
### Code Organization
#### Flutter Structure
```
lib/
├── main.dart # App entry point
├── config/ # Configuration
│ ├── api_config.dart
│ └── theme_config.dart
├── models/ # Data models
│ ├── user.dart
│ ├── post.dart
│ └── chat.dart
├── providers/ # State management
│ ├── auth_provider.dart
│ ├── feed_provider.dart
│ └── theme_provider.dart
├── services/ # Business logic
│ ├── api_service.dart
│ ├── auth_service.dart
│ └── notification_service.dart
├── screens/ # UI screens
│ ├── auth/
│ ├── home/
│ └── chat/
├── widgets/ # Reusable components
│ ├── post_card.dart
│ ├── user_avatar.dart
│ └── chat_bubble.dart
└── utils/ # Utilities
├── constants.dart
├── helpers.dart
└── validators.dart
```
#### Go Structure
```
cmd/
└── api/
└── main.go # Application entry
internal/
├── config/ # Configuration
│ └── config.go
├── models/ # Data models
│ ├── user.go
│ ├── post.go
│ └── chat.go
├── handlers/ # HTTP handlers
│ ├── auth_handler.go
│ ├── post_handler.go
│ └── chat_handler.go
├── services/ # Business logic
│ ├── auth_service.go
│ ├── post_service.go
│ └── notification_service.go
├── repository/ # Data access
│ ├── user_repository.go
│ ├── post_repository.go
│ └── chat_repository.go
├── middleware/ # HTTP middleware
│ ├── auth.go
│ ├── cors.go
│ └── ratelimit.go
└── database/ # Database
├── migrations/
└── queries.go
```
### State Management Patterns
#### Flutter Provider Pattern
```dart
// Authentication Provider
final authServiceProvider = Provider<AuthService>((ref) {
return AuthService();
});
final currentUserProvider = Provider<User?>((ref) {
final authService = ref.watch(authServiceProvider);
ref.watch(authStateProvider);
return authService.currentUser;
});
final authStateProvider = StreamProvider<AuthState>((ref) {
final authService = ref.watch(authServiceProvider);
return authService.authStateChanges;
});
```
#### Go Service Pattern
```dart
// Service Interface
type PostService interface {
CreatePost(ctx context.Context, req *CreatePostRequest) (*Post, error)
GetFeed(ctx context.Context, userID string, pagination *Pagination) ([]*Post, error)
LikePost(ctx context.Context, userID, postID string) error
}
// Service Implementation
type postService struct {
postRepo repository.PostRepository
userRepo repository.UserRepository
notifier services.NotificationService
}
func NewPostService(postRepo, userRepo repository.PostRepository, notifier services.NotificationService) PostService {
return &postService{
postRepo: postRepo,
userRepo: userRepo,
notifier: notifier,
}
}
```
### Error Handling Patterns
#### Flutter Error Handling
```dart
// Result Type
class Result<T> {
final T? data;
final String? error;
Result.success(this.data) : error = null;
Result.error(this.error) : data = null;
bool get isSuccess => error == null;
bool get isError => error != null;
}
// Usage
Future<Result<Post>> createPost(CreatePostRequest request) async {
try {
final post = await apiService.createPost(request);
return Result.success(post);
} catch (e) {
return Result.error(e.toString());
}
}
```
#### Go Error Handling
```go
// Custom Error Types
type ValidationError struct {
Field string
Message string
}
func (e ValidationError) Error() string {
return fmt.Sprintf("validation error on %s: %s", e.Field, e.Message)
}
// Service Error Handling
func (s *postService) CreatePost(ctx context.Context, req *CreatePostRequest) (*Post, error) {
if err := req.Validate(); err != nil {
return nil, ValidationError{Field: "request", Message: err.Error()}
}
post, err := s.postRepo.Create(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to create post: %w", err)
}
return post, nil
}
```
---
## Testing Strategy
### Flutter Testing
#### Unit Tests
```dart
// Example: Post Service Test
void main() {
group('PostService', () {
late MockApiService mockApiService;
late PostService postService;
setUp(() {
mockApiService = MockApiService();
postService = PostService(mockApiService);
});
test('createPost should return post on success', () async {
// Arrange
final mockPost = Post(id: '1', content: 'Test post');
when(mockApiService.createPost(any))
.thenAnswer((_) async => mockPost);
// Act
final result = await postService.createPost(CreatePostRequest(content: 'Test post'));
// Assert
expect(result.isSuccess, true);
expect(result.data?.content, 'Test post');
});
});
}
```
#### Widget Tests
```dart
void main() {
testWidgets('PostCard displays post content', (WidgetTester tester) async {
// Arrange
final post = Post(id: '1', content: 'Test post', author: User(name: 'Test User'));
// Act
await tester.pumpWidget(
MaterialApp(
home: PostCard(post: post),
),
);
// Assert
expect(find.text('Test post'), findsOneWidget);
expect(find.text('Test User'), findsOneWidget);
});
}
```
### Go Testing
#### Unit Tests
```go
func TestPostService_CreatePost(t *testing.T) {
tests := []struct {
name string
request *CreatePostRequest
want *Post
wantErr bool
}{
{
name: "valid request",
request: &CreatePostRequest{
UserID: "user123",
Content: "Test post",
},
want: &Post{
ID: "post123",
UserID: "user123",
Content: "Test post",
},
wantErr: false,
},
{
name: "invalid request",
request: &CreatePostRequest{
UserID: "",
Content: "Test post",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockRepo := &MockPostRepository{}
service := NewPostService(mockRepo, nil, nil)
if !tt.wantErr {
mockRepo.On("Create", mock.Anything, tt.request).Return(tt.want, nil)
}
got, err := service.CreatePost(context.Background(), tt.request)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
}
mockRepo.AssertExpectations(t)
})
}
}
```
---
## Performance Optimization
### Flutter Performance
#### Key Optimizations
1. **Const Constructors**: Use `const` for immutable widgets
2. **Lazy Loading**: Implement `ListView.builder` for large lists
3. **Image Caching**: Use `cached_network_image` for remote images
4. **State Management**: Minimize rebuilds with selective providers
#### Example: Optimized List View
```dart
ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
return PostCard(
key: ValueKey(posts[index].id),
post: posts[index],
);
},
)
```
### Go Performance
#### Database Optimizations
1. **Connection Pooling**: Configure appropriate pool sizes
2. **Query Optimization**: Use prepared statements and proper indexes
3. **Caching**: Implement Redis for frequently accessed data
#### Example: Database Configuration
```go
config, err := pgxpool.ParseConfig(databaseURL)
if err != nil {
return nil, err
}
config.MaxConns = 25
config.MinConns = 5
config.MaxConnLifetime = time.Hour
config.HealthCheckPeriod = time.Minute * 5
pool, err := pgxpool.NewWithConfig(context.Background(), config)
```
---
## Security Considerations
### Authentication Security
- JWT tokens with proper expiration
- Secure token storage (FlutterSecureStorage)
- Refresh token rotation
- Rate limiting on auth endpoints
### Data Protection
- Input validation and sanitization
- SQL injection prevention with parameterized queries
- XSS protection in web views
- CSRF protection for state-changing operations
### Privacy Protection
- Data minimization in API responses
- Anonymous analytics collection
- User data export and deletion capabilities
- GDPR compliance considerations
---
## Deployment Architecture
### Production Stack
```
Internet
Nginx (SSL Termination, Static Files)
Go Backend (API, Business Logic)
PostgreSQL (Data, PostGIS)
File System (Uploads) / Cloudflare R2
```
### Environment Configuration
- **Development**: Local PostgreSQL, mock services
- **Staging**: Production-like environment with test data
- **Production**: Full stack with monitoring and backups
### Monitoring & Observability
- **Application Metrics**: Request latency, error rates, user activity
- **Infrastructure Metrics**: CPU, memory, disk usage
- **Database Metrics**: Query performance, connection pool status
- **Business Metrics**: User engagement, content creation rates
---
**Last Updated**: January 30, 2026
**Version**: 1.0
**Next Review**: February 15, 2026