Using Polaris
The editor
The Polaris CMS admin and its editor: the 11-check SEO score, Markdown with tables, footnotes, code, figures and chart blocks, and the link tools.
The admin#
Everything lives under /studio on your own site. Until you sign in, every admin URL shows the login form in place (no redirects), and every admin response is sent with Cache-Control: no-store and X-Robots-Tag: noindex, nofollow.
| Page | What it does |
|---|---|
| Dashboard | Live, scheduled and draft counts, the average SEO score, media size, the weakest posts, what goes live next, recent edits |
| Articles | Every post with its status, language and SEO score; filter by language |
| Editor | Write and publish one post (below) |
| Media | The image library: upload, alt text, delete |
| Link Genius | Every linkable post and page with its URL and keywords, searchable, one click to copy |
| Link Manager | Every link in every post: broken internal links, links to drafts, duplicates, inbound links per post |
| Visualizer | Pillars and their clusters, per language |
| IndexNow | Submit any set of your URLs to IndexNow |
| Indexing | Google Search Console URL Inspection, one URL at a time (read-only) |
| API Keys | Create and revoke keys, with the API docs for your site |
| Backups | List, download, restore and delete snapshots; take a full backup now |
The kit versions add Comments (moderation) and Ads (ad slots); the Next.js kit also has Messages (a contact-form inbox).
Writing a post#
The editor is a Markdown text area with a toolbar (bold, italic, H2, H3, lists, quote, inline code, link, image from the library, table, chart, code block, divider) and three modes: Write, Split and Preview. The preview uses the same renderer and stylesheet as the live post, so what you see is what gets published.
Shortcuts: ⌘B / Ctrl+B bold, ⌘I italic, ⌘K link, ⌘S save, and Tab indents.
Around the text sit the panels: slug, excerpt and the "In short" summary, language and translation (newest version), status and publish time, categories, featured image from the library, the SEO panel, Link Genius suggestions, content strategy (intent, pillar, belongs to pillar, highlighted) and the author byline.
The SEO score#
The SEO panel runs 11 on-page checks as you type, the same checks Polaris has always used (they follow the RankMath model). The score is the share of checks that pass:
score = round(passed / 11 × 100), graded good from 80, fair from 50, poor below.
| # | Check (as the editor names it) | Passes when |
|---|---|---|
| 1 | Focus keyword in the SEO title | The title contains the focus keyword |
| 2 | Focus keyword in the meta description | The meta description contains it |
| 3 | Focus keyword in the URL slug | The slug contains the keyword with spaces as hyphens |
| 4 | Focus keyword in the first paragraph | The first real paragraph (not a heading or an image) contains it |
| 5 | Focus keyword in a subheading (H2/H3) | At least one ## or ### heading contains it |
| 6 | Keyword density 0.5% to 2.5% | Keyword occurrences ÷ words × 100 is between 0.5 and 2.5 |
| 7 | At least 600 words | The body has 600 words or more |
| 8 | SEO title 60 characters or fewer | The title is 1 to 60 characters long |
| 9 | Meta description 50 to 160 characters | Its length is 50 to 160 characters |
| 10 | At least one internal link | The body has a root-relative link such as [text](/blog/other-post/) (images don't count) |
| 11 | At least one image with alt text | The body has an image with non-empty alt text,  |
Matching is case-insensitive. Checks 1 to 6 fail when there is no focus keyword. The featured image doesn't count for check 11: put at least one figure in the body. The stored seoScore is recomputed on every save; the API's recompute-scores action reruns it for every post (useful after you change the checks).
The Astro kit compares the slug with a transliterated keyword (so crème brûlée matches creme-brulee); the newest version replaces spaces with hyphens only.
Markdown#
Posts are GitHub-flavoured Markdown: tables, footnotes [^1], task lists and strikethrough. Raw HTML is dropped, so content written by an agent can't inject markup or scripts. Use ## and ### for sections: the title is the page's only h1, and a stray # heading becomes ##. Headings get stable ids for the table of contents.
Links to other sites open in a new tab with rel="noopener noreferrer". Give a link the Markdown title nofollow or sponsored to add those rel values:
[the product page](https://example.com/item "sponsored")
The rest of this section is about the newest Astro version. The kit versions render with react-markdown and GFM: tables, footnotes and figures work, but code is not highlighted and chart blocks show as plain code. In the kits, an italic line starting with Photo:, Image: or Credit: right under an image renders as its credit.
Figures#
An image alone in a paragraph becomes a <figure>, and its Markdown title becomes the caption:

Upload images first (Admin → Media or POST /api/cms/upload). Under a strict Content Security Policy such as img-src 'self' data: (the newest version's), images hotlinked from other hosts don't load.
Code#
Fenced blocks with a language are highlighted at render time with highlight.js classes (no inline styles), using highlight.js's common set: ts, js, bash, json, yaml, sql, css, html, python, go, rust, php, diff and more. Aliases such as sh, zsh and yml work too. Other languages render as plain code with their label.
Tables#
Column alignment (:--, --:, :-:) becomes classes, and a wide table scrolls in its own box on phones.
Charts#
A fenced chart block becomes an SVG chart with a caption, a legend for several series, and its numbers in a "Chart data" table under it. It is built from classes only, so it renders under a strict CSP.
```chart
type: bar
title: Organic clicks per month
caption: Source: Google Search Console, Sep–Nov 2026
unit: clicks
---
Month, Clicks
Sep, 120
Oct, 340
Nov, 610
```
- Header lines (before
---):typeisbar,hbar(horizontal bars) orline, and defaults tobar.title,caption(orsource) andunitare optional; the unit is added to the values in the data table. - Data rows: a label, then one value per series. An optional first row names the series (up to 4). Without it a single series is named after the unit.
- Separators: columns are split by
,, or by;or a tab when the line has them. Numbers take.or,as the decimal mark and no thousands separators, so use;when the data has decimal commas:W1; 0,5; 1,2. A value of0,002stays 0.002. A trailing%is ignored. - Limits: 60 rows at most. A block that can't be read renders as a code block with the reason, so a page never breaks.
A line chart with two series:
```chart
type: line
title: Weekly sessions
unit: sessions
---
Week; Blog; Tools
W1; 410; 120
W2; 520; 180
W3; 640; 260
```
Reading time#
Reading time is prose words ÷ 200, at least one minute. Code and chart blocks don't count. (The SEO word-count check counts the whole body.)
Link tools#
- Link Genius scans the draft for phrases that name another post or one of your site's pages (title, tags, focus keyword) and offers to link them: whole words only, phrases of 4 characters or more, skipping headings, code and existing links, a longer phrase first, pillar posts listed first, at most 12 suggestions. One click inserts the link in place. In the newest version it suggests posts in the post's own language.
- Link Manager lists every link in every post: internal links to pages that don't exist, links to drafts, duplicate links in one post, and the inbound links of each post, so orphans stand out. Absolute links to your own host count as internal.
- Visualizer draws pillars and their clusters (see Pillars, clusters and intent).
Open source under MIT. Public release on GitHub and npm in preparation. Roadmap.