Core concepts
The dozen words everything else is written in, and what each one turns into on the device.
The designer has a small vocabulary and uses it consistently. This page defines each term once, says where it lives in the interface, and what it turns into in the generated project. The pages that follow assume it.
Project
A project is one JSON document holding everything: the name, the LVGL version, the theme, the
hardware, the screens, the assets, the filesystem settings, the variables, the automations and the
export options. It autosaves to your browser's localStorage on every change, so a
reload never loses work - but that copy is per-machine. File > Save to account stores
it on the server, which is what makes it openable elsewhere, and File > Download project
file writes the same document as a .json you can keep in version control.
Old projects are migrated when opened: fields added to the application after a project was saved are back-filled with their defaults, so a design from months ago opens cleanly.
Screens
A screen is a top-level LVGL object the size of the panel. A project has at least one, and a
cap per plan - three without an account, five on the free plan, thirty on Pro - applied when you
add one: a guest is asked to sign in, a free account is offered Pro. Each becomes its own ui_<Name>.c with a
ui_<Name>_screen_init() function, and ui_init() creates them all
and loads the first. A screen has two settings of its own: Temporary, which frees it from
RAM when it is unloaded and re-creates it on the next load, and Don't export screen function
for a screen you intend to hand-write.
Widgets
A widget is an LVGL object on a screen - a button, a label, a chart. In the project it is a node with a type, a name, a position, parameters, styles, events and bindings, and it may contain child widgets. The widget catalogue lists all twenty-one; each one's parameters are the setters LVGL offers for that type, and the generator emits exactly the calls those parameters correspond to.
The name matters more than it looks: it becomes the C identifier
ui_<Name> declared in ui.h, which is how your own code in
ui_events.c reaches the object. Two widgets on one screen cannot share a name, and
the validator says so.
Position and alignment
A widget's X and Y are offsets from an alignment anchor on its
parent, exactly as lv_obj_align() understands them - not absolute coordinates. A
widget aligned Center with X=0, Y=0 is in the middle of its parent whatever size the
parent is. Dragging on the canvas keeps the anchor and rewrites the offsets, so a design keeps
its alignment intent through a drag. Position and layout has the
details and the flex and grid options.
Parts and states
LVGL styles an object per part (a slider has a Main, an Indicator and a Knob) and per state (Default, Pressed, Checked, Focused, Edited, Disabled). The Inspector's Style settings section has a Part and a State selector, and every property you set is stored under that pair. Only the properties you change are stored; everything else is the LVGL default theme, which the canvas approximates. That sparse storage is what keeps the exported C free of redundant setters. Styles covers it.
Events and actions
An event is a trigger on a widget (Clicked, Value changed, Screen loaded, Swipe left
and so on) with a list of actions to run: change screen, set a flag, increment a slider,
play an animation, set a variable, call a function of yours. The generator writes one
ui_event_<Name>() handler per widget with events and registers it with
lv_obj_add_event_cb(). Events and actions.
Hardware
The hardware block describes the board: MCU, graphics library, whether PSRAM is enabled, the display (controller, bus, pins, resolution, rotation, colour order, backlight), the touch controller (or a rotary encoder, button pad or keypad), and then the things beyond the panel - extra buses, peripherals on them, I/O extenders, analog inputs and digital I/O. A board preset fills in the first group in one go; the second group is yours and survives a change of preset.
Every pin is validated against the chosen MCU: whether it exists, whether it is input-only, whether it is a strapping or flash pin, and whether something else already uses it. Two devices sharing a named I2C or SPI bus is legitimate and is not flagged; two unrelated signals on one GPIO is an error.
Variables
A variable holds one value - a Float, an Integer or a Boolean - and the firmware refreshes it
on a schedule. Its source is where the value comes from: a peripheral channel (the
BME280's temperature), an analog input, a digital input, a constant, or nothing at all when it is
only ever written by events. A formula converts the raw reading:
raw * 9 / 5 + 32, map(raw, 0, 4095, 0, 100), or something that
references other variables by name. Variables are what bindings and automations read.
Bindings
A binding connects a variable to one property of one widget: its text (with a printf format, a prefix and a postfix), its value, whether it is checked, its selected index, whether it is hidden, its colours, its opacity, or a push onto a chart series. A binding on a control such as a slider or a switch can run the other way too - Widget → variable or Both ways - so touching the widget writes the variable, which other bindings and automations then see.
Automations
An automation is an event raised by the hardware rather than by a finger: on startup, every interval, when a digital input changes or is held, when an analog value crosses a threshold, or when a variable changes. It runs the same action list a widget event does, plus the hardware actions - set a variable, drive a digital output, write to a peripheral, refresh the inputs now.
Assets
An asset is an image. You import a PNG, JPEG, GIF, WebP or BMP; the browser decodes it and the
server packs it into LVGL's binary image format at export, in the colour format you choose per
image. By default images are written to data/ and flashed to the board filesystem
(SPIFFS, LittleFS, FFat or an SD card); an image can instead be compiled into the firmware as a C
array. Images and fonts.
Generation
A generation is one build of a project's complete source, done on the server. It is the one metered thing in the application. A build that fails validation is never counted, and downloading the zip of a build you have just run is part of the same generation. Everything else - designing, styling, wiring, previewing, saving, opening - is free and unlimited. Accounts and limits.
The generated project, in one paragraph
The .ino brings up the backlight, the panel and the touch controller, initialises
LVGL with a partial draw buffer, calls ui_init() to build your screens and
app_init() to start the data layer, then loops on app_poll() and
lv_timer_handler(). lcd_pins.h holds every pin and timing value as a
#define. hardware.cpp owns the buses and devices and caches their
readings; app_logic.cpp owns the variables, bindings and automations. Everything under
ui/ is regenerated on every export except ui_events.c, which is
yours. Export goes file by file.