AM
Personal buildAuto MMO Publisher
Environment prep

Firebase, scheduler, and Facebook connect are the last setup gap.

The repo now has the scheduler and the first real OAuth connect path. Once Firebase admin env and the Meta app env are wired, the dashboard can save live Page credentials without using Graph API Explorer.

connect flow ready
Frontend FirebaseReadycomplete
Server FirebaseReadycomplete
Live Firestore readsEnabledlive path
Scheduled runnerReadysecret set
Production cronReadyCRON_SECRET set
Facebook OAuthReadyapp env set
TikTok OAuthReadyapp env set
Instagram LoginReadyapp env set
Managed asset bucketReadyr2 env set
TikTok onboarding automationThis alias is ready for TikTok account registration. No Cloudflare routing rule is needed; catch-all already sends it to the Worker.
alias active
TikTok verification inboxThe app checks this alias automatically every 15 seconds and extracts the newest OTP or verification link when it arrives.
tiktok-2ptpsjelx7r8gxxp17n6-bc5cfe20@auto-mmo.com
Waiting for a TikTok verification email.
TikTok channel factoryProvision multiple TikTok channels in one batch. Each channel gets its own stable alias and waits for one human Login Kit authorization.0/1 channels connected. TikTok review approval is still required before production publishing.
multi-channel ready
Safe to run again: matching names reuse the same channel and alias.
TikTok Maintiktok-2ptpsjelx7r8gxxp17n6-bc5cfe20@auto-mmo.com · awaiting TikTok authorization
alias-readyAuthorize TikTok
ChannelsChoose the brand/theme identity whose social accounts you are managing.
4 channels
TikTok MainPrimary TikTok affiliate channel · 0 connected account records
Selected
Smoke Test UIUI creation smoke test only; no live publishing. · 0 connected account records
Manage
Auto MMO 2Facebook Page Auto MMO 2 · 1 connected account records
Manage
Smoke Test — Multi-channel V1Temporary routing verification; no live platform token. · 1 connected account records
Manage
Add a channelEach channel can own one Facebook Page, Instagram account, and TikTok account — or multiple accounts later.
collection: channels
Currently managing: TikTok Main.
Automated email aliasesCatch-all now routes aliases to the Worker. Reusing the same channel, platform, and purpose keeps the address stable across retries.
registry ready
Channel: TikTok Main
Facebook connectUse the in-app OAuth flow so the dashboard stores Page credentials directly.
ready to connect
Current active PageNo live Facebook Page is connected yet.
not connected
OAuth sourceThe app will request Page scopes directly and save the selected Page into platform_accounts plus platform_secrets.
direct app login
Connect FacebookStarts the real Facebook login flow, lists manageable Pages, then lets you choose the active Page here.
Instagram publish pathInstagram now has a separate Instagram Login path, so it no longer depends on the broken Facebook Page mapping.
awaiting account
Current active accountNo Instagram professional account is saved yet.
not connected
Last verificationNo Instagram verification attempt has been recorded yet.
not verified
Fastest setup pathThe old Facebook Login path is blocked by Meta asset provisioning. Use Connect Instagram below; the manual form remains only as a legacy fallback.
use instagram login
Connect InstagramOpens Instagram Login, requests instagram_business_basic and instagram_business_content_publish, then saves the Instagram user token here.
This saves the config and immediately checks whether the submitted token, existing Instagram token, or saved Facebook page token can read the target Instagram professional account.
TikTok publish pathTikTok now has an in-app config form so the platform account can be seeded without editing Firestore by hand.
awaiting token
Current active accountNo TikTok creator account is saved yet.
not connected
Last verificationNo TikTok verification attempt has been recorded yet.
not verified
Media restrictionTikTok video and photo posts now use public media URLs through PULL_FROM_URL. The URL domain or prefix must be verified in TikTok Developer Portal.
important
OAuth sourceThe app can now start a real TikTok Login Kit redirect, exchange the code for access and refresh tokens, and save the creator account automatically.
direct app login
Connect TikTokStarts the real TikTok Login Kit flow, saves the returned access and refresh tokens, then immediately runs the creator-info verification check. The callback URL must live on HTTPS.
Manual fallback: paste an existing token if you need to seed or override the saved TikTok credentials without using the OAuth connect button.
Instagram first live testUse this path after the token has already passed the save-and-verify check.
verify account first
1. Keep the job simpleCreate one fresh post on /posts with only Instagram selected, one caption, and exactly one public media URL.
one media item
2. Use the supported media shapeThe live adapter accepts either one image or one video. For the fastest first pass, use one image on the owned asset domain.
image fastest
3. Trigger one publish attemptOpen the matching job on /jobs and run Publish now so the first adapter response is captured immediately.
manual first
4. Record the resultCheck worker note, dispatch history, and externalRef on the job detail screen. The expected success path is a created container id followed by a published remote media id.
capture first response
TikTok first live testKeep the first direct-post attempt narrow so the result is easy to diagnose.
verify account first
1. Start with one videoThe first smoke test uses TikTok direct PULL_FROM_URL with one managed video asset, so the media domain must be verified first.
video path preferred
2. Start with one assetThe UI path on /posts currently creates the cleanest first test with exactly one video and only TikTok selected. Photo posts use the same verified-URL path.
one asset fastest
3. Let the adapter choose a valid privacy levelKeep a default privacy saved here on /settings, but expect the live call to fall back to the creator-info options if needed.
privacy checked live
4. Read back the publish idOpen the matching job detail after Publish now and record the first TikTok API message plus the returned async publish_id.
capture publish_id
Production scheduler readinessThis is the last local checklist before a Vercel cron run can own due-job publishing without the Mac cron fallback.
not ready yet
APP_BASE_URLPresent. The Facebook callback can generate its deployed redirect origin.
set
CRON_SECRETPresent. Vercel cron can authenticate directly against the same scheduler route.
set
Server FirebaseReady. The deployed route can read platform secrets and write dispatch records.
live writes ready
Managed media domainReady. Scheduled publishes can keep using owned public asset URLs instead of third-party source links.
owned-media ready
Active Facebook PageConnect one live Page first so the first deployed scheduler run has a real publish target.
not connected
First remote cron smoke testUse this exact sequence to prove the deployed Vercel scheduler can publish one due Facebook job without the local Mac cron fallback.
finish checklist first
1. Mirror the deployed envSet APP_BASE_URL, CRON_SECRET, FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY, and the full managed asset bucket env set in the Vercel production project.
required first
2. Create one fresh due Facebook jobUse a brand-new post with exactly one managed public media item, schedule it for now or slightly in the past, and leave the matching job in pending before triggering the sweep.
new jobs only
3. Trigger the deployed route with the Vercel secret pathPrefer Bearer auth for this smoke test so the helper exercises the same CRON_SECRET contract used by Vercel Cron.
bearer auth
4. Verify the first production outcomeExpect ok: true in the response, at least one processed job, a new dispatch record, and a real Facebook adapter success or failure message recorded on the job detail.
record result
Remote CLI smoke test

