Skip to content

Code Modifications

poiromaniax edited this page Sep 11, 2025 · 2 revisions

This page covers all the necessary code changes required to make TableSlayer work in a self-hosted environment. These modifications fixed critical bugs and ensure proper integration with your services. These changes have all been implemented in this codebase :)

1. Critical Bug Fixes

Fix Google OAuth Avatar Issue

This fixes the "foreign key constraint" error when users sign up with Google OAuth.

File: apps/web/src/lib/server/user/index.ts

Location: Around line 407, in the createOrUpdateGoogleUser function

Change From:

await db.insert(usersTable).values({
  id: userId,
  name,
  email,
  googleId,
  emailVerified: true,
  passwordHash: null
});

Change To:

await db.insert(usersTable).values({
  id: userId,
  name,
  email,
  googleId,
  emailVerified: true,
  passwordHash: null,
  avatarFileId: null // Add this line - critical fix!
});

Fix Database Schema

This makes the avatarFileId field nullable to prevent constraint errors.

File: apps/web/src/lib/db/app/schema.ts

Location: Around line 22, in the usersTable definition

Change From:

avatarFileId: integer('avatar_file_id')
  .references(() => filesTable.id, { onDelete: 'cascade' })
  .notNull()
  .default(1),

Change To:

avatarFileId: integer('avatar_file_id')
  .references(() => filesTable.id, { onDelete: 'cascade' }),

Generate Database Migration

After making the schema change, generate a migration:

cd apps/web
pnpm run generate

This creates a migration file that makes avatarFileId nullable.

2. Fix Real-time Synchronization

This ensures fog of war, annotations, and other properties sync properly between admin UI and playfield.

File: apps/web/src/routes/(app)/[party]/play/+page@.svelte

Location: Around line 114, in the Y.js data processing section

Ensure these properties are included:

stageProps = {
  ...yjsSceneData.stageProps,
  // Force player mode
  mode: 1,
  // Build scene from scratch
  scene: {
    autoFit: true,
    offset: { x: 0, y: 0 },
    rotation: 0,
    zoom: stageProps.scene?.zoom || 1
  },
  // Don't allow active layer (fog tools, etc)
  activeLayer: MapLayerType.None,
  // Filter markers to remove DM-only ones
  marker: {
    ...yjsSceneData.stageProps.marker,
    markers: (yjsSceneData.stageProps.marker?.markers || []).filter((m: Marker) => m.visibility !== 1)
  },
  // Include fog of war data for proper synchronization
  fogOfWar: {
    ...yjsSceneData.stageProps.fogOfWar
  },
  // Include annotations for proper synchronization
  annotations: {
    ...yjsSceneData.stageProps.annotations
  },
  // Include map settings for proper synchronization
  map: {
    ...yjsSceneData.stageProps.map
  },
  // Include display settings for proper synchronization
  display: {
    ...yjsSceneData.stageProps.display
  },
  // Include grid settings for proper synchronization
  grid: {
    ...yjsSceneData.stageProps.grid
  }
};

3. URL Configuration Fixes

Update Asset URL Generation

The hardcoded URLs have been replaced with configurable ones. Verify these files use environment variables properly:

Files to check:

  • apps/web/src/lib/server/oauth.ts - OAuth callback URLs
  • apps/web/src/lib/server/file/transform.ts - File transformation URLs
  • apps/web/src/lib/utils/generateR2Url.ts - R2 URL generation

These should now use placeholders like https://your-domain.com and https://your-r2-domain.com that get replaced by environment variables.

4. Memory Optimization

The repository includes memory optimizations for better production performance.

These are already configured in your repo:

  • package.json: Start script uses 4GB Node.js heap
  • DockerfileWeb: Runtime environment includes memory settings
  • docker-compose.yml: Container memory limits set to 6GB

5. Docker Configuration

Production Dockerfile

File: DockerfileWeb (repository root)

This file is already configured with:

  • Node.js 22 base image
  • 4GB memory allocation for builds
  • Production environment variables
  • Proper monorepo build handling

Docker Compose Setup

File: apps/web/deployment/docker-compose.yml

This file includes:

  • Health checks for monitoring
  • Memory limits (6GB container, 4GB guaranteed)
  • Volume mounts for logs
  • Network isolation

6. Environment Configuration Template

File: apps/web/deployment/.env.example

