# Sojorn - Setup Guide Quick guide to get Sojorn running locally and deployed. --- ## Prerequisites - [Supabase CLI](https://supabase.com/docs/guides/cli/getting-started) installed - [Deno](https://deno.land) installed (for Edge Functions) - [Git](https://git-scm.com) installed - A [Supabase account](https://supabase.com) (free tier works) --- ## Step 1: Environment Setup ### 1.1 Create Supabase Project 1. Go to [app.supabase.com](https://app.supabase.com) 2. Click "New Project" 3. Choose a name (e.g., "sojorn-dev") 4. Set a strong database password 5. Select a region close to you 6. Wait for project to initialize (~2 minutes) ### 1.2 Get Your Credentials Once your project is ready: 1. Go to **Settings → API** 2. Copy these values: - **Project URL** (e.g., `https://abcdefgh.supabase.co`) - **anon/public key** (starts with `eyJ...`) - **service_role key** (starts with `eyJ...`) 3. Go to **Settings → General** - Copy your **Project Reference ID** (e.g., `abcdefgh`) 4. Go to **Settings → Database** - Copy your **Database Password** (or reset it if you forgot) ### 1.3 Configure .env File Open `.env` in this project and fill in your values: ```bash SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co SUPABASE_ANON_KEY=eyJ...your_anon_key... SUPABASE_SERVICE_ROLE_KEY=eyJ...your_service_role_key... SUPABASE_PROJECT_REF=YOUR_PROJECT_REF SUPABASE_DB_PASSWORD=your_database_password CRON_SECRET=generate_with_openssl_rand NODE_ENV=development API_BASE_URL=https://YOUR_PROJECT_REF.supabase.co/functions/v1 ``` ### 1.4 Generate CRON_SECRET In your terminal: ```bash # macOS/Linux openssl rand -base64 32 # Windows (PowerShell) -join ((48..57) + (65..90) + (97..122) | Get-Random -Count 32 | % {[char]$_}) ``` Copy the output and paste it as your `CRON_SECRET` in `.env`. --- ## Step 2: Link to Supabase ```bash # Login to Supabase supabase login # Link your local project to your Supabase project supabase link --project-ref YOUR_PROJECT_REF # Enter your database password when prompted ``` --- ## Step 3: Deploy Database ### 3.1 Push Migrations ```bash # Apply all migrations to your Supabase project supabase db push ``` This will create all tables, functions, and RLS policies. ### 3.2 Seed Categories Connect to your database and run the seed script: ```bash # Using psql psql "postgresql://postgres:YOUR_DB_PASSWORD@db.YOUR_PROJECT_REF.supabase.co:5432/postgres" \ -f supabase/seed/seed_categories.sql # Or using Supabase SQL Editor: # 1. Go to https://app.supabase.com/project/YOUR_PROJECT/editor # 2. Copy contents of supabase/seed/seed_categories.sql # 3. Paste and run ``` ### 3.3 Verify Database Setup ```bash # Check that tables were created supabase db remote commit ``` Or in the Supabase Dashboard: - Go to **Table Editor** → You should see all 14 tables --- ## Step 4: Deploy Edge Functions ### 4.1 Set Secrets ```bash # Set the CRON_SECRET for the harmony calculation function supabase secrets set CRON_SECRET="your_cron_secret_from_env" ``` ### 4.2 Deploy All Functions ```bash # Deploy each function supabase functions deploy publish-post supabase functions deploy publish-comment supabase functions deploy block supabase functions deploy report supabase functions deploy feed-personal supabase functions deploy feed-sojorn supabase functions deploy trending supabase functions deploy calculate-harmony ``` Or deploy all at once (if you have a deployment script). ### 4.3 Verify Functions Go to **Edge Functions** in your Supabase dashboard: - You should see 8 functions listed - Check logs to ensure no deployment errors --- ## Step 5: Test the API ### 5.1 Create a Test User 1. Go to **Authentication → Users** in Supabase Dashboard 2. Click "Add User" 3. Enter email and password 4. Copy the User ID (UUID) ### 5.2 Manually Create Profile In **SQL Editor**, run: ```sql -- Replace USER_ID with the UUID from step 5.1 INSERT INTO profiles (id, handle, display_name, bio) VALUES ('USER_ID', 'testuser', 'Test User', 'Testing Sojorn'); ``` ### 5.3 Get a JWT Token 1. Use the [Supabase Auth API](https://supabase.com/docs/reference/javascript/auth-signinwithpassword): ```bash curl -X POST "https://YOUR_PROJECT_REF.supabase.co/auth/v1/token?grant_type=password" \ -H "apikey: YOUR_ANON_KEY" \ -H "Content-Type: application/json" \ -d '{ "email": "test@example.com", "password": "your_password" }' ``` 2. Copy the `access_token` from the response ### 5.4 Test Edge Functions ```bash # Set your token export TOKEN="your_access_token_here" # Get a category ID (from seed data) # Go to Table Editor → categories → Copy the 'general' category UUID # Test publishing a post curl -X POST "https://YOUR_PROJECT_REF.supabase.co/functions/v1/publish-post" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "category_id": "CATEGORY_UUID", "body": "This is my first friendly post on Sojorn." }' # Test getting personal feed curl "https://YOUR_PROJECT_REF.supabase.co/functions/v1/feed-personal" \ -H "Authorization: Bearer $TOKEN" # Test Sojorn feed curl "https://YOUR_PROJECT_REF.supabase.co/functions/v1/feed-sojorn?limit=10" \ -H "Authorization: Bearer $TOKEN" ``` --- ## Step 6: Schedule Harmony Calculation ### Option 1: GitHub Actions (Recommended for small projects) Create `.github/workflows/harmony-cron.yml`: ```yaml name: Calculate Harmony Daily on: schedule: - cron: '0 2 * * *' # 2 AM UTC daily workflow_dispatch: jobs: calculate: runs-on: ubuntu-latest steps: - name: Trigger harmony calculation run: | curl -X POST \ https://${{ secrets.SUPABASE_PROJECT_REF }}.supabase.co/functions/v1/calculate-harmony \ -H "Authorization: Bearer ${{ secrets.CRON_SECRET }}" ``` Add secrets in GitHub: - `SUPABASE_PROJECT_REF` - `CRON_SECRET` ### Option 2: Cron-Job.org (External service) 1. Go to [cron-job.org](https://cron-job.org) and create account 2. Create new cron job: - URL: `https://YOUR_PROJECT_REF.supabase.co/functions/v1/calculate-harmony` - Schedule: Daily at 2 AM - Method: POST - Header: `Authorization: Bearer YOUR_CRON_SECRET` --- ## Step 7: Verify Everything Works ### 7.1 Check Tables In **Table Editor**, verify: - [ ] `profiles` has your test user - [ ] `categories` has 12 categories - [ ] `trust_state` has your user (with harmony_score = 50) - [ ] `posts` has any posts you created ### 7.2 Check RLS Policies In **SQL Editor**, test block enforcement: ```sql -- Create a second test user INSERT INTO auth.users (id, email) VALUES (gen_random_uuid(), 'test2@example.com'); INSERT INTO profiles (id, handle, display_name) VALUES ((SELECT id FROM auth.users WHERE email = 'test2@example.com'), 'testuser2', 'Test User 2'); -- Block user 2 from user 1 INSERT INTO blocks (blocker_id, blocked_id) VALUES ( (SELECT id FROM profiles WHERE handle = 'testuser'), (SELECT id FROM profiles WHERE handle = 'testuser2') ); -- Verify user 1 cannot see user 2's profile SET request.jwt.claims TO '{"sub": "USER_1_ID"}'; SELECT * FROM profiles WHERE handle = 'testuser2'; -- Should return 0 rows -- Reset RESET request.jwt.claims; ``` ### 7.3 Test Tone Detection Try publishing a hostile post: ```bash curl -X POST "https://YOUR_PROJECT_REF.supabase.co/functions/v1/publish-post" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "category_id": "CATEGORY_UUID", "body": "This is fucking bullshit." }' ``` Expected response: ```json { "error": "Content rejected", "message": "This post contains language that does not fit here.", "suggestion": "This space works without profanity. Try rephrasing." } ``` --- ## Troubleshooting ### "Relation does not exist" error - Run `supabase db push` again - Check that migrations completed successfully ### "JWT expired" error - Your auth token expired (tokens last 1 hour) - Sign in again to get a new token ### "Failed to fetch" error - Check your `SUPABASE_URL` is correct - Verify Edge Functions are deployed - Check function logs: `supabase functions logs FUNCTION_NAME` ### RLS policies blocking everything - Ensure you're using the correct user ID in JWT - Check that user exists in `profiles` table - Verify RLS policies with `\d+ TABLE_NAME` in psql --- ## Next Steps Now that your backend is running: 1. **Build missing Edge Functions** (signup, follow, like, etc.) 2. **Start Flutter client** (see Flutter setup guide when created) 3. **Write transparency pages** (How Reach Works, Rules) 4. **Add admin tooling** (report review, trending overrides) --- ## Useful Commands ```bash # View Edge Function logs supabase functions logs publish-post --tail # Reset database (WARNING: deletes all data) supabase db reset # Check Supabase status supabase status # View remote database changes supabase db remote commit # Generate TypeScript types from database supabase gen types typescript --local > types/database.ts ``` --- ## Support - [Supabase Docs](https://supabase.com/docs) - [Supabase Discord](https://discord.supabase.com) - [Sojorn Documentation](README.md)