
By Starstack
Real-time SEO and readability analysis for Strapi v5. Inline field stats, content validation, and readability checks - live as you type.
released March 6, 2026
npm install @starstack/strapi-plugin-content-optimizerReal-time SEO and readability analysis for Strapi v5. Inline field stats, content validation, and readability checks - all updating live as you type, directly inside the Content Manager.
| Dependency | Version |
|---|---|
| Strapi | ^5.0.0 |
| React | ^18.0.0 |
| @strapi/design-system | ^2.0.0 |
| Node.js | ≥18, ≤24 |
npm install @starstack/strapi-plugin-content-optimizerIn config/plugins.ts:
export default {
"content-optimizer": {
enabled: true,
},
};Or in config/plugins.js:
module.exports = {
"content-optimizer": {
enabled: true,
},
};npm run build
npm run developOnce installed, two UI elements appear inside any Content Manager edit view:
Injected directly below the Title and Description fields:
142 characters | 23 words | Optimal ●
┌─────────────────────────────────────────┐
│ ✅ Optimal │
└─────────────────────────────────────────┘A Content Statistics panel in the right sidebar that switches context based on the active field:
The plugin uses a two-path extraction strategy for Strapi Blocks fields:
Path 1 - Blocks JSON (preferred): Reads the structured JSON from unstable_useContentManagerContext directly. Accurate for saved and unsaved content.
Path 2 - DOM fallback: Walks the live Slate editor DOM when JSON is unavailable. Uses a leaf-block filter to avoid double-counting Slate's nested <li><p> structure.
Content is classified into three buckets:
headingBlocks (h1–h6) - contribute to word count onlyparagraphBlocks (p, blockquote) - used for paragraph metrics and sentence metricslistBlocks (li) - used for word count and sentence metrics, not paragraph countFields are located by querying the live DOM in priority order:
Title:
[data-strapi-field="title"] inputinput[name="title"]Description:
[data-strapi-field="metaDescription"] textarea[data-strapi-field="description"] textareatextarea[name="metaDescription"]textarea[name="description"]Content editors:
[data-strapi-field] wrappers with a contenteditable child, excluding known SEO fieldscontenteditable elements not under a [data-strapi-field] wrapper (covers dynamic zones)unstable_useContentManagerContext - this is an internal Strapi API marked unstable. It works across current Strapi 5.x releases but may require an update on future Strapi versions.title, description, metaDescription) may require the Strapi data-strapi-field attribute to be present.MIT © Starstack
Share your work with the community and get it listed in the Strapi ecosystem for everyone to discover and use.
Submit
