Open Source
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.
What This Repository Is
The source lives at github.com/usetrmnl/trmnl-framework. Star it, fork it, or clone it from there.
The framework and the site that documents it live together in one Rails app. It has no database. It compiles the CSS, then renders these pages against it and the JavaScript runtime.
Framework development happens against the docs: edit the Sass or JS, watch it rebuild, and check the result on the page it documents.
The fixed hierarchy of Screen, View, Layout, and Title Bar is documented in Structure Structure The framework's exact div hierarchy and how Screen, View, Layout, Title Bar, Columns, and Mashup work together Screen, View, Layout, Title Bar, Columns, and Mashup form the fixed hierarchy that defines the display environment. Plugins render their content inside Views. Follow the exact div setup; deviating causes layout and rendering issues. .
The Design System
The CSS is a Sass design system under app/assets/stylesheets/framework/. It renders one layout correctly across very different screens. The SCSS source and what a custom stack can build from it are documented in
Sass API
Sass API
The framework SCSS source: architecture, cascade layers, and what a custom stack can build from it
The Sass API is the framework's SCSS source, open since 3.2. These pages cover the build-your-own path: compiling from source, adding device profiles, and using the mixins in your own SCSS. A custom stack can also skip the build entirely and serve an official released build, which is what the TRMNL Platform always does.
.
- Bit-depth-aware tokens: a color dithers down to the panel's inks where needed and paints exactly on full color. See
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.
and
Tokens
Tokens
Complete CSS variable reference with root defaults, density, and bit-depth overrides
The Tokens reference lists every Framework CSS variable from
_variables_root.scssand display overrides in_variables_overrides.scss. Use it to understand defaults, 2-bit visual/layout behavior, high-density typography, and 4-bit-and-up scaling. . - Dither and tile backgrounds: grayscale and limited-palette fills are generated tiles, applied with
bg--{shade}. See Background Background Apply color tokens as backgrounds with bg--{token} Use the color palette defined in Colors. Apply these shades with bg--{token} for backgrounds. On 1-bit displays, grayscale uses dither patterns; on 2-bit and 4-bit+, solid colors render. . - Device screen classes:
.screen--<device>bakes each device's dimensions and palette into the build. See Screen Screen Device screen dimensions, orientation, and display properties The Screen component is the outermost container that defines the device dimensions and provides global settings for your content. . - Themes: opt-in stylesheets recolor a whole screen; the device still decides how colors print. See 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. .
The Runtime
The JavaScript runtime lives in app/javascript/ and ships as two files: the readable plugins.js and the minified plugins.min.js production serves, both stamped with the version they were released from. It does the render-time work a static stylesheet cannot.
- terminalize: the layout engine that fills each device's fixed space, handling overflow columns, text clamping, value fitting, and more. See Framework Runtime Framework Runtime The JavaScript pass that measures the screen and fits your content into it at render time Different devices have different, fixed amounts of screen space. The Framework Runtime fills that space when a plugin layout renders, doing the heavy, repetitive measuring and fitting for you. Expand the "Framework Runtime" panel under any example on this site to see the stats for that render. .
- TRMNLPaint: returns what CSS would paint right now as Fill, BorderFill, and TypeSpec objects, so any plugin can read framework colors from JavaScript. See 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. .
- TRMNLCharts: a Highcharts adapter built on TRMNLPaint, so charts adapt to bit depth and themes with the rest of the screen. See 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. .
CSS Is the Single Source of Truth for Paint
One rule shapes the whole project. Every rendering rule exists in CSS first, then TRMNLPaint mirrors it.
TRMNLPaint reads what CSS computed and converts it. It never re-implements color rules, adds contrast tweaks, or invents fallback values in JavaScript.
The same instinct applies to new features. Before adding a pattern, tile, gradient, or one-off variable, check whether the dither and tile system, the border pipeline, or the theme slots already express it. A new bespoke mechanism for one call site is almost always wrong.
The full mandate is in AGENTS.md. See
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.
for how the API does its reading.
The Release Pipeline
Releases are reproducible and need only this repository. A release regenerates the tokens, compiles the Sass, and minifies the CSS and the version-stamped JS runtime. Every artifact is then precompressed as gzip and brotli, and zipped.
The published archive under public/css and public/js keeps every version, so the docs render each version against the exact bundle it shipped. Releases are maintainer-only.
What This Site Loads from Elsewhere
The framework bundles fetch nothing from outside their own origin. Fonts, the only asset they load by URL, come from wherever plugins.css came from.
The docs site around them loads from four third-party origins, all in the page chrome or in a demo. Each one degrades only the feature that uses it, so a host that blocks all four still serves every page here.
- Google Fonts (
fonts.googleapis.com,fonts.gstatic.com): Inter and EB Garamond for this site, Space Mono for code, and Inter again inside every demo iframe. Blocked, the site falls back to system fonts and the screens keep their self-hosted families. See Font Family Font Family Switch between Classic and TRMNL font bundles per device The Framework ships two pixel font bundles: Classic (NicoPups, NicoClean, BlockKie) and TRMNL (TRMNL12, TRMNL16, TRMNL21). Low-density displays use the selected bundle; high-density displays use Inter Variable for legibility. . - unpkg (
unpkg.com): the@trmnl/pickercomponent behind the device selector. Blocked, the picker stays blank. - trmnl.com: Highcharts and Chartkick, on the chart page and in the Shopify example. Blocked, those charts render empty. See 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. .
- jsDelivr (
cdn.jsdelivr.net): opentype.js, which reads the glyph tables. Blocked, those tables stay empty. See Font Glyphs Font Glyphs Browse every glyph available in each Framework font bundle Browse every glyph available in each Framework font. Switch between the Classic and TRMNL bundles to view their full character inventory. .
The docs site can mount as an engine in another Rails app; doing so brings all four origins with it. docs/ENGINE_INTEGRATION.md repeats this list with the CSP directives each origin needs.
License
The framework code is released under the MIT license. See the LICENSE file in the repository.
The MIT grant covers the code; the bundled fonts are licensed separately. The TRMNL pixel fonts (by Heavyweight Digital Type Foundry), Inter, and the Nico fonts ship under the SIL Open Font License 1.1; BlockKie ships under CC BY 3.0. Each font bundle download carries the full terms in its README and OFL.txt.
Highcharts is a commercial library the framework does not include. The chart examples load it from trmnl.com, where TRMNL serves it under its own license, and TRMNLCharts is only the adapter. A custom stack brings its own charting library and license: see
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.
.
Start Here
- Want to help build it? Read 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. .
- New to the framework? Start with Structure Structure The framework's exact div hierarchy and how Screen, View, Layout, Title Bar, Columns, and Mashup work together Screen, View, Layout, Title Bar, Columns, and Mashup form the fixed hierarchy that defines the display environment. Plugins render their content inside Views. Follow the exact div setup; deviating causes layout and rendering issues. and 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. .
- Adopting the 3.2 features? See V3.2 Overview V3.2 Overview What's new in Framework 3.2: themes, the TRMNLPaint JS API, adaptive charts and icons, and theme-driven borders 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. .