See annotations drive rendering
Trace AEON data and node templates into an annotation stream, then into generated HTML.
Start typing to search the site.
Processing Walkthrough
The language walkthroughs introduce the surface syntax. This page follows a small document through the processing stages that make AEON useful in real systems: source text, canonical form, assignment events, schema validation, meaning validation, and Tonic materialization.
The examples borrow the shape of the Hello World, Goodnight Moon, and Sayonara Sun demos: friendly messages, explicit datatypes, staged validation, and a runtime object that only appears after the consumer has accepted the document.
Step 1
The edited document is ordinary AEON. It declares strict mode, then gives the consumer a greeting configuration with a custom datatype label, a separator version, two messages, and the small numeric window used by the app.
aeon:header = {
mode:string = "strict"
}
moon:greeting = {
version:ver[.] = ^1.0.0
daytime:string = "Hello World"
nighttime:string = "Goodbye Moon"
hoursBeforeMidnight:number = 4
hoursAfterMidnight:number = 5
}
Visible claimsThe document says it wants strict mode and that moon is a greeting. It does not prove those claims by itself.
Typed valuesThe messages, version, and hour fields keep their intended value families visible before any runtime object exists.
Step 2
Canonical form is not a new meaning layer. It is the same document normalized for stable comparison, signing, hashing, cache keys, review diffs, and reproducible processing.
aeon:header = {
mode:string = "strict"
}
moon:greeting = {
daytime:string = "Hello World"
hoursAfterMidnight:number = 5
hoursBeforeMidnight:number = 4
nighttime:string = "Goodbye Moon"
version:ver[.] = ^1.0.0
}
The consumer can compare this stable representation without pretending that canonicalization has performed domain validation. It has only made the representation deterministic.
Step 3
AEON does not need to jump directly from text into a runtime model. The parser can expose a stream of assignments: each event has a path, value family, datatype claim, and source order.
event:object = {
order:number = 1
path:string = "$.moon"
nodeType:string = "ObjectNode"
datatype:string = "greeting"
}
event:object = {
order:number = 4
path:string = "$.moon.nighttime"
nodeType:string = "StringLiteral"
value:string = "Goodbye Moon"
}
event:object = {
order:number = 5
path:string = "$.moon.hoursBeforeMidnight"
nodeType:string = "IntegerLiteral"
value:number = 4
}
This is the point where tooling can inspect what was written without accepting the document as valid config yet.
Step 4
A schema checks that the required paths exist and that each path carries the expected literal family. The schema does not coerce values, repair types, or silently decide that a different shape is close enough.
aeos:schema = {
id:string = "example.greeting.v1"
version:string = "1"
rules:list<object> = [
{
path:string = "$.moon"
constraints:object = {
required:boolean = true
type:string = "ObjectNode"
datatype:string = "greeting"
}
}
{
path:string = "$.moon.version"
constraints:object = {
required:boolean = true
type:string = "SeparatorLiteral"
}
}
{
path:string = "$.moon.daytime"
constraints:object = {
required:boolean = true
type:string = "StringLiteral"
}
}
{
path:string = "$.moon.nighttime"
constraints:object = {
required:boolean = true
type:string = "StringLiteral"
}
}
{
path:string = "$.moon.hoursBeforeMidnight"
constraints:object = {
required:boolean = true
type:string = "IntegerLiteral"
}
}
]
}
schemaResult:validation = {
status:toggle = on
accepted:list<string> = [
"$.moon"
"$.moon.version"
"$.moon.daytime"
"$.moon.nighttime"
"$.moon.hoursBeforeMidnight"
"$.moon.hoursAfterMidnight"
]
}
Step 5
The schema can prove the shape. It cannot decide whether the greeting window makes sense for this application. That belongs to consumer policy, profile rules, or domain validators.
meaningRules:object = {
datatype:string = "greeting"
hoursBeforeMidnight:range = ^0..6
hoursAfterMidnight:range = ^0..6
daytime:required = yes
nighttime:required = yes
}
meaningResult:validation = {
status:toggle = on
checks:list<string> = [
"moon datatype is greeting"
"hoursBeforeMidnight is between 0 and 6"
"hoursAfterMidnight is between 0 and 6"
"daytime and nighttime messages are present"
]
}
A consumer can make those rules stricter in one context and looser in another without changing what AEON Core is responsible for.
Step 6
A Tonic is where the accepted document becomes something useful to an application. In the Moon example it can become a Greeting object. In the Sun example the same staged pattern becomes a Farewell object.
tonic:materialized = {
class:string = "Greeting"
sourcePath:string = "$.moon"
daytime:string = "Hello World"
nighttime:string = "Goodbye Moon"
activeWindow:string = "19:00-05:00"
messageAt22:string = "Goodbye Moon"
}
The runtime object is trusted because the consumer walked through the boundaries it cares about: compile errors, datatype checks, schema rules, meaning rules, and finalization errors.
Step 7
Once the pattern is routine, the repetitive checks can move into helper functions while the config loader still reads in phase order: load, require datatype, require schema, require ranges, require clean finalization, then construct the Tonic.
sun:farewell = {
version:ver[.] = ^1.1.0
daytime:string = "Hello, Sun"
farewell:string = "Sayonara, Sun"
sunsetHour:number = 18
cooldownHours:number = 3
}
loader:sequence = [
"loadAeonDocument"
"requireDatatype"
"requireSchema"
"requireUnsignedIntegerRange"
"requireNoFinalizeErrors"
"new Farewell"
]
The code becomes shorter, but the trust boundary stays visible. The helper layer reduces boilerplate without collapsing the phases.
Next
Trace AEON data and node templates into an annotation stream, then into generated HTML.
Edit data and template AEON side by side, then render the output in the browser.
Use the playground to try source documents, invalid forms, and stream output.