Sotto
We built Sotto for agencies running social engagement across dozens of client accounts. It scrapes the feeds, scores every post, drafts comments in each client's exact voice, and hands the agency a ready queue every morning. The agency clicks post when they're happy.

What we built
Sotto is a multi-tenant SaaS for social media agencies. Every account is a Clerk organisation, every client lives under that organisation, and every monitored Facebook or Instagram page hangs off the client. Clean separation, no cross-tenant leakage, twelve tables that all join through orgId.
The product is the pipeline. Scrape feeds with Playwright. Score each post with the client's preferred AI provider. Generate brand-voice comments. Queue them. Email a digest. Hand the agency a Chrome extension that drops the chosen comment straight into Facebook or Instagram with one click.
Most of the engineering complexity sits in two places. The first is the brand-voice config: every client gets a tone, an expertise list, an emoji style, example comments, and topics to avoid. The second is the AI provider router that dispatches each job to Claude, OpenAI, or Gemini based on client choice and post type.
Why we built it
Engagement is the cheapest reach a brand can buy. Comments, replies, conversations under other people's posts. The algorithm rewards it, the audience expands, the brand grows. But doing it well, in the client's voice, on the right posts, every morning, does not scale by hand.
Agencies were burning the same hour every day on it. Scroll the feeds, screenshot anything interesting, paste into a chatbot, copy a suggestion back, post it. We watched the workflow, mapped it, and rebuilt it as a system that does everything except the final click.
The five-minute morning review replaced the hour-long morning scroll. The agency still picks every comment. Sotto just does the work that the agency was never paid enough to enjoy.
How it works
Five stages, every morning.
- 01
Scrape
A Playwright crawler reads each client's monitored Facebook and Instagram pages. Selector-health tracking watches for DOM drift so the scraper stays alive when Meta ships changes.
- 02
Score
Each new post runs through an AI scorer. It produces a summary, an engagement score from 1 to 10, and a list of tones that would land. Anything below 5 is filed away.
- 03
Generate
For each top-scoring post, Sotto drafts multiple comments in the client's exact voice. The model reads the last 20 comments for that page so nothing repeats.
- 04
Queue
Comments land in a morning queue. A Resend digest emails the agency a one-line summary so they know there is work to look at.
- 05
Paste
The Chrome extension drops the chosen comment straight into the Facebook or Instagram comment box. The agency stays in control of every post.
Brand voice
Every client,
their own voice
Each client gets their own tone, expertise list, emoji style, example comments, and topics to avoid. Sotto reads the config and writes accordingly. Supportive for a charity, sharp for a tech startup, warm for a hospitality brand. Same product, different voices.

