DEV Community

NextBlock™ CMS
NextBlock™ CMS

Posted on

We Built a Real-Time SEO Auditor in a Next.js 16 CMS (Without Token Costs or HTML Parsing Taxes)

When designing on-page SEO tooling for a modern CMS, teams usually make one of two mistakes:

They parse unstructured HTML strings using regex or heavy DOM packages, wrecking editor performance and causing hydration headaches.

They pipe entire drafts to an LLM on every keystroke, introducing UI lag and racking up unnecessary API costs.

Because NextBlock CMS stores all content as a strict, node-based PostgreSQL JSONB tree rather than raw HTML, we solved this with a hybrid architecture:

  1. Deterministic Client-Side AST Engine (0ms Latency, Zero API Cost)
    Our editor inspects editor.getJSON() debounced at 300ms. We evaluate heading hierarchy semantics (strict single-H1 enforcement, non-skipping depth validation), compute the Flesch Reading Ease index via lightweight syllable counting, and calculate focus keyphrase density across the first 100 words, subheadings, and metadata.

  2. On-Demand Cortex AI Remediation
    Nothing leaves the user's browser during typing. Only when an editor clicks an actionable warning does Cortex AI kick in to synthesize a missing heading, simplify complex prose, or generate missing image alt text using Bring-Your-Own-Key (BYOK) OpenRouter routing.

  3. Edge-Level Technical SEO
    Beyond the editor canvas, we added an administrative redirects dashboard backed by a indexed cms_redirects Supabase table, evaluated directly inside Next.js edge middleware before page render, alongside dynamic app/robots.ts generation.

The result: Editors get a live 100/100 SEO checklist directly in the authoring canvas without degrading Core Web Vitals or bloating the client bundle.

Try the live editor sandbox: https://nextblock.dev

Explore the source: https://github.com/nextblock-cms/nextblock

Top comments (1)

Collapse
 
citedy profile image
Dmitry Sergeev

tbh the "without HTML parsing taxes" part is what actually caught my eye, how are you handling dynamic content that loads via client-side JS if you're skipping the DOM?