Architecture overview
This section is for contributors and the deeply curious. The authoritative, detailed specifications live in the repository's spec/ directory; this page is the orientation map.
The one-paragraph version
Kog compiles standard TSX into JavaScript that targets a fine-grained signals runtime: component functions run once at mount, building LVGL widgets directly through a ~10-function host interface, and every dynamic JSX expression becomes an effect subscribed to exactly the signals it reads. The app ships as precompiled bytecode running on MQuickJS, an embedded JS engine (parser removed on device) that executes bytecode in place from read-only flash — the property that makes Kog fit on a bare, PSRAM-less ESP32. The native side is a portable C core — one task owning both LVGL and the JS engine, an event loop where LVGL's timer wheel doubles as the JS scheduler, and a hardware layer on a separate worker task. The same C core compiles into the desktop simulator (SDL) and the ESP32 firmware.
Layer diagram
Your app (TSX, hooks) packages: @kog/react, @kog/ui, @kog/hardware
──────────────────────────────
Compiler (Babel via esbuild) @kog/compiler: reactive-read rewriting,
tsc --noEmit gate JSX → host calls, Show/For lowering,
style interning, prop-ID interning
──────────────────────────────
Signals runtime (JS, tiny) @kog/runtime: $signal/$memo/$effect,
batching, ownership/disposal, show/forEach
──────────────────────────────
__kog host interface ~10 functions; u16 IDs from kog-protocol
──────────────────────────────
Portable C core handle table, prop dispatch tables,
(kog_core, kog_bindings, kog_mquickjs) style interning, unified event loop, GC policy
──────────────────────────────
Ports kog_port_sdl + kog_hal_sim (simulator)
kog_port_esp + kog_hal_esp (ESP-IDF)
──────────────────────────────
LVGL v9 · MQuickJS · FreeRTOS/SDL
Load-bearing design decisions
- No VDOM on a retained-mode renderer. LVGL widgets already persist; diffing a virtual tree against them would duplicate state on the device with the least RAM. Fine-grained effects write straight to widget setters.
- One shared ID vocabulary.
kog-protocolgenerates both the C enums and the compiler's tables from one JSON file; its version is the ABI. No property-name strings ever cross the wire or live on the device. - One task owns the UI. JS and LVGL share a thread by construction, so application code cannot race the renderer; everything else (network, hardware buses) marshals in through queues.
- Bytecode-only devices. Apps are compiled to bytecode on the host; devices don't ship a JS parser — smaller, faster to boot, smaller attack surface.
- The simulator is the runtime. Same C core, same bytecode, same dev protocol — hardware included, via a virtual pin table.
- The engine behind one seam. All JS-engine API use is isolated in a single adapter, so the engine — MQuickJS, which runs bytecode in place from flash — sits behind a stable seam with everything above the
__koghost interface engine-agnostic. (An earlier build used that seam to keep a second engine, quickjs-ng, swappable behindKOG_JS_ENGINE; Kog has since unified on MQuickJS and retired quickjs-ng.)
Spec index (repository spec/)
| Doc | Contents |
|---|---|
00-overview.md | Decision log and repo map |
01-language-semantics.md | Run-once semantics, transform rules, divergences |
02-compiler-pipeline.md | Build stages, ABI stamping |
03-host-interface.md | The __kog surface and C signatures |
04-native-runtime.md | Tasks, event loop, memory budgets, GC |
05-ota-versioning.md | Partitions, bundle format, signing, rollback |
06-boards.md | board.yaml schema, three-tier build |
07-hardware-io.md | HAL, pin registry, per-chip capability tables |
08-dev-server.md | Dev protocol, hot reload, discovery, flashing |
09-components-styling.md | Component surfaces, StyleSheet, navigation, FlatList contract |
10-roadmap.md | Post-v1: AOT tier, Fast Refresh, expanders |
11-web-simulator.md | The WASM simulator + in-browser docs playground |
12-web-flash-devlink.md | Browser flashing + the framed serial dev-link |
13-networking.md | Zero-import fetch/WebSocket/sockets/Wi-Fi across all targets |
16-rom-bytecode-inplace.md | MQuickJS: run bytecode in place from flash, deploy/relocation layout (draft) |