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, 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 framework and the site that documents it live together in one Rails app. It has no database. It compiles the CSS and JavaScript, then renders these pages against them.
Framework development happens against the docs: edit the Sass or JS, watch it rebuild, and check the result on the page it documents. The screen below is a plugin layout built from framework classes, the same building blocks every example here uses.
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. A custom stack serves either an official released build or its own build compiled from this source; these pages document the build-your-own path. The TRMNL Platform always serves official builds.
.
- Bit-depth-aware tokens: a color resolves to dither patterns on 1-bit, palette images on limited color, and solids 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 repaint a whole screen while preserving device-capability rendering. See Themes Themes Opt-in stylesheets that re-theme screens while preserving device-capability rendering Themes are standalone stylesheets that re-point semantic channels, component slots, and utility tokens at different palette tokens. A themed screen still renders through its device mode: dither patterns on 1-bit, palette images on limited color, solids on full color. .
The Runtime
The JavaScript runtime lives in app/javascript/ and ships as a stamped pair: the readable plugins.js and the minified plugins.min.js production serves, both carrying the build marker of the released version. 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 How the runtime applies layout, clamping, overflow, and presentation adjustments 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: reads the live CSS cascade and returns canonical Fill, BorderFill, and TypeSpec objects, so any plugin can resolve framework colors from JavaScript. See Paint API Paint API TRMNLPaint: read the live CSS cascade from JavaScript to resolve framework colors and tile patterns TRMNLPaint is the framework's public JavaScript paint API. It reads the live CSS cascade (bit depth, dark mode, theme, limited palette, and tiles all resolved) and hands back a canonical Fill, so token mappings are never duplicated in JavaScript. Charts are just one consumer; any plugin can resolve framework colors from JS for any purpose. .
- TRMNLCharts: a Highcharts adapter built on TRMNLPaint, so charts adapt to bit depth, dark mode, and themes with the rest of the screen. See Chart Chart Visualize data optimized for 1-bit rendering With careful, minimal styling choices, TRMNL can display a variety of numerical or time centric content as charts and graphs. .
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 the live cascade and converts it. It never re-implements token mappings, adds contrast heuristics, 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 live CSS cascade from JavaScript to resolve framework colors and tile patterns
TRMNLPaint is the framework's public JavaScript paint API. It reads the live CSS cascade (bit depth, dark mode, theme, limited palette, and tiles all resolved) and hands back a canonical Fill, so token mappings are never duplicated in JavaScript. Charts are just one consumer; any plugin can resolve framework colors from JS for any purpose.
for how the API reads the cascade.
The Release Pipeline
Releases are reproducible and need only this repository. A release regenerates the tokens, compiles the Sass with Dart Sass, processes the CSS and the version-stamped JS runtime through the bundle pipelines, precompresses every artifact as gzip and brotli deterministically, and zips the result.
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. Pattern images and fonts 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 fails on its own page, 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 optimized for 1-bit rendering With careful, minimal styling choices, TRMNL can display a variety of numerical or time centric content as charts and graphs. .
- 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. .
Mounting the engine in another Rails app brings all four 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, and BlockKie 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 optimized for 1-bit rendering
With careful, minimal styling choices, TRMNL can display a variety of numerical or time centric content as charts and graphs.
.
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 makes plugins theme-aware. It adds opt-in theme stylesheets, the TRMNLPaint JavaScript paint API, adaptive charts and icons, rebuilt border, outline, and stroke utilities, and Fluid Mashups for arranging views, all on top of the v3 color system. Existing markup keeps working; every 3.2 feature is opt-in. .