Document (dev.stxt.website): Frequently asked questions | STXT Metadata: Last modif: 2026-09-16 Description: Frequently asked questions about STXT: what the name means, how it differs from XML, YAML, TOML, JSON and Markdown, how validation works and how to get started. Header: Frequently asked questions Subheader: The language Subsubheader: What does the name STXT mean? Content >> The first version of the language was called **STxT** (*Semantic Text*); that is where the name and the "S-text" pronunciation come from. @STXT@ is its evolution: it keeps the spirit, the motivation and the base syntax, but has changed significantly since then. References to *STxT* that may still be found refer to the old language. The term *Semantic Text* has also been retired. The current name is @STXT@. Subsubheader: How is STXT pronounced? Content >> "ESS-text": first the letter `S`, then `text`, like *S-text*. Subsubheader: Is it a language or a format? Content >> Both. @STXT@ defines itself as a **language**: a grammar meant to be written by hand, normative specifications, schemas and tools. It also **acts as a format**, since systems can use it to store or display information. The two words do not exclude each other; XML is _Extensible Markup Language_ and also _a file in XML format_. Subsubheader: Is it a data format or a document format? Content >> Both. An email has fields and a body; a contract, clauses and metadata; a configuration, values and long comments. @STXT@ is a tree of named nodes, and each node carries a value, children or a block of text. This describes both a document and a data format. Subsubheader: What sets it apart from other formats? Content >> @STXT@ is designed for people, and the characteristics that define it follow from that principle: * **Few rules.** * A node is `Name: value` or `Name >>` * The hierarchy is the indentation * No braces, brackets, quotes, closing tags or list syntax * **No escape characters.** * **Linear parsing.** Line by line, in a single pass, with no backtracking or references. * **Parsing safety by design.** No entities, references, anchors, file inclusion or code execution; ASCII namespaces, no ambiguous identifiers. * **Namespaces and validation in the language.** A document declares which namespace it belongs to. A schema layer can also be added, which validates it against its definition. Subsubheader: Which file extension and media type are used? Content >> Extension `.stxt`; media type `text/stxt` (IANA registration planned, not yet registered), with `text/plain` as a compatible alternative. UTF-8 encoding without BOM (a parser also accepts the BOM), `LF` line endings (`CRLF` is accepted). Subsubheader: Can you show us a real use? Content >> This site. Every page of `stxt.dev` is written in @STXT@. The [generator](https://github.com/stxt-lang/stxt-cms) turns them into HTML. The `.stxt` link in the header opens the source of the current page. `.stxt` can also be appended to the address of any page to see its source code; for example [faq.stxt](faq.stxt). Subheader: Why not...? Subsubheader: Why not XML, YAML or TOML? Content >> | | @STXT@ | XML | YAML | TOML | |---|---|---|---|---| | **Hierarchy** | Indentation, one tab or four spaces per level; a single spelling | Opening and closing tags | Indentation of free width; block and flow syntax for the same structure | `[a.b]` headers with the full path; also dotted keys and inline tables | | **Values** | Always text; the type is declared by the definition | Text; the type is declared by the schema | The spelling decides the type (`no`, `3.10`), with different rules in 1.1 and 1.2 | The spelling decides the type; strings always in quotes | | **Free text** | Literal `>>` blocks: any character, no escapes | Escape `<` and `&`, or CDATA | Block scalars, literal or folded, with chomping indicators | Multi-line strings between triple quotes; the indentation goes into the value | | **Namespaces** | In the language | In the language | No | No | | **Schemas** | In the language, optional, closed content model | DTD, XSD, RELAX NG, Schematron | No; external tools | No; external tools | | **Parsing** | Linear, line by line, in a single pass | Entities, internal DTD and namespaces the parser resolves | Extensive grammar; two versions with different type resolution | Small grammar; dates, times and inline tables as native types | | **Attack surface** | No entities, references, anchors or code execution | External entities (XXE), entity expansion | Expandable anchors; tags that instantiate objects | No entities or references | The full comparison with each format can be seen on the following pages: * [STXT vs XML](stxt-vs-xml) * [STXT vs YAML](stxt-vs-yaml) * [STXT vs TOML](stxt-vs-toml) Subsubheader: Why not Markdown? Content >> Markdown gives **format** to text (bold, links, lists), while @STXT@ gives **structure** to the document: nodes, hierarchy and validation. @STXT@ uses Markdown as one of the allowed text types, which yields structured documents, with validation and with Markdown semantics for the text blocks: Code >> Article (example.article): Style guide Introduction >> An **STXT** document allows multiple ways of displaying the content. Here we explain the recommended ones. Summary >> A MARKDOWN block admits **bold**, [links](https://stxt.dev) or lists; the structure of the document comes from the nodes around it. Template (@stxt.template): example.article Structure >> Article: Introduction: (?) MARKDOWN Summary: (?) MARKDOWN Subsubheader: Why not JSON? Content >> Because JSON is a serialization format and is not meant to be written by hand. Everything goes between quotes, braces and commas; line breaks are written `\n`; there are no comments, and a long text is a single line with escapes. The main goal of @STXT@ is the writing of documents by people, who can read and modify them without other tools. Subsubheader: Why are there no lists? Content >> Because everything is a list. The children of a node are an ordered sequence, and the same name may be repeated as many times as needed. Moreover, the tree preserves the order of appearance. An @STXT@ document is already a list of root nodes, and every inline node is a list of children. That is why no separate syntax is needed to express one. Example: Code >> Authors: Author: María Pérez Author: Juan García Author: Ana López Subsubheader: Why are there no escape characters? Content >> Because they are not needed. @STXT@ syntax only validates the node name and that a separator exists (`:` or `>>`). Everything that follows is a value or literal text. A value may contain `:`, a block may contain `#` or `>>`, and a backslash is a backslash. Code >> Path: C:\Users\ana\docs Note >> The symbols :, #, >>, \n mean nothing here. Subsubheader: Why are other characters not allowed in names? Content >> Technically it was possible to exclude only the characters that delimit the syntax (`:`, `>` and the parentheses), but following the Human-First principle they are limited to letters, digits and the separators `-`, `_` and space. This way no meaning that does not exist in @STXT@ is suggested. Subsubheader: Why can a text block not have children? Content >> By design: * **Visual noise.** To know where the text ends and the children begin, an end-of-block marker would be needed, and a document would no longer read like an outline of notes. * **More complexity in the parser.** * **Mixed meaning.** A node that needs both children and a text block is describing two different things, and that points to two nodes. That is why a node is either inline or block, and not both at once. When needed, it has to be split explicitly into two nodes. Code >> Chapter: Introduction Author: María Pérez Summary >> Basic concepts: monoliths, microservices and design criteria. Content >> The chapter presents... Subheader: Writing documents Subsubheader: Tabs or spaces? Content >> Both are valid and equivalent: * **One tab is one level and four spaces are one level.** * Mixing them in the indentation of a single line is not valid. * A document may use different styles for different lines, although it is not recommended. Subsubheader: Why a fixed width? Content >> The fixed width is deliberate: the level of a line is computed from its indentation, independently of the other lines. This derives from the KISS principle, with parsers that are simpler to implement and documents that are simpler to write. Subsubheader: Do case, accents and spaces matter in names? Content >> Names are compared case-insensitively, but keeping the accents. Spaces are compared by reducing them to a hyphen (and leading and trailing ones are removed). So: * `Date of birth`, `date_of_birth` and `Date-Of-Birth` are the same node. * `Título` and `título` are the same node; `Titulo` is another one. * `Caña` and `cana`, or `Peña` and `pena`, are different nodes. **Namespaces** are stricter: ASCII `[a-z0-9]` and dots only, and at least `a.b`. They are also lower-cased during parsing. Subsubheader: How is a value with a colon or a hash inside written? Content >> Without any marker. In an inline node the value is everything after the **first** `:`, so `Time: 10:30` has the value `10:30`, and `#` only opens a comment when it is the first non-blank character of the line. Inside a `>>` block everything is literal text. Code >> Meeting: 10:30 in room 2 # this is part of the value Notes >> # this is text too, not a comment Key: value >> not a node either Subsubheader: Can a document have several root nodes? Content >> Yes. A file may contain several level-0 nodes, each with its own tree. That allows *streaming* parsing of large files. Moreover, namespaces are not inherited sideways between roots, since each declares its own. Subsubheader: Can a document use several namespaces? Content >> Yes. Any node may declare its own namespace, and its descendants inherit it directly from it. Moreover, each namespace has its own independent validation. Example: Code >> Book (com.acme.book): Title: Modern Software Architecture Review (com.acme.reviews): Reviewer: Ana López Score: 9 Content >> And the templates of the two namespaces: Code >> Template (@stxt.template): com.acme.book Structure >> Book: Title: (1) Review (com.acme.reviews): (*) Template (@stxt.template): com.acme.reviews Structure >> Review: Reviewer: (1) Score: (1) NUMBER Content >> `Reviewer` and `Score` belong to `com.acme.reviews`, and each namespace is validated against its own template. Subsubheader: Are comments indented? Content >> A comment is indented like a node. This is not strictly necessary, but it keeps it within the homogeneous style of @STXT@ (Human-First principle). Subheader: Schemas and templates Subsubheader: Are schemas mandatory? Content >> No. A document without a namespace can be parsed without problem, and one with a namespace contains more information than one without. If it has a namespace, it is the parsing tool that decides whether or not to validate the document with the schema. Subsubheader: Schema or template? Content >> They are two different syntaxes for the same model, and **every template is equivalent to a schema**. The template (`@stxt.template`) is written much like the document it describes, so it is the most direct way to create a definition. Even so, a template has implicit decisions that must be taken into account. A schema, on the other hand, is more explicit, but less compact than a template. Subsubheader: How does a tool find schemas and templates? Content >> It depends on the tool, because definition resolution is not part of the base language: it is one more optional layer, like schemas and templates themselves. An application without a file system resolves it its own way (the playground, for instance, associates documents and grammars by namespace within the workspace). For when files and projects are involved, [STXT-DISCOVERY-SPEC](stxt-discovery-ref) defines a common resolution, which a tool may or may not implement. Today, the CLI, the VS Code extension and the three libraries implement STXT-DISCOVERY-SPEC. Subsubheader: Where are schemas and templates placed? Content >> In the tools that follow [STXT-DISCOVERY-SPEC](stxt-discovery-ref), in a directory called **`.stxt/`** in the project: every `.stxt` file inside it is loaded, recursively, regardless of file names and subdirectories. The resolution chain of a document is every `.stxt/` of its ancestor directories, then `~/.stxt`, and finally `/etc/stxt` (on Windows, `%USERPROFILE%\.stxt` and `%ProgramData%\stxt`). The closest level wins, namespace by namespace. The `STXT_PATH` variable replaces the whole chain with a list of directories, for instance in CI. Subsubheader: What if Titel is written instead of Title? Content >> With validation enabled, it is rejected, since the content model is **closed**. A node only admits the children defined, and if it has no children defined, it admits none. Subsubheader: Is the order of children validated? Content >> No. Cardinality is validated, but not position. Two documents with the same children in a different order validate the same way. Moreover, the order is preserved in the tree, so the meaning depends on the application that consumes it and not on the validator. Subsubheader: How is a schema evolved without breaking documents? Content >> By extending the definition without invalidating what is already written: every document that validated keeps validating if the change only allows more cases. No new version is needed to: * Add an **optional** node: with cardinality `(?)`, `(*)` or any other with a minimum of zero. * Relax a cardinality: lower a minimum or raise a maximum, such as going from `(2,5)` to `(1,5)` or to `(2,6)`. One nuance: compatibility is relative to the extended definition. A document that uses the addition does not validate against an earlier copy, so if the consumers of the namespace do not update the definition at the same time, extensions are worth versioning too. Adding a mandatory node, removing one or narrowing a cardinality always breaks compatibility. For those changes the recommended practice is to **version the namespace**, for example `com.example.docs.v1` → `com.example.docs.v2`. Subheader: Tools Subsubheader: How is validation run in CI? Content >> With Node.js installed, it can be done from the command line, with nothing else to add: Listing >> npx @stxt-lang/cli validate --recursive docs/ npx @stxt-lang/cli format --check --recursive docs/ Subsubheader: Is there a canonical representation of an STXT document? Content >> Yes. Every valid document has a **canonical tree** in JSON, defined in [STXT-TREE-SPEC](stxt-tree-ref): an array of roots with `name`, `canonicalName`, `namespace` and `value`, plus `children` (inline) or `lines` (block). It includes no positions and no comments: it is the logical content of the document. Subsubheader: Which languages have a parser? Content >> The `stxt-lang` organization maintains three: TypeScript/JavaScript (`@stxt-lang/core`), Java (`dev.stxt:stxt-core`) and Python (`stxt`). Subsubheader: What stability can be expected? Content >> Stability is explained in [Stability and versions](stability). The specifications carry no version number: each one carries a **date** (that of its current text) and a **status**, which only moves forward and defines the degree of stability: * *Genesis*: under construction, unstable. * *Aurora*: usable; few incompatible changes expected. * *Zenith*: no incompatible changes, and things are only added. * *Twilight*: closed/obsolete. Subsubheader: Where do I ask, or give feedback? Content >> In the [discussions](https://github.com/orgs/stxt-lang/discussions) of the `stxt-lang` organization on GitHub: questions, ideas, ambiguities in the specifications and anything you have built with STXT. Bugs in a specific tool should be reported in its repository.