Navigation

Scrabble Backend API (SnappyIdioms.com)

Server-side implementation for idiom syncing, pearl economy, and game session management

Architecture Overview

📍 Function Location:

functions/gameAPISupabase

🔗 Integration Flow:

  1. 1. Famous.ai game → Platform API Proxy (Famous.ai server)
  2. 2. Platform Proxy → verifyGameToken (token validation)
  3. 3. Platform Proxy → gameAPISupabase (this function)
  4. 4. gameAPISupabase → Supabase (pearl balances, idioms, sessions)

⚠️ Security Notes:

  • • Uses Supabase Service Role Key (server-side only)
  • • Validates tokens via verifyGameToken endpoint
  • • Implements CORS for cross-origin requests
  • • Direct REST API fallback if supabase-js fails
Pearl Economy System

💎 Pearl Caps:

  • • Free Users: 50 pearls per week
  • • Premium Users: 200 pearls per week
  • • Week Reset: Every Monday at 00:00 UTC

🧮 Pearl Calculation Formula:

pearls = 1 + Math.floor(score / 100) + (isPerfect ? 5 : 0)

Base 1 pearl + 1 per 100 points + 5 bonus for perfect round

✅ Pearl Award Flow:

  1. 1. Game completes → Famous.ai calls action: 'report-completion'
  2. 2. Backend calculates pearls earned
  3. 3. Checks weekly cap (free vs premium)
  4. 4. Awards capped amount
  5. 5. Updates pearl_balances table
  6. 6. Logs transaction in pearl_rewards
  7. 7. Returns total + weekly remaining
Database Schema

📊 Tables:

synced_idioms

{
  id: serial primary key,
  phrase: text unique not null,
  words: text[],
  definition: text,
  example: text,
  difficulty: text,
  category: text,
  points: integer,
  source: text,
  mothership_id: text,
  updated_at: timestamp
}

pearl_balances

{
  username: text primary key,
  total_pearls: integer default 0,
  weekly_pearls: integer default 0,
  week_start: date,
  is_premium: boolean default false,
  updated_at: timestamp
}

pearl_rewards

{
  id: serial primary key,
  username: text not null,
  pearls_awarded: integer,
  score: integer,
  level: integer,
  is_perfect: boolean,
  idioms_completed: text[],
  week_start: date,
  created_at: timestamp
}

mothership_config

{
  id: serial primary key,
  app_id: text,
  auth_token: text,
  entity_name: text default 'Idiom',
  is_connected: boolean default false,
  sync_status: text,
  last_sync_at: timestamp,
  last_sync_count: integer,
  updated_at: timestamp
}

game_sessions

{
  id: serial primary key,
  username: text,
  source: text,
  referrer: text,
  character: text,
  difficulty: text,
  embed_mode: boolean,
  mothership_user_id: text,
  score: integer,
  level: integer,
  idioms_completed: integer,
  session_start: timestamp default now(),
  session_end: timestamp
}
API Endpoints

GET ?action=idioms

Fetch all synced idioms from database

Response: {
  success: true,
  idioms: [...],
  count: 1234
}

GET ?action=pearl-balance&username=X

Get pearl balance for specific user

Response: {
  total_pearls: 150,
  weekly_pearls: 25,
  weekly_cap: 50,
  weekly_remaining: 25,
  is_premium: false,
  cap_reached: false,
  week_resets_at: "2026-02-24T00:00:00.000Z"
}

POST action: 'report-completion'

Award pearls for completed game round

Request: {
  action: 'report-completion',
  username: 'player123',
  score: 450,
  level: 3,
  is_perfect: true,
  completed_idioms: ['break the ice', 'piece of cake']
}

Response: {
  success: true,
  pearls_calculated: 10,
  pearls_awarded: 10,
  total_pearls: 160,
  weekly_pearls: 35,
  weekly_remaining: 15,
  cap_reached: false,
  message: 'Earned 10 pearls!'
}

POST action: 'sync-stash'

Sync offline pearl rewards when player reconnects

Request: {
  action: 'sync-stash',
  username: 'player123',
  stash: [
    { score: 300, level: 1, is_perfect: false },
    { score: 500, level: 2, is_perfect: true }
  ]
}

Response: {
  success: true,
  synced: 2,
  pearls_synced: 12,
  total_pearls: 172,
  weekly_remaining: 3
}

POST action: 'connect'

Connect to Base44 mothership for idiom syncing

Request: {
  action: 'connect',
  app_id: '68eed6a8ca9efc733033fb04',
  auth_token: 'optional_bearer_token',
  entity_name: 'Idiom'
}

Response: {
  success: true,
  connected: true,
  test_count: 1234,
  message: 'Connected to Base44 app. Found 1234 test idioms.'
}

POST action: 'fetch-idioms'

Fetch and sync all idioms from Base44

Response: {
  success: true,
  fetched: 1234,
  synced: 1230,
  errors: 4,
  message: 'Successfully synced 1230 idioms from mothership'
}

POST action: 'session'

Create game session for analytics

Request: {
  action: 'session',
  username: 'player123',
  character: 'snappy',
  difficulty: 'intermediate'
}

Response: {
  success: true,
  session_id: 42
}
Error Handling & Fallbacks

🛡️ Direct REST API Fallback:

If supabase-js client fails, the function automatically falls back to direct Supabase REST API calls:

  • • directSupabaseInsert() - POST to /rest/v1/table
  • • directSupabaseSelect() - GET from /rest/v1/table
  • • directSupabaseUpdate() - PATCH to /rest/v1/table
  • • directSupabaseUpsert() - POST with merge-duplicates

⚙️ Safe Wrapper Functions:

async function safeInsert(supabase, table, data) {
  try {
    // Try supabase-js first
    const { error, data: result } = await supabase
      .from(table).insert(data).select().single();
    if (error) throw error;
    return result;
  } catch (e) {
    // Fall back to direct REST
    console.warn('Trying direct REST...');
    return await directSupabaseInsert(table, data);
  }
}

⚠️ Common Issues:

  • • Invalid Supabase URL: Validates and cleans URL before use
  • • Missing credentials: Clear error messages for missing env vars
  • • Guest mode: Returns error when username is 'guest'
  • • Weekly cap reached: Returns cap_reached: true
Environment Variables

Required Secrets:

SUPABASE_URL=https://YOUR_PROJECT.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJhbGc...your_key_here

Set these in Base44 Dashboard → Settings → Environment Variables

Full Implementation Reference

This backend function implements the complete idiom sync and pearl economy system. Key features:

  • ✅ Idiom syncing from Base44 → Supabase
  • ✅ Pearl earning with weekly caps (free vs premium)
  • ✅ Offline pearl stash syncing
  • ✅ Game session tracking
  • ✅ Direct REST API fallbacks for reliability
  • ✅ CORS support for cross-origin requests

📄 Full Source Code:

View the complete implementation in functions/gameAPISupabase