All work
Case study / SEO product · MCP server · marketing site · 2026

Keep the thread from search to site.

Querywright is the SEO intelligence layer for AI. It researches a site, measures what people actually search, lets your AI propose which page should own which query, waits for a human to approve, hands the AI grounded context to write from, and checks the accepted copy against the approved strategy before it ships. Every step leaves a signed, immutable artifact, so the next session starts where the last one ended.

ProjectQuerywright (my product)
RoleFounder · sole dev
ScopeApp + MCP server + marketing site
Shipped2026 · live, owner-scoped

/ four evidence states · never collapsed into one

querywright.com Seven steps · two are yours
Querywright homepage: a mint-green layout with seven overlapping workflow steps from Research to Verify.

Project breakdown

/ The brief

Replace one Semrush subscription. Find out if there’s a product underneath.

Querywright started on August 3, 2026 as the Keyword Opportunity Engine, an internal tool for A&C Meridian. The first goal was modest and already paid for itself on paper: a direct DataForSEO integration with caching, a keyword table, filtering, CSV export, and cost logging, so the studio could stop renting keyword research by the seat.

The second goal was the interesting one, and the brief refused to conflate the two. Keyword tools are good at answering what exists and what it costs. The valuable question is what you should actually build. That page-level decision engine had to earn its engineering time with evidence from real studio work before it became a product requirement. It did, and then it changed shape.

/ Part I · The reset

Three weeks in, I deleted the clever half.

Version two grew fast into a control plane: a contract kernel describing what a site should be, a deterministic verifier checking whether it obeyed, an evidence registry, a findings layer, and CI enforcement. On top of that sat the question that mattered: could a language model interpret all that deterministic state without inventing any of it?

Instead of assuming, I ran an evaluation phase with zero product integration. A frozen adversarial corpus, at least three runs per case, a provider-agnostic interface so no vendor leaked into the domain, and hard grounding gates that failed a run for any unknown source ID, unsupported number, or provenance slip. A local Gemma model on an RTX 5090 was the reference benchmark. The results drew a clean line through the product.

On August 26 the reset shipped as an architecture decision. Hosted AI analysis, strategy adjudication, contract materialization, and the governance ceremony around them were retired. What stayed was the chassis: provider truth, measured demand, crawl inventory, evidence provenance, and a read-only MCP surface. The new division of labor is one sentence. The host AI owns semantic mappings, rationale, prose, and review. Querywright owns evidence identity, measurements, immutable artifacts, and deterministic verification. Querywright itself never calls a model.

/ Part II · The product

Seven steps. Two of them are yours.

Research, then Demand, then Proposal, then Approval, then Generate, then Review, then Verify. The fourth and sixth steps belong to a person, and the product is built so a recommendation can never quietly become a decision. Five words carry the whole system: observed, measured, inferred, approved, verified. They are kept separate in the data model, in the UI, and in what the AI is allowed to say.

  • Next.js 16 on Cloudflare Workers through OpenNext at app.querywright.com, Postgres through Hyperdrive, Drizzle ORM, 64 tables, 43 migrations that are never rewritten
  • DataForSEO behind mock and live modes, a live-enable switch, request-scoped cost accounting, and one rule stated plainly: ambiguous provider contact is never retried automatically
  • Research, approved strategies, reviewed copy, and verification results are signed with a server-side key, so an artifact is authenticated, not just stored
  • Generation briefs hand the AI a bounded context: 4,000 characters for an existing page target, 16,000 for a new page’s site context, chosen deterministically
  • Pre-publish verification checks lineage, structure, and title, H1, and anchor phrases with contiguous token matching, and reports “needs a human” explicitly instead of guessing
  • A V3 control plane shipped September 12: site map, pages, strategies, briefs, reviewed copy, verifications, with contrast measured on every state color
/ Part III · The MCP server

The AI gets a key to the library, not the vault.

