AI SaaS

AI SEO Content Platform

Context

A platform that generates and publishes SEO content programmatically, pushing output into whichever CMS a customer already runs. The heavy lifting happens in background pipelines rather than request/response code.

The Hard Part

Publishing into 8 different CMS platforms means 8 different APIs, auth models, and failure modes — the pipeline architecture had to isolate each integration so one flaky CMS could not stall the rest.

What I Built

  • 13 Inngest background pipelines for content generation and publishing
  • 8 CMS adapters behind a single publishing interface
  • 100 API routes on Next.js with Supabase as the data layer
  • LLM orchestration through OpenRouter
  • n8n automations connecting the platform to external workflows
  • 74 test files over a schema evolved through 79 migrations

The Build

The work does not fit inside a request

Generating an article and publishing it somewhere is not one action. It is a sequence — produce the content, prepare it for a specific destination, send it, confirm it actually landed — and several of those steps are slow, involve a model, or depend on a service belonging to somebody else. The whole chain takes minutes and touches systems that can be unavailable at any point in it.

That rules out the obvious design before anything else is decided. A user cannot click a button and wait, because the request would have to stay open across work that is not yours to hurry, and a connection dropping halfway would leave an article generated, paid for, and never published. Long-running work needs somewhere durable to live, which is why the heavy lifting happens in background pipelines rather than request/response code.

The second shaping decision is publishing into whichever CMS a customer already runs. That is the difference between a product a marketing team can adopt and a product that first requires them to migrate their website — and asking a customer to change CMS is, in practice, asking them not to buy. The cost of that promise is that the platform inherits every system its customers happen to use.

Eight destinations that agree on nothing

Publishing into 8 different CMS platforms means 8 different APIs, auth models, and failure modes. They disagree about what a post is, how a draft differs from a published item, where images live, how categories and tags are represented, and what counts as success. Authentication alone spans several unrelated schemes, and each platform versions on its own schedule without consulting anyone building against it.

The requirement that follows is isolation: one flaky CMS cannot be allowed to stall the rest. This is not error handling as an afterthought but a constraint on the architecture, because the naive shape — a queue where jobs for all destinations share a fate — means a single unreachable platform blocks customers who have nothing to do with it. Failures have to be contained to the integration that produced them.

Generation adds a different pressure. Model calls are slow, non-deterministic, and billed by usage, which changes what a retry means. Re-running a failed publish costs a network call; re-running generation costs money and may produce different output than the attempt that failed. Those two things cannot be retried under the same policy, and treating them as one unit of work is how a transient CMS outage turns into a duplicated bill.

Pipelines, adapters, and one internal vocabulary

Thirteen Inngest pipelines carry the work, and the number matters less than the fact that it is thirteen rather than one. Splitting generation, preparation, publishing, and their surrounding concerns into separate pipelines is what allows each to have its own retry behaviour and its own failure boundary — so a publish that fails can be retried on its own, without regenerating content that was already produced correctly and already paid for.

Durability is the property that makes this work at all. A background pipeline records where it got to, so a step that fails resumes rather than restarting, and work in progress survives a deploy. That is the difference between a job system and a script that happened to be running when something went wrong.

The 8 CMS adapters sit behind a single publishing interface, which is the decision that keeps the rest of the system sane. The platform speaks one internal vocabulary for what a piece of content is, and each adapter translates that into whatever its destination expects. Nothing upstream of the interface knows which CMS it is publishing to. The practical consequence is that a ninth destination is a new adapter rather than a change threaded through the codebase, and a breaking change in one platform's API is contained to the file that speaks to it.

LLM orchestration through OpenRouter applies the same reasoning one layer up: the platform is not written against a single model provider, so model choice stays a configuration decision rather than an architectural commitment. n8n covers the connections to external workflows, which is the sensible place for customer-specific automation that should not be hardcoded into the product.

Underneath it all is Supabase and 100 API routes on Next.js, and 74 test files over a schema that evolved through 79 migrations. That last pairing is the one worth reading twice — a schema changing that many times means the requirements genuinely moved, and a test suite of that size is what makes a moving schema survivable rather than terrifying.

What these numbers are, and what they are not

The figures on this study describe structure rather than outcomes. 13 pipelines, 8 adapters, 100 routes and 74 test files measure the size and shape of the system, not traffic, revenue, or content performance — and it is more honest to say so than to imply otherwise.

Read that way they still carry real information. 8 adapters is the product claim made concrete: the promise to publish into whichever CMS a customer already runs is worth exactly as much as the number of platforms actually supported. 13 pipelines and 100 routes describe a system with substantial surface area rather than a wrapper around a model call. And 74 test files against 79 migrations describes the discipline that made continuous schema change possible without the codebase becoming something nobody wanted to touch.

What none of them show is the failure mode the architecture was built to avoid — the version where one CMS having a bad afternoon stops publishing for every customer on the platform. That absence never appears as a metric, which is usually true of the decisions worth making.

Measured Results

13

Inngest pipelines

8

CMS adapters

100

API routes

74

test files

Tech Stack

Next.jsSupabaseOpenRouterInngestn8n
AI SEO Content Platform — interface screenshot
Visit ranksector.com

More Case Studies

Have a similar project?

I would love to help you build something great. Let's discuss your requirements.