CX · Reference guide50 Ways to Love Your CX Data
PlaygroundDownloadsAboutv0.18.0-pre.1

50 Ways to Love Your CX Data

Fifty examples that walk through CX data — bare attributes through anchors and merge, with stops at quoted strings, multi-line text, comments, collection literals, typed columns, and a final whole-shop document. Each step adds one shape; no shape requires anything the earlier ones do not already give you. The companion §15 covers directives.

1. The atom

Just name=value. In CX this is a valid document on its own — logfmt mode, intended for log lines and structured events.

      size=large
    

2. Several atoms — a one-line event

A whole log line — no brackets, no root, just attributes.

      time=2026-05-09T12:00:00Z level=INFO svc=oven pizza=Margherita
    

3. Empty element

Brackets give a name. Empty, but a thing.

      [pizza]
    

4. Element with one property

The atom from example 1, now attached to a pizza.

      [pizza size=large]
    

5. Several properties

Keep adding. No commas required between attrs.

      [pizza size=large crust=thin price=12]
    

6. Bare flag (no equals-value)

Presence means yes, absence means no — same idea as --verbose or HTML's required. Here, this pizza is controversial.

      [pizza name=Hawaiian controversial]
    

7. Explicit boolean values

When you want both polarities, write the word.

      [pizza vegan=true gluten-free=false]
    

8. Booleans are ordinary attributes

Booleans are ordinary attributes — name=true / name=false; the bare tokens auto-type as bool.

      [pizza vegan=true nuts=false gluten=false]
    

9. Numbers — int, decimal, negative, hex, underscores

All bare, all auto-typed. Underscores in numbers are readability sugar.

      [pizza price=12.50 discount=-2 ovens=4 mask=0xFF00FF batch=1_000_000]
    

10. Quoted — single quotes

Reads: attribute name, value is the string "BBQ Chicken".

      [pizza name='BBQ Chicken']
    

11. Quoted — double quotes

Pick the quote that does not appear in the value.

      [pizza name="Quattro Formaggi"]
    

12. Mix when the value has an apostrophe

Double-quote around an apostrophe; no escaping needed.

      [pizza name="Tony's Special"]
    

13. The empty string

Distinct from missing: the attribute is there, just empty.

      [pizza name=Mystery description=""]
    

14. Escape sequences inside quotes

Same family as C and JSON: \\n, \\r, \\t, \\uXXXX, \\", \\\\.

      [pizza alert='Hot!\\nHandle with care.\\tCafé']
    

15. Entity references (XML-style)

&amp;, &lt;, &gt; are recognized in body text — they round-trip faithfully, and an --xml emit renders them as proper XML entities. In attribute values they are not decoded: the characters stay literal (and --xml escapes the ampersand a second time). For a literal & or < in an attribute, just write the character inside quotes.

      [note Cheese &amp; Pepper]
    

16. Null

A real null value, distinct from empty string or the word "null" as a string.

      [pizza discount=null reviewed=null]
    

17. Date and datetime literals

ISO 8601 shapes are auto-typed as date or datetime.

      [promo starts=2026-05-01 ends=2026-05-31 cutoff=2026-05-31T23:59:00Z]
    

18. Plain text body

After the name, the rest of the bracket is text.

      [motto Hand-tossed since 1987]
    

19. Attributes plus text body

Reads: element pizza, attribute name=Margherita, then text body "Classic since day one.".

      [pizza name=Margherita Classic since day one.]
    

20. Multi-line text — preserved as written

Whitespace and newlines inside a text body are kept literally.

      [description
           Stone-baked, hand-stretched,
           and ready in 90 seconds.]
    

21. Triple-quoted string

Three quotes open and close. Single and double quotes inside need no escaping. Common leading whitespace is stripped.

      [bio '''
           Born in Naples, 1955.
           Started New Haven in 1987.
           Still on the line every Friday.
         ''']
    

22. Block content [| … |]

