Document (dev.stxt.website): STXT: prose inside structure Metadata: Last modif: 2026-09-24 Description: STXT puts prose inside structure. The same lesson in Markdown with Frontmatter, MDX, Markdoc, YAML and STXT: where the structure goes and what each one validates. Header: @STXT@, prose inside structure Assert >> Frontmatter, MDX and Markdoc embed the structure in the prose. @STXT@ embeds the prose in the structure, so **the whole document can be validated**. Subheader: CMS and structure validation Content >> When a document needs prose, Markdown is the usual choice. The problem appears when it also needs a structure that must be validated. The usual solution is to insert the structure **inside** Markdown, using another language. Most of the time this allows a partial validation, but with solutions that look more like a hack than a structural answer. The cost is this: - More languages in play - Harder writing for non-technical people - Less readability overall - Less uniform environments - Text mixed with code This article shows how @STXT@ inverts the solution: it inserts the prose inside a structure that can be validated. We show the same document, a `Lesson` with a specific structure, and how it is validated with each of the current solutions. We also show it in YAML and in KDL, two formats that do allow prose inside the structure, although they are not usual in a CMS. Subheader: @STXT@ with Markdown Code >> Lesson (com.example.school): What is STXT? Authors: Author: Joan Costa Author: James Smith Teacher: Sheila Jones Difficulty: easy Introduction >> STXT is a **hierarchical text format**: easy for people to read and trivial for machines to parse. Content >> A document is a tree of nodes. There are only two kinds: - `Name: value`, for short inline values. - `Name >>`, for a block of literal text, like this one. Indentation *is* the structure: no closing tags, no quotes and no escape characters. Question: Do you know another similar format? Answer: XML, for example Content >> Comments are all the lines that start with `#`. Documents may have namespaces. You define them with `Name (namespace.name)`. Conclusion >> With two kinds of node and indentation you can describe any document. A template adds **validation** on top, without changing the syntax. Quiz: Question: How is the structure of a document expressed? Answer >> With indentation: a node is a child of the closest previous node with one level less. Question: What happens to the text inside a `>>` block? Answer >> It is kept literally. Nothing inside is interpreted. It can be Markdown, code or any other text. Content >> And the template that validates structure and cardinality: Code >> Template (@stxt.template): com.example.school Structure >> Lesson: Authors: (1) Author: (+) Teacher: (1) Difficulty: (?) ENUM [easy, medium, hard] Introduction: (?) MARKDOWN Content: (*) MARKDOWN Question: (*) Answer: (1) MARKDOWN Conclusion: (?) MARKDOWN Quiz: (?) GROUP Question: (+) @Question Content >> The whole document can be validated with the template: structure, cardinality and content. In the prose, no escape characters are needed. A document with errors does not validate: Code >> # ERROR: this document does not validate Lesson (com.example.school): What is STXT? Authors: Author: Joan Costa # `Teacher` is missing # `trivial` is not a difficulty from the list Difficulty: trivial Introduction >> STXT is a **hierarchical text format**. Subheader: Frontmatter Markdown >> --- type: lesson title: What is STXT? authors: - Joan Costa - James Smith teacher: Sheila Jones difficulty: easy --- # Introduction STXT is a **hierarchical text format**: easy for people to read and trivial for machines to parse. # Content A document is a tree of nodes. There are only two kinds: - `Name: value`, for short inline values. - `Name >>`, for a block of literal text, like this one. Indentation *is* the structure: no closing tags, no quotes and no escape characters. **Question**: Do you know another similar format? **Answer**: XML, for example # Content Comments are all the lines that start with `#`. Documents may have namespaces. You define them with `Name (namespace.name)`. # Conclusion With two kinds of node and indentation you can describe any document. A template adds **validation** on top, without changing the syntax. # Quiz ## How is the structure of a document expressed? With indentation: a node is a child of the closest previous node with one level less. ## What happens to the text inside a `>>` block? It is kept literally. Nothing inside is interpreted. It can be Markdown, code or any other text. Content >> The question, the answer and the quiz are a convention, and nothing checks that structure. The Frontmatter can be validated with an external schema: JSON Schema, or a Zod schema in Astro content collections. Subheader: MDX Markdown >> --- type: lesson title: What is STXT? authors: - Joan Costa - James Smith teacher: Sheila Jones difficulty: easy --- import { Question, Quiz } from '../components/Lesson' # Introduction STXT is a **hierarchical text format**: easy for people to read and trivial for machines to parse. # Content A document is a tree of nodes. There are only two kinds: - `Name: value`, for short inline values. - `Name >>`, for a block of literal text, like this one. Indentation *is* the structure: no closing tags, no quotes and no escape characters. XML, for example # Content Comments are all the lines that start with `#`. Documents may have namespaces. You define them with `Name (namespace.name)`. # Conclusion With two kinds of node and indentation you can describe any document. A template adds **validation** on top, without changing the syntax. With indentation: a node is a child of the closest previous node with one level less. It is kept literally. Nothing inside is interpreted. It can be Markdown, code or any other text. Content >> `Question` and `Quiz` are JavaScript components defined in another file. The document compiles to a JavaScript module, mixing the document with code. In the prose, `<` and `{` open JSX and expressions, so they must be escaped. Subheader: Markdoc Markdown >> --- type: lesson title: What is STXT? authors: - Joan Costa - James Smith teacher: Sheila Jones difficulty: easy --- # Introduction STXT is a **hierarchical text format**: easy for people to read and trivial for machines to parse. # Content A document is a tree of nodes. There are only two kinds: - `Name: value`, for short inline values. - `Name >>`, for a block of literal text, like this one. Indentation *is* the structure: no closing tags, no quotes and no escape characters. {% question text="Do you know another similar format?" %} XML, for example {% /question %} # Content Comments are all the lines that start with `#`. Documents may have namespaces. You define them with `Name (namespace.name)`. # Conclusion With two kinds of node and indentation you can describe any document. A template adds **validation** on top, without changing the syntax. {% quiz %} {% question text="How is the structure of a document expressed?" %} With indentation: a node is a child of the closest previous node with one level less. {% /question %} {% question text="What happens to the text inside a `>>` block?" %} It is kept literally. Nothing inside is interpreted. It can be Markdown, code or any other text. {% /question %} {% /quiz %} Content >> The schema is a JavaScript object. It declares the tags, their attributes and which children they accept: TypeScript >> const config = { tags: { question: { render: 'Question', attributes: { text: { type: String, required: true }, }, }, quiz: { render: 'Quiz', children: ['tag'], }, }, }; const ast = Markdoc.parse(source); const errors = Markdoc.validate(ast, config); Content >> Cardinality is not declarative, and the document is mixed with code in another language. Subheader: YAML with Markdown Yaml >> type: lesson title: What is STXT? authors: - Joan Costa - James Smith teacher: Sheila Jones difficulty: easy introduction: | STXT is a **hierarchical text format**: easy for people to read and trivial for machines to parse. body: - content: | A document is a tree of nodes. There are only two kinds: - `Name: value`, for short inline values. - `Name >>`, for a block of literal text, like this one. Indentation *is* the structure: no closing tags, no quotes and no escape characters. - question: Do you know another similar format? answer: XML, for example - content: | Comments are all the lines that start with `#`. Documents may have namespaces. You define them with `Name (namespace.name)`. conclusion: | With two kinds of node and indentation you can describe any document. A template adds **validation** on top, without changing the syntax. quiz: - question: How is the structure of a document expressed? answer: | With indentation: a node is a child of the closest previous node with one level less. - question: What happens to the text inside a `>>` block? answer: | It is kept literally. Nothing inside is interpreted. It can be Markdown, code or any other text. Content >> Here the prose is inside the structure, as in @STXT@, with one important difference: In **YAML** keys are unique, so repeated items have to go into an (artificial) list. This makes it visually harder to tell whether a `-` character belongs to the structure nodes or is part of the prose. In @STXT@ repetition is natural and no list is needed: everything is a structure of text nodes. Assert >> The **mental model** of YAML and @STXT@ is very different when writing content in a CMS. YAML is closer to JSON: there are maps and lists. @STXT@ is more like XML, with trees of text. Subheader: KDL Listing >> lesson "What is STXT?" { authors { author "Joan Costa" author "James Smith" } teacher "Sheila Jones" difficulty "easy" introduction """ STXT is a **hierarchical text format**: easy for people to read and trivial for machines to parse. """ content """ A document is a tree of nodes. There are only two kinds: - `Name: value`, for short inline values. - `Name >>`, for a block of literal text, like this one. Indentation *is* the structure: no closing tags, no quotes and no escape characters. """ question "Do you know another similar format?" { answer "XML, for example" } content """ Comments are all the lines that start with `#`. Documents may have namespaces. You define them with `Name (namespace.name)`. """ conclusion """ With two kinds of node and indentation you can describe any document. A template adds **validation** on top, without changing the syntax. """ quiz { question "How is the structure of a document expressed?" { answer """ With indentation: a node is a child of the closest previous node with one level less. """ } question "What happens to the text inside a `>>` block?" { answer """ It is kept literally. Nothing inside is interpreted. It can be Markdown, code or any other text. """ } } } Content >> An excerpt of the schema, also written in KDL: Listing >> document { node "lesson" { min 1 max 1 value { type "string" } children { node "teacher" { min 1; max 1; value { type "string" } } node "difficulty" { max 1; value { enum "easy" "medium" "hard" } } node "content" { value { type "string" } } node "question" { value { type "string" } children { node "answer" { min 1; max 1; value { type "string" } } } } } } } Content >> KDL is the closest format to @STXT@ on this page: named nodes, ordered, repeatable and with children. The differences are in the syntax. As with YAML, it is harder to tell the different components apart visually. Values go between quotes, and in the prose `\` is an escape character. Subheader: This site Content >> Every page of `stxt.dev` is an @STXT@ document with its prose in Markdown. The source of any page can be seen by adding `.stxt` to its address, for example [stxt-vs-markdown.stxt](stxt-vs-markdown.stxt).