Skip to content

Text

Text carries most of what a document says: the title, the price, the description, the legal note. This page covers the text element from the simplest label to a paragraph with mixed formatting that receives its value from data. Each technique is explained once, then shown twice: in the editor (what to click) and in the document (the JSON, for agents and integrations). The two are the same thing — the editor saves exactly the document shown.

All the examples on this page are collected in the text lab, a one-page template that shows every technique side by side.

The text lab: overflow behaviours on the left, mixed formatting, letter spacing, fields, page numbers, weights and decorations on the right

A text element is a box: left, top, width and height in points. The text wraps at the box’s width, and the box’s height is the limit of what prints. A value longer than the box does not spill onto the page: it is cut, shrunk or grown according to rules you choose (see When the text is longer than its box).

Property What it does Default
text The text itself; \n starts a new line —
fontFamily, fontWeight, fontStyle The font: family name, normal/bold or a number 100–900, normal/italic Roboto, normal, normal
fontSize Size in points 16
fill Color, #RRGGBB #000000
textAlign left, center, right, justify left
lineHeight Distance between lines as a multiple of the size (1.3 = 130%) 1.16
charSpacing Letter spacing in thousandths of an em: 100 adds a tenth of the size between letters; negative tightens 0
underline, linethrough Decorations false
shadows Drop shadows: color, opacity, offset, blur none

In the document

{ "$type": "text", "id": "5c0de000-0000-4000-8000-000000000031", "name": "Intro",
"left": 40, "top": 330, "width": 330, "height": 90,
"text": "Five summer evenings in the library courtyard.",
"fontFamily": "Inter", "fontSize": 12, "fill": "#1c2430", "lineHeight": 1.4 }

In the editor

Choose Add text in the tool bar on the left and click on the page. With the text selected, the bar above the page shows the text controls: font, size, Bold, Italic, Underline, Strikethrough, the four alignments, bulleted and numbered lists and the text color. Line height, letter spacing and weights other than regular and bold are set through a text style (see Fonts and weights).

While you type static text in the editor, the box grows to hold it. A value that arrives from data at render time does not move the box: it follows the rules below.

A font must exist in the workspace: one of the 31 built-in families (Inter, Montserrat, Playfair Display, Roboto…) or a font the workspace has uploaded. List them with list_fonts (MCP) or GET /api/v1/fonts (REST) — each family comes with its available weights and styles, workspace fonts first.

  • Name the family exactly as the list spells it (Playfair Display, not PlayfairDisplay or Playfair). An unknown family is not rejected: the text prints in a substitute font. Check the preview.
  • Weights: normal (400) and bold (700) exist for most families; many families also have light (300), medium (500), semibold (600) or black (900). Write the number: "fontWeight": "600". When a family does not have the weight you ask for, the closest one it has prints — a semibold becomes bold, a light becomes regular.
  • Italic needs an italic file in the family; without it the upright style prints.
  • Every character must exist in the font. A glyph the font lacks does not print. Check symbols such as →, €, ², ✓ and non-Latin text in a preview.
  • A text can pin an exact font revision with a font reference (the object list_fonts returns). The editor always writes it; in a document you write, family and weight are enough.

In the editor

The font picker in the text bar lists the workspace’s families. Bold and Italic are enabled only when the family has that variant. For other weights, and for line height and letter spacing, open the Styles panel on the right, add a text style, choose its Weight, Line height and Character spacing, and apply it to the text. A style keeps the same typography consistent across the template; styles have their own page.

One text can mix formats — a bold word, a colored word, a subscript, a bulleted list — through rich text: paragraphs made of runs, where each run overrides only what changes.