“This is such an important conversation. Thank you for sharing your experience and helping others feel less alone.”
“Fascinating approach to edge computing. The latency improvements align with what we saw in our own infrastructure migration last quarter.”
“Nothing beats that first morning view from the terrace. Hope you enjoyed every moment, you deserve the rest.”
“That form is looking solid. The consistency is clearly paying off. Keep pushing, the results speak for themselves.”
“Thank you for normalising this conversation. So many people need to hear that it's okay to ask for help.”
“Stunning property. The natural light in that living area is a real standout. Would love to know more about the neighbourhood.”
“Okay but that cheese pull is absolutely criminal. Saving this for when I need convincing to order delivery tonight.”
“The glow. That skincare routine is clearly working. Would love to know what serum you used in step three.”
“That face. You can just tell how loved this little one is. Wishing them the speediest recovery.”
The AI router
One product, three model providers.
Each agency client picks Claude, OpenAI, or Gemini for their brand. The router handles the rest. Different prompt templates, different streaming behaviour, different rate limits, all hidden behind one interface so the engine code stays clean.
Anthropic Claude
Strong on tone, holds character across long brand-voice prompts. Picked by most agencies for text-led posts.
OpenAI GPT
Familiar to agencies migrating from existing GPT pipelines. Good for short, punchy comment styles.
Google Gemini
Video posts always route to Gemini regardless of client preference. It is the only provider that natively processes video frames.
The principle
We chose not to
auto-post.
The engineering work to push every approved comment back into Facebook or Instagram automatically was small. We had the session, the cookies, the page object. We deliberately did not ship it.
Auto-commenting at scale gets accounts banned. Meta's spam detectors look for it. The whole point of the product is to expand agency reach, not collapse it. So Sotto stops at the queue. The Chrome extension is the bridge: a human reviews each comment, clicks once, and the comment lands as if they typed it.
Engagement is supposed to grow accounts, not get them banned.
The bridge
A Chrome extension that keeps it human.
The queue lives on the server. The posting lives in the browser. Sotto's Chrome extension is the bridge between them, opening as a Chrome side panel right next to whichever Facebook, Instagram, or TikTok page the agency is reviewing.
Manifest V3, side-panel surface
Pinned to the side of the browser, not a popup that disappears on click. Built on the latest Chrome extension API so the UX persists across tabs.
Facebook, Instagram, TikTok
Host permissions scoped to the platforms the agency actually engages on. The extension knows which platform the visible tab is on and surfaces the right comments.
Per-user tokens, revocable
Each browser holds a hashed extension token tied to a Clerk user. Tokens can be revoked from the dashboard if a device is lost. No password ever lives in the extension.
Approve the comment in the side panel. One click. The text drops into the platform's native comment box, ready to post as if the agency typed it themselves.
Resilience
Selector-health tracking
Meta breaks Facebook and Instagram DOM constantly. Class names shuffle, container hierarchy shifts, attributes change. Every scraper that targets these platforms ages.
Sotto's scraper logs every selector hit and every miss against a health table. Within hours of a Meta change, we know which CSS path stopped resolving. We patch in business hours, the product keeps running, agencies do not notice.
Illustrative. Actual health stays under our agency dashboard.
The build journey
From a daily hour to a five-minute review.
An hour a day, every day, on the same workflow
Social media agencies were paying staff to scroll a wall of feeds, screenshot interesting posts, paste them into ChatGPT for comment ideas, and post the result. The same loop, every morning, across every client. We wanted to compress that hour into a five-minute review.
Multi-tenant from day one
Every client's brand voice, every page they monitor, every comment ever posted. All of it lives in a single Postgres schema scoped by Clerk organisation id. Twelve tables, every query filtered by orgId, no cross-tenant leakage possible.
One product, three model providers
We routed each client's traffic to their preferred provider (Anthropic, OpenAI, or Gemini) and built a fall-through for video. Video posts always go to Gemini because it natively processes video frames. Image and text use whichever model the agency picked.
Selector-health tracking
Meta breaks Facebook and Instagram DOM constantly. The scraper logs each selector hit and miss, so we know within hours when a CSS path stops resolving. The product keeps running while we patch.
We chose not to auto-post
The engineering work to auto-post comments was small. We deliberately did not build it. Auto-posting at scale gets accounts banned by Meta, and the whole point of the product is to grow agency reach, not torch it.
Sotto.social, in the wild
Live multi-tenant SaaS, agencies onboarding, comments shipping out of the queue every morning. Built and shipped end-to-end from our Sant studio in Christchurch, NZ.
What we learned
The lessons we carry forward.
Auto-posting is the trap.
We could have shipped fully automated posting. We chose not to. Engagement is supposed to grow account reach, not get accounts banned. The Chrome extension keeps the human in the loop on purpose.
Brand voice is the product.
The hardest part wasn't the scraping or the queueing. It was getting the AI to write like a charity, and like a tech startup, and like a hospitality brand, on the same morning. The voice config schema took more iterations than the rest of the stack.
Selector tracking buys you nights and weekends.
Without it, every Meta DOM change would have woken someone up. With it, we get an alert, we patch in business hours, the product keeps running.
Provider switching matters more than provider choice.
Different agencies have different opinions on which model writes best. Building a clean router meant we never had to argue. Each client picks. Video falls to Gemini. The team focuses on the product, not the model.
Built with
The Sant services that shipped this product.