STXT Tutorial
This tutorial teaches how to read and write STXT documents from scratch, and ends with a document validated against its own template. No prior knowledge is required: a text editor is enough.
1. An STXT document in ten lines
An STXT document is a tree of named nodes. Every line is a node, and indentation says whose child it is:
Book:
Title: Modern Software Architecture
Authors:
Author: María Pérez
Author: Juan García
ISBN: 978-84-123456-7-8
Published: 2025-10-01
Summary >>
This book offers a practical view of patterns and best practices
for designing distributed, scalable systems.This example already shows almost the whole language:
Title: Modern…is an inline node: a name, a colon and a value on the same line.Authors:is an inline node with no value, which exists to group its children.Authorappears twice: a name may be repeated as many times as needed. That is how lists are written.Summary >>is a text block: everything indented below it is literal text, exactly as written.- There are no quotes, braces or closing tags. Indentation is the structure.
The rest of the tutorial develops each of these points. The full document this
example comes from is tutorial/book-raw.stxt in the
repository.
Reference: STXT-SPEC §1.
2. Before starting
A text editor is enough to follow the tutorial. Two options make the work easier:
- The playground, in the browser with nothing to install. Every example on this page has an Open in the playground button that loads it into the editor with validation on.
- Visual Studio Code with the official extension
stxt-lang.stxt
(
code --install-extension stxt-lang.stxt): highlighting, errors in the editor, completion from the template and go to definition.
The book example is reused in Working environment, which shows how to organize a project and validate it from the terminal; the full list of tools is in Tools.
3. Inline nodes and text blocks
Every node begins with its name, followed by a separator. The separator decides which of the two forms the node takes:
Name: value— inline node. The value is whatever follows the colon up to the end of the line; it may be empty. An inline node may have children: the lines indented below it.Name >>— text block. Nothing follows the>>; its content is the lines indented below, and it is literal text::,#and>>mean nothing inside, and there are no escape sequences.
Chapter: Introduction to architecture
Pages: 24
Content >>
This chapter presents basic concepts:
monoliths, microservices and design criteria.Chapter is inline with a value and two children; Pages is inline with a value
and no children; Content is a block. A block never has children: if a node needs
both structure and a long text, the text goes in a block child, like Content
inside Chapter. That combination —an inline node grouping short values and
blocks— is the usual shape of an STXT document.
A value may contain any character, colons included: in Path: C:\Users\ana, the
value is C:\Users\ana. The first : on the line is the separator; the rest is
value.
Reference: STXT-SPEC §4 (the node), §5 (inline nodes) and §6 (text blocks).
4. Indentation is the structure
The level of a line —how many indentation units it carries— is the only thing that decides which node it belongs to. There is no other hierarchy marker.
There are four rules:
- One tab is one level.
- Four spaces are one level. Always multiples of four: two spaces are not half a level, they are an error.
- They are not mixed on the same line. Either only tabs, or only spaces.
- Levels are consecutive. From level 1 there is no jump to 3.
In this example, . stands for a space and |--> for a tab:
Book:
|-->Title: correct, one tab = level 1
....ISBN: correct, four spaces = level 1
..Publisher: ERROR, two spaces are not a level
.|-->Summary: ERROR, space and tab on the same line
Different lines of the same document may use different styles, because what is
compared is the level, not the column. It is not an error, but for readability it is
better to pick one style and keep it; stxt format --tabs or --spaces unify it.
These rules are deliberately strict. A line mixing tabs and spaces looks different
depending on each editor's tab width, and the hierarchy would no longer be evident
when reading; and a fixed level width makes it possible to compute the level of a
line by looking at that line alone. The errors have their own codes:
INDENTATION_MIXED, INDENTATION_SPACES_NOT_VALID and
INDENTATION_LEVEL_NOT_VALID.
Reference: STXT-SPEC §8 (indentation and hierarchy) and §8.3 (level errors).
5. Inside a text block
A block has a block level: that of the >> node plus one. That indentation
prefix is the only thing the parser removes; everything after it is text, and any
additional indentation is part of the text:
Summary >>
This line is at the block level.
This one is indented further, and that indentation is part of the text.
# This is not a comment: it is text.
Title: this is not a node either.The block ends at the first non-empty line whose indentation is less than or equal
to that of the >> node, whether a node or a comment. Empty lines do not close it:
those that precede more text are part of the block as empty lines, whether written
with nothing or with the block's indentation; those left at the end are discarded
when the block closes, because they are visual separation of the document, not
content.
That is why a block serves for any content —a paragraph, a code fragment, a piece of Markdown, text in another format— without transforming or escaping anything.
Reference: STXT-SPEC §6.1 (block rules) and §10.2 (lines inside blocks).
6. Lists: everything is a list
STXT has no list syntax because it does not need one: the children of a node are an ordered sequence, and the same name may be repeated. A list of elements of the same kind is a container node with the same child repeated:
And a sequence of different elements is written, simply, in order:
Book: Modern Software Architecture
Chapter: Introduction
Chapter: Communication between services
Appendix: Glossary
Chapter: DeploymentThe tree preserves the order of appearance, so an application can give meaning to position if it needs to. When the document is validated later, the template will say how many times each child may appear; until then, any number is fine.
Reference: STXT-SPEC §8.5 and the FAQ.
7. Node names
A name admits letters, digits and combining marks from any script —Latin, Greek,
Cyrillic, Arabic, Devanagari, CJK…—, plus the separators -, _ and space. It
admits no other symbol: no :, no parentheses, no #. It must contain at least
one letter or digit.
To decide whether two nodes are the same, STXT compares their canonical name,
obtained by lowercasing the name, reducing each run of separators to a single -
and removing hyphens at both ends. Accents and script are kept:
Un nombré con äcento: un-nombré-con-äcento
UN NOMBRÉ CON ÄCENTO: un-nombré-con-äcento
TAMaÑo número 2__ y 3: tamaño-número-2-y-3
Пример 1: пример-1
Nombre 日本語: nombre-日本語Title, title and TITLE- are the same node.Peña and Pena are different nodes, as they are different words.
It is the same criterion applied by internationalized domain names: a document can be written in any language without the language altering the words or merging two names that are different to the reader. The only exception is namespaces, covered in section 9: those are limited to ASCII.
Reference: STXT-SPEC §4.2 (allowed characters) and §4.3 (canonical name).
8. Comments
A line whose first character, after indentation, is # is a comment. The parser
discards it: it is part of neither the tree nor the data.
# A book record
Book:
# The title comes first
Title: Modern Software Architecture
ISBN: 978-84-123456-7-8Three things worth knowing:
- Comments are whole-line. There are no end-of-line comments: in
Title: My book # note, the#and what follows are part of the value. - The indentation of a comment is validated like a node's (homogeneous style and, at most, one level deeper than the last node), although it does not move the hierarchy. The natural thing is to align it with the node it describes.
- Inside a
>>block there are no comments: a#there is text. A comment at the level of the>>node or less closes the block.
Reference: STXT-SPEC §9 and §9.1.
9. Namespaces
So far, the book document is only syntax: a tree of names and texts that any parser reads, but whose meaning nobody knows. A namespace gives it identity: it says which vocabulary its nodes belong to, and it is what makes validation possible later on.
The namespace is written in parentheses after the node name:
Book (com.acme.book):
Title: Modern Software Architecture
Authors:
Author: María Pérez
Author: Juan García
ISBN: 978-84-123456-7-8
Publisher: ACME Editorial
Published: 2025-10-01
Summary >>
This book offers a practical view of patterns and best practices
for designing distributed, scalable systems.
Chapter: Introduction to architecture
Content >>
This chapter presents basic concepts:
monoliths, microservices and design criteria.
Chapter: Communication between services
Content >>
Protocols, messaging and integration patterns are described.It is the same document as in section 1 (tutorial/book-ns.stxt), with a single
difference: Book declares the namespace com.acme.book. And that is enough,
because the namespace is inherited: Title, Authors, Author, Chapter,
Content… every descendant of Book belongs to com.acme.book without writing it.
A child may declare another namespace, and then its own descendants inherit the new
one.
The form rules are few: only ASCII [a-z0-9] and dots, at least two parts (a.b),
and uppercase is lowercased (COM.ACME.BOOK is the same). The convention is to use
a reversed domain of one's own, as in Java, so that two organizations do not
collide.
Namespaces starting with @ are special: the @stxt.* branch is reserved for the
language itself, and two of them appear in the next section, @stxt.template and
@stxt.schema. A namespace of one's own never starts with @.
The base language validates nothing with the namespace: it only defines how it is written and how it is inherited. A document with a namespace for which there is no definition is a valid document that simply cannot be validated.
Reference: STXT-SPEC §7 (namespaces), §7.1 (ASCII restriction) and §7.2 (inheritance).
10. Validating with a template
A template describes what shape the documents of a namespace must have: which
nodes exist, how many times each one appears and what type their values are. It is
just another STXT document, with namespace @stxt.template, and its
Structure >> block has the same shape as the documents it describes:
Template (@stxt.template): com.acme.book
Description >>
Book: Template for publisher book records
Structure >>
Book:
Title: (1)
Authors: (1)
Author: (+)
ISBN: (1)
Publisher: (?)
Published: (?) DATE
Summary: (?) TEXT
Chapter: (+)
Content: (?) TEXTIt reads almost like the book document. What is in parentheses is the cardinality —how many times that node may appear inside its parent— and what follows, if anything, is the type of the value:
Title: (1)— exactly one.AuthorsandISBN, the same.Author: (+)— one or more.Publisher: (?)— zero or one.Published: (?) DATE— optional and, if present, aYYYY-MM-DDdate.Summary: (?) TEXT— optional, and its value is text (inline or block).Chapter: (+)withContent: (?) TEXTinside — at least one chapter, each with its optional text.
What the template does not say also matters: Book admits no child that is not
on this list. That is the closed content model: a Pages node inside Book is
not extra data to be ignored, it is an error.
10.1 Cardinalities
| Form | Meaning |
|---|---|
(1) |
Exactly one. |
(?) |
Zero or one. |
(*) |
Any number. |
(+) |
One or more. |
(n) |
Exactly n. |
(n+) |
n or more. |
(n-) |
Up to n. |
(min,max) |
Between min and max. |
10.2 Types
The type follows the cardinality; if none is given, it is INLINE. The most common:
| Type | Value form | What it validates |
|---|---|---|
INLINE |
inline | Plain text. Admits children. The default type. |
GROUP |
no value | Structure only: the node groups, it carries no value. |
TEXT |
inline or >> |
Text, uninterpreted. |
MARKDOWN |
inline or >> |
Text that consumers must treat as Markdown. |
NUMBER |
inline | A number. |
DATE |
inline | YYYY-MM-DD date, calendar-checked. |
ENUM |
inline | One of the values of a list: ENUM [a, b, c]. |
Only INLINE and GROUP admit children. As soon as a type validates a concrete
datum —a number, a date, a text—, that node is a datum, and a datum is a leaf.
Reference: STXT-TEMPLATE-SPEC §6 (the Structure block),
§7 (cardinalities), §8 (types) and
§9 (ENUM); the full list of types, in
STXT-SCHEMA-SPEC §9.
11. What validation detects
With the template above, the document of section 9 validates: it has everything
mandatory, nothing undeclared, and Published is a date. This other one does not:
# ERROR: Pages is not declared, Published is not a date and ISBN is missing
Book (com.acme.book):
Title: Modern Software Architecture
Authors:
Author: María Pérez
Pages: 320
Published: 2025-13-01
Chapter: IntroductionA validator reports three things, each with its code and line: Pages is not
declared in Book (CHILD_NOT_DECLARED), 2025-13-01 is not a valid date
(INVALID_VALUE) and ISBN, which was mandatory, is missing (TOO_FEW_CHILDREN).
The codes are the same in every tool; the message text is not.
This is the difference between a well-formed document and a valid one: any parser reads the first; the second, in addition, honours the contract of its namespace.
Reference: STXT-SCHEMA-SPEC §6 (closed model) and §13 (validation errors).
12. The same with a schema
A schema (@stxt.schema) describes exactly the same as a template, but node by
node and explicitly: each Node with its type and the list of its Child entries
with Min/Max cardinalities. It is the canonical form; every template compiles to
an equivalent schema, and validating with either gives the same result.
Schema (@stxt.schema): com.acme.book
Node: Book
Type: GROUP
Children:
Child: Title
Min: 1
Max: 1
Child: Authors
Min: 1
Max: 1
Child: ISBN
Min: 1
Max: 1
Child: Publisher
Max: 1
Child: Published
Max: 1
Child: Summary
Max: 1
Child: Chapter
Min: 1
Node: Authors
Children:
Child: Author
Min: 1
Node: Chapter
Children:
Child: Content
Max: 1
Node: Title
Node: Author
Node: ISBN
Node: Publisher
Node: Published
Type: DATE
Node: Summary
Type: TEXT
Node: Content
Type: TEXTThe template is shorter and resembles the document; the schema is longer and more explicit, and is the natural place for per-node descriptions. For a namespace there can be only one active definition, template or schema; when there are several at different levels, the one closest to the document wins.
Reference: STXT-SCHEMA-SPEC §7 (Node),
§8 (Children) and §10 (cardinalities);
the equivalence with the template, in STXT-TEMPLATE-SPEC §13;
which definition wins when there are several, in
STXT-DISCOVERY-SPEC §5.
13. The final document
A complete document that validates with both the template and the schema:
Book (com.acme.book):
Title: Modern Software Architecture
Authors:
Author: María Pérez
Author: Juan García
ISBN: 978-84-123456-7-8
Published: 2025-10-01
Summary: A practical introduction to the architecture of modern systems.
Chapter: Introduction
Content >>
Basic concepts and goals of the book.Summary is inline here and was a block in section 9: TEXT admits both forms, and
the value is the same text. Publisher does not appear, and need not: it was (?).
How it is done in a real project —the template in a .stxt/ directory, the
document next to it and stxt validate from the terminal, or the errors in the
editor— is shown in Working environment.
14. Several namespaces in one document
Nothing forces the whole document to belong to a single namespace. Any node may
declare its own in parentheses, just as Book did, and its descendants inherit
the new one from it onwards. Each namespace is validated against its own
definition, so a vocabulary is defined once and incorporated from others:
reviews, for instance, which tomorrow could accompany any other product just as
well.
In the template that incorporates the foreign vocabulary, the external node is declared with its namespace and, at most, its cardinality: its shape is not described there, but in the template of its own namespace. The complete set —the document and the two templates— fits in a single file:
Book (com.acme.book):
Title: Modern Software Architecture
Authors:
Author: María Pérez
Author: Juan García
ISBN: 978-84-123456-7-8
Published: 2025-10-01
Review (com.acme.reviews):
Reviewer: Ana López
Score: 9
Comment >>
A clear, well-structured guide, with examples
that are easy to follow.
Review (com.acme.reviews):
Reviewer: Luis Martín
Score: 8
Template (@stxt.template): com.acme.book
Structure >>
Book:
Title: (1)
Authors: (1)
Author: (+)
ISBN: (1)
Published: (?) DATE
Review (com.acme.reviews): (*)
Template (@stxt.template): com.acme.reviews
Structure >>
Review:
Reviewer: (1)
Score: (1) NUMBER
Comment: (?) TEXTThe book template —reduced here— adds a single new line,
Review (com.acme.reviews): (*): a book admits any number of reviews, and what
a review is, the template of com.acme.reviews says. In the document, every
Review declares its namespace, and Reviewer, Score and Comment inherit
it without writing it: the reviews are validated against their template, and
the rest of the book against its own.
An STXT document may have several root nodes, and this one has three: the book and the two templates. They travel together on purpose: Open in the playground loads the whole block, and the two templates validate the document that accompanies them.
Reference: STXT-SPEC §7.2 (namespace inheritance),
§8.5 (several root nodes),
STXT-TEMPLATE-SPEC §10 (namespaces inside Structure)
and STXT-SCHEMA-SPEC §8 (children from another
namespace).
15. Where to go next
- Working environment: organizing a project, installing templates, validating from the terminal and in continuous integration.
- Design principles: why the language is the way it is.
- FAQ: short answers with a link to the rule.
- The specifications: STXT-SPEC for the syntax, STXT-SCHEMA-SPEC and STXT-TEMPLATE-SPEC for validation, STXT-DISCOVERY-SPEC for where definitions are looked up and STXT-TREE-SPEC for the JSON tree the tools produce.
The language's style rules —recommendations, not rules— are in STXT-SPEC §4.4 and §9.2.