# ESP32 Lua API Guidelines This is a clean contract for repositories under the same owner's control. Choose the best shared API without preserving old names, signatures, or behavior; consumers migrate to the contract. Every firmware implements all declarations under `lua/api/core/`. Optional hardware contracts live under `lua/api/features/`, as one file or one directory per feature; `sys.hasFeature(name)` guarantees the complete matching contract. Every namespace belongs to exactly one feature or to core, so a feature is a provider pointer rather than a claim to validate: a panel is the `screen` feature (`screen` and `tree`, including the saved rotation and theme), registered only when the firmware supplies a `GuiProvider`, and calibration is `touch.setCalibration()`. The runtime owns what survives a teardown and nothing else: `sys.startApp(path, args)` closes the `lua_State`, loads a path, and hands the next one its arguments as JSON. Routing, history, titles and data directories are that Lua file's, because a back stack that cannot outlive the VM is not a back stack, and everything else about where an app came from can. Encoding happens in the state that still holds the table, so unencodable arguments raise at the call rather than stranding a launch. A global namespace is a provider contract a firmware implements; anything this library provides itself is a module instead, so `require` and globals divide by who supplies the code. Those live in `native/src/bindings/lib/` and register into `package.preload`, which puts them ahead of the SD-card searcher so nothing shadows an implementation. Pure-Lua modules stay in `lua/lib/`, where shadowing is allowed because a module there is self-contained: it belongs in `lua/lib/` only if replacing it can break nothing but itself. Lua-language sources stay under `lua/`; C/C++ and the vendored interpreter stay under `native/`. Apps are fully trusted; keep permissions and sandboxing out of scope. Firmware commits dirty display content and owns panel refresh policy. Binding annotations under `native/src/bindings/` generate matching `lua/api/` files; regenerate instead of editing files marked generated. Callbacks are fields on the table an app returns, so a `@lua-app` block generates a class an app composes (`---@class PaintApp : App, TouchHandlers`) rather than global functions. Each `@lua-module`/`@lua-augment` directive sits immediately above the `luaL_Reg` table it describes, which is how one source declares several namespaces. This repository owns portable `lua/lib/` modules; shared UI owns theme application and persistence. Use `ble` for BLE/GATT and reserve `bt` for a future Classic Bluetooth contract.