Run this from the repo root after the due Facebook job exists.

CRON_SECRET=your-vercel-cron-secret \
SCHEDULER_BASE_URL=https://auto-mmo-publisher.vercel.app \
npm run scheduler:run -- --auth bearer --limit 1
Raw curl fallback

Use this if you want to test the deployed route without the repo helper.

curl -X POST "https://auto-mmo-publisher.vercel.app/api/scheduler/run?limit=1" \
  -H "Authorization: Bearer $CRON_SECRET"
Auth shell planRecommended first setup before you start using the app across devices
prepared
ProviderGoogle sign-in first, because it is the fastest personal setup
recommended
Access controlAllowlist your main email first, then expand later if needed
next
Session modelFrontend signs in, backend keeps privileged writes on admin path
aligned
Firestore collections stagedThese are the collections the app is already shaped around
ready to seed
channelsA brand, theme, or content identity that owns one or more platform accounts.
10 fields
postsOne content item that can be published to multiple platforms at different times.
12 fields
assetsCanonical media records that let the publish pipeline track one public asset across posts, retries, and future bucket imports.
9 fields
platform_accountsPer-platform connection records so tokens and readiness live outside the content model.
13 fields
platform_secretsOptional per-platform secret documents referenced by platform_accounts.tokenRef.
7 fields
publish_jobsPlatform-specific execution units that the Cloud Run worker will claim and process.
9 fields
publish_job_dispatchesQueued handoff records created by manual dashboard triggers before a worker claims the job.
7 fields
platform_connect_sessionsShort-lived server-side OAuth sessions used while a user logs in and chooses which Facebook Page to activate.
6 fields
email_aliasesStable catch-all email aliases allocated per channel, platform, account, and workflow purpose.
8 fields
inbound_emailsIdempotent, normalized verification emails received from the Cloudflare Email Worker.
12 fields
Environment placeholdersThese are the first values to prepare for the next build slice
file: .env.example
NEXT_PUBLIC_FIREBASE_API_KEYPlaceholder added in the repo for later wiring.
Layerfrontend
Sensitivityconfig
Statuspresent
NEXT_PUBLIC_FIREBASE_AUTH_DOMAINPlaceholder added in the repo for later wiring.
Layerfrontend
Sensitivityconfig
Statuspresent
NEXT_PUBLIC_FIREBASE_PROJECT_IDPlaceholder added in the repo for later wiring.
Layerfrontend
Sensitivityconfig
Statuspresent
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKETPlaceholder added in the repo for later wiring.
Layerfrontend
Sensitivityconfig
Statuspresent
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_IDPlaceholder added in the repo for later wiring.
Layerfrontend
Sensitivityconfig
Statuspresent
NEXT_PUBLIC_FIREBASE_APP_IDPlaceholder added in the repo for later wiring.
Layerfrontend
Sensitivityconfig
Statuspresent
FIREBASE_PROJECT_IDPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
FIREBASE_CLIENT_EMAILPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
FIREBASE_PRIVATE_KEYPlaceholder added in the repo for later wiring.
Layerserver
Sensitivitysecret
Statuspresent
FACEBOOK_APP_IDPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
FACEBOOK_APP_SECRETPlaceholder added in the repo for later wiring.
Layerserver
Sensitivitysecret
Statuspresent
TIKTOK_CLIENT_KEYPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
TIKTOK_CLIENT_SECRETPlaceholder added in the repo for later wiring.
Layerserver
Sensitivitysecret
Statuspresent
TIKTOK_OAUTH_SCOPESPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
INSTAGRAM_APP_IDPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
INSTAGRAM_APP_SECRETPlaceholder added in the repo for later wiring.
Layerserver
Sensitivitysecret
Statuspresent
INSTAGRAM_OAUTH_SCOPESPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
PUBLISH_RUNNER_SECRETPlaceholder added in the repo for later wiring.
Layerserver
Sensitivitysecret
Statuspresent
APP_BASE_URLPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
CRON_SECRETPlaceholder added in the repo for later wiring.
Layerserver
Sensitivitysecret
Statuspresent
R2_ACCOUNT_IDPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
R2_ACCESS_KEY_IDPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
R2_SECRET_ACCESS_KEYPlaceholder added in the repo for later wiring.
Layerserver
Sensitivitysecret
Statuspresent
R2_BUCKET_NAMEPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
R2_PUBLIC_BASE_URLPlaceholder added in the repo for later wiring.
Layerserver
Sensitivityconfig
Statuspresent
Scheduled runner hookUse this endpoint from cron, Cloud Scheduler, or another secure trigger
ready to wire
GET /api/scheduler/run?limit=10Also accepts POST. The route scans due jobs, creates dispatches, and reuses the live worker path.
internal route
Scheduler authUse x-publish-runner-secret with PUBLISH_RUNNER_SECRET, or send a Bearer token with either PUBLISH_RUNNER_SECRET or CRON_SECRET.
required
Legacy jobsAuto-run is reliable for new posts because the composer now stores ISO time plus timezone metadata.
new posts first
Runs one server-side due-job sweep immediately without exposing the runner secret to the browser.