Skip to content
led-ticker

Tutorial 2: Your first config

What you'll have by the end of this chapter — a single message scrolling across the sign in pink.
What you'll have by the end of this chapter — a single message scrolling across the sign in pink.

You’ve cloned the repo and seen the bundled preview in your browser. Now you’ll write your own config/config.toml from scratch. By the end of this chapter you’ll have a working one-section config and understand the structure every led-ticker config follows.

~10 min · no hardware needed

Picks up from Chapter 1 — you’ll need the repo cloned and make try running (or ready to run). No new prerequisites.

Delete any existing config/config.toml and start fresh:

Terminal window
rm -f config/config.toml
Reset block — start of Chapter 2

If you ever want to reset to exactly the starting point for this chapter, create config/config.toml with just the [display] and [web] blocks and no widgets yet:

[display]
rows = 64
cols = 256
chain_length = 1
default_scale = 4
brightness = 60
[web]
# lets make try show your sign live in the browser; harmless on the Pi deploy

Open a new config/config.toml in your editor. Add the display block first, then a [web] block on the line below it:

[display]
rows = 64
cols = 256
chain_length = 1
default_scale = 4
brightness = 60
[web]
# lets make try show your sign live in the browser; harmless on the Pi deploy

What each field does:

  • rows = 64 and cols = 256 — the physical dimensions of the panel array in pixels. The bigsign is eight 32×64 panels arranged in a 2×4 serpentine grid, giving a 256×64 physical canvas.
  • chain_length = 1 — number of chains. The bigsign uses a single chain of eight panels.
  • default_scale = 4 — the logical-to-physical ratio. All drawing happens on a logical canvas of cols / scale × rows / scale = 64×16 pixels. Every logical pixel expands to a 4×4 block on the real panel. This keeps font sizes and layout coordinates manageable, and is why the BDF pixel font looks crisp at display size.
  • brightness = 60 — panel brightness, 0–100. 60 is a comfortable starting point.
  • [web] — publishes the display engine’s state so the browser preview can show your sign live. An empty block is enough; the defaults are fine for laptop use. The same block enables the web dashboard on a real Pi deploy — it’s harmless to leave it in your production config.

There are several Pi-specific hardware knobs you’ll see in the example configs — pixel_mapper_config, gpio_slowdown, hardware_mapping, pwm_bits, rp1_pio. These control low-level GPIO timing and panel chaining. They have no effect on the laptop preview and are safe to omit until you’re deploying to real hardware. See Hardware → Bigsign for details on those.

Below the [web] block, add a section with one message widget:

[[playlist.section]]
mode = "ticker"
loop_count = 1
[[playlist.section.widget]]
type = "message"
text = "Welcome to Firebird Yoga"
font_color = [225, 48, 108]

A few things to notice:

The double brackets [[...]][[playlist.section]] and [[playlist.section.widget]] use TOML’s array-of-tables syntax. Each [[playlist.section]] header appends a new section to the playlist array; each [[playlist.section.widget]] header appends a new widget to the most recently opened section. This is a common gotcha for TOML newcomers: single brackets [...] define a single table, double brackets [[...]] append to an array.

mode = "ticker" — the section joins all its widgets into one continuous scrolling stream. The text enters from the right, scrolls left, and the loop repeats. Other modes (slideshow, one_at_a_time) are covered in Chapter 3.

loop_count = 1 — how many times to run the section before the playlist advances. For a multi-section config, 1 means each section plays once per playlist cycle.

font_color = [225, 48, 108] — an RGB triple. led-ticker accepts colors as [r, g, b] lists anywhere a color is expected. This particular value is the Instagram magenta ([225, 48, 108]) the social handle uses.

Before previewing, run the config validator. With make try running, use the try container itself (a second terminal — no Python install needed):

Terminal window
docker exec led-ticker-try-engine led-ticker validate /code/config/config.toml

On a machine with the dev toolchain (make dev once), the direct form works too: uv run led-ticker validate config/config.toml.

If everything is correct you’ll see:

Validating config/config.toml...
No issues found.

Try introducing a deliberate error — change font_color = [225, 48, 108] to font_color = "pink" and run validate again:

Validating config/config.toml...
✗ ERROR section[0].widget[0]: unknown font_color style 'pink'; available: ['color_cycle', 'gradient', 'rainbow', 'random']
Fix: See error message for details.
1 issue(s): 1 error(s), 0 warning(s)

The validator catches type errors, unknown fields, and missing required values before you ever preview. Get in the habit of running it after every edit. Revert the typo before continuing.

With your config saved and the validator passing, run make try:

Terminal window
make try

Open http://localhost:8080 and click the live preview tab. You should see “Welcome to Firebird Yoga” scrolling in pink across a black background — identical to the demo at the top of this page:

The browser preview — rendered live from your config/config.toml
The browser preview — rendered live from your config/config.toml

If make try is still running from Chapter 1, stop it first (Ctrl-C) and run make try again — the Chapter 1 session started on the bundled example before your config/config.toml existed, and the config choice happens at startup. From now on you won’t need to restart: saved edits to your config hot-reload into the preview within one playlist cycle. (The exception is [display]-level fields, which always need a Ctrl-C + make try.)

Most led-ticker development follows a tight loop: edit the TOML, validate, save, and check the browser preview. Try a few concrete changes to get comfortable with it:

Change the text. Edit text = "Welcome to Firebird Yoga" to something longer, then save. The browser preview updates within one playlist cycle. If you want to capture the result as a GIF with a longer duration, call the renderer directly (needs make dev once — see the aside above):

Terminal window
uv run python tools/render_demo/render.py config/config.toml -o preview.gif --duration 20

Change the color. Try a different [r, g, b] triple — for example [124, 173, 232] (sky blue) or [255, 92, 38] (flame orange). Validate and save after each change, then check the preview.

Add a second widget. Append another [[playlist.section.widget]] block immediately after the first (still under the same [[playlist.section]]):

[[playlist.section.widget]]
type = "message"
text = "Open Tuesday – Sunday * 10am – 8pm"
font_color = [255, 240, 200]

Save. In ticker mode both messages appear back-to-back in a single continuous stream, separated by a small gap. The * character renders as a mid-dot separator — a common convention in ticker text.

Each edit-validate-preview cycle takes under ten seconds on a laptop. Keep the loop tight and build confidence before moving on to the more complex sections in Chapter 3.

Chapter 3 introduces multiple sections, the slideshow and one_at_a_time modes, the two_row widget for two-line layouts, and hi-res emoji. You’ll go from a single message to a sign that rotates through distinct content cards.