Meteor Sync Specialist
When to Use This Skill
Use this skill when:
- •Running Meteor to Supabase data sync (full, incremental, or entity-specific)
- •Migrating MongoDB users to Supabase auth.users
- •Syncing media (dancer, organization, profile, post media)
- •Debugging sync failures or entity creation errors
- •Investigating duplicate entities or stale cache issues
- •Implementing new entity mappers
- •Analyzing change detection logic
- •Working with
meteor_entity_mappingtable - •Resuming failed sync runs
- •Comparing MongoDB vs Supabase record counts
DO NOT use for:
- •Querying MongoDB directly (use
mongodb-production-queryskill) - •Airtable sync issues (use
airtable-sync-specialistskill) - •General database migrations (use
database-migration-managerskill)
Connection Configuration
Environment Variables (Required)
# MongoDB connection (Meteor production database) export METEOR_MONGO_URL="mongodb://root:<password>@mdb-p-0.ballee.db-eu2.zcloud.ws:60601,mdb-p-1.ballee.db-eu2.zcloud.ws:60602,mdb-p-2.ballee.db-eu2.zcloud.ws:60603/meteor?authSource=admin&ssl=true&tlsInsecure=true&replicaSet=mdb-p" # Supabase staging database export SUPABASE_DB_PASSWORD_STAGING="<password>" export SUPABASE_DB_HOST="db.hxpcknyqswetsqmqmeep.supabase.co" # Optional, has default # Supabase production database (use with caution) export SUPABASE_DB_PASSWORD_PROD="<password>"
S3 Configuration (Media URLs)
const S3_REGION = 'eu-central-1';
const S3_BUCKET = 'ch.akson.dance.bucket';
// URL format for media files
const mediaUrl = `https://s3.${S3_REGION}.amazonaws.com/${S3_BUCKET}/${s3Key}`;
R2 Configuration (Newer media)
// R2 URLs follow this pattern const r2Url = 'https://pub-2541aa5053334bd4bcd4a619e7ad3428.r2.dev/...';
Migration Statistics (2025-12-09)
Final Entity Counts
| Entity Type | Count | Notes |
|---|---|---|
| auth.users | 14,864 | Migrated from MongoDB users |
| profiles | 14,864 | Auto-created by trigger |
| profiles with meteor_id | 14,819 | Linked to MongoDB |
| professional_profiles with user_id | 14,603 | Linked to auth users |
| dancer_media | 47,156 | photos: 37,822, headers: 7,251, videos: 2,079 |
| organization_media | 3,809 | Logos and headers |
| profile_media | 2,283 | User-uploaded media (orphan media) |
| post_media | 1,631 | Media attached to posts |
| profile_posts | 1,491 | Community posts |
| community_events | 293 | Community events |
Media URL Verification
All media URLs have been verified functional (HTTP 200):
- •S3 URLs:
https://s3.eu-central-1.amazonaws.com/ch.akson.dance.bucket/... - •R2 URLs:
https://pub-2541aa5053334bd4bcd4a619e7ad3428.r2.dev/... - •YouTube embeds:
https://www.youtube.com/embed/...
Architecture Overview
Core Components
- •
MeteorSyncService (
meteor-sync.service.ts)- •Main orchestration service
- •Coordinates mappers, deduplication, change detection
- •Manages sync runs and metrics
- •
MeteorDuplicatePreventionService (
meteor-duplicate-prevention.service.ts)- •Prevents duplicate entities using MongoDB
_id - •Validates cached entities still exist
- •Auto-cleanup of stale cache entries
- •Prevents duplicate entities using MongoDB
- •
MeteorChangeDetectorService (
meteor-change-detector.service.ts)- •Hash-based change detection (MD5)
- •Field-level change tracking
- •Incremental sync filtering
- •
Entity Mappers (
mappers/)- •Transform MongoDB documents to Supabase format
- •Handle field mapping, type conversion, FK resolution
- •
Media Transfer Service (
media-transfer.service.ts)- •Transfers files from Meteor S3 to Supabase Storage
- •Handles media URL generation
Database Tables
-- Entity mapping cache (deduplication) CREATE TABLE meteor_entity_mapping ( meteor_id text PRIMARY KEY, entity_type text NOT NULL, entity_id uuid NOT NULL, source_hash text, -- MD5 hash for change detection source_data jsonb, -- Cached MongoDB document first_synced_at timestamptz, last_synced_at timestamptz, sync_count integer DEFAULT 1, sync_status text DEFAULT 'synced', -- synced | pending | error | skipped error_message text ); -- Sync run tracking CREATE TABLE meteor_sync_runs ( id uuid PRIMARY KEY, sync_type text NOT NULL, -- full | incremental | entity | resume status text NOT NULL, -- running | completed | failed | partial trigger_type text, -- manual | cron | script | webhook triggered_by uuid, started_at timestamptz, completed_at timestamptz, duration_seconds integer, metrics jsonb -- created, updated, skipped, failed counts ); -- Change tracking CREATE TABLE meteor_sync_changes ( id uuid PRIMARY KEY, sync_run_id uuid REFERENCES meteor_sync_runs(id), meteor_id text, entity_type text, operation text, -- created | updated | skipped | error changed_fields jsonb, -- Array of field changes error_message text, created_at timestamptz ); -- Sync state (for incremental sync) CREATE TABLE meteor_sync_state ( entity_type text PRIMARY KEY, last_sync_at timestamptz, last_meteor_id text, -- For resume capability checkpoint_data jsonb );
Quick Commands Reference
Local Sync (Direct MongoDB Access)
# Full sync of all entities pnpm meteor:sync --full # Incremental sync since last run pnpm meteor:sync --incremental # Sync specific entity type pnpm meteor:sync --entity organization pnpm meteor:sync --entity candidate pnpm meteor:sync --entity media # Preview changes without applying pnpm meteor:sync --dry-run # Resume a failed sync pnpm meteor:sync --resume <run-id>
Requirements:
- •
METEOR_MONGO_URL- MongoDB connection string - •
SUPABASE_URLandSUPABASE_SERVICE_KEYenvironment variables
Staging/Production Sync (Remote via API)
# Check sync status pnpm meteor:staging status # Trigger a full sync pnpm meteor:staging trigger # Trigger incremental sync pnpm meteor:staging trigger --type incremental # Sync specific entity type pnpm meteor:staging trigger --entity organization # Dry run (preview only) pnpm meteor:staging trigger --dry-run # View sync history pnpm meteor:staging history pnpm meteor:staging history --limit 20 # View detailed logs for a specific run pnpm meteor:staging logs <run-id> # View sync statistics pnpm meteor:staging stats # Watch sync status in real-time pnpm meteor:staging watch pnpm meteor:staging watch --interval 3
Requirements:
- •
METEOR_SYNC_API_KEY- API key for authentication - •
STAGING_URL(optional) - defaults tohttps://staging.ballee.app
User Migration
migrate-users.ts
Migrates MongoDB users to Supabase auth.users with bcrypt password hash preservation:
# From skill scripts folder cd .claude/skills/meteor-sync-specialist/scripts # Preview migration (no changes) npx tsx migrate-users.ts --dry-run # Run full migration npx tsx migrate-users.ts
What it does:
- •Fetches all MongoDB users
- •Creates auth.users entries (preserving bcrypt hashes for seamless login)
- •Creates auth.identities for email provider
- •Triggers create profiles via
on_auth_user_createdtrigger - •Updates profiles with
meteor_idfor linking - •Links
professional_profiles.user_idviapreferredUserCandidateId - •Removes duplicate profiles created by trigger
Important: Before running, ensure trigger functions use public. schema prefix (see Troubleshooting section).
sync-orphan-media.ts
Syncs media that only has userId (no candidateId/organizationId) to profile_media:
# Preview sync npx tsx sync-orphan-media.ts --dry-run # Run sync npx tsx sync-orphan-media.ts
Prerequisites: Users must be migrated first (migrate-users.ts)
sync-post-media.ts
Syncs media references from MongoDB Posts to post_media table:
# Preview sync npx tsx sync-post-media.ts --dry-run # Run sync npx tsx sync-post-media.ts
Prerequisites: Posts must be synced first (profile_posts populated)
Entity Mappers Reference
Mapper Overview
| Mapper | MongoDB Collection | Supabase Table(s) | Status |
|---|---|---|---|
OrganizationMapper | Organizations | organizations | Active |
OrganizationMediaMapper | Media | organization_media | Active |
CandidateMapper | Candidates | profiles + professional_profiles + dancer_profiles | Active |
DancerMediaMapper | Media | dancer_media | Active |
ExperienceMapper | Experiences | experiences | Active |
PostMapper | Posts | posts | Active |
LikeMapper | Likes | likes | Active |
FollowMapper | Follows | follows | Active |
AuditionMapper | VacanciesCollection | auditions | Planned |
AuditionApplicationMapper | Applications | audition_applications | Planned |
Entity Types
type MeteorEntityType = | 'organization' | 'organization_media' | 'candidate' | 'media' | 'experience' | 'post' | 'follow' | 'like' | 'application' | 'offer' | 'user' | 'audition' | 'audition_application';
Sync Order (Dependencies)
Entities must be synced in this order to resolve foreign keys:
Level 1 (No dependencies): ├── organization ├── organization_media ├── candidate └── media (dancer_media) Level 2 (Depends on Level 1): ├── experience (refs: organization, candidate) ├── audition (refs: organization) └── post (refs: candidate, organization) Level 3 (Depends on Level 2): ├── audition_application (refs: audition, candidate) ├── like (refs: post, candidate) ├── follow (refs: candidate, organization) └── comment (refs: post, candidate)
Field Mapping Conventions
| MongoDB Field | Supabase Field | Transform |
|---|---|---|
_id | meteor_id | Store for deduplication |
meta.createdAt | created_at | ISO timestamp |
meta.modifiedAt | updated_at | ISO timestamp |
meta.createdBy | created_by | Resolve to user_id |
| camelCase | snake_case | Field name transform |
| ObjectId refs | UUID | Resolve via entity_mapping |
CandidateMapper (Complex - 3 Tables)
The candidate mapper splits MongoDB documents across 3 Supabase tables:
// MongoDB Candidate document
{
_id: ObjectId,
userId: ObjectId,
firstName: string,
lastName: string,
stageName: string,
birthdate: Date,
bio: string,
danceStyles: string[],
height: number,
weight: number,
availableForHire: boolean,
// ... 30+ more fields
}
// Supabase Tables:
// 1. profiles (basic user info)
{
id: uuid,
display_name: string,
first_name: string,
last_name: string,
birthdate: date
}
// 2. professional_profiles (career info)
{
id: uuid,
user_id: uuid,
stage_name: string,
bio: text,
dance_styles: text[],
available_for_hire: boolean,
social_handles: jsonb
}
// 3. dancer_profiles (physical attributes)
{
id: uuid,
professional_profile_id: uuid,
height_cm: integer,
weight_kg: integer,
pointe_work: boolean,
acrobatics: boolean
}
OrganizationMapper
// MongoDB → Supabase
{
_id: ObjectId, // → meteor_id
name: string, // → name
type: 'school' | 'company' | 'agency', // → type
logoMediaId: ObjectId, // → logo_media_id (resolve via mapping)
headerMediaId: ObjectId, // → header_media_id
bio: string, // → description
website: string, // → website
location: { // → address, city, country
city: string,
country: string
}
}
Sync Modes
Full Sync
Syncs all documents from MongoDB regardless of previous sync state:
pnpm meteor:sync --full
- •Fetches all documents from each collection
- •Skips unchanged documents (via hash comparison)
- •Updates metrics for all operations
- •Use for: Initial migration, data recovery, full refresh
Incremental Sync
Only syncs documents modified since last successful sync:
pnpm meteor:sync --incremental
- •Uses
meta.modifiedAt> last sync timestamp - •Much faster for routine updates
- •Requires
meteor_sync_stateto track last sync - •Use for: Daily/hourly sync jobs
Entity Sync
Syncs specific entity types only:
pnpm meteor:sync --entity organization pnpm meteor:sync --entity candidate
- •Useful for targeted updates
- •Respects dependency order if syncing multiple
- •Use for: Fixing specific entity sync issues
Resume Sync
Continues a failed sync from the last checkpoint:
pnpm meteor:sync --resume <run-id>
- •Reads checkpoint from
meteor_sync_state - •Skips already-synced entities
- •Use for: Recovering from network/timeout failures
Troubleshooting
Issue 0: User Migration Fails with "relation does not exist"
Symptoms:
- •Migration fails with errors like
relation "profiles" does not exist - •Or
relation "professional_profiles" does not exist
Cause:
Trigger functions on auth.users reference tables without public. schema prefix.
When running outside the normal application context, PostgreSQL can't find the tables.
Solution: Fix the trigger functions to use fully qualified table names:
-- Fix trigger_generate_profile_slug CREATE OR REPLACE FUNCTION public.trigger_generate_profile_slug() RETURNS TRIGGER AS $$ DECLARE v_base_slug TEXT; v_slug TEXT; v_counter INTEGER := 0; v_user_row RECORD; BEGIN -- Get user info - USE public.profiles instead of profiles SELECT first_name, last_name, display_name INTO v_user_row FROM public.profiles WHERE id = NEW.user_id; -- ... rest of function -- Replace all 'profiles' with 'public.profiles' END; $$ LANGUAGE plpgsql SECURITY DEFINER; -- Fix create_dancer_profile_on_signup CREATE OR REPLACE FUNCTION public.create_dancer_profile_on_signup() RETURNS TRIGGER AS $$ BEGIN -- Use public.professional_profiles and public.dancer_profiles INSERT INTO public.professional_profiles (id, user_id, profile_type, ...) VALUES (gen_random_uuid(), NEW.id, 'dancer', ...); INSERT INTO public.dancer_profiles (id, ...) VALUES (...); RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER; -- Fix setup_new_user CREATE OR REPLACE FUNCTION public.setup_new_user() RETURNS TRIGGER AS $$ BEGIN -- Use public.accounts INSERT INTO public.accounts (id, name, slug, ...) VALUES (...); RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER;
Key tables to prefix with public.:
- •
profiles→public.profiles - •
professional_profiles→public.professional_profiles - •
dancer_profiles→public.dancer_profiles - •
accounts→public.accounts - •
accounts_memberships→public.accounts_memberships
Issue 1: Duplicate Entities Created
Symptoms:
- •Multiple Supabase records for same MongoDB document
- •
meteor_entity_mappinghas duplicate entries
Debugging:
-- Check for duplicate mappings SELECT meteor_id, entity_type, COUNT(*) FROM meteor_entity_mapping GROUP BY meteor_id, entity_type HAVING COUNT(*) > 1; -- Find entities without meteor_id SELECT id, name, created_at FROM organizations WHERE meteor_id IS NULL AND created_at > NOW() - INTERVAL '1 day';
Solution:
- •Review
MeteorDuplicatePreventionService.findExistingEntity() - •Ensure MongoDB
_idis correctly passed - •Check for race conditions in parallel sync
Issue 2: Stale Cache Entries
Symptoms:
- •Sync skips creating entities but they don't exist
- •Cache shows entity_id but Supabase query returns null
Debugging:
-- Find stale cache entries SELECT mem.meteor_id, mem.entity_type, mem.entity_id FROM meteor_entity_mapping mem LEFT JOIN organizations o ON o.id = mem.entity_id WHERE mem.entity_type = 'organization' AND o.id IS NULL;
Solution:
-- Clean up stale entries DELETE FROM meteor_entity_mapping mem WHERE NOT EXISTS ( SELECT 1 FROM organizations WHERE id = mem.entity_id ) AND entity_type = 'organization';
Issue 3: Foreign Key Resolution Failed
Symptoms:
- •Sync fails with "constraint violation" errors
- •Entity references non-existent foreign key
Debugging:
# Check sync order pnpm meteor:staging logs <run-id> # Verify dependency exists pnpm sql:local "SELECT * FROM organizations WHERE meteor_id = '<org_meteor_id>'"
Solution:
- •Ensure entities are synced in correct dependency order
- •Check if referenced entity was skipped due to error
- •Re-run sync for dependent entity type first
Issue 4: Change Detection Not Working
Symptoms:
- •Sync doesn't update entities when MongoDB data changes
- •Entities stuck with old data
Debugging:
-- Check source_hash in mapping SELECT meteor_id, source_hash, last_synced_at FROM meteor_entity_mapping WHERE meteor_id = '<meteor_id>';
Solution:
- •Review
MeteorChangeDetectorService.hasChanges() - •Ensure hash excludes volatile fields (
_id,meta) - •Force update by deleting cache entry
Issue 5: Sync Run Stuck in "Running"
Symptoms:
- •Sync status shows "running" but no progress
- •API returns timeout errors
Debugging:
-- Check for stuck runs
SELECT id, sync_type, status, started_at,
NOW() - started_at as duration
FROM meteor_sync_runs
WHERE status = 'running'
ORDER BY started_at DESC;
Solution:
-- Mark stuck run as failed
UPDATE meteor_sync_runs
SET status = 'failed',
completed_at = NOW(),
duration_seconds = EXTRACT(EPOCH FROM NOW() - started_at)::integer
WHERE status = 'running'
AND started_at < NOW() - INTERVAL '30 minutes';
API Endpoint Reference
Endpoint: /api/sync/meteor
Authentication
All requests require Authorization: Bearer <METEOR_SYNC_API_KEY> header.
GET Endpoints
| Action | Description |
|---|---|
?action=status | Check MongoDB connection and environment |
?action=history&limit=10 | Get sync run history |
?action=stats | Get entity sync statistics |
?action=logs&runId=<id> | Get detailed logs for a sync run |
POST Endpoint
Trigger a sync:
{
"syncType": "full|incremental|entity",
"entityTypes": ["organization", "candidate"],
"dryRun": false,
"batchSize": 100,
"continueOnError": true
}
Response:
{
"success": true,
"syncRunId": "uuid",
"status": "running",
"startedAt": "2025-12-09T10:00:00Z"
}
Diagnostic Scripts
diagnose-sync-status (meteor-diagnose.cjs)
Check overall sync health:
# From apps/web directory cd apps/web && node scripts/meteor-diagnose.cjs
Checks:
- •MongoDB connection status
- •Recent sync runs and their status
- •Entity mapping statistics
- •Stale cache entries
- •Stuck running syncs
- •Entities with errors
- •Sync state for incremental sync
validate-entity-mapping.ts
Validate cache integrity (TypeScript version in skill folder):
# From apps/web directory with tsx available cd apps/web && npx tsx ../../.claude/skills/meteor-sync-specialist/scripts/validate-entity-mapping.ts
Checks:
- •Cache entries pointing to deleted entities
- •Orphaned cache entries
- •Duplicate mappings
compare-counts.ts
Compare MongoDB vs Supabase counts:
cd apps/web && npx tsx ../../.claude/skills/meteor-sync-specialist/scripts/compare-counts.ts
Output:
Entity Type MongoDB Supabase Diff Synced% ───────────────────────────────────────────────────────── organization 428 425 -3 99.3% candidate 20018 19854 -164 99.2% media 75140 73278 -1862 97.5% post 1492 1490 -2 99.9%
Best Practices
Duplicate Prevention
- •Always use MongoDB
_id- Never rely on name/email matching - •Validate cached entities - Check entity exists before trusting cache
- •Auto-cleanup stale entries - Remove cache when entity deleted
- •Log all cache operations - Aids debugging
Change Detection
- •Exclude volatile fields - Don't hash
_id,meta.* - •Use consistent ordering - Sort keys before hashing
- •Log detected changes - Show what triggered update
- •Batch updates - Don't update one field at a time
Error Handling
- •Continue on error - Don't stop sync for one bad document
- •Track failed entities - Record in
meteor_sync_changes - •Log with context - Include meteor_id, entity_type
- •Allow resume - Save checkpoint for recovery
Performance
- •Batch size - Default 100 documents per batch
- •Parallel where possible - Independent entity types can run in parallel
- •Index meteor_id - Ensure B-tree index on
meteor_idcolumns - •Incremental preferred - Use incremental sync for routine updates
Common Code Patterns
Safe Entity Lookup
// CORRECT - Validates entity exists
const existingId = await duplicatePrevention.findExistingEntity(
meteorId,
'organization'
);
if (existingId) {
// Entity exists and is valid
const hasChanges = changeDetector.hasChanges(newData, cachedData);
if (hasChanges) {
await updateEntity(existingId, newData);
}
} else {
// Create new entity
await createEntity(newData);
}
Idempotent Sync
async function syncDocument(doc: MeteorDocument) {
const meteorId = doc._id.toString();
// Check if exists (validates entity still exists)
const existingId = await duplicatePrevention.findExistingEntity(
meteorId,
entityType
);
if (existingId) {
// Get cached data for comparison
const cachedData = await duplicatePrevention.getCachedSourceData(meteorId);
if (changeDetector.hasChanges(doc, cachedData)) {
await updateEntity(existingId, mapper.mapToSupabase(doc));
await duplicatePrevention.updateEntityMapping(meteorId, doc);
return { operation: 'updated' };
}
return { operation: 'skipped' };
} else {
const newId = await createEntity(mapper.mapToSupabase(doc));
await duplicatePrevention.registerEntity(meteorId, entityType, newId, doc);
return { operation: 'created' };
}
}
Batch Processing with Error Handling
async function syncBatch(documents: MeteorDocument[]) {
const results = {
created: 0,
updated: 0,
skipped: 0,
failed: 0,
errors: [] as Array<{ meteorId: string; error: string }>
};
for (const doc of documents) {
try {
const result = await syncDocument(doc);
results[result.operation]++;
} catch (error) {
results.failed++;
results.errors.push({
meteorId: doc._id.toString(),
error: error.message
});
// Mark in entity mapping for retry
await duplicatePrevention.markEntityError(
doc._id.toString(),
entityType,
error.message
);
// Continue processing other documents
console.error(`Failed to sync ${doc._id}:`, error);
}
}
return results;
}
Reference Files
Core Sync Infrastructure
- •Main service:
apps/web/app/admin/sync/_lib/server/meteor/meteor-sync.service.ts - •Duplicate prevention:
apps/web/app/admin/sync/_lib/server/meteor/meteor-duplicate-prevention.service.ts - •Change detector:
apps/web/app/admin/sync/_lib/server/meteor/meteor-change-detector.service.ts - •Media transfer:
apps/web/app/admin/sync/_lib/server/meteor/media-transfer.service.ts
Entity Mappers
- •Mapper index:
apps/web/app/admin/sync/_lib/server/meteor/mappers/index.ts - •Organization:
apps/web/app/admin/sync/_lib/server/meteor/mappers/organization.mapper.ts - •Candidate:
apps/web/app/admin/sync/_lib/server/meteor/mappers/candidate.mapper.ts - •Experience:
apps/web/app/admin/sync/_lib/server/meteor/mappers/experience.mapper.ts - •Dancer media:
apps/web/app/admin/sync/_lib/server/meteor/mappers/dancer-media.mapper.ts - •Organization media:
apps/web/app/admin/sync/_lib/server/meteor/mappers/organization-media.mapper.ts - •Post:
apps/web/app/admin/sync/_lib/server/meteor/mappers/post.mapper.ts - •Like:
apps/web/app/admin/sync/_lib/server/meteor/mappers/like.mapper.ts - •Follow:
apps/web/app/admin/sync/_lib/server/meteor/mappers/follow.mapper.ts
CLI Scripts
- •Local sync:
scripts/meteor-sync/run-sync.ts - •Staging sync:
scripts/meteor-sync/staging-sync.ts - •Media sync:
scripts/sync-remaining-media.ts
Migration Scripts (in skill folder)
- •User migration:
.claude/skills/meteor-sync-specialist/scripts/migrate-users.ts - •Orphan media:
.claude/skills/meteor-sync-specialist/scripts/sync-orphan-media.ts - •Post media:
.claude/skills/meteor-sync-specialist/scripts/sync-post-media.ts - •Entity validation:
.claude/skills/meteor-sync-specialist/scripts/validate-entity-mapping.ts - •Count comparison:
.claude/skills/meteor-sync-specialist/scripts/compare-counts.ts - •Sync diagnostics:
.claude/skills/meteor-sync-specialist/scripts/diagnose-sync-status.ts
API & Admin UI
- •API route:
apps/web/app/api/sync/meteor/route.ts - •Admin page:
apps/web/app/admin/sync/meteor/page.tsx - •Trigger panel:
apps/web/app/admin/sync/meteor/_components/meteor-sync-trigger-panel.tsx - •History component:
apps/web/app/admin/sync/meteor/_components/meteor-sync-history.tsx - •Stats component:
apps/web/app/admin/sync/meteor/_components/meteor-sync-stats.tsx
Server Actions
- •Sync actions:
apps/web/app/admin/sync/meteor/_actions/meteor-sync.actions.ts - •User sync:
apps/web/app/admin/sync/meteor/_actions/meteor-user-sync.actions.ts
Database Migrations
- •Infrastructure:
apps/web/supabase/migrations/20251207131700_create_meteor_sync_infrastructure.sql - •Media meteor_id:
apps/web/supabase/migrations/20251207145437_add_meteor_id_to_media_and_comments.sql - •Community meteor_id:
apps/web/supabase/migrations/20251207160100_add_meteor_id_to_community_tables.sql - •Dancer media meteor_id:
apps/web/supabase/migrations/20251208183601_add_meteor_id_to_dancer_media.sql
Documentation
- •Sync README:
scripts/meteor-sync/README.md - •Migration README:
scripts/migration/README.md - •WIP - Meteor parity:
docs/wip/active/WIP_achieving_100_percent_meteor_parity_2025_12_09.md - •WIP - Media sync:
docs/wip/active/WIP_syncing_remaining_mongodb_media_2025_12_09.md
Related Skills
- •MongoDB queries:
.claude/skills/mongodb-production-query/SKILL.md - •Airtable sync:
.claude/skills/airtable-sync-specialist/SKILL.md