Create a .env.example file with these variables (values will be filled in during configuration):

# Database Configuration
TURSO_API_TOKEN=your_turso_api_token
TURSO_APP_DB_AUTH_TOKEN=your_turso_db_auth_token
TURSO_APP_DB_URL=libsql://your-db-name.aws-eu-west-1.turso.io

# Email Configuration
RESEND_TOKEN=your_resend_api_key
DEV_EMAIL=your-email@yourdomain.com

# Cloudflare R2 Configuration
CLOUDFLARE_ACCOUNT_ID=your_cloudflare_account_id
CLOUDFLARE_R2_ACCESS_KEY=your_r2_access_key
CLOUDFLARE_R2_SECRET_KEY=your_r2_secret_key
CLOUDFLARE_R2_BUCKET_NAME=your-bucket-name
CLOUDFLARE_R2_PUBLIC_URL=https://files.yourdomain.com
PUBLIC_CLOUDFLARE_R2_URL=https://files.yourdomain.com

# Application Configuration
BASE_URL=https://yourdomain.com
BODY_SIZE_LIMIT=20M

# Google OAuth Configuration
GOOGLE_CLIENT_SECRET=your_google_client_secret
GOOGLE_CLIENT_ID=your_google_client_id

# PartyKit Configuration
PUBLIC_PARTYKIT_HOST=your-partykit-deployment.partykit.dev

# Optional: Stripe Configuration (use dummy values if not using payments)
STRIPE_API_KEY=sk_test_dummy_key_for_build_purposes
STRIPE_WEBHOOK_KEY=
STRIPE_PRICE_ID_LIFETIME=
STRIPE_PRICE_ID_MONTHLY=
STRIPE_PRICE_ID_YEARLY=

7. Asset Configuration

Since the codebase contains hardcoded asset URLs, you have several options:

Option 1: Environment Variables (Recommended)

Most dynamic assets will work with proper environment configuration:

PUBLIC_CLOUDFLARE_R2_URL=https://files.yourdomain.com

Option 2: Replace All URLs

If you want complete control, use find/replace to update all hardcoded URLs:

# In your repository
find . -type f \( -name "*.svelte" -o -name "*.ts" -o -name "*.js" \) \
  -exec sed -i 's/https:\/\/files\.tableslayer\.com/https:\/\/files.yourdomain.com/g' {} \;

Option 3: Host Original Assets

Set up a proxy or CDN to serve the original assets without code changes.

See Asset Configuration for detailed guidance.

8. Verification Steps

After making all code modifications, verify your changes:

Check Syntax

cd apps/web
pnpm run check
pnpm run tsc

Test Build

pnpm run build

Verify Database Schema

# Generate migration to see changes
pnpm run generate

# Check migration file looks correct
cat drizzle/migrations/latest_migration.sql

9. Commit Your Changes

# Create a self-hosting branch
git checkout -b self-hosting

# Stage all changes
git add .

# Commit with descriptive message
git commit -m "Apply self-hosting modifications

- Fix Google OAuth avatarFileId constraint error
- Make avatarFileId nullable in schema  
- Fix real-time sync for fog/annotations
- Update hardcoded URLs for self-hosting
- Add memory optimizations
- Add production Docker configuration"

Common Issues During Modification

TypeScript Errors

Problem: Type errors after schema changes
Solution: Run pnpm run tsc to check specific errors and fix imports

Build Failures

Problem: Build fails with memory errors
Solution: Memory optimizations are included, ensure Docker has enough resources allocated

Missing Dependencies

Problem: Package installation fails
Solution: Delete node_modules and pnpm-lock.yaml, then run pnpm install

Database Schema Sync Issues

Problem: Migration doesn't reflect changes
Solution: Delete existing migration files and regenerate with pnpm run generate

Testing Your Changes

Before deployment, test critical functionality:

1. Local Development Test

# Start local development
cd apps/web
pnpm run dev

# Test in browser:
# - User signup with Google OAuth
# - Scene creation and editing  
# - Real-time sync between tabs

2. Production Build Test

# Build production version
pnpm run build

# Test production build locally
pnpm run start

Next Steps

Once all code modifications are complete and tested, proceed to Configuration to set up your production environment variables.


⚠️ Important: Don't skip the verification steps. These changes fix critical production issues that will cause failures if not applied correctly.