Configuration files
A configuration is a document read by two audiences: the person who adjusts it and the program that loads it. STXT serves both with the same file, and with a template it catches in the editor the error that would otherwise show up in production.
Configuration files start small and grow without a plan: keys are added, blocks are copied between environments, comments accumulate explaining why a value is what it is. Over time, the rules that make the file valid —which keys exist, which values they admit, which ones are mandatory— live only in the head of whoever maintains it and in the code that reads it. A misspelled name does not fail on load: it is simply ignored, and the default value comes in silently.
STXT addresses this with three things: a visible hierarchy, which needs neither braces nor ambiguous indentation; text blocks where the long explanation lives next to the value it explains; and a template that turns the implicit rules into a contract the editor applies while typing.
A service's configuration
Server Config (com.acme.server):
Name: api-gateway
Environment: production
Network:
Host: 0.0.0.0
Port: 8080
Public url: https://api.acme.com
Threads:
Min: 8
Max: 64
Timeouts:
Read ms: 5000
Write ms: 5000
Logging:
Level: INFO
Format: json
Features:
Feature: experimental-cache
Enabled: false
Feature: audit-logging
Enabled: true
Notes >>
Main configuration of the API gateway. Versioned with the application and
deployed with it.
Changes to Network and Timeouts go through Reliability review: the 5000 ms
limit comes from the SLA with the payments provider.Each group (Network, Threads, Logging) is a node without a value that groups
its children; each setting is a node with a value; each feature flag is a node whose
value is its name and whose child is its state. The Notes >> block carries what in
other formats goes in scattered comments: here it is part of the document, with
paragraphs, and a program can display it or ignore it.
The template
The template makes explicit what the program loading the configuration takes for granted:
Template (@stxt.template): com.acme.server
Description >>
Server Config: Configuration of a gateway service
Features: Feature switches, one per node
Structure >>
Server Config:
Name: (1)
Environment: (1) ENUM [dev, staging, production]
Network: (1)
Host: (1)
Port: (1) NATURAL
Public url: (?) URL
Threads: (?)
Min: (1) NATURAL
Max: (1) NATURAL
Timeouts: (?)
Read ms: (?) NATURAL
Write ms: (?) NATURAL
Logging: (?)
Level: (1) ENUM [DEBUG, INFO, WARN, ERROR]
Format: (?) ENUM [text, json]
Features: (?)
Feature: (*)
Enabled: (1) BOOLEAN
Notes: (?) TEXTWith it, the typical configuration errors stop being silent (closed content model):
Ports: 8080(with an extras) isCHILD_NOT_DECLARED, not an ignored key that leaves the service listening on the default port.Port: 80aorEnabled: yesareINVALID_VALUE: a natural is a natural and a boolean istrueorfalse.Level: infoin lowercase is notINFO: theENUMcompares the value as written.Networkis missing, orHostinsideNetwork:TOO_FEW_CHILDREN.
And all of that is visible in the editor, underlined, before the file is saved. In
continuous integration, stxt validate config/ performs the same check and stops
the deployment of an invalid configuration (The command line).
Several environments, one structure
When the same application is configured for several environments, the temptation is to copy the file and change values. With STXT a single document can be kept with one node per environment, and the template guarantees that all of them declare the same things:
Application Config (com.acme.app):
App name: Billing
Environments:
Environment: dev
Database:
Url: jdbc:postgresql://localhost/dev
Max connections: 5
Debug: true
Environment: staging
Database:
Url: jdbc:postgresql://staging/db
Max connections: 10
Debug: false
Environment: production
Database:
Url: jdbc:postgresql://prod/db
Max connections: 30
Debug: falseTemplate (@stxt.template): com.acme.app
Description >>
Application Config: Configuration of an application across all its environments
Structure >>
Application Config:
App name: (1)
Environments: (1)
Environment: (+)
Database: (1)
Url: (1)
Max connections: (1) NATURAL
Debug: (1) BOOLEANThe difference between staging and production is a three-line diff, and an
environment missing Database does not validate. If the application prefers one
file per environment, the same document is split in three with the same namespace
and the same template; the guarantee does not change.
How the program reads it
The program that loads the configuration does not parse text: it receives a tree.
With the library of its language it walks the nodes by canonical name —port,
max-connections— and obtains values already validated against the template, so
the loading code does not need to check types or allowed values: that has already
happened. The TypeScript, Java and
Python guides show the traversal; template resolution follows the
chain of .stxt/ directories of STXT-DISCOVERY-SPEC, the same
as in the editor, so validator and program apply the same definition.
Limits
STXT describes the configuration; it does not compute it. There are no variables, no references to other values, no file inclusion, no expressions: a value is the text that is written. It is a design decision (Design principles), in exchange for a configuration file never being able to execute anything or depend on another. Composition —a base file plus one per environment— is done by the application on load, explicitly.
Nor are there default values in the template: a field is mandatory or optional, and if it is optional and missing, the program decides what it is worth.
How this use compares with the formats most often chosen for configuration is developed in STXT vs YAML and STXT vs JSON; the tutorial covers the language itself.