Improve local TRMNL registry and catalog browsing
BYOS Next.js for TRMNL 🖥️
🚀 Overview
BYOS (Build Your Own Server) Next.js is a Next.js implementation that powers device management, playlist-driven content scheduling, and on-demand BMP generation for e-ink displays.
✨ Features
- Device management UI with MAC/API key registration, status tracking, and refresh scheduling.
- Playlist-based screen rotation with time and weekday rules, custom durations, and per-device assignment.
- On-demand screen rendering to 1-bit BMP via Takumi/Satori with caching and revalidation.
- Postgres backed persistence for devices, logs, and playlists.
- Recipes gallery to prototype screens and compare direct vs. bitmap rendering before pushing to hardware.
- Tailwind v4 + TypeScript + Next.js 16 + React 19; Biome lint/format baseline.
- Docker Compose for app + Postgres; deploy-ready Vercel button with Supabase/Neon integration.
Table of Contents
Highlights
- Dynamic BMP generation with Next.js 16, React 19, Tailwind CSS v4, and TypeScript.
- Supabase-backed device management, logging, and playlist scheduling.
- No-DB fallback mode for quickly previewing screens without a database.
- Docker Compose support for local PostgreSQL.
- Recipes gallery for rapid screen prototyping before deploying to devices.
- Clean codebase with Biome linting and formatting.
Demo & Screens
- Live demo: https://byos-next-demo.vercel.app
Quickstart
Deploy to Vercel
- Click the Vercel button above.
- Link a Supabase or Neon project when prompted.
- Deploy, then open the app and initialize tables.
- Point your TRMNL device at the deployed URL.
- Sync environment variables locally via
vercel linkandvercel env pullif you also develop on your machine.
Run with Docker Compose (app + Postgres)
- Copy
.env.exampleto.envand fill in the required values. At minimum:POSTGRES_PASSWORD=your_password BETTER_AUTH_SECRET=a_random_32_character_secretdocker-compose.ymlreads from.env(not.env.local). Generate a secret withopenssl rand -base64 32. - Start the stack:
docker-compose up -d # visit http://localhost:3000
Browser-based renderer (optional)
For pixel-perfect TRMNL Framework UI compatibility, run the browser renderer alongside a headless Chrome container:
docker-compose -f docker-compose.yml -f docker-compose.browser.yml up -d
This sets REACT_RENDERER=browser and starts a Chromium debugger that renders recipes via /recipes/[slug]/preview. See the Environment section for renderer options.
Run Locally
git clone https://github.com/usetrmnl/byos_next
cd byos_next
pnpm install
Start the dev server:
pnpm dev
Format/lint:
pnpm lint
Environment
Create .env.local (for pnpm dev) or .env (for Docker Compose) with the keys you need. See .env.example for the full list. Common variables:
| Variable | Purpose |
|---|---|
DATABASE_URL |
Postgres connection string. |
POSTGRES_PASSWORD |
Used by docker-compose.yml to bootstrap the Postgres container. |
BETTER_AUTH_SECRET |
Required when AUTH_ENABLED=true. Generate with openssl rand -base64 32. |
BETTER_AUTH_URL |
Public URL of your deployment (defaults to http://localhost:3000). |
AUTH_ENABLED |
Set to false to disable authentication (mono-user mode). |
ADMIN_EMAIL |
Email that receives admin role on first sign-up. |
REACT_RENDERER |
takumi (default), satori, or browser. See below. |
ENABLE_EXTERNAL_CATALOG |
Allow fetching the community / TRMNL recipe catalog. |
Renderer Options
takumi(default): fast Rust-backed Satori-compatible renderer.satori: original Vercel Satori renderer.browser: headless Chrome viapuppeteer-core, required for full TRMNL Framework UI components and pixel-perfect parity with the official cloud. Use thedocker-compose.browser.ymloverlay or setBROWSER_URLto a reachable Chrome DevTools endpoint.
Database Options
- Supabase or Neon: run migrations in
migrations/in order, or use the in-app Initialize button on first launch. Note: migration0009_add_user_tenancy.sqlassumes apostgressuperuser role. On managed providers where the connection role differs, editGRANT byos_app TO <your_role>before running it (see #46). - Docker/Postgres: set
POSTGRES_PASSWORDandBETTER_AUTH_SECRETin.env, then rundocker-compose up -d. - No-DB mode: run
pnpm devwithout DB env vars to preview screens only (device management disabled).
Project Structure
app/- Next.js routes and screens (including/recipes).components/- UI components.migrations/- SQL migrations for Postgres.public/- Static assets and screenshots.scripts/,utils/,lib/- helpers for rendering, caching, and device logic.docs/api.md- HTTP API reference.
Playlists
- Schedule screens by time and weekday with custom durations.
- Assign playlists to devices to rotate content automatically.
- Enable playlist mode per device in the UI.
Recipes
Visit /recipes to browse screens and compare direct vs. bitmap rendering. To add one:
- Create a folder under
app/recipes/screens. - Add your component and data fetching logic.
- Register it in
app/recipes/screens.json.
See docs/recipes.md for more detail.
Documentation
- API endpoints and payloads:
docs/api.md - Recipes reference:
app/recipes/README.md - Contributing guide:
CONTRIBUTING.md
Roadmap
- Better recipe management system
- Compatibility with TRMNL recipes
Support & Feedback
- GitHub Issues: https://github.com/usetrmnl/byos_next/issues
- Discussions: https://github.com/usetrmnl/byos_next/discussions
- Email: manglekuo@gmail.com
- TRMNL Discord: reply to the maintainer thread.
License
MIT - see LICENSE.
