# 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
