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.
  • Author appears 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: valueinline 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:

Authors:
	Author: María Pérez
	Author: Juan García
	Author: Ana López

And a sequence of different elements is written, simply, in order:

Book: Modern Software Architecture
	Chapter: Introduction
	Chapter: Communication between services
	Appendix: Glossary
	Chapter: Deployment

The 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-8

Three 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: (?) TEXT

It 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. Authors and ISBN, the same.
  • Author: (+) — one or more.
  • Publisher: (?) — zero or one.
  • Published: (?) DATE — optional and, if present, a YYYY-MM-DD date.
  • Summary: (?) TEXT — optional, and its value is text (inline or block).
  • Chapter: (+) with Content: (?) TEXT inside — 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: Introduction

A 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: TEXT

The 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: (?) TEXT

The 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

The language's style rules —recommendations, not rules— are in STXT-SPEC §4.4 and §9.2.