A precompiler for
Roku/BrightScript/SceneGraph
Declarative field/derived bindings that
compile straight to SceneGraph onChange handlers โ
no observeFieldScoped, no forceUpdate,
no observer cascades.
How it works
Validated end to end on one real component, compiled to a working SceneGraph node with generated observer wiring.
.thr source
field / derived / private-public function, template markup that is always valid XML.
packages/compiler
Parses with flash-parserโs own vendored BrightScript + XML grammar, adapted from kopytko-brightscript-parser but not delegated to it at parse time.
.xml + .brs
Static SceneGraph tree, generated init()/onChange handlers โ zero vdom, zero diffing.
Real Roku device
Sideloaded and verified live โ reactive fields update the screen with no hand-written observer.
Try it live
Edit the .thr source on the left โ this runs the real
compiler (packages/compiler) in your browser, not a
canned example.
<?xml version="1.0" encoding="utf-8" ?>
<component name="PlaygroundWidget" extends="Group">
<interface>
<field id="enabled" type="boolean" value="false" onChange="on_enabledChange" />
<field id="label" type="string" value=""Off"" onChange="on_labelChange" />
<field id="ft_routeReady" type="boolean" value="false" />
<function name="ft_unmount" />
</interface>
<children>
<Rectangle id="box" color="0x1A1A1AFF" width="200" height="60">
<Label id="statusLabel" />
</Rectangle>
</children>
<script type="text/brightscript" uri="PlaygroundWidget.brs" />
</component>
Documentation
Every shipped feature, one topic per page โ syntax, a real code showcase, and what's not (yet) supported. This is a knowingly narrow subset of the target flash-theater language โ enough to validate the architecture end to end before investing in the rest.
Getting started
Project layout, the <component> root tag, and the compile CLI.
Reactive state
field / derived / state, the global store, read/watch.
Statements & expressions
if/else, ternary, ==/!=, chain safety, loops, try/catch, anonymous functions.
Template & binding
Dynamic attributes, {#if}/{#if:destroy}, {#each}, bind:.
Focus & navigation
focusable, on:key, and the cross-component LRUD focus system.
Router
router.navigate, RouterOutlet, default-focus, the vacuum rule.
Theme
<theme-template>/<theme>, bare theme.a.b access, switchTheme.
Classes (.flsh)
Reusable BrightScript-only logic: extends, override, super.
Streams
Per-instance pub-sub between objects inside one component.
Task manager
taskManager.run/cancel, priority queues, alerting, onResult.
Requests
request Http {}, response caching, safe build/parse hooks.
Timer statements
setTimeout/setInterval/clearTimeout/clearInterval โ JS-shaped Timer sugar.
Animation
animation {} declarations, transition:/in:/out:, animate:.
Scale
Design-resolution-aware scaling for numbers, arrays, and AAs.
Environments
env.<name>, environments/<name>.config.json, manifestOverrides, --env.
Full status: docs/features.md. Exact grammar: GRAMMAR.md.
Packages
Two npm packages, published separately โ the parser and the compiler built on top of it.
Get started
Clone the repo, build the compiler, and compile the sample apps โ see Getting started for the full project layout and CLI reference.
git clone https://github.com/bchelkowski/flash-theater
cd flash-theater
npm install
npm run build # builds flash-parser then packages/compiler
npm test # flash-parser's tests, then packages/compiler's
# compile .thr components and package the sample app
npm run build:roku