A custom Lovelace card that turns your Home Assistant dashboard into a retro split-flap (flip-board) display — the kind you'd see at airports and train stations. Push messages to it from any automation.
Inspired by FlipOff, a free split-flap display emulator.
- Realistic split-flap scramble animation — only tiles that change will flip
- Synthesised mechanical flap sound (two types: mechanical and soft)
- Driven by any entity —
input_text, template sensors, or anything with a text state - Customisable fonts (Google Fonts supported) and font weight
- Random colour mode — each tile keeps a colour from the palette
- Configurable accent bars (rainbow, solid, or off) and background colour
- Animation on/off toggle for e-ink displays
- Visual config editor with entity search — no YAML required
- Fully local — no cloud, no subscriptions, no external dependencies
Or manually:
- Open HACS in Home Assistant
- Click the three dots in the top right → Custom repositories
- Add
https://github.com/RazManSource/splitflap-cardwith category Dashboard - Search for "Split-Flap" and click Install
- Restart Home Assistant
- Download
splitflap-card.jsfrom the latest release - Copy it to your Home Assistant
/config/www/folder - Add it as a resource:
- Go to Settings → Dashboards → ⋮ (top right) → Resources
- Click Add Resource
- URL:
/local/splitflap-card.js - Type: JavaScript Module
- Hard refresh your browser (Ctrl+F5)
- Go to Settings → Devices & Services → Helpers → Create Helper → Text
- Name it whatever you like (e.g. "Splitflap Message")
- Set max length to 132 (6 rows × 22 columns)
All options are available in the visual editor — no YAML needed. The entity field has a searchable dropdown of all your entities.
type: custom:splitflap-card
entity: input_text.splitflap_messagetype: custom:splitflap-card
entity: input_text.splitflap_message
title: "" # optional heading above the board
rows: 6 # default 6
columns: 22 # default 22
# Appearance
font_family: "Courier New" # any system font or Google Font (see list below)
font_weight: "bold" # "light", "normal", "bold", "extra-bold"
font_size: auto # "auto" scales to card width, or a fixed value e.g. "24px"
accent_color: "#e8572a" # accent colour used by bars
background_color: "#1a1a1a" # board background colour, or "transparent"
bar_style: "rainbow" # "rainbow" (multicolour), "solid" (accent colour), "off" (hidden)
color_mode: "default" # "default" (dark tiles) or "random" (each tile keeps a colour)
scramble_colors: # colours used during scramble and by random colour mode
- "#e8572a"
- "#f5a623"
- "#4a90d9"
- "#7ed321"
- "#bd10e0"
# Animation
animation: true # set false for e-ink displays (instant update, no scramble)
scramble_duration: 600 # ms — how long each tile scrambles before settling
stagger_delay: 25 # ms — delay between each tile starting its animation
# Sound
sound: false # enable flip sound (default off)
sound_type: "mechanical" # "mechanical" (click + flutter + thud) or "soft" (gentle clack)
sound_delay: 0 # ms offset to shift sound timing vs animation (can be negative)
sound_every: 3 # play a sound every N tiles (1 = every tile, 3 = every 3rd)
# Text
word_wrap: true # wrap long text across rows
line_separator: "|" # character to force a new line in messagesThe following fonts are available in the editor dropdown. Google Fonts are loaded automatically:
| Font | Type |
|---|---|
| Courier New | System |
| Consolas | System |
| Roboto Mono | Google Font |
| JetBrains Mono | Google Font |
| Fira Mono | Google Font |
| Source Code Pro | Google Font |
| IBM Plex Mono | Google Font |
| Space Mono | Google Font |
| Ubuntu Mono | Google Font |
| PT Mono | Google Font |
Select Custom... in the dropdown to enter any other font name (system or Google Font).
Browsers block auto-playing audio until the user interacts with the page. On a wall-mounted tablet, tap the card once to unlock audio — after that, sounds will play automatically on every message change.
The card works with any entity that has a text state, not just input_text helpers. You can also use template sensors to build dynamic messages:
template:
- sensor:
- name: "Splitflap Weather"
state: >
{{ now().strftime('%A').upper() }} {{ now().strftime('%H:%M') }}|{{ states('sensor.outside_temperature') | round(0) }} DEGREES OUTSIDEThen point the card at sensor.splitflap_weather.
The card watches the entity you configure. To change what's displayed, just set its value. Use | for line breaks.
Go to Developer Tools → Services and call:
service: input_text.set_value
target:
entity_id: input_text.splitflap_message
data:
value: "HELLO WORLD"automation:
- alias: "Splitflap Morning Weather"
trigger:
- platform: time
at: "07:00:00"
action:
- service: input_text.set_value
target:
entity_id: input_text.splitflap_message
data:
value: >-
GOOD MORNING|IT IS {{ states('sensor.outside_temperature') | round(0) }} DEGREES|OUTSIDE TODAY - alias: "Splitflap Doorbell"
trigger:
- platform: state
entity_id: binary_sensor.front_door_motion
to: "on"
action:
- service: input_text.set_value
target:
entity_id: input_text.splitflap_message
data:
value: "SOMEONE IS|AT THE DOOR" - alias: "Splitflap Live Temp"
trigger:
- platform: state
entity_id: sensor.outside_temperature
action:
- service: input_text.set_value
target:
entity_id: input_text.splitflap_message
data:
value: >-
{{ now().strftime('%A').upper() }} {{ now().strftime('%H:%M') }}|{{ states('sensor.outside_temperature') | round(0) }} DEGREES OUTSIDEAny automation that can call input_text.set_value can push messages to the board — weather, calendar events, appliance notifications, solar generation, you name it.
When you replace the JS file, your browser may cache the old version. To force a reload, add a version query string to your resource URL:
/local/splitflap-card.js?v=2
Bump the number each time you update the file, then hard refresh (Ctrl+F5) your dashboard.
MIT
