A DatoCMS manual field extension that turns a JSON field into a single-line text input where selected text can be made bold — and nothing else. Editors get a clean one-line field; the value is stored as structured JSON (a segment array), so there's no HTML to parse or sanitize.

<strong> or
raw JSON.The plugin is on the DatoCMS Marketplace:
Then attach it to a field:
json fields).That’s it — edit a record and the field behaves like a single-line input with a bold toggle.
An empty field stores null. A non-empty field stores a JSON string holding the
normalized segment array plus a plain-text mirror:
{ "segments": [ { "value": "This is my ", "mark": false }, { "value": "highlighted", "mark": true }, { "value": " text", "mark": false } ], "raw": "This is my highlighted text"}Each segment is a run of text that is either bold (mark: true) or not. The array
is normalized — adjacent runs with the same mark are merged and there are no empty
runs — so a given rendered text always serializes to exactly one array. See
SPEC.md for the full data contract and normalization rules.
The JSON→HTML transform is owned by the consuming app (intentionally out of scope for the plugin). A minimal renderer:
type Segment = { value: string; mark: boolean };
const escapeHtml = (s: string) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
export function renderStrong(fieldValue: string | null): string { if (!fieldValue) return ''; const { segments } = JSON.parse(fieldValue) as { segments: Segment[] }; return segments .map((s) => (s.mark ? `<strong>${escapeHtml(s.value)}</strong>` : escapeHtml(s.value))) .join('');}If you only need the unformatted text (slugs, meta tags), use the raw mirror
directly.
npm installnpm run dev # serve the plugin at http://localhost:5173npm run build # typecheck (tsc -b) + production build into dist/npm test # run the segment / bridge test suites (vitest)To try local changes against a real project, run npm run dev, then in DatoCMS go
to Settings → Plugins → Add new plugin → Advanced and register
http://localhost:5173 as the entry-point URL. Dato loads the plugin in an iframe
from that URL, so changes hot-reload as you edit.
Built with React + Vite + TypeScript on datocms-plugin-sdk / datocms-react-ui,
using Lexical as the editor engine.
MIT © 9elements