Cuttlefish UI

Build the display screen using HTML and CSS — Cuttlefish turns it into the drawing commands a small TFT or OLED screen understands. You write a .ui file (an HTML template, CSS, and an optional TypeScript script), and when you build, Cuttlefish turns it into C++ that draws directly to a display over SPI or I2C. No browser, DOM, or CSS engine runs on the device. Layout, style resolution, and font subsetting (keeping only the characters you use) all happen at build time; the firmware only runs the resulting draw calls.

The authoring library is @typecad/ui (compile-time only — none of its code ships to the device). It pairs with the display driver support built into @typecad/cuttlefish.


Topics

TopicWhat you’ll learn
ElementsThe full HTML element catalog (<screen>, <view>, <text>, <button>, <check>, <radio>, <select>, <progress>, <range>, <input>, <list>, <canvas>, <img>)
CSS & StylingBox model, flexbox via Yoga, colors, typography, selectors, transitions, CSS variables, theming
Display ConfigurationWiring displays in cuttlefish.config.ts, built-in profiles, touch input, display drivers
Authoring APIThe ui.* functions (mount, signal, bind, drawCanvas, …) and the .ui file format

First example

A minimal .ui file — a screen with a label and a button. The template, styles, and script live in one file:

Template:

<screen>
  <text id="label">Hello, Cuttlefish</text>
  <button id="ok">OK</button>
</screen>

Styles:

screen { display: flex; flex-direction: column; gap: 12px; padding: 16px; }
#label { font-size: 20px; color: #fff; }
#ok { background: #2563eb; color: #fff; padding: 10px; text-align: center; }

Script:

import { ui } from '@typecad/ui';
ui.mount(screen);
screen.ok.onClick(() => { screen.label.value = 1; });

Build with cuttlefish build --compile --upload --port COM4. When you build, Cuttlefish resolves the layout, keeps only the font characters you use, and emits the draw calls; ui.mount(screen) is intercepted and becomes display initialization plus the first-frame draw.

How it works

  • Author in HTML + CSS. Use the elements catalog and a CSS subset that includes flexbox, the box model, colors, typography, and selectors.
  • Resolved at build time. Layout runs through Yoga (a layout library), styles are resolved, fonts keep only the characters you actually use, and images are embedded as RGB565 byte arrays (a compact color format used by most TFT displays).
  • Retained-mode runtime. The device holds a tree of elements and only redraws what changed; ui_tick() polls inputs, evaluates reactive bindings, and repaints only the dirty regions (no full-screen flicker on small updates). On boards with PSRAM (extra memory on some ESP32 boards), a full-screen framebuffer may be used.
  • Display-agnostic. The same UI drives ILI9341 TFTs, SSD1309 OLEDs, ST7796 TFTs, SSD1680 e-ink panels, and an SDL desktop window for development.

Read Elements next for the full component catalog.