V3.2 Overview
Framework 3.2 goes open source and adds themes, adaptive charts and icons, a JavaScript paint API, rebuilt borders and strokes, Text Scale, complete Scale modifiers, and Fluid Mashups. Existing markup keeps working; every 3.2 feature is opt-in.
Open Source
The design system behind every TRMNL screen is now yours to read, fork, and build on. It lived inside the core product since inception; 3.2 pulled it out into its own public repository at github.com/usetrmnl/trmnl-framework.
It is yours to shape too. Test suites and CI run on every pull request, and the Open Source Open Source What this repository is, how it fits together, and the paint mandate that shapes it The TRMNL Framework is open source as of version 3.2. It is the design system TRMNL plugin screens are built with, tuned for 1-bit, 2-bit, 4-bit, and limited-color ePaper displays. This repository holds the CSS, the JavaScript runtime, the design tokens, and the documentation site you are reading. and Contributing Contributing Run the framework locally, find your way around, run the tests, and open a good pull request Everything you need to make your first contribution to the TRMNL Framework: run it locally, find your way around the code, run the test suites, and open a pull request that lands. Start here, then read CONTRIBUTING.md for the fine print. guides show where everything lives and how to ship a change.
The v3 Color Foundation
3.2 builds on the color system introduced in v3.0: 10 hues with 14 lightness steps, semantic roles (primary, success, error, warning), and a 14-step grayscale, listed in full on Colors Colors Complete palette definition: grayscale, chromatic hues, and semantic roles The Colors system defines the complete palette for the framework: grayscale, chromatic hues, and semantic roles (primary, success, error, warning). Use these tokens with bg--, text--, and other utilities. See Background and Text Color for usage examples. . Every color adapts to the device's palette and bit depth on its own, with no per-device markup.
Independent Text Scale
Text Scale resizes all framework text without touching the rest of the interface. It stacks with Scale, so a dense layout can keep its text large instead of shrinking both together. See Text Scale Text Scale Scale all framework typography independently of interface geometry Text Scale adjusts every framework font size and pixel line height from one screen modifier. It composes with Scale, so you can change text readability without applying the same factor to interface geometry or text strokes. .
Themes
Recolor a whole screen by loading one extra stylesheet and adding screen--theme-<id>. The theme picks the colors; each device renders them with the inks it has. 3.2 ships three themes: Black and Yellow, White and Red, and Dark.
- Author your own theme with the
theme-slotsmixins and validate it withrake framework:themes:lint. - Preview any docs example with a theme via the Style selector in the screen picker.
Full reference: Themes Themes Visually customize any plugin with a drop-in stylesheet that recolors the whole screen Themes are a simple way to visually customize any TRMNL plugin. A theme adjusts the framework's colors (backgrounds, text, borders, chart colors) without touching plugin markup, and gracefully adapts to every supported device, from 1-bit ePaper to full color. .
TRMNLPaint: the JavaScript Paint API
Read any framework color, border, text style, or size from JavaScript. TRMNLPaint returns what CSS would paint right now, with the device, scale, and theme already applied, so your JavaScript never hardcodes a color.
- Resolvers read one value each:
bg(),text(),semantic(),series(),border(),type(), and more. - Painters:
apply(),applyBorder(),applyType()write resolved paint onto nodes. watch()re-runs your build function whenever the screen's device, scale, mode, dark mode, or theme changes.cssVar()reads any public--*variable, which is how a theme hands values to plugin code.scale()reads the current scale factor, andpx()converts pixel numbers with it.
Full reference: Paint API Paint API TRMNLPaint: read the exact colors and patterns CSS paints right now, from JavaScript TRMNLPaint is the framework's JavaScript API for its paint: colors, border lines, and text styles. Ask it for any framework color and it returns what CSS would actually paint right now, with the device and the active theme already applied. Use it wherever JavaScript draws: charts, canvases, or your own rendering. .
Generated Paint Assets
Every dither pattern is now generated at build time as an inline SVG instead of shipping as a PNG image, so a screen paints with zero image fetches.
- CSS and JavaScript share the same generated patterns:
TRMNLPaintreads back exactly what CSS paints. - Every screen mode, Raw/Preview included, paints from the same generated set, so pattern shapes never change between modes.
Adaptive Charts
The runtime now bundles TRMNLCharts, a Highcharts adapter built on TRMNLPaint. Series colors, grid lines, and chart text all come from the framework, so a chart adapts with the rest of the screen instead of carrying its own fixed colors.
options()andmerge()give you adaptive Highcharts defaults under your own settings.series(i, n)picks each series color;applySwatches()paints matching legend markers.watch()rebuilds the chart on device, scale, mode, dark mode, or theme changes.TRMNLPaint.px()scales numeric chart dimensions from the same live CSS contract.
Usage and live examples: Chart Chart Visualize data with charts that adapt to the device and theme Plugins can draw charts with any JavaScript charting library. The TRMNLCharts helper supplies the framework's colors, so a chart adapts to the device and themes like the rest of the screen. . For charting beyond Highcharts, use Paint API Paint API TRMNLPaint: read the exact colors and patterns CSS paints right now, from JavaScript TRMNLPaint is the framework's JavaScript API for its paint: colors, border lines, and text styles. Ask it for any framework color and it returns what CSS would actually paint right now, with the device and the active theme already applied. Use it wherever JavaScript draws: charts, canvases, or your own rendering. directly.
Adaptive Icons
Add image--adaptive to a monochrome icon and the framework recolors it the way it colors text: it follows the device, Raw/Preview, and the active theme. One set of icons works everywhere, as long as they are same-origin or CORS-readable. See
Image
Image
Place images with size, object fit, dithering, inversion, and adaptive icon utilities
Place images on a screen and control their size, object fit, and inversion. On 1-bit displays, dithering arranges black and white pixels so an image still reads as shades of gray.
.
Rebuilt Borders, Outlines, and Strokes
The Border, Outline, Text Stroke, and Image Stroke utilities were rebuilt the same way as the color system and now follow the device and themes on their own.
- Borders:
border--h-{step}andborder--v-{step}now use the same 10 to 75 shade scale as backgrounds, plusborder--h-blackandborder--h-white. Lines render as generated gradients instead of PNG tiles, so a bordered screen fetches no images. The numbered levelsborder--h-1throughborder--h-7still work but are deprecated. See Border Border Draw horizontal and vertical rules on the same shade scale as backgrounds Draw a horizontal or vertical rule on any element with the border--h and border--v utilities, named on the same 10 to 75 shade scale as backgrounds. On 1-bit displays a step renders as a dither pattern of black and white pixels, so a rule can read as gray. 4-bit and full-color screens draw all 14 steps; everywhere else two neighboring steps share a line. . - Outline: draws a pixel-perfect dotted rounded border on 1-bit, and a solid rounded border on 2-bit and 4-bit. See Outline Outline Draw a pixel-perfect dotted rounded border on any element The Outline utility draws a pixel-perfect dotted rounded border on any element. On 1-bit displays it places single-pixel dots at exact integer coordinates with pure CSS gradients; on 2-bit, 4-bit, and full-color displays it draws a standard CSS border with border-radius instead. .
- Text Stroke: renders as stacked drop shadows instead of native
-webkit-text-stroke, so the stroke sits behind the letters in every browser, even when the text is filled with a pattern. Sizes runtext-stroke--smalltotext-stroke--xlarge. See Text Stroke Text Stroke Legible text when displayed on shaded backgrounds Outline text so it stays legible on a shaded background. Set the stroke width and color with the text stroke utilities. . - Image Stroke: outlines transparent images with the same size and color variants. See Image Stroke Image Stroke Legible images when displayed on shaded backgrounds Outline a vector or transparent raster image so it stays legible on a shaded background. Set the stroke width and color with the image stroke utilities. .
Mashup Backdrop
The screen--backdrop modifier now follows themes like every other surface. See
Mashup
Mashup
Assemble multiple plugin views into a single interface
A Mashup arranges multiple plugin views within a single screen. A fixed mashup modifier (e.g. mashup--1Lx1R, mashup--2x2) positions the views, while each view's own modifier sets how much space it occupies. Fluid Mashups use the mashup--3x3 layout and cell placement modifiers for custom tilings.
.
Fluid Mashups
Fluid Mashups sit alongside the fixed layouts: place views on a three by three grid with mashup--3x3 and the mashup-cell modifiers, no inline styles needed. Every cell keeps its frame and a compact title bar at any size, on every device and under themes. See
Mashup
Mashup
Assemble multiple plugin views into a single interface
A Mashup arranges multiple plugin views within a single screen. A fixed mashup modifier (e.g. mashup--1Lx1R, mashup--2x2) positions the views, while each view's own modifier sets how much space it occupies. Fluid Mashups use the mashup--3x3 layout and cell placement modifiers for custom tilings.
.
Complete Scale Modifiers
Scale modifiers now resize everything: gaps, pixel utilities, image presets, component geometry, radii, and strokes, on top of each device's own density. The new screen--scale-xxsmall level adds a 66% scale for dense mashups, and TRMNLPaint.px() lets JavaScript convert pixel numbers the same way. See
Scale
Scale
Scale interface to affect content density and readability
Scale the whole interface from one screen modifier by changing the UI scale factor. Use it to match content density to viewing distance or user preference.
.
Under the Hood
- Smaller stylesheets: the responsive and device rules were refactored onto
:is()selectors.
Start Here
- Upgrading an existing plugin? → V3.2 Upgrade Guide V3.2 Upgrade Guide Compatibility notes for upgrading plugins to Framework 3.2 Framework 3.2 is fully backward compatible with 3.0 and 3.1. Existing class names render unchanged, and every new feature is opt-in. This guide lists the few things worth reviewing when you upgrade. .
- Want to adopt themes, adaptive charts, and adaptive icons? → V3.2 Enhancement Guide V3.2 Enhancement Guide Make your plugin theme-ready and adopt adaptive charts, icons, and JS paint Framework 3.2 lets an existing plugin follow themes and device modes everywhere: in markup, in charts, in icons, and in outlined text and images. This guide walks through the enhancements one at a time; adopt them in any order. .