{ "$type": "text", "id": "5c0de000-0000-4000-8000-000000000032", "name": "Menu intro",
"left": 315, "top": 60, "width": 240, "height": 150,
"fontFamily": "Inter", "fontSize": 12, "fill": "#1c2430", "lineHeight": 1.35,
"text": "Our menu is seasonal and local.\nStarters\nMains\nDesserts\nH2O and CO2 at 5 €/m2",
"richText": { "schema": "madoo.rich-text/v1", "paragraphs": [
{ "runs": [ { "text": "Our menu is " }, { "text": "seasonal", "fontWeight": "bold" }, { "text": " and " },
{ "text": "local", "fill": "#c0643a", "fontStyle": "italic" }, { "text": "." } ] },
{ "list": { "kind": "bullet", "level": 0 }, "runs": [ { "text": "Starters" } ] },
{ "list": { "kind": "bullet", "level": 1 }, "runs": [ { "text": "Mains" } ] },
{ "list": { "kind": "ordered", "level": 0 }, "runs": [ { "text": "Desserts" } ] },
{ "runs": [ { "text": "H" }, { "text": "2", "fontSize": 8, "baselineShift": -2 },
{ "text": "O and CO" }, { "text": "2", "fontSize": 8, "baselineShift": -2 },
{ "text": " at 5 €/m" }, { "text": "2", "fontSize": 8, "baselineShift": 4 } ] }
] } }
  • A run can change fontFamily, fontSize, fontWeight, fontStyle, fill, underline, linethrough and baselineShift (points, positive upwards: superscript, negative: subscript). Everything else comes from the element.
  • text must equal the rich text’s plain content: the runs of each paragraph joined, paragraphs separated by \n. A mismatch is rejected (DESIGN_RICH_TEXT_INVALID: The plain text projection must match the rich text content).
  • A paragraph with list becomes a list item: kind bullet or ordered, level 0–8 for nesting, start to restart a numbering. Markers (•, ◦, 1.) are drawn for you and are never part of the text.
  • A \n inside a run is a line break within the same paragraph (the same list item); a new paragraph is a new item.

In the editor

Double-click the text to edit it, select words, and apply bold, italic, color or size from the text bar; Ctrl+B, Ctrl+I and Ctrl+U work while typing. The list buttons turn the current paragraphs into a bulleted or numbered list. Shift+Enter breaks the line inside a list item. Superscript, subscript and Clear formatting are under More text properties (the … button at the end of the text bar).

A text becomes a field when it carries a placeholder: its value comes from data, and the text you wrote is the example shown in the editor. See Fields and data for field types and codes.

  • The value replaces the whole text. A line break in the value ("12 Harbour Street\nFalmouth") starts a new line.
  • A value is printed with the element’s own format — its font, size, color and alignment. Rich formatting written on a field’s example text does not apply to the value: a field prints in one format. To give part of a line another format, use two texts, or two fields (a bold name and a regular role).
  • A number field is formatted by its number format, a boolean field prints its labels — both are texts too, and everything on this page applies to them.

In the editor

Choose Add text placeholder in the tool bar, or select an existing text and choose Make Placeholder from the … menu of its action bar. The dialog asks for the name, the code, whether it is required, a default value and a description. The editor calls fields placeholders; they are listed in the Fields panel on the right.

A title that is sometimes three words and sometimes twelve, a description that varies from one line to six: the same box must serve all of them. Four behaviours are available.

