ESPHome
This tutorial walks you through designing a UI in Lopaka and exporting it to an ESPHome configuration for any ESPHome-supported microcontroller.
What is ESPHome?
ESPHome turns common ESP8266/ESP32 microcontrollers into smart home devices managed through a single YAML file. Its display: component drives a wide range of screens — OLED, TFT, e-paper, and more — using a C++ lambda for drawing commands.
Getting Started with ESPHome and Home Assistant: https://esphome.io/guides/getting_started_hassio/
Prerequisites
- A device supported by ESPHome.
- A basic ESPHome YAML configuration for your device with a
displayplatform defined.
Step 0: Create a new project
- Navigate to lopaka.app and create a new project.
- Select ESPHome from the platform list.
- Set the Screen Size to match your display resolution.
- Set the background color (default is black
#000000).
Step 1: Design and export from Lopaka
- Draw your UI using the toolbar. Name each layer clearly — layer names become code comments and variable names in the output. Use the eye icon in the layer list to hide layers you do not want exported.
- In the Code Settings panel, configure your export options:
- Include Fonts — required if using custom text or fonts.
- Declare Images — enable if your design contains icons or painted graphics.
- Declare Variables — enable if your UI relies on dynamic data.
- Uncheck Wrapper Function if you are pasting directly into an existing ESPHome
lambda:block, so Lopaka only outputs theit.*draw calls. - Click Copy to save the generated code to your clipboard.
Platform characteristics
Before drawing, note the constraints that apply to all ESPHome projects in Lopaka:
- Color model: Full RGB. Colors are encoded as
Color(R, G, B)in the generated lambda. - Images: XBMP (1-bit monochrome) only — there is no RGB bitmap export for ESPHome. Icons and painted layers are always exported as binary bitmaps.
- No rounded rectangles: The ESPHome display API has no rounded-rectangle primitive.
Available drawing tools
All standard Lopaka tools are available for ESPHome projects:
| Tool | ESPHome method |
|---|---|
| Line | it.line(x1, y1, x2, y2, color) |
| Rectangle (outline) | it.rectangle(x, y, w, h, color) |
| Rectangle (filled) | it.filled_rectangle(x, y, w, h, color) |
| Circle (outline) | it.circle(x, y, r, color) |
| Circle (filled) | it.filled_circle(x, y, r, color) |
| Triangle (outline) | it.triangle(x1,y1, x2,y2, x3,y3, color) |
| Triangle (filled) | it.filled_triangle(x1,y1, x2,y2, x3,y3, color) |
| Polygon | Series of it.line() calls |
| Text | it.print(x, y, id(font), color, "text") |
| Icon / Image | it.image(x, y, id(image), color) |
Step 2: Add the code to ESPHome
- Open your device's ESPHome YAML configuration file.
- Locate the
displaycomponent and itslambdablock or use one from Lopaka if it does not exist. - Paste the UI rendering code inside the
lambdasection. Make sure the indentation (tabs or spaces) matches ESPHome's strict YAML requirements.
When the Wrapper Function setting is on, the full output looks like:
font:
- file: 'gfonts://Roboto'
id: roboto_24
size: 24
display:
lambda: |-
// title
it.print(10, 10, id(roboto_24), Color(255, 255, 255), "Hello ESPHome!");
// border
it.rectangle(0, 0, 128, 64, Color(255, 255, 255));Paste this at the root level of your YAML. If you already have a font: or display: section, merge the new entries rather than duplicating the key.
Step 3: Fix font and declaration errors
A common error when pasting Lopaka code directly into ESPHome is having missing or improperly placed font declarations.
Move fonts outside the lambda
The code exported from Lopaka includes a font: section. This must be placed at the root level of your YAML — not inside the display lambda.
WARNING
font: and image: are top-level YAML keys. Placing them inside the lambda: string will cause a compilation error.
Remove duplicates
If your ESPHome configuration already has a font: block, do not add a second one. Merge the Lopaka font entries into your existing declarations.
Font types
Google Fonts are the easiest option — fetched automatically at compile time via gfonts://:
font:
- file: 'gfonts://Roboto'
id: roboto_24
size: 24Images
Icon and painted layers are converted to XBMP and exported as BINARY images. Download the corresponding PNG file and place it in an images/ subfolder:
# You may need to download images and put them into esphome folder
image:
- file: 'images/my_icon.png'
id: img_my_icon
resize: 32x32
type: BINARYVariables
Enable Declare Variables to make layer properties dynamic at runtime. Any layer property (position, size, text, color) marked as a variable is extracted into a typed declaration at the top of the lambda:
const char* my_label_text = "Hello";
int my_label_x = 10;
// my_label
it.print(my_label_x, 20, id(roboto_24), Color(255, 255, 255), my_label_text);Variable names come from the layer title — rename layers in the layer list to get clean names in the output.
Step 4: Install and flash
Once the fonts are properly separated from the lambda and no validation errors remain:
- Click Install in the ESPHome dashboard.
- Choose your installation method — Wirelessly (OTA) or Via USB.
- Wait for the firmware to compile and upload. Once the upload is successful, your device reboots and displays the UI you created in Lopaka.
Code settings reference
| Setting | Default | Effect |
|---|---|---|
| Wrapper Function | On | Wraps output in a display: lambda: block |
| Comments | On | Adds a // layer name comment before each draw call |
| Include Fonts | On | Outputs the font: block for all used fonts |
| Declare Images | On | Outputs the image: block for all bitmap layers |
| Declare Variables | On | Extracts variable layer properties into typed declarations at the top of the lambda |
Troubleshooting
Font not declared The font: block is missing or placed inside the lambda. Move it to the root level of your YAML.
Duplicate key font You already have a font: block. Merge the Lopaka font entries into it rather than adding a second block.
Image file not found Create an images/ subfolder next to your ESPHome YAML and place the PNG files there.