Web & Frontend DevelopmentDocumentedScanned

trmnl

Generate content for TRMNL e-ink display devices using the TRMNL CSS framework.

Share:

Installation

npx clawhub@latest install trmnl

View the full skill documentation and source below.

Documentation

TRMNL Content Generator

Generate HTML content for TRMNL e-ink display devices.

Quick Start Workflow

  • Check for $TRMNL_WEBHOOK environment variable

  • If missing, prompt user for webhook URL

  • Ask user to verify TRMNL display markup is set to:
    {{content}}

  • Confirm device type (default: TRMNL OG, 2-bit, 800x480)

  • Read relevant reference docs based on content needs

  • Generate HTML using TRMNL framework classes

  • Send via POST to webhook (use temp file method)

  • Send minimal confirmation only - Do NOT echo content back to chat
  • Device & Setup

    Default target: TRMNL OG (7.5" e-ink, 800x480px, 2-bit)

    Display markup required:

    <div>{{content}}</div>

    Webhook:

    export TRMNL_WEBHOOK=""

    Sending content (temp file method):

    cat > /tmp/trmnl.json << 'EOF'
    {"merge_variables":{"content":"<div class=\"layout\">HTML</div>"}}
    EOF
    curl "$TRMNL_WEBHOOK" -H "Content-Type: application/json" -d @/tmp/trmnl.json -X POST

    Webhook Limits

    TierPayload SizeRate Limit
    Free2 KB (2,048 bytes)12 requests/hour
    TRMNL+5 KB (5,120 bytes)30 requests/hour
    Check payload size before sending:
    python3 scripts/check_payload.py /tmp/trmnl.json

    Tips to reduce payload size:

    • Minify HTML (remove unnecessary whitespace)

    • Use framework classes instead of inline styles

    • Use short class names the framework provides

    • Remove comments from HTML

    • Use deep_merge strategy for incremental updates


    Reference Documentation

    Read these files as needed:

    FileWhen to Read
    references/patterns.mdStart here - Common plugin patterns from official examples
    references/framework-overview.mdDevice specs, e-ink constraints, responsive prefixes
    references/css-utilities.mdColors, typography, sizing, spacing utilities
    references/layout-systems.mdFlexbox, grid, overflow/clamp engines
    references/components.mdTitle bar, dividers, items, tables, charts
    references/webhook-api.mdPayload format, rate limits, troubleshooting
    assets/anti-patterns.mdCommon mistakes to avoid
    assets/good-examples/HTML reference implementations
    Scripts:
    ScriptPurpose
    scripts/check_payload.pyVerify payload size before sending (run on /tmp/trmnl.json)

    Standard Plugin Structure

    Every plugin follows this pattern:

    <div class="layout layout--col gap--space-between">
      <!-- Content sections separated by dividers -->
    </div>
    <div class="title_bar">
      <img class="image" src="icon.svg">
      <span class="title">Plugin Name</span>
      <span class="instance">Context</span>
    </div>
    • layout + layout--col = vertical flex container
    • gap--space-between = push sections to edges
    • title_bar = always at bottom, outside layout
    • divider = separate major sections
    • CRITICAL: Only ONE .layout element per view (no nesting)

    Grid System (10-Column)

    Column spans should sum to 10:

    <div class="grid">
      <div class="col--span-3">30%</div>
      <div class="col--span-7">70%</div>
    </div>

    Simple equal columns: grid--cols-2, grid--cols-3, etc.

    Item Component

    Standard data display pattern:

    <div class="item">
      <div class="meta"><span class="index">1</span></div>
      <div class="content">
        <span class="value value--xlarge value--tnums">$159,022</span>
        <span class="label">Total Sales</span>
      </div>
    </div>

    Value Typography

    Always use value--tnums for numbers.

    ClassUsage
    value--xxxlargeHero KPIs
    value--xxlargeLarge prices
    value--xlargeSecondary metrics
    value--smallTertiary data
    value--tnumsAlways for numbers
    Auto-fit: ...

    Columns (for Lists)

    <div class="columns">
      <div class="column" data-overflow="true" data-overflow-counter="true">
        <span class="label label--medium group-header">Section</span>
        <div class="item">...</div>
      </div>
    </div>

    Grayscale Dithering

    Use dithered classes, not inline gray colors:

    • bg--black, bg--gray-60, bg--gray-30, bg--gray-10, bg--white

    • text--black, text--gray-50


    Data Attributes

    AttributePurpose
    data-fit-value="true"Auto-resize text to fit
    data-value-format="true"Auto-format numbers (locale-aware)
    data-clamp="N"Limit to N lines
    data-overflow="true"Enable overflow management
    data-overflow-counter="true"Show "and X more"
    data-overflow-max-cols="N"Max columns for overflow
    data-content-limiter="true"Auto-adjust text size
    data-pixel-perfect="true"Crisp text rendering
    data-table-limit="true"Table overflow with "and X more"

    Label & Title Variants

    <span class="label label--small">Small</span>
    <span class="label label--medium">Medium</span>
    <span class="label label--underline">Underlined</span>
    <span class="label label--gray">Muted/completed</span>
    <span class="title title--small">Compact title</span>

    Gap Utilities

    gap--space-between | gap--xxlarge | gap--xlarge | gap--large | gap--medium | gap | gap--small | gap--xsmall | gap--none

    Typography Guidelines

    Recommended: Georgia serif font for e-ink readability.

    Content-aware sizing:

    • Short content = bigger fonts (24-28px body)

    • Long content = smaller fonts (20px body)

    • Headings: 36-48px


    User Experience

    Critical: Do NOT echo content back to chat. Just confirm "Sent to TRMNL".

    Anti-Patterns

  • Tiny fonts for short content

  • Center-aligning columns with different lengths (use layout--start)

  • Spoiling content in chat confirmation

  • Missing value--tnums on numbers

  • Missing title_bar

  • Not using data-fit-value on primary metrics

  • Skipping data-overflow on variable lists

  • Using inline gray colors instead of bg--gray-*

  • Forgetting dividers between sections
  • Best Practices

  • Verify
    {{content}}
    display markup

  • Use layout + title_bar structure

  • Always value--tnums for numbers

  • Use data-fit-value on primary metrics

  • Use data-overflow on variable lists

  • Use item component pattern

  • Use divider between sections

  • Use bg--gray-* dithered classes

  • Content-aware font sizing

  • Top-align columns (layout--start)

  • Temp file method for curl

  • Minimal confirmations
  • Mashup Layouts (Multi-Plugin)

    For dashboard views with multiple plugins:

    LayoutDescription
    mashup--1Lx1R2 columns (50/50)
    mashup--1Tx1B2 rows (50/50)
    mashup--2x24 quadrants
    See references/layout-systems.md for all 7 layouts.

    Troubleshooting

    ProblemSolution
    Webhook failsVerify URL, check rate limits (12/hour free)
    Content missingCheck display markup is
    {{content}}
    Payload too largeRun scripts/check_payload.py, keep under 2KB (free) or 5KB (TRMNL+)
    Numbers misalignedAdd value--tnums
    Text overflowUse data-clamp or data-overflow
    Columns misalignedUse layout--start not layout--center
    Multiple layouts errorKeep only ONE .layout element per view
    Nested content failsUse .richtext for nested/formatted content