Like a text body, but indentation and newlines are kept verbatim; the block closes with |]. Unlike triple-quoted, inner elements such as [em best] are still real markup.

      [poem [|
           Roses are red,
             violets are blue,
           the [em best] pizza
             is waiting for you.
         |]]
    

23. Raw text [# … #]

The CDATA of CX. Brackets, quotes, <, > — all literal characters. The terminator is #].

      [snippet [# if (x < 10) { return "[pizza]"; } #]]
    

24. Embedded code in another language

Raw text is how you embed SQL, JS, or regex without escaping every quote.

      [query language=sql [#
           SELECT name, price FROM pizza
           WHERE price < 15 AND vegan = true;
         #]]
    

25. Line comment

# comments out the rest of the line. Lives outside elements, like a script header.

      # weekend special — pulled Monday
         [pizza name=TruffleSpecial price=24]
    

26. Inline block comment

Element-shaped — fits inside brackets where # cannot reach.

      [pizza name=Diavola [; TODO confirm price ] price=14]
    

27. Multi-line block comment

Canonical for multi-line notes.

      [;
           Pricing review:
             - Diavola: bump to 16?
             - Hawaiian: hold at 14
         ]
    

28. When to use which

# for line-scoped headers; [; … ] when the comment must nest inside an element or span lines. Not HTML's <!-- … --> — CX has its own.

      # top-of-file header
         [shop [; inline aside on this branch ] port=8080]
    

29. Nesting

Brackets inside brackets.

      [pizza name=Margherita [base tomato]]
    

30. Siblings

Same shape, side by side. No separators required.

      [pizza [topping cheese] [topping basil] [topping oil]]
    

31. Inline prose with markup

Prose and tags interleave freely. The same shapes you would write in HTML.

      [note Try the [b Margherita] — our [em best seller], hand-tossed [strong daily].]
    

32. A whole article — prose and data

Headings, paragraphs, links, emphasis — CX handles document text as cleanly as XML.

      [article
           [h1 New Haven Story]
           [p Founded in [em 1987]. See the [a href=/menu menu].]
           [p Still [strong hand-tossing] every pie.]]
    

33. Deeper nesting — children with their own data

Each child carries its own attributes.

      [pizza name=Quattro
           [topping cheese price=2]
           [topping ham    price=3]
           [topping olives price=2]]
    

34. Multiple top-level elements (no required root)

A document can be a flat list.

      [pizza name=Margherita]
         [pizza name=Hawaiian]
         [pizza name=Diavola]
    

35. Multi-document file

One file, several independent documents. Same separator as YAML — three dashes on a line by themselves between documents.

36. Sequence (a, b, c) — flat list

Reads: element toppings, body is the sequence of three strings. Collections live in a child element's body — attributes hold a single scalar, never a collection.

      [pizza [toppings (cheese, basil, oil)]]
    

37. Array [a, b, c] — nested list

Arrays preserve structure; sequences flatten. Use arrays when nesting matters.

      [grid [cells [1, 2, 3]]]
    

38. Nested arrays

A matrix is just an array of arrays.

      [board
           [cells [[1, 0, 1],
                   [0, 1, 0],
                   [1, 0, 1]]]]
    

39. Map {k: v} — named key to value

Reads: element prices, body is a map with three entries.

      [pizza [prices {small: 9, medium: 12, large: 15}]]
    

40. Collections in body position

Sequences, arrays, and maps can sit inside an element body too.

      [favorites
           (Margherita, Hawaiian, Diavola)]
    

41. Mixed-shape composition

Map of sequences, multi-line. Compose freely.

      [stats {
           monday: (12, 8, 14),
           tuesday: (10, 9, 11),
           wednesday: (15, 11, 18)
         }]
    

42. Explicit type annotation

A glued ::T ascription on the name pins the body's type, overriding auto-typing.

      [count::int 42]
         [ratio::decimal 3.14159]
    

43. Typed array as body

::int[] for typed; ::[] for inferred (string array here).

      [oven-temps::int[] 220 240 260 480]
         [tags::[] cheap fast tasty]
    

44. Plain table — header plus rows

The [table[…]] block declares column names once. Each line below is a row.

      [menu [table[name size price]]
           Margherita medium 12
           Hawaiian   large  14
           Diavola    medium 13]
    

45. Typed columns

Each column can carry a colon-type. Cells parse accordingly.

      [orders [table[item::string qty::int paid::bool when::date]]
           Margherita 2 true  2026-05-09
           Hawaiian   1 false 2026-05-09]
    

46. Quoted cells and nulls

Quote cells with spaces. null is a real null in the cell.

      [shifts [table[cook hours::int notes]]
           Pepe       8 morning
           Maria      6 'closing crew'
           'Jean-Luc' 4 null]
    

47. Anchor and alias

&classic names this element; [*classic] is an alias node referencing it. Which reading you get depends on the projection. The lossless projections carry the reference as written: canonical CX emit prints [*classic] back out, and --xml marks it with a cx: attribute, so the document round-trips byte-faithfully. The semantic projections resolve it: under --json/--yaml/--csv (any lossy projection) and inside a program's $doc, each alias expands to a deep copy of its anchor — the JSON of the example below carries two full Margheritas inside menu. cx lint (CX-L004) errors on a reference whose anchor does not exist, and a lossy projection of a dangling alias refuses outright.

      [pizza &classic name=Margherita price=12 [base tomato]]
         [menu [*classic] [*classic]]
    

48. Merge declaration

*classic declares a merge from the anchor, with the element's own attrs as overrides. The same split as the alias: the lossless projections keep the declaration as written — canonical emit prints [pizza *classic …], --xml emits a cx:merge="classic" attribute — while the semantic projections apply it: under a lossy projection or $doc, the second pizza inherits name=Margherita price=12 [base tomato] and its own attrs win on collision, so it comes out name=ClassicXL size=large price=16 with the tomato base. CX-L004 checks the target anchor exists.

      [pizza &classic name=Margherita price=12 [base tomato]]
         [pizza *classic name=ClassicXL size=large price=16]
    

49. A recipe — prose, data, table, all together

Tabular ingredients, prose steps with inline markup, multi-line notes — all in one document, one syntax.

      [recipe name=Margherita serves=2
           [ingredients [table[item amount::string]]
             flour      300g
             water      200ml
             yeast      2g
             'San Marzano tomato' 150g
             mozzarella 120g
             basil      'a handful']
           [steps
             [step Mix the dough and rest [em 24 hours] cold.]
             [step Stretch by hand — no rolling pin.]
             [step Bake at [strong 480 degrees] for 90 seconds.]]
           [notes '''
             A wetter dough gives a softer cornicione.
             Do not skip the cold rest.
           ''']]
    

50. The whole shop

XML decl, anchor, block comments, typed table, a merge declaration (carried on the lossless projections, applied on the semantic ones — see 48), map and sequence children, triple-quoted text. One syntax, everywhere.

      [?xml version=1.0 encoding=UTF-8]
         [shop &flagship name='New Haven' port=8080 open=true
           [; opening hours ]
           [hours mon-fri=11-22 sat=12-23 sun=closed]
           [; menu reviewed 2026-05-01 ]
           [menu [table[name::string size price::decimal vegan::bool]]
             Margherita medium 12.00 true
             Hawaiian   large  14.00 false
             Diavola    medium 13.00 false]
           [staff [cook &lead name=Pepe shift=morning founder=true]
                  [cook *lead name=Maria shift=closing founder=false]]
           [contact address='123 Via Forno'
             [coords {lat: 40.8518, lon: 14.2681}]
             [phones ('+39 555 0101', '+39 555 0102')]]
           [tagline '''
             Hand-tossed since 1987.
             Still tossing.
           ''']]
    

The arc. Bare attribute → element → strings → text bodies → comments → structure → collections → typed arrays → tables → anchors → the whole shop. Every step adds one shape; no shape requires anything the earlier ones do not already give you.