01
BYOK at every stage
Anthropic, OpenAI, OpenRouter, Ollama — pick your provider per stage, paste your key. pr never imposes a default model on your spend. Workspace settings override env defaults; the DB row wins.
pr · Content & SEO engine
pr is the producer side of the Eleven11 content stack. It reads Search Console signals, names the gap, runs an opinionated five-stage pipeline — Discover, Write, Curate, Moderate, Package — and ships the artifact to a branded consumer over a signed HMAC contract. Two repos, one secret, no manual cycle.
Driven by profile + factBundle. BYOK per stage. Producer, not store — your archive lives on the consumer you control.
Surface signal
Status
LIVE
Contract
Signed HMAC
API
pr-api:4010 / v1
The thing nobody admits about content marketing
Agencies sell hours. Writing tools sell tokens. Both leave you with a CMS to babysit, an editorial calendar that nobody owns, and a publishing rhythm that breaks the moment one person is on leave. The work that actually matters — reading Search Console signals, naming the gaps, writing toward them, packaging the result for every channel — collapses back onto a single coordinator the moment the retainer ends.
pr is the opposite shape. It is an editorial pipeline as infrastructure. Topic in, signed publish out — with the same discipline every run. No CMS to operate. No agency to hold the rope.
Self-sustained by design
A content engine that depends on a vendor's writing tool, a multi-tenant CMS, and a per-seat agency contract is three failure modes in a trench coat. pr is built so none of those three are load-bearing.
01
BYOK at every stage
Anthropic, OpenAI, OpenRouter, Ollama — pick your provider per stage, paste your key. pr never imposes a default model on your spend. Workspace settings override env defaults; the DB row wins.
02
Signed contract, revocable
Every publish is HMAC-SHA256 over the raw body, header X-Pr-Signature: sha256=<hex>. Rotate the secret on the consumer, the producer stops landing posts that minute. The trust is a string in a row, not a vendor login.
03
Producer, not store
pr does not own your content. It produces, signs, and dispatches; the consumer (your blog, your CMS, your newsletter) is the system of record. Tear pr down tomorrow and your archive is intact.
04
In-fleet inference available
sphitih-ollama runs inside the e11-edge network for stages where local inference makes sense. Customer LLM keys handle the heavy drafting. The two compose; neither is mandatory.
05
Owned mail for notifications
Run lifecycle and LLM pool exhaustion fire into e11-alerts on owned infrastructure, then out to your channels. Nothing routes through a third-party Slack-app you didn't approve.
The primitive
pr is built on a small, opinionated trio — a profile that says what kind of content this workspace produces, a factBundle that grounds the draft, and a publishIntent that wraps the result for signed dispatch. Everything else is a stage transition between those three.
α · What you give
POST /v1/profiles
A content_type_profile holds the editorial rules — channels, template shape, SEO posture, voice, moderation tier. It is the knob that tells the pipeline what kind of artifact this workspace produces, and it is wired into every prompt as profileRules.
β · What grounds it
POST /v1/fact-bundles
A fact_bundle is the grounding payload — facts, document references, claims you want preserved. Write and Moderate read the bundle so the draft cannot drift into fabrication. Profile + factBundle is what makes pr a producer with a viewpoint, not a generic generator.
γ · What it produces
POST /v1/publish
A publish_intent wraps a stage artifact for outbound dispatch. Status moves queued → delivered → (optionally) rolled_back. Schedule it for later. Cancel it before delivery. Re-dispatch with action: unpublish to draft a delivered post on the consumer.
How it fits the fleet
pr is rarely the surface customers think they are buying — they see the blog, the email, the post. pr is the engine that fills all of them from one topic. Every adjacent tool either feeds it ground truth or consumes its output.
blog
The default consumer. POST /api/internal/pr-dispatch on the e11-web blog ingest endpoint verifies the X-Pr-Signature HMAC and upserts the post. Producer and consumer are two repos and one shared secret — the most testable seam in the fleet.
alerts
Every run lifecycle event — created, started, completed, failed, moderate.rejected, search.failed, publish.scheduled / delivered / failed — fires into /v1/events with per-phase idempotency keys, so one failed run does not collapse the rest of the queue.
operator
The /pr page in operator is the human surface for stage routing, per-provider keys, publish settings, and stage smoke tests. DB wins over env, and operator is how you edit the DB without touching a server shell.
architect
Architect can name a topic and a profile inside a session and hand it to pr without leaving the canvas. The publish intent then comes back into the matter as a delivered artifact — drafting, decision, and distribution in one trace.
discovery
Search Console signals and asset-surface intelligence land in discovery first. pr reads from that ground truth when it asks SearxNG for context, so the topic queue is shaped by your own footprint, not a generic content calendar.
dhara
When pr is sold standalone, the in-fleet Ollama-as-a-Service endpoint at dhara.eleven11.pro/ollama is the fallback for stages where you would rather not pay a frontier provider for cheap rewrites.
Surfaces & contracts
pr is API-first — five producer routes and one consumer ingest. The smallest contract that does the job, with the seam at the HMAC.
POST /v1/runs
Start a run
Body is { profileId, inputs: { topic }, factBundleId?, idempotencyKey? }. The same idempotency key returns the existing run, never a duplicate. The run lands in the BullMQ queue and the worker picks it up.
GET /v1/runs/:id
Watch the pipeline
Returns the run with its stages in pipeline order — Discover, Write, Curate, Moderate, Package — plus the artifactSummary for each. This is what an operator UI binds to.
POST /v1/publish
Schedule the dispatch
Wraps a packaged artifact into a publish_intent. Optional scheduledAt (ISO 8601) defers delivery; the worker queues a delayed BullMQ job. Omitted means the next worker tick.
POST /v1/publish/:id/rollback
Pull it back
Queued intents get cancelled in place. Delivered intents re-dispatch with action: unpublish and payload.status: draft, so the consumer hides the post without needing a separate API.
PUT /v1/llm-settings
Per-stage model routing
stageModelsJson maps each stage to { provider, models[primary, …fallbacks] }. providerApiKeysJson holds the per-workspace BYOK keys. DB wins over env. Pool fallback advances on transient failures, never on auth or billing errors.
POST /api/internal/pr-dispatch
The consumer side
Validates X-Pr-Signature: sha256=<hex> against the raw body using PR_PUBLISH_SECRET (or the prPublishSecret SiteSettings row), then upserts the post. The blog repo's ingest endpoint is byte-for-byte compatible with the producer's signRawBodySha256Hex.
Senior engineering, visible
Five decisions visible in the stage graph, the parser invariants, the migration discipline, and the alert idempotency — not adjectives, design choices.
Five stages, named, each with its own pool
Discover → Write → Curate → Moderate → Package. Each stage holds its own provider, its own model pool, its own system prompt, its own output parser. A 429 on Write advances to the fallback model; a 401 fails fast, because auth and billing aren't transient.
The clean-article-text invariant
Curate and Moderate receive clean article text, never a JSON blob of a prior stage's output. Package's content field is sourced from Curate or Write — never re-emitted by the package LLM. Earlier versions truncated articles mid-sentence; this invariant is what closed that class of bug.
Producer / consumer parity, byte-for-byte
src/lib/outbound-sign.ts on the producer and verifyPrPublishSignature on the consumer are the exact same HMAC over the exact same raw body. The seam is one helper on each side, tested against each other, with no JSON re-serialization in the middle.
Idempotency at every hop
runs.idempotencyKey is workspace-unique — re-POSTing the same payload returns the existing run. Alerts emit per-phase idempotency keys (pr.run:{id}:created, :started, :completed) so the 24h Redis dedup on alerts-api does not collapse a lifecycle into one event.
DB > env > defaults, every time
workspace_publish_settings (URL + HMAC secret), workspace_llm_settings (stage routing + provider keys), DEFAULT_STAGE_MODELS — three tiers, written down. Operator edits the DB; env is the bootstrap; defaults are the floor. No silent override paths.
Who this is for
pr earns its keep when the cost of a content team you do not control starts to exceed the cost of a pipeline you do.
FAQ
No. Writing assistants help one person write one thing. pr is an editorial pipeline that runs without a person — Discover, Write, Curate, Moderate, Package, then signed publish. The framing is agency-in-a-box, not autocomplete.
No. The consumer is anything that verifies an X-Pr-Signature HMAC header — a blog, a newsletter API, a CMS webhook, a Zapier hook. The reference deployment is e11-web's blog because that is what we use. The contract is published; the adapter pattern is generic.
Yours. pr is BYOK at the workspace level — Anthropic, OpenAI, OpenRouter, Ollama, in any combination per stage. We never bill you through us; we never hold a copy of your model keys outside your workspace settings row.
Moderate runs as the fourth stage; on pass: false the run transitions to failed with the issues joined as the error, and emits pr.moderate.rejected. The BullMQ queue keeps draining other jobs. One bad topic does not block the editorial calendar.
Discuss pr
pr is partner-deployed today — bundled with the e11-blog consumer or pointed at any HMAC-verifying endpoint you control. Talk to us about topology, BYOK routing, or how to migrate off an agency without losing rhythm.
Direct line
Consultation requests stay owned. We reply from e11 after reviewing fit and timing.