# 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 # iOS flutter run -d ``` ### 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.*