# Lopaka — Full Documentation > Lopaka is a browser-based graphics editor for designing embedded UIs and generating source code for display libraries used in embedded systems (Arduino, ESP32, RP2040, Flipper Zero, and more). Lopaka.app lets you visually design pixel-accurate screens on a virtual display, then export ready-to-paste C, C++, Python, or YAML code targeting the display library of your choice. Source: https://lopaka.app/llms.txt --- # Getting Started Lopaka.app is a browser-based editor for designing embedded user interfaces and generating code for supported display platforms. ## Sign in Open `lopaka.app` and continue with one of the available sign-in methods: - Email magic link - GitHub - Google After authentication, Lopaka takes you to the **Projects** page. ## Projects page The **Projects** page shows all of your saved projects and their screens. From here you can: - Create a new project - Open an existing project - Filter projects by platform, title, display size, or favourites - Add more screens inside a project ## Create a new project Click **New Project** on the Projects page to open the project wizard. The wizard asks for the main project settings: 1. **Title**: the name shown in your projects list 2. **Platform**: the target framework or device family 3. **Screen Size**: choose a preset display, or enable the **Custom** switch to enter your own width and height 4. **Background**: pick the default screen background color when the selected platform supports it 5. **Publish to Gallery**: enable this option to make the project visible to other users in the gallery When you confirm, Lopaka creates the project with an initial screen named **Screen 1** and opens it in the editor. --- # Editor Overview The editor is a grid with five regions: ``` ┌──────────┬──────────────────────────┬─────────────┐ │ │ Top bar │ │ │ Layers ├──────────────────────────┤ Inspector │ │ panel │ Canvas │ panel │ │ ├──────────────────────────┴─────────────┤ │ │ Code panel │ Code settings │ └──────────┴──────────────────────┴─────────────────┘ ``` | Region | Purpose | | --------------- | ---------------------------------------------- | | Layers panel | Screens list, layer list and groups, resizable | | Top bar | Project details, drawing tools, actions | | Canvas | The virtual screen you draw on | | Inspector panel | Properties for the selected layer | | Code panel | Live-generated source code, resizable | | Code settings | Code output toggles and downloads | ## Drawing tools Tools that are not supported by the active platform are hidden. The following tools exist: | Tool | How to use | | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | **Image** | Opens the image import wizard (upload or paste a PNG/BMP/GIF; pick from built-in icon packs; or paste a raw byte array — converts to a bitmap layer) | | **Paint** | Freehand pixel-level drawing on a bitmap layer; right-click erases; hold Shift to draw straight lines | | **Text** | Click activates the tool; a text layer is placed at the center of the screen automatically | | **Rectangle** | Click-drag to define opposite corners | | **Circle** | Click-drag from center; radius follows the drag | | **Ellipse** | Click-drag to define the bounding box | | **Line** | Click-drag from start to end point | | **Triangle** | Three-click multi-point: click each vertex, double-click or Escape to finish | | **Polygon** | Multi-click: place any number of vertices, double-click or Escape to finish; double-click an existing polygon to edit vertices | LVGL-only tools: Text Area, Panel, Button, Checkbox, Switch, Slider. ## Canvas interactions | Interaction | Effect | | ------------------------------- | -------------------------------------- | | Click empty area | Deselect all layers | | Click layer | Select that layer | | Shift + click | Add or remove layer from selection | | Click-drag empty area | Draw a rubber-band selection rectangle | | Click-drag selected layer | Move the layer | | Click-drag resize handle | Resize the selected layer | | Hold Shift while resizing | Constrain to original aspect ratio | | Hold Alt while resizing | Resize from center | | Double-click a grouped layer | Selects that individual layer only | | Double-click Polygon / Triangle | Enter vertex edit mode | | Right-click (Paint tool) | Erase pixels | | Ctrl/Cmd + scroll wheel | Zoom in / out, centered on the cursor | ## Layers list Layers appear in render order (top of the list = drawn last = on top). Actions: | Action | How | | --------------------- | ----------------------------------------------------------- | | Select a layer | Click its row | | Multi-select | Ctrl A to select all layers | | Reorder | Drag-and-drop a row to a new position | | Reorder with keyboard | Select a layer, then Ctrl ↑ / Ctrl ↓ | | Show / hide | Click the eye icon on hover | | Lock / unlock | Click the lock icon on hover | | Delete | Select, then Delete or the Delete button in the Inspector | Groups: Ctrl G to group, Ctrl Shift G to ungroup. ## Inspector The inspector panel shows properties for the selected layer. Common fields: | Field | Type | Layers | | ---------------------------- | ----------- | -------------------------------------------- | | X, Y | Number | All positionable layers | | W, H | Number | All sized layers | | Radius / RX / RY | Number | Circle, Ellipse | | Fill | Boolean | Rectangle, Circle, Ellipse, Triangle | | Inverted (XOR) | Boolean | Most shape layers | | Color / Fill / Back / Border | Color | Platform-dependent | | Font | Font picker | Text, Text Area, Button, Checkbox | | Text | String | Text, Text Area, Button, Checkbox | | Overlay | Boolean | Dims layer and skips it from code generation | The **variable toggle** next to numeric and color fields marks a property as a variable in the generated code. ## Code panel Shows source code generated from the current canvas in real time, with syntax highlighting. When you select a layer, the panel scrolls to the corresponding generated line. The code panel is split into three zones: ``` // [BEGIN lopaka generated] … generated draw calls … // [END lopaka generated] ``` The prefix zone (above BEGIN) and suffix zone (below END) are fully editable — type #include directives, variable declarations, a setup() function, or anything else. The generated section is read-only. ## Autosave Changes are persisted to the cloud every second after the last edit. There is no manual save button. --- # Platforms A **platform** in Lopaka is the target drawing library or runtime. Selecting a platform: 1. Constrains the editor to the color model and fonts the target library understands. 2. Drives the code generator — each platform produces its own syntax and declarations. 3. Determines which code settings are available. ## Choosing a platform - **OLED / monochrome LCD (SSD1306, SH1106, SSD1309)** — U8g2 or AdafruitGFX Mono - **Color TFT (ILI9341, ST7789, GC9A01)** — TFT_eSPI, ArduinoGFX, or AdafruitGFX Color - **Rich touch UI on ESP32/STM32** — LVGL - **Flipper Zero / One** — Flipper platform - **ESPHome smart home device** — ESPHome - **E-paper display** — GxEPD2 - **RP2040 / ESP32 with MicroPython** — MicroPython - **CircuitPython board** — CircuitPython - **Mockup or export image only** — Free Drawing ## Platform comparison | Platform | Output | Color model | Fonts | Images | | ---------------------- | ----------------- | ------------------ | ------------------ | ------------ | | U8g2 | C / C++ | Monochrome (1-bit) | BDF (large set) | XBMP | | TFT_eSPI / M5 / Lovyan | C++ | RGB565 | GFX | XBMP, RGB565 | | AdafruitGFX Color | C++ | RGB565 | GFX | XBMP, RGB565 | | AdafruitGFX Mono | C++ | Monochrome (1-bit) | GFX | XBMP | | ArduinoGFX | C++ | RGB565 | GFX | XBMP, RGB565 | | LVGL | C | RGB + alpha | Montserrat (TTF) | RGB565 | | Flipper Zero / One | C | Monochrome (1-bit) | 4 fixed fonts | XBMP | | ESPHome | YAML + C++ lambda | RGB | Google Fonts (TTF) | XBMP | | MicroPython | Python | Monochrome (1-bit) | Fixed (Petme 8×8) | Raw buffer | | CircuitPython | Python | RGB | Terminus (BDF) | Raw buffer | | GxEPD2 | C++ | Indexed palette | GFX | XBMP | | Free Drawing | — | RGB | All fonts | — | ## U8g2 Targets the U8g2 monochrome display library. Generates C++ (Arduino) or C (ESP-IDF) code. - **Color:** Binary — white (1) or black (0). Inverted-color mode available. - **Fonts:** Large BDF font library. Font names compile to `u8g2_font__tr`. - **Images:** XBMP bitmaps declared as `uint8_t` arrays in PROGMEM. - **Templates:** Arduino (C++) and ESP-IDF (C), each with a progmem toggle. - **Limitations:** No RGB. Font size is determined by the BDF file. ## TFT_eSPI / M5 / Lovyan Covers TFT_eSPI, M5Stack GFX, and LovyanGFX — all share the same API surface. - **Color:** Full RGB, packed as RGB565. - **Fonts:** Adafruit built-in plus GFX fonts. Custom TTF, OTF, WOFF, and BDF fonts can be uploaded and converted to GFX format. - **Images:** XBMP (1-bit) or RGB565 pixel arrays. - **Limitations:** RGB565 only — no alpha in the output. ## AdafruitGFX Color Targets Adafruit GFX Library on color displays. - **Color:** RGB565. - **Fonts:** Adafruit built-in plus GFX fonts. Custom TTF/BDF upload supported. - **Images:** XBMP or RGB565 pixel arrays. - **Limitations:** No alpha channel. ## AdafruitGFX Mono Same as AdafruitGFX Color but for monochrome OLED/LCD (SSD1306, SH1106, etc.). - **Color:** Binary — 1 (white) or 0 (black). - **Screen clear:** Calls `clearDisplay()` instead of `fillScreen()`. ## ArduinoGFX Targets Arduino_GFX. - **Color:** RGB565, high-byte-first encoding (differs from Adafruit's low-byte order). - **Fonts:** GFX fonts with custom scale factor. ## LVGL Targets LVGL — a feature-rich embedded GUI library. - **Color:** Full RGB with alpha channel. Colors encoded as `lv_color_hex(0xRRGGBB)`. - **Fonts:** Montserrat TTF at arbitrary sizes. - **Widgets:** Panels, buttons, sliders, switches, checkboxes, text areas in addition to primitive shapes. - **Renderer:** Smooth (anti-aliased) canvas rendering. - **Generated code targets LVGL C API (v9).** ## Flipper Zero / One Targets the Flipper Zero and Flipper One GUI canvas API (`canvas_draw_*`). - **Color:** Monochrome. - **Fonts:** Four fixed fonts only — FontPrimary (Helvetica 8 bold), FontSecondary (Haxrcorp 4089), FontKeyboard (ProFont 11), FontBigNumbers (ProFont 22). - **Display presets:** Zero Horizontal (128×64), Zero Vertical (64×128), One Horizontal (256×144), One Vertical (144×256). ## ESPHome Targets the ESPHome display component lambda. - **Output:** YAML with embedded C++ lambdas. - **Color:** Full RGB encoded as `Color(R, G, B)`. - **Fonts:** Google Fonts via `gfonts://`. Font declarations go into the top-level `font:` YAML key. - **Images:** XBMP exported as BINARY image assets. - **No round corners** — ESPHome's display API has no rounded-rectangle primitive. ## MicroPython Targets MicroPython's `framebuf` module on RP2040, ESP32, and similar. - **Output:** Python. - **Color:** Monochrome — 1 (white) or 0 (black). - **Fonts:** Single built-in font (Petme 8×8). - **Images:** Raw bytearray buffers (packed 1-bit, row-major). ## CircuitPython Targets CircuitPython's `displayio` and `vectorio` stack. - **Output:** Python. - **Color:** RGB, encoded as 24-bit hex (0xRRGGBB). - **Fonts:** Terminus BDF font. Font choice is fixed. - **Images:** Raw bytearray buffers. ## GxEPD2 Targets the GxEPD2 e-paper display library. Extends AdafruitGFX. - **Color:** Indexed palette — GxEPD_BLACK, GxEPD_WHITE, GxEPD_DARKGREY, GxEPD_LIGHTGREY, GxEPD_RED, GxEPD_YELLOW, GxEPD_BLUE, GxEPD_GREEN, GxEPD_ORANGE. - **Fonts:** Adafruit built-in plus GFX fonts. Custom TTF/BDF upload supported. - **Images:** XBMP only. ## Free Drawing Design-only mode with no code export. Full RGB, all fonts available. --- # Fonts Fonts in Lopaka are platform-specific. Lopaka works with three font formats internally: | Format | Description | Used by | | -------------------- | -------------------------------------------------------------------------- | ----------------------------------------- | | **BDF** | Bitmap Distribution Format — a plain-text bitmap font standard | U8g2, CircuitPython | | **GFX** | Adafruit GFX — a C header (.h) containing a bitmap array and glyph table | TFT_eSPI, AdafruitGFX, ArduinoGFX, GxEPD2 | | **TTF / OTF / WOFF** | TrueType and OpenType vector fonts | LVGL, ESPHome | When you upload a custom font, Lopaka converts it to the format the active platform needs automatically. ## Importing a custom font Select a text layer, open the font dropdown in the Inspector, and click **Import font…**. - **GFX header (.h)** — used as-is on TFT_eSPI, AdafruitGFX, ArduinoGFX, GxEPD2. - **BDF font** — uploaded directly on U8g2; auto-converted to GFX on GFX-based platforms. - **TTF / OTF / WOFF** — opens the Font Wizard where you set the target pixel height; rasterized to GFX format. Font Wizard only covers printable ASCII (space through tilde, 95 characters). ## Font size by platform | Platform | Size control | | -------------------------------------------- | ---------------------------- | | U8g2 | None — pick a different font | | TFT_eSPI / AdafruitGFX / ArduinoGFX / GxEPD2 | Integer scale (1×, 2×, …) | | LVGL | Fixed Montserrat | | ESPHome | Free numeric (px) | | Flipper Zero | None | | MicroPython / CircuitPython | None | ## Practical tips - Minimum readable size on monochrome OLEDs: 8 px (e.g. helvB08). - GFX fonts occupy flash: FreeMono12pt7b ≈ 1.7 KB; FreeMonoBold24pt7b ≈ 4.5 KB. - Custom font converters only encode printable ASCII. For accented or CJK characters, use a pre-built .h file. - Custom fonts are tied to the project, not the platform. A GFX .h font will not work on U8g2, and a BDF font will not work on TFT_eSPI. --- # Code Generation Lopaka generates platform-specific source code from your visual design in real time. ## How the output is built Every time you change a layer, Lopaka rebuilds the entire code block. The output depends on: 1. **Platform** — each platform has its own code template and syntax. 2. **Layers** — only visible, non-overlay layers appear in the output, in their stacking order. 3. **Screen title** — becomes the wrapper function name. 4. **Code settings** — toggles that control which sections are included. ## Screen title and the wrapper function The screen title becomes the name of the generated wrapper function: | Screen title | Generated function | | --------------- | ------------------------------ | | Main Screen | void drawMain_Screen(void) | | gauge display | void drawgauge_display(void) | | 123 Alert | void draw_123_Alert(void) | Rules: spaces and special characters become underscores; names starting with a digit get a leading underscore. If **Wrapper function** is off in Code Settings, bare draw calls are output without any enclosing function. ## Variables Mark a property as a variable to replace hard-coded values with named identifiers: 1. Select a layer. 2. In the Inspector, click the variable toggle (hexagon icon) next to a supported property. 3. Enable **Declare variables** in Code Settings. ```cpp int label_x = 10; int label_y = 20; const char* label_text = "Hello"; display.setCursor(label_x, label_y); display.print(label_text); ``` Variable names are derived from the layer name and property name. ## Code Settings | Setting | What it does | | ---------------------- | ----------------------------------------------------------------------------- | | **Wrapper function** | Wraps all draw calls in `void draw{ScreenTitle}(void) { ... }` | | **Comments** | Emits a `// layer name` comment before each draw call | | **Include fonts** | Adds font declarations or #include directives for fonts used in the design | | **Declare images** | Adds image array declarations for bitmap and icon layers | | **Declare variables** | Extracts marked layer properties into typed variable declarations | | **Clear/Fill display** | Adds a screen-clear call at the top of the function | | **PROGMEM** | Marks image and font arrays with Arduino's PROGMEM storage class (U8g2 only) | ## Exporting - **Copy from code panel:** Click the **Copy** button to copy the full output to clipboard. - **Download as a file:** Share menu → Save As → Text file. Named after the screen title. - **Download fonts and images:** In Code Settings panel, download links appear for custom fonts and bitmap layers. Font files: .h for GFX-based platforms, .bdf for U8g2. Image files: .h or .bmp depending on platform. ## Import (experimental) Lopaka can parse existing platform source code and reconstruct layers. - **Paste into code panel:** Ctrl V — Lopaka detects source code and triggers the import dialog. - **Import from a file:** Click the **Import** button in the code panel. Both methods append reconstructed layers to the current design. Existing layers are not removed. | Parsed construct | Reconstructed as | | ---------------------------- | ----------------------------- | | drawLine / line | Line layer | | drawRect / fillRect | Rectangle layer | | drawCircle / fillCircle | Circle layer | | drawPixel | Dot layer | | print / drawString | Text layer | | drawBitmap / drawXBitmap | Image / paint layer | Known limitations: layer names are not restored; variable state is not restored; no settings detection. --- # Importing Images Two ways to start an import: - Click the **Image** tool in the toolbar to open the Import Wizard. - Drag a PNG or BMP file directly onto the canvas to import with default settings. ## Import Wizard ### Step 1 — Choose a source - **Icon Packs** — browse built-in monochrome icon library grouped by set (arrows, UI symbols, weather, etc.). - **Upload file** — drag files or click Browse files. Accepted: any raster image (PNG, JPEG, BMP, WebP, etc.) and .gif. GIF frames are extracted as separate images automatically. - **Input byte array** — paste a raw XBMP byte array with width and height. ### Step 2 — Image editor - **Color mode:** Monochrome (1-bit XBMP) or RGB (RGB565, 2 bytes per pixel). - **Dimensions:** Set target width and height. Reset or Fit Screen buttons available. - **Crop area:** Blue selection rectangle — drag center to reposition, drag corners to resize. - **Resampling:** none, nearest, bilinear, spline, lanczos, gaussian, mitchell. - **Brightness / Contrast:** −100% to +100%. - **Grayscale first:** Convert to grayscale before thresholding. - **Dithering (monochrome only):** Floyd-Steinberg. On for photos/gradients; off for logos/icons. - **Invert palette (monochrome only):** Swaps black and white before dithering. - **Invert result:** Inverts the final bitmap after all processing. Each imported image becomes a **Paint (bitmap) layer** on the canvas. --- # Keyboard Shortcuts ## General | Shortcut | Action | | ----------------------- | ----------------------------- | | Ctrl Z | Undo | | Ctrl Shift Z | Redo | | Ctrl A | Select all layers | | Ctrl C | Copy selected layers | | Ctrl V | Paste | | Ctrl X | Cut | | Ctrl G | Group selected layers | | Ctrl Shift G | Ungroup | | Escape | Deselect / cancel active tool | | Delete or Backspace | Delete selected layers | ## Navigation and zoom | Shortcut | Action | | --------------------- | -------------------------------- | | Ctrl + | Zoom in | | Ctrl - | Zoom out | | Ctrl/Cmd + scroll | Zoom in/out (centered on cursor) | | Scroll (no modifier) | Pan canvas | ## Moving layers | Shortcut | Action | | -------------------- | --------------------------------------- | | Arrow keys | Move selected layer 1 px | | Shift + Arrow keys | Move selected layer 10 px | | Ctrl ↑ / Ctrl ↓ | Move layer up / down in the layer stack | ## Paint tool | Shortcut | Action | | ------------ | -------------------- | | Right-click | Erase pixels | | Hold Shift | Draw a straight line | ## Polygon / Triangle tools | Shortcut | Action | | --------------------------- | ----------------------- | | Click | Place a vertex | | Double-click | Finish placing vertices | | Escape | Finish placing vertices | | Double-click existing shape | Enter vertex edit mode |