Viewport ← Back to viewport

Setting up Viewport

Viewport schedules videos to Instagram, YouTube and TikTok and reads back how they did. You run your own copy: your accounts, your database, your hosting.

About 30 minutes. Mostly creating free accounts and pasting keys between browser tabs.


What you need first

ServiceWhat it does here
SupabaseYour queue, your metrics, your uploaded videos
ComposioThe connection to Instagram and YouTube
CloudflareServes the app, starts the publish job on time
GitHubRuns the publishing and the metrics sync

All four are free at the volume Viewport uses. You also need Node 22 or newer, your licence key, and an Instagram Business or Creator account.


1 · Supabase

Create a project. Any region, any name.

Create the tables. Open SQL Editor, paste all of keyup-scheduler-cron/supabase/schema.sql, run it.

Create the bucket. Storage → New bucket, named exactly keyup-videos, with Public: on.

Copy two values from Project Settings → API: the Project URL and the service_role key.


2 · Composio

Create a project and copy its API key. That is all.


3 · Your settings file

In keyup-scheduler-cron/, create .env:

SUPABASE_URL=https://yourproject.supabase.co
SUPABASE_SERVICE_KEY=your-service-role-key
COMPOSIO_API_KEY=your-composio-key
YOUTUBE_DEFAULT_PRIVACY=unlisted

Leave YouTube on unlisted until your first post has gone out correctly.

Check it:

npm install
npm run doctor

This asks every service whether it can do what Viewport will ask of it, and names the one that cannot. Do not continue until Supabase is clean.


4 · GitHub

Put the code in your own repository — fork it or push it to a new private one. The publish job runs there, on your Actions minutes.

Add these as secrets under Settings → Secrets and variables → Actions:

SUPABASE_URL
SUPABASE_SERVICE_KEY
COMPOSIO_API_KEY
VIEWPORT_RELAY_URL
VIEWPORT_LICENCE_KEY

The last two came with your licence and are what let the publish job reach TikTok. Add GROQ_API_KEY as well if you want written insights — free at console.groq.com.

Create a token so the app can start that job. Settings → Developer settings → Personal access tokens → Fine-grained tokens:

Copy it now; GitHub will not show it again.


5 · Cloudflare

From keyup-scheduler/:

npm install
npx wrangler login

Name your Worker. In wrangler.jsonc, change "name" and set GITHUB_REPO to your repository:

"name": "my-viewport",
"vars": {
  "GITHUB_REPO": "your-username/your-repo"
}

Add your secrets. Each command prompts for the value:

npx wrangler secret put SUPABASE_URL
npx wrangler secret put SUPABASE_SERVICE_KEY
npx wrangler secret put GITHUB_DISPATCH_TOKEN
npx wrangler secret put SCHEDULER_PASSWORD
npx wrangler secret put SCHEDULER_TOKEN_SECRET
npx wrangler secret put COMPOSIO_API_KEY
npx wrangler secret put VIEWPORT_RELAY_URL
npx wrangler secret put VIEWPORT_LICENCE_KEY

SCHEDULER_PASSWORD is what you will type to open Viewport — choose a real one. SCHEDULER_TOKEN_SECRET signs your session and nobody ever types it, so make it long and random:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Add GROQ_API_KEY here too if you are using insights.

Deploy:

npx wrangler deploy

Wrangler prints your URL. Open it, enter your password, and you are in.


6 · Check the whole thing

Back in keyup-scheduler-cron/, run the check with your GitHub token — the one part it could not see before:

GITHUB_REPO=your-username/your-repo GITHUB_DISPATCH_TOKEN=your-token npm run doctor

Everything should read [ ok ]. If not, the line names the service and what to do.


7 · Connect your accounts

Open Viewport → SettingsConnect next to each of Instagram, YouTube and TikTok. Each opens that platform's own login in a new tab; Viewport never sees your password. The row turns green when it is done.


8 · Your first post

Schedule something small a few minutes out, to Instagram or YouTube only.

Once a post has gone out correctly, set YOUTUBE_DEFAULT_PRIVACY=public.


When something is wrong

Run npm run doctor first. It exists so you do not have to guess which of four services broke.

What you seeWhat it usually is
App opens but everything is emptyThe anon key instead of service_role, or schema.sql was never run
Upload failsThe keyup-videos bucket is missing or not public
Posts sit at "pending" foreverThe GitHub token lacks Actions: read and write, or GITHUB_REPO is wrong
Instagram refuses the postThe account is personal, not Business or Creator
TikTok will not connectVIEWPORT_RELAY_URL or VIEWPORT_LICENCE_KEY is missing or mistyped
TikTok says the daily limit is fullFifteen posts per day per licence. It resets; the post waits in the queue
Analytics numbers look oldThey are. Refresh asks for new ones

Appendix A · Running without a licence key

Skip this unless you have no licence and want TikTok anyway.

Instagram and YouTube work either way — Composio supplies those OAuth apps. TikTok does not work that way. TikTok only lets an unaudited app post to a private account, so to post publicly on your own you must register a TikTok developer app, own a domain and serve your terms and privacy pages from it, verify that domain with TikTok, record a demo video of the whole flow, give their reviewer a working login, and wait — usually days, sometimes two weeks.

Once TikTok has approved your app, add it as an auth config in your Composio project, and leave VIEWPORT_RELAY_URL and VIEWPORT_LICENCE_KEY out entirely. Viewport then posts through your app instead of ours.


Appendix B · The desktop app

Viewport runs in any browser. The desktop app is a thin window around the same site, so it stays current by itself.

From keyup-scheduler-desktop/, set APP_URL at the top of main.js to your Worker URL, then:

npm install
npm run build:icon
npm run dist

The installer lands in the output directory named in package.json.