mcp.querywright.com is a separate Cloudflare Worker exposing 31 tools to any MCP-capable host. It connects to Postgres through a SELECT-only database role. The deployed bundle contains no provider credentials and cannot start a provider request. OAuth grants live in KV. Every JSON request is capped at one mebibyte with both declared-length and streamed-byte enforcement, because a host that can send a reviewed-copy payload can also send a bomb.

  • Exactly one tool can spend money. measure_demand calls a named RPC entrypoint on the app Worker over an account-scoped service binding, so the credentials never leave the app
  • The tool is annotated as non-idempotent and non-read-only, so a host can truthfully warn its user that a cache miss may create one billable request
  • Approval, copy acceptance, and verification write through the same narrow service bindings. The MCP Worker’s own database role stays read-only
  • Bounded rediscovery instead of a history browser: contextual reads accept ONLY or LATEST, fetch at most two rows, and refuse ties rather than picking one
42
Architecture decision records, enforced in CI
31tools
On the MCP server. One can spend money
0
Model calls made by Querywright itself
/ Part IV · The marketing site

A site that speaks in evidence states.

querywright.com is an Astro 7 static build with no framework islands. Outfit for the body, Newsreader for the voice, and a single forest-green scale from #051f20 to #daf1de that the app later adopted as its own brand pass. The centerpiece is a scroll-driven chain of seven panels, one per workflow step, each carrying real-looking records from a real session: cache fresh, provider cost $0.0103, search volume 0 marked measured zero, not unknown. The two human steps are tagged “You.”

  • Content Security Policy with no unsafe-inline anywhere. The build hashes every inline script and style Astro emits and writes the headers file itself
  • CSP cannot hash a style attribute, so the build rewrites every one into a hashed per-page style element. Components keep writing custom properties; runtime changes go through the CSSOM
  • A Chromium check loads the built site under the generated headers and fails the deploy on any violation
  • The social card is rendered from HTML with the site’s own fonts and palette, then committed. One URL per page, no trailing slashes, and a real 404
/ Decisions

What I picked, and what I didn’t.

  1. 01

    null is not zero.

    A provider returning no data for a phrase and a provider measuring a real zero are different facts, and the second is more valuable than the first. Querywright keeps four states distinct all the way down: measured positive, measured zero, no provider evidence, unmeasured. Nullable columns, explicit checks in every aggregation, and tests that assert the two never merge. Different sources may disagree without overwriting each other, and no source is canonical by default. It is the second ADR in the repo and the one the marketing site quotes.

    Considered: coercing missing to 0 like every dashboard does, dropping unmeasured rows, last-write-wins merging across providers

  2. 02

    The product never calls a model.

    I built hosted AI analysis, evaluated it properly against a frozen corpus with grounding gates, and then retired it. The evaluation showed that the machine’s judgment is most useful when it sits on the host side, where the user already has a model they trust, and Querywright’s job is to make that judgment checkable. Host judgments are not evidence. Approval is a decision, never an inference. The product got smaller and became honest about what it knows.

    Considered: a qualified hosted model behind the UI (built, measured, retired), an opportunity score, keyword difficulty, a traffic forecast

  3. 03

    One billable tool, behind a service binding.

    The MCP Worker was read-only and credential-free from the first ADR that governed it, and letting an AI host measure demand meant it needed a way to spend money. Rather than copy provider secrets into the MCP bundle, the app Worker exposes a single RPC entrypoint reachable only through an account-scoped Cloudflare service binding. The MCP tool forwards explicit queries, a location code, and a language code, and nothing else. Every real provider contact keeps the same cache, accounting, kill-switch, and no-retry semantics as the app.

    Considered: provider credentials in the MCP Worker, returning ephemeral unaccounted results, letting the tool accept site or strategy identifiers

/ Result

Dogfooded on a real studio. Live for one owner, on purpose.

The authenticated proof on the V3 release was A&C Meridian itself: 46 observed pages in one research snapshot and fifteen distinct approvals, each with its own copy and verification lineage. One verification came back ready with 23 checks passing. Another came back not ready, with 28 passing, two needing a human, and four not verifiable, and the browser showed exactly that instead of rounding it up to a score.

The codebase is about 35,000 lines of TypeScript with more than 800 tests across the app and the MCP Worker, including suites that create, migrate, and destroy a disposable Postgres database on every run. Customer sign-up and billing are built and switched off. The deployment stays owner-scoped until tenancy and workspaces clear their launch gates, because a product about not overstating evidence should not overstate its own readiness.