# Other platforms: LinkedIn, Google Business Profile, YouTube, TikTok, Pinterest, Threads, Reddit Facebook and Instagram still come through the agency's Meta system user. Every other platform is connected **per client** on the **Connections** page: an admin signs in to the client's account once ("Connect"), and from then on posts to that platform go through Publishing with the same draft → approve → publish flow. ## How it fits together | Piece | Where | |---|---| | Connections page (set up apps, connect/disconnect accounts, choose company Page / location) | `dashboard/web/src/pages/Connections.jsx` | | "Post to" picker with each platform's fields, used in New post and library Schedule | `dashboard/web/src/PlatformPicker.jsx` | | API routes, OAuth callback `/oauth//callback`, media links `/m//` | `dashboard/server/index.js` | | Encrypted store for app keys and tokens (`data/connections.json`, AES-256-GCM) | `connector/src/platforms/vault.js` | | Sign-in (OAuth 2, PKCE for Google), token refresh | `connector/src/platforms/oauth.js`, `index.js` | | One adapter per platform | `connector/src/platforms/.js` | | Queue integration (validation, publishing) | `connector/src/schedule.js` | | Agent tools: `list_connections`; `schedule_post` / `schedule_from_library` accept all platforms + `options` | `connector/src/server.js` | | Offline tests (simulated platform APIs) | `connector/test/platforms.test.mjs` → `node --test connector/test/platforms.test.mjs` | Tokens and app secrets are encrypted with a key derived from `DASHBOARD_SECRET` (or `QUORLA_SECRET_KEY`). They are never sent to the browser. If that secret changes, every platform shows "Reconnect needed". ## What each platform needs before it works for real Every platform requires a developer app owned by the agency, with the Redirect URI shown in its **Set up** dialog (`https://app.quorlasocial.com/oauth//callback`), plus the privacy policy and terms pages on quorlasocial.com. | Platform | Posts | Developer app | Approval needed for real use | Until approved | |---|---|---|---|---| | LinkedIn | text, image, multi-image, video; as a person or company Page | linkedin.com/developers | **Community Management API** (company Pages, analytics) | Personal profiles only: set Scopes to `openid profile w_member_social` | | Google Business Profile | update with photo and button | Google Cloud (OAuth client) | **Business Profile API access** form + OAuth consent verification | API calls return quota errors; test users only | | YouTube | video (Shorts when vertical, under 3 min) | Google Cloud (same OAuth client) | **YouTube API audit** + consent verification | Uploads are forced to Private; small daily quota | | TikTok | video, photo / photo carousel | developers.tiktok.com | **App review** for Content Posting API (Direct Post) | Posts are "Only me"; sandbox users only | | Pinterest | image, multi-image (2–5), video Pins on a board | developers.pinterest.com | **Standard access** (demo video) | Trial: set `PINTEREST_SANDBOX=true`, Pins go to the sandbox | | Threads | text, image, video, carousel | Meta for Developers (Threads use case) | **Meta app review** for Threads permissions | Only accounts added as Threads testers | | Reddit | text or link post to a subreddit | reddit.com/prefs/apps (web app) | Reddit's approval for commercial API use | Works for the agency's own account; check each subreddit's rules | Platforms that fetch media from a link (TikTok photos, Threads, Google Business Profile) get a signed link to the file that expires after 6 hours. On the server this uses `PUBLIC_URL`, or `https://APP_DOMAIN` when that's set. TikTok also needs the domain verified in its developer portal. ## What was tested, and what wasn't - **Tested offline (15 tests, all passing):** encryption at rest, sign-in links for every platform (client ID parameter, scopes, PKCE, offline access), the callback state check, token refresh and "reconnect needed", and each platform's publish requests (LinkedIn image to a company Page with hashtags, YouTube resumable upload, GBP post with button and photo link, TikTok video chunks and photo pull, Pinterest base64 Pin, Threads long-lived token and image post, Reddit text post and error handling), plus format and field validation. - **Tested against the local dashboard (21 checks):** admin-only setup and connect, secrets never returned, sign-in redirect and callback errors (forged state, cancelled, signed out), media links (served, tampered refused), drafts to connected and unconnected platforms, per-platform captions, disconnect. - **Not tested:** real calls to each platform. Each platform needs its developer app and keys first. The request formats follow each platform's documentation as of this build, but expect small fixes the first time each one connects and posts. Test with the agency's own accounts before connecting clients. - **Not built yet:** comments/inbox and analytics for these platforms (only follower counts are shown), Reddit image posts, Pinterest video cover images, LinkedIn document (PDF) posts, X (paid API). ## Suggested order after merging 1. Deploy (`git pull && docker compose up -d --build`), then Connections → Set up for one platform at a time. 2. Start with **LinkedIn** (personal-profile scopes) and **Google Business Profile**, using Metatroncube's own accounts. 3. Apply for the approvals in the table above. They take days to weeks, which is why they should start early. 4. Connect client accounts once each platform is approved.