396 lines
9.9 KiB
Markdown
396 lines
9.9 KiB
Markdown
# Sojorn Architecture & Deployment Guide
|
|
|
|
> **Last Updated:** 2026-02-03
|
|
> **Maintainer:** MPLS LLC
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
1. [Overview](#overview)
|
|
2. [Project Structure](#project-structure)
|
|
3. [Flutter App](#flutter-app)
|
|
4. [Go Backend](#go-backend)
|
|
5. [Server Deployment](#server-deployment)
|
|
6. [Database](#database)
|
|
7. [Common Commands](#common-commands)
|
|
8. [Troubleshooting](#troubleshooting)
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
**Sojorn** is a social media platform with the following core features:
|
|
- **Posts & Feeds:** Category-based content discovery
|
|
- **Chains (Threads):** Reddit-style threaded conversations
|
|
- **Beacons:** Location-based ephemeral posts
|
|
- **E2EE Chat:** End-to-end encrypted direct messaging
|
|
- **Profiles:** User profiles with follow/friend system
|
|
- **Reactions:** Custom emoji reactions on posts
|
|
|
|
### Tech Stack
|
|
| Component | Technology |
|
|
|-----------|------------|
|
|
| Mobile/Web App | Flutter (Dart) |
|
|
| Backend API | Go (Gin framework) |
|
|
| Database | PostgreSQL |
|
|
| Media Storage | Cloudflare R2 |
|
|
| Realtime | WebSockets |
|
|
|
|
---
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
C:\Webs\Sojorn\
|
|
├── sojorn_app/ # Flutter application
|
|
│ ├── lib/ # Dart source code
|
|
│ │ ├── screens/ # UI screens
|
|
│ │ ├── widgets/ # Reusable widgets
|
|
│ │ ├── services/ # Business logic & API calls
|
|
│ │ ├── models/ # Data models
|
|
│ │ ├── providers/ # Riverpod state management
|
|
│ │ └── theme/ # App theming
|
|
│ ├── web/ # Web-specific assets
|
|
│ ├── android/ # Android configs
|
|
│ ├── ios/ # iOS configs
|
|
│ └── pubspec.yaml # Dependencies
|
|
│
|
|
├── go-backend/ # Go API server
|
|
│ ├── cmd/api/ # Main entry point (main.go)
|
|
│ ├── internal/
|
|
│ │ ├── handlers/ # HTTP route handlers
|
|
│ │ ├── repository/ # Database queries
|
|
│ │ ├── services/ # Business logic
|
|
│ │ ├── models/ # Go structs
|
|
│ │ ├── middleware/ # Auth, CORS, rate limiting
|
|
│ │ └── config/ # Environment configuration
|
|
│ └── pkg/utils/ # Shared utilities
|
|
│
|
|
└── sojorn_docs/ # Documentation
|
|
```
|
|
|
|
---
|
|
|
|
## Flutter App
|
|
|
|
### Running Locally
|
|
|
|
```powershell
|
|
cd C:\Webs\Sojorn\sojorn_app
|
|
|
|
# Web (Chrome)
|
|
flutter run -d chrome
|
|
|
|
# Android
|
|
flutter run -d <device-id>
|
|
|
|
# iOS
|
|
flutter run -d <simulator-id>
|
|
```
|
|
|
|
### API Configuration
|
|
The app connects to the production API at:
|
|
```
|
|
https://api.gosojorn.com (or http://194.238.28.122:8080)
|
|
```
|
|
|
|
Configuration is in: `lib/config/api_config.dart`
|
|
|
|
### Key Files
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `lib/services/api_service.dart` | All backend API calls |
|
|
| `lib/services/auth_service.dart` | Authentication & token management |
|
|
| `lib/services/secure_chat_service.dart` | E2EE messaging |
|
|
| `lib/screens/profile/profile_screen.dart` | User's own profile |
|
|
| `lib/screens/profile/viewable_profile_screen.dart` | Viewing other profiles |
|
|
|
|
---
|
|
|
|
## Go Backend
|
|
|
|
### Local Development
|
|
|
|
```powershell
|
|
cd C:\Webs\Sojorn\go-backend
|
|
|
|
# Run locally
|
|
go run ./cmd/api
|
|
|
|
# Build binary
|
|
go build -o sojorn-api ./cmd/api
|
|
```
|
|
|
|
### Environment Variables
|
|
Create `.env` file or set environment variables:
|
|
```env
|
|
DATABASE_URL=postgres://user:pass@localhost:5432/sojorn?sslmode=disable
|
|
PORT=8080
|
|
JWT_SECRET=your-secret
|
|
CORS_ORIGINS=*
|
|
R2_ACCESS_KEY=...
|
|
R2_SECRET_KEY=...
|
|
```
|
|
|
|
### Key Files
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `cmd/api/main.go` | Server setup & route registration |
|
|
| `internal/handlers/post_handler.go` | Post CRUD & feed endpoints |
|
|
| `internal/handlers/user_handler.go` | Profile & social endpoints |
|
|
| `internal/repository/post_repository.go` | Post database queries |
|
|
| `internal/repository/user_repository.go` | User database queries |
|
|
|
|
---
|
|
|
|
## Server Deployment
|
|
|
|
### Server Details
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| **IP Address** | `194.238.28.122` |
|
|
| **SSH User** | `patrick` |
|
|
| **SSH Key** | `C:\Users\Patrick\.ssh\mpls.pem` |
|
|
| **Sudo Password** | `P22k154ever!` |
|
|
|
|
### Directory Structure on Server
|
|
```
|
|
/opt/sojorn/
|
|
├── bin/
|
|
│ └── api # ⚠️ THE RUNNING BINARY
|
|
├── go-backend/ # Git repo clone
|
|
│ └── ...
|
|
├── .env # Environment variables
|
|
└── sojorn-api # Build output (copy to bin/api)
|
|
```
|
|
|
|
### Systemd Service
|
|
**Service Name:** `sojorn-api`
|
|
**Config File:** `/etc/systemd/system/sojorn-api.service`
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=Sojorn Golang API Server
|
|
After=network.target postgresql.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=root
|
|
WorkingDirectory=/opt/sojorn
|
|
ExecStart=/opt/sojorn/bin/api # ⚠️ IMPORTANT: Uses bin/api
|
|
Restart=always
|
|
RestartSec=5s
|
|
EnvironmentFile=/opt/sojorn/.env
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
### Deployment Workflow
|
|
|
|
```bash
|
|
# 1. SSH to server
|
|
ssh -i "C:\Users\Patrick\.ssh\mpls.pem" patrick@194.238.28.122
|
|
|
|
# 2. Pull latest code
|
|
cd /opt/sojorn/go-backend
|
|
git fetch origin
|
|
git reset --hard origin/ThreadRestoration # or main branch
|
|
|
|
# 3. Build
|
|
go build -o sojorn-api ./cmd/api
|
|
|
|
# 4. Stop service, copy binary, start service
|
|
sudo systemctl stop sojorn-api
|
|
sudo cp sojorn-api /opt/sojorn/bin/api
|
|
sudo systemctl start sojorn-api
|
|
|
|
# 5. Verify
|
|
sudo systemctl status sojorn-api
|
|
```
|
|
|
|
### Quick Deploy Command (from Windows)
|
|
```powershell
|
|
ssh -i "C:\Users\Patrick\.ssh\mpls.pem" patrick@194.238.28.122 "cd /opt/sojorn/go-backend && git fetch origin && git reset --hard origin/ThreadRestoration && go build -o sojorn-api ./cmd/api && echo 'P22k154ever!' | sudo -S systemctl stop sojorn-api && echo 'P22k154ever!' | sudo -S cp sojorn-api /opt/sojorn/bin/api && echo 'P22k154ever!' | sudo -S systemctl start sojorn-api"
|
|
```
|
|
|
|
---
|
|
|
|
## Database
|
|
|
|
### Connection Details
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| **Host** | `localhost` (from server) |
|
|
| **Port** | `5432` |
|
|
| **Database** | `sojorn` |
|
|
| **User** | `postgres` |
|
|
| **Password** | `A24Zr7AEoch4eO0N` |
|
|
|
|
### Connection String
|
|
```
|
|
postgres://postgres:A24Zr7AEoch4eO0N@localhost:5432/sojorn?sslmode=disable
|
|
```
|
|
|
|
### Key Tables
|
|
| Table | Purpose |
|
|
|-------|---------|
|
|
| `profiles` | User profiles |
|
|
| `posts` | All posts (regular, chains, beacons) |
|
|
| `post_metrics` | Like/comment counts |
|
|
| `post_likes` | Who liked which post |
|
|
| `post_saves` | Saved/bookmarked posts |
|
|
| `post_reactions` | Emoji reactions |
|
|
| `follows` | Follow relationships |
|
|
| `conversations` | E2EE chat conversations |
|
|
| `messages` | Chat messages |
|
|
| `categories` | Content categories |
|
|
| `category_settings` | User category preferences |
|
|
|
|
### Useful Queries
|
|
```sql
|
|
-- Check saved posts
|
|
SELECT COUNT(*) FROM post_saves;
|
|
|
|
-- Check user's saved posts
|
|
SELECT * FROM post_saves WHERE user_id = 'uuid-here';
|
|
|
|
-- Check posts table
|
|
SELECT id, author_id, body, created_at FROM posts LIMIT 10;
|
|
```
|
|
|
|
---
|
|
|
|
## Common Commands
|
|
|
|
### Flutter App
|
|
```powershell
|
|
# Run on Chrome
|
|
flutter run -d chrome
|
|
|
|
# Build web
|
|
flutter build web
|
|
|
|
# Run tests
|
|
flutter test
|
|
|
|
# Analyze code
|
|
flutter analyze
|
|
```
|
|
|
|
### Go Backend
|
|
```powershell
|
|
# Run locally
|
|
cd C:\Webs\Sojorn\go-backend
|
|
go run ./cmd/api
|
|
|
|
# Build
|
|
go build -o sojorn-api ./cmd/api
|
|
|
|
# Format code
|
|
go fmt ./...
|
|
```
|
|
|
|
### Server Management
|
|
```bash
|
|
# SSH to server
|
|
ssh -i "C:\Users\Patrick\.ssh\mpls.pem" patrick@194.238.28.122
|
|
|
|
# Service commands
|
|
sudo systemctl status sojorn-api
|
|
sudo systemctl restart sojorn-api
|
|
sudo systemctl stop sojorn-api
|
|
sudo systemctl start sojorn-api
|
|
|
|
# View logs
|
|
sudo journalctl -u sojorn-api -f
|
|
|
|
# Database access
|
|
PGPASSWORD=A24Zr7AEoch4eO0N psql -h localhost -U postgres -d sojorn
|
|
```
|
|
|
|
### Git Operations
|
|
```powershell
|
|
# Commit and push (from local)
|
|
cd C:\Webs\Sojorn\go-backend
|
|
git add .
|
|
git commit -m "Your message"
|
|
git push
|
|
|
|
# Pull on server
|
|
ssh ... "cd /opt/sojorn/go-backend && git pull"
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Route Not Found (404) After Deployment
|
|
**Cause:** Old binary is still running.
|
|
**Solution:** Stop service before copying new binary:
|
|
```bash
|
|
sudo systemctl stop sojorn-api
|
|
sudo cp sojorn-api /opt/sojorn/bin/api
|
|
sudo systemctl start sojorn-api
|
|
```
|
|
|
|
### "Text file busy" Error
|
|
**Cause:** Trying to overwrite running binary.
|
|
**Solution:** Stop the service first.
|
|
|
|
### Server Not Responding
|
|
1. Check service status: `sudo systemctl status sojorn-api`
|
|
2. Check logs: `sudo journalctl -u sojorn-api -n 50`
|
|
3. Verify port: `sudo netstat -tlnp | grep 8080`
|
|
|
|
### Database Connection Errors
|
|
1. Check PostgreSQL: `sudo systemctl status postgresql`
|
|
2. Verify credentials in `/opt/sojorn/.env`
|
|
3. Test connection: `psql -h localhost -U postgres -d sojorn`
|
|
|
|
### Flutter Build Errors
|
|
1. Clean build: `flutter clean && flutter pub get`
|
|
2. Analyze: `flutter analyze`
|
|
3. Check Dart version: `flutter doctor`
|
|
|
|
---
|
|
|
|
## API Endpoints Reference
|
|
|
|
### Authentication
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| POST | `/api/v1/auth/register` | Register new user |
|
|
| POST | `/api/v1/auth/login` | Login |
|
|
| POST | `/api/v1/auth/refresh` | Refresh token |
|
|
|
|
### Profile
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/api/v1/profile` | Get own profile |
|
|
| GET | `/api/v1/profiles/:id` | Get profile by ID |
|
|
| PATCH | `/api/v1/profile` | Update profile |
|
|
|
|
### Posts
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| POST | `/api/v1/posts` | Create post |
|
|
| GET | `/api/v1/posts/:id` | Get single post |
|
|
| GET | `/api/v1/feed` | Get user's feed |
|
|
| GET | `/api/v1/users/:id/posts` | Get user's posts |
|
|
| GET | `/api/v1/users/:id/saved` | Get user's saved posts |
|
|
| POST | `/api/v1/posts/:id/save` | Save a post |
|
|
| DELETE | `/api/v1/posts/:id/save` | Unsave a post |
|
|
|
|
### Social
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| POST | `/api/v1/users/:id/follow` | Follow user |
|
|
| DELETE | `/api/v1/users/:id/follow` | Unfollow user |
|
|
| POST | `/api/v1/posts/:id/like` | Like post |
|
|
| DELETE | `/api/v1/posts/:id/like` | Unlike post |
|
|
|
|
---
|
|
|
|
*This document should be updated whenever deployment procedures or architecture changes.*
|