Behaviour Where it works What happens to a long value
Keep the box (default) anywhere The size stays; the lines that do not fit are left out
Fixed height, shrink anywhere The size decreases until the text fits, down to minFontSize; below that, lines are left out
Fixed height, cut with … anywhere The size stays; the last visible line ends with an ellipsis
Grow in a flowing Layout or a repeated list row The box takes the lines the value needs, up to maxLines; what follows moves
Grow, on a free text anywhere else: on the page, in a Group, in a Layout that does not flow The box keeps its place and height; the value may take up to maxLines lines and no more than the box holds, then beyond applies
{ "fixedHeight": 44, "overflowMode": "shrink", "minFontSize": 8 }
{ "fixedHeight": 44, "overflowMode": "clip_ellipsis" }
{ "grow": { "maxLines": 2, "beyond": "shrink", "height": "content" } }
  • fixedHeight turns the fixed-height behaviours on; overflowMode is shrink, clip or clip_ellipsis. Shrink suits titles and names; cut with … suits descriptions, where a truncated sentence is acceptable.
  • grow makes the box follow the value where the text can push something: in a flowing Layout whose children size to their content, or directly in a repeated list row. maxLines is 1–50; beyond decides what happens past the limit: ellipsis, shrink, or fail, which stops the render with DESIGN_TEXT_TOO_LONG when cutting would be wrong (a legal note, a price condition). "height": "content" makes a short value exactly as tall as its lines, so a one-line title pulls up what follows. With shrink the value keeps its limit in lines too: a smaller size never wraps it onto more lines than maxLines, so a name with maxLines: 1 stays on one line. A value too long even at minFontSize (6 points unless set) prints at that size within the limit, the rest left out, and the preview reports it (too long even at the minimum size). Flowing Layouts and lists have their own pages.
  • On a free text — directly on the page, in a Group, or in a Layout that keeps drawn sizes — there is nothing to push, so the box keeps its place and height, and grow limits what it prints: the value may take up to maxLines lines and no more than the box holds, at least one. A value that needs more follows beyond: it is shrunk or cut with … inside the box, or the render stops with DESIGN_TEXT_TOO_LONG, which says how many lines the value needs and how many the text has room for. A value that fits prints as drawn. { "grow": { "maxLines": 1, "beyond": "shrink" } } on a one-line box is the simplest way to keep a name or a title on its line whatever its length; height has no effect there. The editor canvas shows the text as written; the exact preview and the PDF apply the rule to the sample or runtime value.
  • A preview reports every text that did not fit, with what happened to it: DESIGN_TEXT_OVERFLOW — 5 text(s) did not fit their box: A (too long even at the minimum size, lines left out), C (cut with …)…. It is a warning, not an error: read it, and fix the box or the rule.

In the editor

The Fixed height button in the text bar (the wrap icon) turns the fixed-height behaviours on; the menu next to it chooses Shrink, Clip or Clip…, and with Shrink a number sets the minimum font size. Growing texts are set in the settings of the Layout or the list that contains them: under Texts (in a Layout) or Long texts (in a list row), tick the text, then choose Up to lines and Beyond that — Cut with …, Shrink to fit or Stop the render.

A text can contain the tokens {{page}}, {{pages}} and {{sequencePages}}: they print the page number, the pages of the document and the pages of the current numbering sequence, and they are right even when a list adds pages. They are covered with masters and numbering sequences in the multi-page page.

In the editor

The Special fields tool adds a ready-made page text — the page number, Page 1, 1 / 12, Page 1 of 12, for the document or for the current sequence; on any text, Fields in the text bar (or Edit fields under More text properties) opens the page text editor, which inserts the tokens.

You need Do
A small label above a title (an eyebrow) Montserrat or another geometric sans, bold, 7–9 pt, capitals, charSpacing 100–150, accent color
A title that is sometimes long Display font, fixedHeight with shrink and a minFontSize no smaller than 70% of the size — or grow with maxLines: 2 and beyond: shrink, in a Layout or on a free text drawn two lines tall
A description of variable length fixedHeight with clip_ellipsis, or grow with maxLines: 6 and beyond: ellipsis in a Layout
An old price next to the new one Two texts: the old one linethrough in a muted color, the new one bold in the accent
An address or a signature block One text field; the data carries the line breaks (\n)
A legal note that must never be cut grow with beyond: fail, in a Layout or on a free text: a note too long stops the render instead of printing incomplete
A tight display title charSpacing −10 to −20 on a large serif
Chemical formulas, units, footnote marks Rich text runs with a smaller fontSize and a baselineShift
  • Every family is spelled as list_fonts returns it, and every weight exists or has a close neighbour.
  • Every symbol and accent prints (check the preview, not the editor).
  • Every text field has a behaviour for its longest value — shrink, cut, grow or fail — chosen on purpose.
  • The preview reports no DESIGN_TEXT_OVERFLOW you did not decide to accept.
  • Rich text only on static texts; fields print in one format.