Skip to main content

Architecture overview

This section is for contributors and anyone curious about the internals. 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 host interface of ~30 __kog methods (~70 functions including hw/flatlist/net), 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 that executes precompiled bytecode in place from read-only flash. That property is what 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 also serves 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 ~30 methods (~70 incl. hw/flatlist/net);
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_web + kog_hal_sim (WASM simulator)
kog_port_esp + kog_hal_esp (ESP-IDF)
──────────────────────────────
LVGL v9 · MQuickJS · FreeRTOS/SDL

Key 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-protocol generates 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 and devices never parse app source, so they boot faster and need far less JS heap. (The parser is still linked on device, because the ROM stdlib exposes global eval.)
  • The simulator is the runtime. Same C core, same engine, same dev protocol. Hardware is included too, via a virtual pin table. (During kog dev, the simulator evaluates the JS bundle while a board receives precompiled bytecode.)
  • The engine behind one seam. All JS-engine API use is isolated in a single adapter. The engine (MQuickJS, which runs bytecode in place from flash) sits behind that stable seam, and everything above the __kog host interface is engine-agnostic. (An earlier build used that seam to keep a second engine, quickjs-ng, swappable behind KOG_JS_ENGINE; Kog has since unified on MQuickJS and retired quickjs-ng.)

Spec index (repository spec/)​

DocContents
00-overview.mdDecision log and repo map
01-language-semantics.mdRun-once semantics, transform rules, divergences
02-compiler-pipeline.mdBuild stages, ABI stamping
03-host-interface.mdThe __kog surface and C signatures
04-native-runtime.mdTasks, event loop, memory budgets, GC
05-ota-versioning.mdPartitions, bundle format, signing, rollback
06-boards.mdboard.yaml schema, three-tier build
07-hardware-io.mdHAL, pin registry, per-chip capability tables
08-dev-server.mdDev protocol, hot reload, discovery, flashing
09-components-styling.mdComponent surfaces, StyleSheet, navigation, FlatList contract
10-roadmap.mdPost-v1: AOT tier, Fast Refresh, expanders
11-web-simulator.mdThe WASM simulator + in-browser docs playground
12-web-flash-devlink.mdBrowser flashing + the framed serial dev-link
13-networking.mdZero-import fetch/WebSocket/sockets/Wi-Fi across all targets
16-rom-bytecode-inplace.mdMQuickJS: run bytecode in place from flash, deploy/relocation layout (draft)