Skip to content
Case dossier  /  Client win

A shared social media workspace that drafts on brand and publishes on schedule

One shared workspace where the marketing team drafts, reviews, schedules, and measures every social post, with brand rules enforced before anything goes out.

5networks

LinkedIn, Facebook, Instagram, X, and Google Business Profile in one composer.

16tools

In the connector that lets the team draft and schedule from Claude or ChatGPT.

5min

Scheduler cadence, run inside the database, so a 9 AM post goes out at 9 AM.

01

The problem

The client's marketing team runs social media for two divisions. Each division has its own LinkedIn page and its own voice, and the company shares one account each on Facebook, Instagram, and X. Posting meant signing in to every network separately, keeping the schedule in people's heads, and hoping nobody booked the same slot twice.

The team also wanted AI help with writing, but not the kind that invents a project, gets the tagline wrong, or drops markdown into a LinkedIn post. The capable open source schedulers need servers and background workers that do not fit the hosting the rest of the client's apps run on. So we built it.

02

What we built

A shared web workspace, deployed the day we started, then extended over five weeks of walkthroughs with the marketing team.

  • Composer. Pick channels, override the text per channel, attach images or video, and watch a character counter per network. AI assist drafts from a topic and adapts a post for each platform.
  • Calendar and queue. Every post shows its status per channel, with the error and a retry button when one fails. Posts scheduled outside the app can be logged so nobody double-books.
  • Brand Brain. Each division's voice, plus a short brief of approved facts the app rebuilds weekly from the client's own websites and feeds into every prompt.
  • Image studio. On-brand graphics with the right division logo. Headline text is set in code, because image models misspell painted text. An approved photo library is searchable by what is in each picture.
  • Analytics. Every post on every connected channel, including posts from before the app existed, follower counts by day, the mix of team-written and AI-drafted posts, and which weekdays and formats perform. New drafts use each channel's best recent posts as a style reference.
  • News. Industry topics and mentions of the company, with a "draft a post" button that attaches the article.
  • Review. Send a post to a teammate for approval. Editing after approval sends it back to review.
  • Connector. One URL the team adds to Claude or ChatGPT to draft, schedule, and check posts from their own chat.

The LinkedIn integration came straight from Networker, our own LinkedIn product, including its hard-won rule that only a real authorization failure disconnects an account, never a throttled request or a server error.

03

How it works

A post is claimed in one step before anything is sent, so two overlapping scheduler runs can never both publish it. The scheduler runs inside the database every five minutes. The first version relied on a daily timer, which meant a 9 AM post could never fire on time.

The guardrails live in code, not in the model's good intentions. Posts start as drafts. Scheduling or publishing runs a quality check first, and a flagged post is held as a draft with the issues listed. Instagram posts without an image, X posts over the limit, and times in the past are refused before anything is sent. Taglines, em dashes, and markdown are checked on every AI output, because a live end-to-end test caught both the model and the quality check passing a tagline written in the wrong case.

The connector signs each person in with standard OAuth. Codes are single use, tokens are stored only as hashes and rotate on refresh, and every call re-checks that the person is still on the team.

The client's email security opens every link in incoming mail, which used up one-time sign-in links before anyone clicked them. Invites and password resets now send a typed code instead.

Before the LinkedIn release, an adversarial code review confirmed six real issues. The serious one: the sign-in handshake proved our app had started it, but not which browser had, so a captured link could have connected an attacker's account to a teammate's profile. It now requires a short-lived cookie from the browser that began the flow.

04

The result

The marketing team works from one place. Both LinkedIn pages synced their post history when connected, and LinkedIn posts publish from the app. Facebook and Instagram history and insights sync too; publishing to them has the right permissions but had not been used for a real post as of the last log. X is built and waiting on the account connection. Editing live posts on LinkedIn and Facebook is built and has not yet been tried on a live post.

Real use found real bugs, and each got a fix. A review digest that emailed every five minutes now re-reviews a post only when its content changes. Photo uploads that failed in Safari now go straight from the browser to storage, scaled first (a 23MB photo became 2MB in under a third of a second). Retries no longer create duplicate posts.

We have to do code based because IT taps every link.
John McIntoshFounder, Salvus AI

Your turn

Same problem? Different industry?

We work with one client per vertical at a time. If your shape matches one of our dossiers, we’ll tell you straight.