My experience building with AI

Local Convex Data Reset
Use this when you want to start testing with an empty Convex database while keeping the current schema and functions deployed.
What This Does
- Clears documents from the configured Convex testing deployment.
- Keeps
packages/convex-backend/src/convex/schema.tsand all Convex functions intact. - Clears Convex component data too, including Better Auth and Convex Agent tables.
- Does not run
bun run dev.
Current Project Note
This checkout does not currently have a Convex deployment registered as local.
The .env.local files point at a dev: deployment, so the reset command used here targets:
--deployment devIf you later create a true local Convex deployment, replace --deployment dev with:
--deployment localReset Commands
Run these from packages/convex-backend:
backup="/tmp/elevator-convex-before-reset-$(date +%Y%m%d-%H%M%S).zip"
empty_dir="$(mktemp -d /tmp/elevator-convex-empty-snapshot.XXXXXX)"
empty_zip="${empty_dir}.zip"
bunx convex export --deployment dev --path "$backup"
bunx convex data --deployment dev --format jsonArray | while IFS= read -r table; do
[ -n "$table" ] || continue
mkdir -p "$empty_dir/$table"
: > "$empty_dir/$table/documents.jsonl"
done
(
cd "$empty_dir"
zip -qr "$empty_zip" .
)
bunx convex import --deployment dev --replace-all --yes "$empty_zip"Verify The Wipe
Check that user tables are empty:
tables_json="$(bunx convex data --deployment dev --format jsonArray | jq -R -s -c 'split("\n") | map(select(length > 0))')"
bunx convex run --deployment dev --typecheck disable --inline-query "
const tables = $tables_json;
const nonempty = [];
for (const table of tables) {
const docs = await ctx.db.query(table).take(1);
if (docs.length > 0) nonempty.push(table);
}
return { checkedTables: tables.length, nonempty };
"Expected result:
{
"checkedTables": 158,
"nonempty": []
}Check that functions and schema metadata still exist:
bunx convex function-spec --deployment dev | jq '{functionCount: (.functions | length), url}'For this reset, Convex reported 395 functions after the data wipe.
Rollback Snapshot
This reset saved a pre-wipe snapshot outside the repo:
/tmp/elevator-convex-before-reset-20260601-181645.zipTo restore that data, run from packages/convex-backend:
bunx convex import --deployment dev --replace-all --yes /tmp/elevator-convex-before-reset-20260601-181645.zipBackground Data Sync Audit Report
Project: Milogs Application
Date:
Auditor: Claude (AI Agent)
Scope: Deep audit of cross-platform background/foreground data synchronization behavior
Executive Summary
No, this application does NOT reliably continue syncing data when closed or backgrounded on any platform.
The app implements a foreground-only sync model with very limited background capabilities. When the app is closed (killed/terminated), data sync completely stops . When backgrounded (still running), there is minimal sync activity—only periodic media upload retries on native, and only service-worker-triggered single-pass uploads on web. There is no true background data sync (push/pull of all data types) when_flush’ing when minimized or closed.
1. Web Platform (Browser)
When Minimized / Tab in Background
- Sync Behavior: Sync HALTS immediately.
- Evidence:
syncEngine.tsline 359-365:appLifecycle.onHidden()callback tears down the real-time sync state subscription (teardownRuntimeSyncStateSubscription()) and cancels any pending sync timer (clearTimeout(syncScheduledTimeout)).appLifecycle.tsline 32: Listens todocument.visibilitychangeandwindow.pagehide; both triggeronHidden.- There is no web worker, no periodic timer, and no
setIntervalthat survives tab backgrounding. JavaScript execution is throttled or frozen.
- Limitation: Web does not have a background sync mechanism that runs periodically or when the tab is not visible. The app only relies on the browser’s
pagehide/visibilitychangeevents, which are used to stop sync, not to continue it.
When Closed (Tab Closed / Browser Closed)
- Sync Behavior: Sync STOPS COMPLETELY .
- Evidence:
- The service worker (
service-worker.ts) only handles a'sync'event with the tag'milogs-upload-sync', but this only posts a message to any active window clients (client.postMessage). - If no window/tab is open, there is no client to receive the message, and no sync runs.
- The service worker does not call any sync function directly; it delegates to the app window.
- There is no
periodicSync,pushevent handler for data sync, or background fetch logic in the service worker.
- The service worker (
- Conclusion: Closing the browser means zero sync until the user reopens the app.
2. Native iOS
When Backgrounded (App Switcher but not closed)
- Sync Behavior: Sync HALTS .
- Evidence:
syncEngine.tsline 359-365:appLifecycle.onHidden()callback fires when the app is backgrounded (viaApp.addListener('appStateChange')), which tears down subscriptions and cancels sync timers.- There is no iOS Background Fetch, Background URL Session (for sync data), or
BGTaskSchedulerconfigured. - The only background task is
handleEventsForBackgroundURLSessioninAppDelegate.swift(line 56-58), which handles AI model downloads (not data sync).
When Closed (Killed / Swiped Away)
- Sync Behavior: Sync STOPS COMPLETELY .
- Evidence:
- Apple's iOS background execution model does not allow arbitrary code to run when the app is terminated.
- There are no iOS Push Notifications via APNS that trigger a background sync (only local notifications for reminders).
- The app does not register for remote notifications that could wake it up.
3. Native Android
When Backgrounded (Recent Apps, but not closed)
- Sync Behavior: Very limited sync— only media uploads via a background interval timer.
- Evidence:
backgroundUpload.tslines 17-30: On native,App.addListener('pause', ...)starts腹中 starts asetIntervalloop (BACKGROUND_UPLOAD_INTERVAL_MS = 15_000/ 15 seconds) that only runsrunSync(true, { uploadsOnly: true }).- This is uploads-only and does not pull new data.
- The loop is stopped on
resume.
- No Background Sync for Pull: There is no full sync (push + pull) when the app is backgrounded.
When Closed (Killed / Swiped Away)
- Sync Behavior: Sync STOPS COMPLETELY .
- Evidence:
- Android BroadcastReceivers (
ReminderBootReceiver,FinAlertBootReceiver) only handle boot/system events to restore notification channels and alarm schedules. They do not trigger data sync. - No
WorkManager,JobScheduler, orAlarmManagertasks are registered for periodic sync. - The
AndroidForegroundServiceis used only for active audio recording and transcription—not for sync.
- Android BroadcastReceivers (
4. Service Worker Analysis
What the Service Worker Does
- Caching: Caches static assets (JS, CSS, images) for offline-first loading (
service-worker.tslines 7-24). - Sync Event: Listens for the
'sync'event with tag'milogs-upload-sync'(service-worker.tsline 26-38). When triggered, it tries to notify any open window clients to run an upload-only sync pass. - Fetch Interception: Caches image assets on fetch (
service-worker.tslines 40-77).
What the Service Worker Does NOT Do
- No Periodic Sync: No
periodicSyncregistration or handling. - No Push-Triggered Sync: No
pushevent handler. - No Direct Sync Execution: Does not call
runSync()or any sync engine functions directly. It rely entirely on an active window/tab being open to receive thepostMessage. - No Background Data Processing: Cannot push non-media entities or pull remote changes when the app is closed.
5. Live Update / OTA (Capgo Plugin)
- The
CapacitorUpdaterplugin is configured withautoUpdate: 'atBackground'(capacitor.config.ts). - This triggers Over-The-Air (OTA) updates when the app is backgrounded, but this is not related to data sync . It updates the app's web assets, not user data.
6. Summary Table
| Platform | Minimized / Background Tab | App Closed (Killed) | Notes |
|---|---|---|---|
| Web | 国际社会 | 国际社会 | Sync halts on visibilitychange → hidden. No background execution. |
| iOS Native | 国际社会 | 国际社会 | No Background Fetch, WorkManager, or periodic sync. Foreground-only. |
| Android Native | Limited (uploads-only, every 15s) | 国际社会 | Only media uploads via setInterval prefer-background timer. No pull. |
7. Recommendations (No Code Changes Per Request)
Since the user explicitly requested no code changes, here are documented observations for future action:
- Web: Consider implementing Background Sync API (
periodicSync) or Push Notifications to wake the service worker and run sync logic directly (not via windowpostMessage). - iOS: Consider implementing Background Fetch (
BGAppRefreshTask) or Background Processing (BGProcessingTask) to periodically sync data when the app receives system background execution time. - Android: Consider using WorkManager with
PeriodicWorkRequestorOneTimeWorkRequestto schedule sync tasks that survive app closure. - Push Notifications: Implement push-triggered sync via a push notification service (FCM for Android, APNS for iOS) that wakes the app to perform a sync cycle.
- Foreground Service: For critical real-time sync, consider a persistent foreground service (with user-facing notification) on Android that keeps the sync engine alive.
This report was generated by a comprehensive codebase audit focusing on lifecycle hooks, service workers, native background capabilities, and sync engine behavior.