A Tuesday special goes on the menu at four in the afternoon. Somebody has to post it to Instagram, to Facebook, and to the email list before dinner service starts. None of that is hard on its own. Doing it three times, in three different tools, and having it look like the same restaurant each time — that’s where the evening gets eaten up.

That is a real problem at restaurants, and it’s the same problem at most small businesses: not a shortage of ideas, but a shortage of time to turn one idea into three or four versions of itself without breaking the brand along the way. A first pass at fixing it was a simple wizard — pick a post type, fill in a short form, let AI draft the caption for each platform, crop and brand the photo automatically, then hit publish. That tool ran two restaurant brands from one app well enough to make clear the problem was bigger than one restaurant.

MessageKit homepage: Write it once. Send it everywhere.

The value is reusing content, not checking another inbox

MessageKit is that tool, generalized into a product open for signups today. The pitch sounds familiar — write it once, send it everywhere — because Buffer, Mailchimp, and Hootsuite already claim some version of it. What’s different is what “once” actually means.

Most tools treat social, email, and text as separate products wearing the same login. MessageKit treats them as one brand talking through three doors. A Content Module — one piece of content, with its own words and artwork per channel — gets built once and reused for the next campaign, the next social push, the next reminder text. A post that already went out can be saved straight into the library instead of retyped from scratch next time. The brand’s colors, fonts, and logo apply automatically everywhere that content shows up, because they live on the brand, not on whoever happens to be building the post that day.

No blank canvas, on purpose

The composer doesn’t hand anyone a blank page or a color picker. A brand sets its palette, its fonts, and its overlay templates once; everyone posting for that brand works inside those choices instead of making new ones every time. That sounds like a limitation. It’s a feature, for two reasons.

First, a blank canvas is where good intentions die. Somebody notices a great moment worth sharing, opens a design tool, and gets stuck picking fonts instead of posting. Fewer choices means faster posts.

Second, it’s what lets a junior staffer post at all. A brand-locked composer means the newest person on the team can put something out without a manager checking every font and color choice first, because the brand already made those choices. What’s left to get wrong is much smaller.

AI writes the draft. A person still hits send.

Every post runs through Claude to generate an image headline and platform-specific copy — different length, different tone, different hashtags for Facebook versus Instagram versus a text message. None of it goes out on its own. Marketing is sensitive, tone drifts, and a brand’s voice is one of the easiest things for a model to get subtly wrong, especially running several brands with different personalities side by side. The model gets a person past the blank page. A person still reads the draft, edits it if it’s off, and decides when it goes out.

Why not just use Mailchimp

Mailchimp, Klaviyo, and their peers got a real look before MessageKit became its own product. They’re built for companies with a marketing function — someone whose whole job is running the tool, with the audience size and the time to justify the complexity. For a two-person team running a restaurant, a boutique, or a small brand, that’s a lot of machine for the job: a blast cannon where the work calls for a chisel. The composers are powerful and hard to keep consistent, and a small team ends up spending more time fighting the tool than using it.

SMS is a First Class channel

Email and social get most of the attention, but text is the most direct channel there is. Industry figures commonly put SMS open rates near 98 percent, against roughly 20 percent for email, with nine in ten texts read within three minutes of arriving. A brand that wants to reach somebody today, not sometime this week, reaches for a text. MessageKit treats SMS as the third leg of the marketing stool.

Where it stands

MessageKit is live and open for signups now, with a free plan and no card required to start. It’s early — a beta in every sense that matters, not a finished product with the rough edges sanded off, so set expectations accordingly going in. What isn’t early: the core loop of building a brand once, posting everywhere, and staying on-brand without a marketing hire already works, today, for real accounts.

Sign up at messagekit.co →

Stuff for nerds

MessageKit, under the hood

MessageKit is a Rails 8.1 app: PostgreSQL, Sidekiq with sidekiq-cron for the handful of jobs that run on a schedule, Redis, Hotwire (Turbo and Stimulus) instead of a JavaScript framework, Bootstrap 5, esbuild for the JS bundle, Dart Sass for CSS. Tests run on Minitest with Capybara and Selenium for the system tests, standardrb enforces style, Brakeman scans for security issues, and GitHub Actions runs all of it on every push.

Built on SparrowKit

Accounts, organizations, roles, billing, and transactional email are not built into MessageKit's own codebase. They come from SparrowKit, a set of four private Rails engines — sparrow_auth, sparrow_mail, sparrow_pay, sparrow_ui — pulled in from a git source pinned to a tag, so they upgrade on purpose and never by accident. Organization is the tenant, Account is a person, Membership joins them with a role. Reused infrastructure instead of rebuilt infrastructure, which is the whole point of building more than one product this way.

sparrow_mail is what sends every transactional email — invitations, receipts, account notices — and it sends them through Postmark. That's a different job and a different provider from the marketing email a customer's audience receives, which is MessageKit's own, running through Amazon SES.

Brand is the center of the data model

Brand is MessageKit's own concept, not SparrowKit's, and it's the thing everything else hangs off: one identity to post as — label, colors, fonts, logo, voice guidelines, overlay geometry. An organization can run several. Each brand has channels (a Buffer channel per platform), overlay_templates (a PNG plus a text box per post type and platform), and posts. A Post has one PostVariant per platform, carrying that platform's generated copy, its crop, and its publish state.

An email is a document, not a post

An Email is a subject line and an ordered set of EmailBlocks — text, image, button, divider, spacer — a real document model, kept deliberately separate from Post because an email is a document and a social post is one picture with one string of copy per platform. What ties them together is a shared brand and a shared Content Library, not a shared table.

The interesting constraint lives in the email composer: there is no color picker. A text block picks a style the brand already defined — Heading, Subheading, Normal Text, Small Text — and the brand's own theme decides what each style looks like. A color applied inside a sentence is stored as the brand's name for it (accent), never a hex code, so changing a brand's accent color updates every email that ever used it, and a name the brand no longer has just stops being painted instead of breaking. The text itself is stored as escaped content with a small closed set of markup — bold, italic, a brand color, a link, a list — never raw HTML, never an arbitrary style. That closed set is what makes the whole system resistant to going off-brand by accident.

The AI pipeline

Two Claude models, split by job. Haiku writes the two-to-five-word overlay headline that gets set into the image — cheap, fast, tightly bounded output. Sonnet writes the platform copy, with a separate prompt per platform: Facebook and Instagram get different length targets, different tone instructions, different hashtag conventions, because what reads well on one reads wrong on the other.

The context sent to the model is built from the post's own form fields, in the order the brand defined them for that post type, plus the brand's voice guidelines — not a hardcoded prompt per post type, so a brand can invent a new kind of post without anyone shipping new code for it. Hashtags come back on their own marked line rather than mixed into the caption, so the app can store them structurally, filter by them in the Content Library, and drop them entirely for channels that don't use them, like email and SMS.

Publishing goes through Buffer today, on purpose

Posting straight to a customer's Facebook Page or Instagram account requires Meta's App Review before the permissions that matter actually work — there's no configuration that skips this and no tier that pays it away. Buffer already went through that review. Routing publishing through Buffer means the customer connects their own Buffer account and hands over a token, so the review happened, just to Buffer instead of to MessageKit. It's an onboarding cost, not a technical one: an organization can't publish until someone has created a Buffer account, connected pages there, and pasted a key into settings.

The unified alternatives — Ayrshare, Post for Me, and others — got a real evaluation and were set aside for now. Putting every customer behind one shared vendor app means a restriction against that app takes down every customer's publishing at once, with no fix available from this side. Building MessageKit's own Meta app removes that dependency. That's the next phase of work.

Multi-tenant safety, the same rule twice

Neither Buffer nor Amazon SES hands out a credential scoped to one customer, so the binding between a customer and their own sending identity has to be enforced by MessageKit itself — and it's enforced at the same point both times: immediately before the network call, never earlier. A campaign chunk re-checks its sender's domain against the organization's verified domains right before SES sends it; a post variant re-checks the organization's Buffer token right before publishing. Each row moves through its send states with one conditional update, so a job that retries after a crash can never double-send.

Campaign email and text ride their own rails

Campaign email sends through Amazon SES rather than Postmark, because a campaign needs a sending domain that belongs to the customer — their own subdomain, their own reputation — verified and rechecked before every send, which is a multi-tenant problem Postmark's transactional API was never built to solve. Text messages go through Twilio's REST API, with inbound webhooks checked against Twilio's request signature before anything is trusted, and a quiet-hours rule that refuses to send outside the hours a brand allows.

Images

Overlay artwork is a transparent PNG the brand supplies per post type and platform, laid over a photo that gets auto-cropped and resized to 1080×1080 (ruby-vips handles the crop and resize; ttfunk draws variable and static fonts through the same code path, so a headline actually matches the brand's real typography instead of a stand-in). Files live on Cloudflare R2 through Active Storage's S3-compatible adapter.