Product · Social media publishing
uContents
Write, schedule, publish and measure content across nine social networks from one place.
- SaaS · Multi-tenant platform
- 2026 · v1 then a full v2 rewrite

About uContents
Introduction
Creators and agencies make plenty of content. What eats their week is everything after: writing a caption for each platform, picking the page, choosing the date, re-uploading the same file nine times — then doing it again tomorrow. uContents turns that into a publishing system. Upload once, set the rules, and it keeps publishing across Facebook, Instagram, Threads, YouTube, TikTok, X, LinkedIn, Pinterest and Bluesky, then reads the analytics back. The version live today is a ground-up rewrite of an earlier Laravel product, rebuilt as a multi-tenant platform with workers, queues and an AI layer that looks at the media before it writes a word.
Details
- Project
- uContents
- Timeframe
- 2026 · v1 then a full v2 rewrite
- Type
- SaaS · Multi-tenant platform
- Live
- ucontents.com
- Next.js
- NestJS
- PostgreSQL
- Redis
- BullMQ
- Drizzle
- Stripe
- Docker
- Problem
- Posting the same content to many networks is manual, repetitive work: separate apps, repeated uploads, captions written without looking at the media, and analytics scattered across dashboards.
- What we built
- A multi-network publishing platform with bulk campaigns from a folder or CSV, recurring schedules and automatic reposts, AI captions drafted from sampled video frames, a visual builder for comment auto-replies, and brand workspaces with roles and 2FA.
- Outcome
- Live at ucontents.com. Version two replaced the original Laravel application with a NestJS and Next.js platform built for multiple brands and background publishing at scale.
- networks published to, with analytics read back from each
- 9
- background queues, split across five groups of workers
- 16
- tools behind the AI agent and the MCP server
- 36
- AI chat providers, with failover between them
- 12
Inside the customer app.
The dashboard a brand works in every day, rebuilt here in code from its own screens. It opens on a workflow; pick another screen, or click the sidebar.
Comments answered on a canvas
A visual builder of triggers, conditions, branches, actions and delays. A workflow starts on a new Facebook or Instagram comment, or on a schedule.
- Conditions on sentiment, intent, language and more
- AI reply, like, hide, notify
- Generate and publish posts
- An approvals panel for anything risky
Recreated from the product’s interface. Labels and options are the app’s own; the brand, posts and numbers are samples.
The parts, up close.
Pieces of the app that carry the most weight, at full size.
Composer
Checked before it is saved
Each network’s rules apply while the post is written, so one that cannot publish never reaches the queue.
Posts
Nine states, never published twice
A due post is claimed by one atomic status change, so two workers can never pick up the same one.
Campaigns
A schedule that keeps going
Slots in the campaign’s own timezone, a queue order, a rule for missed times, and a second lane that reposts what already went out.
Workflows
Comments answered while you sleep
A trigger, a condition on what the comment means, and the actions that follow. Anything risky waits in the approvals panel.
Studio
Nothing runs until you approve it
The agent plans, writes and generates, then stops at anything that costs credits or changes data.
Analytics
When your posts perform
Engagement by day and hour, so the calendar’s best times come from the brand’s own audience.
Brand voice
Written in the brand’s words
The Studio and the AI Writer read the same brief, kept per brand, with a memory of what it learns.
AI Writer
Captions on four dials
Tone, goal, style and length, set per post or per campaign, with the media in view before a word is written.
Integrations
Run it from your AI client
An MCP server lets agents work with posts, campaigns, media and analytics. Writes are proposed first and confirmed within fifteen minutes.
What went into it.
- 01
Publishing engine
Nine network integrations, scheduled and bulk publishing through BullMQ workers, with analytics read back from each platform.
- 02
AI layer
Captions, titles and hashtags drafted from frames sampled across each video, paid for in credits, with automatic failover between AI providers.
- 03
Workflows & workspaces
A visual workflow builder that answers comments, multi-brand workspaces with roles and 2FA, plus an MCP server for Claude.
How it is built.
The running parts
- API and realtime
- One NestJS codebase split into libraries, running as an API and a separate WebSocket gateway.
- Workers and scheduler
- BullMQ workers in five groups — core, media, AI, publishing and engagement — each its own service, plus a scheduler that elects a single leader.
- Three web apps
- The customer app, the marketing site and the admin, all on Next.js.
- Data
- PostgreSQL through Drizzle with row-level security, one Redis for queues and one for cache, and S3-compatible storage for media.
- Deployment
- Docker Compose on Dokploy. A migration step runs once and every other service waits for it.
The hard parts
- 01
Tenant isolation lives in the database
Every query runs inside a transaction that names the brand, and PostgreSQL row-level security does the filtering. With no brand in context the call fails instead of returning everything, and a check script fails when a brand table has no policy.
- 02
A post is never published twice
Due posts are claimed by a single atomic status change, so two workers cannot pick up the same one. A reaper resets anything stuck in publishing for over fifteen minutes, and every campaign slot has a stable key.
- 03
Retries that respect the network
Publishing gets four attempts, backing off for as long as the network asks and a little more. Failures are classified, and only account or channel failures count towards switching a channel off after three strikes.
- 04
Tokens renewed before they expire
A scan every ten minutes renews any access token that is past half of its remaining life, so a scheduled post does not fail on a login that expired overnight.
- 05
One brand cannot starve the rest
Campaign preparation shares a queue, so each brand holds a limited number of leases, taken atomically in Redis. A lease expires by itself if the worker holding it dies.
Want to see more?
Start here
Have a problem worth solving?
Tell us what is slow, manual or missing. You will hear back within one working day — then get a written scope and a fixed quote, or an honest no.
- # New project brief
- ## What is slow, manual or missing?
- - [x] Written scope
- - [x] Fixed quote
- - [x] Or an honest no

