Roadmap

On Thu, 15 Oct 2026, by @lucasdicioccio, 794 words, 0 code snippets, 14 links, 1images.

Roadmap

No package in this repository has had a stable release yet, and the language itself is still settling — see the repository README for where the language grammar stands. This page is about something narrower: which implementations of tramaj exist, and which are wanted next.

Where things stand today

Six independent implementations target the same grammar and are checked against a shared, language-neutral conformance corpus — template/context/expected-output triples that all must reproduce byte-for-byte, per case, in both concrete and symbolic evaluation modes. That’s a deliberately strong bar: a case belongs in the corpus only if independently written implementations can run it identically.

ImplementationLanguageStatus
tramajPureScriptreference implementation, checked against the corpus; tramaj-halogen folds to Halogen, tramaj-cli is its CLI
tramaj-hsHaskellindependent port, checked against the same corpus
tramaj-rsRustindependent port, checked against the same corpus; tramaj-cli-rs is its CLI
tramaj-jsJavaScript / TypeScriptindependent port, checked against the same corpus; tramaj-react folds to React
tramaj-pyPythonindependent port on the standard library alone, checked against the same corpus; python -m tramaj is its CLI
tramaj-goGoindependent port on the standard library alone, checked against the same corpus; tramaj-go is its CLI

Every corpus case is run in both modes by each implementation, and every output must equal the expected output byte for byte

tramaj-purs and tramaj-halogen are on the PureScript registry (0.4.1), tramaj-hs on Hackage (0.4.0.0), tramaj-rs and tramaj-cli-rs on crates.io (0.2.0), tramaj-py on PyPI as tramaj (0.2.0), and tramaj-js and tramaj-react on npm as @lucasdicioccio/tramaj-js and @lucasdicioccio/tramaj-react (0.2.0), each with language v5. tramaj-go and tramaj-cli are in no package registry yet, and are used as source or git dependencies. Each has its own changelog page and Atom feed. See Integrating tramaj for what’s actually usable from each right now, including the fold each one does or doesn’t ship.

The native-implementation wish list is done

Earlier versions of this page asked for native JavaScript, Python and Rust implementations, so that hosts in those ecosystems would get what PureScript and Haskell hosts already had: an in-process parser and evaluator, with no subprocess and no JSON round-trip just to get a Node. All three exist now — tramaj-js, tramaj-py and tramaj-rs — and each passes the full corpus in both modes, v3 and v4 extensions included. A Go port, tramaj-go, has since joined them on the same terms.

Language v5, in all six: two number types, arithmetic, sorting and number formatting

Numbers are now an integer and a float, two types, and a template can compute with ten named arithmetic builtins, round among them. It can also sort a list with sort-by and sort-by-descending, and write a number with format-number. Together these are language v5, announced here. The specification and the corpus fixtures are written, and all six implementations have all of it:

ImplementationLanguage v5Released in
tramaj (PureScript), tramaj-halogen, tramaj-cli, playgroundyestramaj-purs and tramaj-halogen 0.4.1 (PureScript registry)
tramaj-hsyes0.4.0.0 (Hackage)
tramaj-js, tramaj-reactyes0.2.0 (npm)
tramaj-rs, tramaj-cli-rsyes0.2.0 (crates.io)
tramaj-goyeson main, no tagged version
tramaj-pyyes0.2.0 (PyPI, as tramaj)

The corpus cases for these carry a "profiles" field, and an implementation skips the cases that list a name it does not provide. All six provide every name but one: the integer range, 53 bits in PureScript and TypeScript and 64 bits in the other four, so each skips the few cases written for the other range. The number split and the arithmetic profile are no longer skippable: a case that lists "int-float" or "arithmetic" fails in an implementation that does not provide it. The split changes existing output: Migrating to integers and floats lists how.

?shape is an accepted design without normative text, and no implementation has it. See Two designs accepted.

Desired next: folds, and Python type definitions

  • Folds. Only PureScript (tramaj-halogen) and JavaScript (tramaj-react) ship a fold to a rendering target. A DOM fold for JS, a fold to a common Python templating output, and a fold for at least one Haskell or Rust UI or markup library are the obvious next pieces.
  • Type definitions for the Python modules. tramaj-py annotates its functions, but ships no py.typed marker, so a type checker treats the installed package as untyped. Shipping type definitions would let a Python host check its calls the way a TypeScript host already can.
  • Releases. Every registry now has a v5 release. Releases happen when there are major changes, and each package’s version tracks the language version it implements in its major digit.

This is a wish list, not a schedule: there’s no committed timeline or assigned owner for any of it.

What “done” looks like for a new implementation

tramaj-hs, tramaj-rs, tramaj-js, tramaj-py and tramaj-go are the templates to follow, since they were added after the language had settled on a normative spec and output format (tramaj-py is the smallest: one module per concern, standard library only). A new implementation is considered on par with the existing ones once it:

  • implements the grammar and evaluation rules in reference.md, including the static restrictions that make imports, action keys, and ctx(...) paths analyzable without evaluation (see Properties);
  • encodes and decodes the Node AST exactly per node-json.md, including the round-trip guarantee (decode(encode(n)) == n);
  • passes every case in the conformance corpus, in both concrete and symbolic mode, byte-for-byte against expected.json;
  • optionally, but ideally: a fold analogous to tramaj-halogen’s foldToHalogen for at least one popular rendering target in that ecosystem (e.g. a DOM fold for JS, a common Python templating output for Python).

The v3 (?/!, v3-symbols.md) and v4 (%, v4-types.md) extensions are both shipped and part of the same conformance bar — a new implementation isn’t considered complete while targeting only the v2 core.

Contributing an implementation

If you’re taking on one of these, the corpus is the fastest way to find out what you got wrong: it’s meant to be run against a from-scratch implementation just as it’s run against the six that exist, and a case that byte-for-byte matches all of them today is a strong signal your evaluation semantics agree with theirs. Open an issue on the repository before investing heavily in one — coordinating on which language is being worked on avoids duplicate effort.