Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DRIPFEED

Multi-user SaaS: people sign up, upload a batch of videos, set one daily post time, and DRIPFEED auto-posts the next video in their queue to Instagram every day — with an AI-generated caption + hashtags.

frontend/index.html   -> single-file app (Firebase Auth + Firestore + Storage), deploy anywhere static (GitHub Pages works great)
worker/                -> Cloudflare Worker: Instagram OAuth handoff + the daily cron that posts
firestore.rules
storage.rules

How it fits together

  • Frontend talks directly to Firebase (Auth, Firestore, Storage) for everything except Instagram connection — sign-up, uploading videos, editing the schedule, viewing the queue. No backend needed for any of that.
  • Worker holds the three secrets the frontend must never see (Composio key, OpenAI key, Firebase service-account key) and does two things:
    1. Two HTTP routes that hand the user off to Composio's hosted Instagram OAuth flow and record the result.
    2. A cron job (every 15 min) that checks which users' daily post time has arrived, generates a caption with OpenAI, and publishes the next queued video as a Reel through Composio.

1. Firebase project

  1. Create a project at console.firebase.google.com.
  2. Enable Authentication → Email/Password.
  3. Enable Firestore (production mode) and Storage.
  4. Deploy the rules in this repo:
    firebase deploy --only firestore:rules,storage:rules
    
  5. Firestore will ask you to create a composite index the first time the Worker runs its cron query (igConnected == true + nextPostAt <= now). The error it throws contains a direct "create index" link — click it once.
  6. Create a service account for the Worker: Project Settings → Service Accounts → Generate new private key. You'll use its client_email and private_key as Worker secrets below.
  7. Copy your web app config (Project Settings → General → Your apps) into frontend/index.html's firebaseConfig block.

2. Composio

  1. Sign up at composio.dev and create a project.
  2. In the dashboard, add the Instagram toolkit and create an auth config for it (this is what lets your users connect their own Instagram accounts). Copy its id — that's COMPOSIO_INSTAGRAM_AUTH_CONFIG_ID.
  3. Grab a project API key — that's COMPOSIO_API_KEY.
  4. Before going live, confirm the exact Instagram tool slugs used in worker/src/composio.js — Composio's naming can shift:
    curl "https://backend.composio.dev/api/v3.1/tools?toolkit_slug=instagram" \
      -H "x-api-key: $COMPOSIO_API_KEY"
    
    Update TOOL_SLUGS in composio.js if the container-create / publish / status tool names differ from what's there.
  5. Instagram itself only allows professional (Business or Creator) accounts linked to a Facebook Page to publish via the API — personal accounts can't connect. Your users will need that set up on their end. For a public multi-user app, Meta also requires app review for the instagram_content_publish permission before non-test users can connect; budget time for that before launch.

3. OpenAI

Create an API key at platform.openai.com. That's OPENAI_API_KEY.

4. Deploy the Worker

cd worker
npm install
npx wrangler login

npx wrangler secret put GCP_CLIENT_EMAIL
npx wrangler secret put GCP_PRIVATE_KEY
npx wrangler secret put OPENAI_API_KEY
npx wrangler secret put COMPOSIO_API_KEY
npx wrangler secret put COMPOSIO_INSTAGRAM_AUTH_CONFIG_ID

# edit wrangler.toml [vars]: APP_URL, WORKER_URL, GCP_PROJECT_ID
npx wrangler deploy

APP_URL must match wherever you host frontend/index.html (used for CORS and post-connect redirects). WORKER_URL is the *.workers.dev URL you get after your first deploy (or a custom route, if you set one up).

5. Deploy the frontend

Fill in firebaseConfig and WORKER_URL at the top of frontend/index.html, then push it to GitHub Pages (or any static host) — it's a single file, no build step.

Data model

users/{uid}
  email, dailyPostTime ("09:00"), timezone (IANA string), niche
  igConnected, igUsername, composioConnectedAccountId, composioConnectionId
  nextPostAt (UTC timestamp, Worker-owned)

users/{uid}/queue/{videoId}
  fileName, storagePath, downloadUrl, note, uploadedAt
  status: "queued" | "posted" | "failed"
  caption, hashtags, igMediaId, postedAt / failedAt / errorMessage

The queue is FIFO by uploadedAt — each cron run takes the oldest queued video for a due user, posts it, and marks it posted (or failed, with the error visible in the UI, on the next queued item left untouched for the next day's run).

Notes / things to sanity-check before real users touch this

  • Instagram's publishing API needs the video reachable at a public HTTPS URL during the container-create call — the Firebase Storage download URL used here works, but Storage rules currently make videos/** world-readable so Meta's servers can fetch it. If that's a concern, swap it for short-lived signed URLs generated by the Worker instead.
  • The cron runs every 15 minutes, so a post can land up to ~15 minutes after the exact scheduled time — fine for a daily cadence, but worth knowing.
  • One video posted per user per due cycle, so a backlog never floods Instagram — if the queue is empty when it's a user's turn, that day is skipped and lastSkipReason: "queue_empty" is recorded on their user doc.

About

Instagram auto poster

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages