A theme is a folder with a config.json and, optionally, a wallpaper.jpg. Pushing one changes the
launcher's dock, layout and look on the TV without rebuilding the APK: the launcher reads
config.json as an overlay over its built-in config.xml the next time it starts.
Choices made in Launcher settings take priority until you choose Follow theme. Pushing a theme or
using tools/theme.sh --reset also clears those on-TV column and motion choices.
TV_HOST=192.168.1.50 tools/theme.sh themes/aurora # push a theme and restart Home
TV_HOST=192.168.1.50 tools/theme.sh --reset # back to the built-in config.xml
powershell -ExecutionPolicy Bypass -File tools\theme.ps1 -TvHost 192.168.1.50 themes\aurora| Theme | What it does |
|---|---|
default/ |
The built-in look written out as JSON, as a starting point for your own |
aurora/ |
A dark aurora wallpaper (teal and violet on navy, darker at the bottom) with a matching background colour |
dussehra/ |
Festive skin for Dussehra (ends 21 Oct 2026): a marigold toran, a faint gold rangoli, a diya for Wi-Fi, a bell for Inputs, a marigold for Settings and a petal shower |
scenes/ |
14 dark illustrated landscapes in wallpapers/, a new one every hour; drawn from code by tools/scenes_wallpapers.py |
six-columns/ |
Six smaller tiles per row and one grid row visible under the dock |
Every key is optional; a missing key keeps the value from config.xml, an unknown or wrongly typed key
is ignored, and a file that doesn't parse is ignored as a whole, so a theme can never break Home.
| Key | Type | Meaning |
|---|---|---|
dock_apps |
list of package names | The dock row, in order; missing apps are skipped |
fill_dock |
bool | Fill the dock slots dock_apps leaves free with the first grid apps (true by default); false leaves them empty |
hidden_apps |
list of package names | Never shown as tiles |
live_tv_package, live_tv_action |
string | The Live TV app and, if it has no leanback entry, the action to start it with |
source_panel_service, source_panel_action |
string | The TV's own source panel, for sets with no TvInputManager: a service, or an activity (BYINTEK U4). Without a Live TV app, the Inputs pill opens it directly |
launch_actions |
list of "package=action" |
Tiles that open a screen of the app instead of its start screen; an action that no longer resolves opens the app normally (MagentaTV's guide: com.telekom.onetv.tv.pl=com.telekom.onetv.tv.pl.action.PROGRAM_GUIDE) |
app_labels |
list of "package=Name" |
A tile's name instead of the app's own (MagentaTV as com.telekom.onetv.tv.pl=TV) |
app_banners |
list of "package=banner_name" |
A tile's artwork from a banner_* drawable bundled with the launcher (banner_tv: magenta with the Live TV glyph) |
input_action |
string | Action sent with an HDMI/AV row's channel URI when nothing handles the standard VIEW (XGIMI: com.xgimi.action.hdmiPlayer) |
columns |
1 to 8 | Tiles per row; tiles shrink to fit from 5 up |
rows_below_dock |
0 to 3 | Grid rows left visible under the dock; tiles shrink if the dock, its title and that many rows would not fit the screen height |
dock_title |
bool | The focused dock app's name in large type above the dock (true); false keeps only the glow |
dock_row |
bool | The dock as its own row with a band (true); false makes the dock apps the first tiles of one plain grid |
reorder_button |
bool | A reorder button in the top bar (false by default); reordering is always in the Settings button's long-press menu |
show_network_pill |
bool | The Wi-Fi/Ethernet pill in the top bar (true by default); false hides it |
icon_only_buttons |
bool | Wi-Fi and Settings as round icon buttons; Inputs keeps its label (false by default) |
wifi_label_width |
0 to 300 | With icon_only_buttons, keep the network name on the Wi-Fi pill up to this width in dp, cut with an ellipsis; 0 leaves only the icon |
library_button |
bool | The app library as a round button in the top bar, beside Settings; needs app_library. Closing the library returns to it |
always_show_names |
bool | Names under every tile, dimmed until focused, the dock included (its band grows to hold them); false by default shows only the focused tile's name |
wallpaper_true_color |
bool | Decode wallpapers in 32-bit colour (8 MB at 1080p) instead of RGB_565 (4 MB), which bands dark gradients such as a night sky; for TVs with 2 GB or more (false by default) |
app_library |
bool | An App library pill after the last Home row: every installed app, add one to Home or take it off (false by default). The choices stay on the TV when a theme is pushed or reset; see docs/app-library.md |
shamsi_date |
bool | Show the Solar Hijri date above the Gregorian one |
greeting_name |
string | A name after the greeting, e.g. "Mr. Trịnh" for GOOD MORNING, MR. TRỊNH; empty for the greeting alone |
module_cards |
bool | Look for module cards and ask about them (true); false turns the feature off |
reduced_motion |
bool | Calmer motion for weak GPUs: stiff highlight spring, no tile overshoot, short fades, no entrance replay |
vpn_app |
string | App the network pill opens when a VPN is configured; also shows a red "VPN off" badge while no VPN is up |
animations |
bool | Basic focus, glass, title and tile entrance motion; true by default |
advanced_effects |
bool | Optional lifted tile, icon zoom, smooth ambient colour and app opening effects; false by default |
show_home_settings_shortcut |
bool | Keep the optional Default-home tile visible when the TV has a home picker; false by default |
show_stats |
bool | One line under the clock with CPU, free memory and free storage. Off unless set |
background_color |
#RRGGBB |
Colour behind everything; black by default |
sky_intensity |
0 to 100 | Time-of-day backdrop: a dark gradient that follows the clock, 0 hides it (default) |
wallpaper |
bool | Show wallpaper.jpg from the theme folder (true), or ignore it (false) |
wallpaper_rotation_minutes |
0 to 1440 | Rotate images in the theme's wallpapers/ folder at this interval; 0 keeps the single-image behaviour. A negative or non-numeric value is ignored, and 0 means "no rotation", not "every minute" |
wallpaper_order |
shuffle or sequential |
How a collection advances. shuffle (the default, and what launchers did before this key existed) avoids repeating the current picture; sequential walks the folder in filename order and wraps at the end. An unknown value falls back to shuffle |
wallpaper_dim |
0 to 90 | Black overlay over wallpaper images, in percent; 0 by default and no shade view at all |
festival |
string | Turns on a festive skin: the network pill becomes a diya whose flame follows the connection, Inputs a temple bell, Settings a marigold, and the first Home of the day gets a petal shower. dussehra and diwali have built-in greetings |
festival_until |
YYYY-MM-DD |
Last day the festive skin shows; it switches itself off after that. A malformed date turns it off |
greeting |
string | Replaces the time-of-day greeting while the festive skin is on |
accent_color |
#RRGGBB |
Colour of the focus glow while the festive skin is on; diya gold if not set |
settings_key_keycodes |
list of keycodes | Remote buttons that open Settings, for HomeKeyService (TCL Google TV gear: [83]) |
settings_key_panel |
bool | Those buttons open a small quick settings panel (TV settings, Display, Network, Apps, Launcher settings) instead of the TV's Settings |
input_key_keycodes |
list of keycodes | More remote buttons that open the input switcher, for InputKeyService (KEYCODE_TV and KEYCODE_TV_INPUT always do) |
app_keys |
list of strings | Remote buttons that open an app, as "190:com.google.android.youtube.tv" or "KEYCODE_BUTTON_3:com.google.android.youtube.tv", or by scancode as "scan:490:com.wbd.hbomax" for remotes that share one keycode between app buttons (Sony BRAVIA), for InputKeyService or HomeKeyService |
race_calendar |
list of races | F1 race-weekend mode: from 12 hours before a weekend's first session until 4 hours after the race starts, a panel under the clock shows the next session with a countdown (or the live one) and the weekend's session times in the TV's time zone. Write it with tools/race_calendar.py <theme folder>, which fetches the season from the free Jolpica API; the launcher itself never goes online |
home_idle_clock_minutes |
0 to 1440 | Minutes Home may sit untouched before it shows the clock screensaver (a thin clock and date drifting over a slow glow, as the system "Clock" screensaver does). Any key returns to Home. It starts only from Home, never over Live TV or an app; 0 is off (default) |
cinematic_home |
bool | Cinematic top shelf: the focused dock app's artwork, softened, fills the top of the screen in its colour, with a larger name, "Last opened" (apps opened from Home), dock position dots, a focus glow in the app's colour and a translucent dock band; off by default |
ambient_glow |
bool | The glow behind the dock in the focused app's colour (true by default); false keeps only background_color or the wallpaper, e.g. for a calm photo background |
wallpaper.jpg is drawn full screen behind the launcher, centre-cropped. Keep it dark, 1920×1080 and
under about 300 KB: the text, the hero name and the dock band are designed for black, and a 1 GB TV
decodes the picture into memory on every Home start. Pictures larger than the screen are scaled down to
it; a picture that is still over 4K (about 8.4 million pixels) after it is sampled down to the screen is not shown at all, and the plain colour stays.
For a wallpaper collection, place JPEG, PNG or WebP files in the theme’s wallpapers/ folder beside config.json, then set:
{ "wallpaper": true, "wallpaper_rotation_minutes": 30, "wallpaper_dim": 40, "wallpaper_order": "sequential" }The last displayed picture is remembered on the TV, so a restart or reboot resumes from it rather than
starting over at the first image in sequential mode. Missing an interval while the TV is asleep or
unplugged does not replay the missed pictures: Home moves on at most once when it wakes. Replacing the
collection starts playback from the new collection's first picture. A collection with one picture is
shown once and never blanked on a timer. Images are centre-cropped to fill the 16:9 screen; dimming is
drawn as a black overlay above the picture and below the launcher's text.
When you apply a theme, its collection replaces the one already on the TV. Use filenames containing
only letters, digits, underscores, dots and hyphens. Images can come from any source; check that you
have permission to use them. The launcher considers
up to 100 nonempty images, at most 10 MB each, skips unreadable files and keeps the last good background.
An empty collection falls back to wallpaper.jpg, or the background colour if no image is available.
"wallpaper": false disables both single-image and collection backgrounds.
Selection is random without an immediate repeat when alternatives exist. The current image and its change time survive app/process restarts. Rotation runs only while Home is visible; on return from another app, an overdue background changes then. Images are decoded on a worker thread and bounded to the screen size. There is no download service, Internet permission or computer-side scheduler. The original system idle screensaver is left unchanged.
On the TV, Launcher settings has a Wallpaper row: pick one picture from the collection (or the theme's
wallpaper.jpg), or None. A pick shows that one picture and stops the rotation until you choose Theme
default, press Follow theme, or push a theme again.
"reduced_motion": true keeps the look but calms the movement: the highlight spring is stiff instead
of bouncing, tiles zoom without overshoot, fades are shorter, and Home does not replay the tile
entrance when you come back to it. Use it on TVs whose GPU cannot keep up; a MediaTek MT5895 on
Android 10 is the known case. The default, false, keeps the normal motion.
{ "reduced_motion": true }"sky_intensity": 60 draws a dark gradient over the wallpaper and behind everything else, that follows the
clock: night blues, a soft blue day, then a warm horizon that peaks just before eight in the evening.
The glow near the bottom edge travels from left to right with the sun. The colours stay dark so the
white clock, the hero name and the dock band keep their contrast. It is drawn as one 480×270 bitmap
and redrawn once a minute, never animated, so even a 1 GB TV has nothing to keep up with. 0 keeps
the plain background; the default is off (the reference launcher looks exactly as before).
{ "sky_intensity": 60 }Open a PR with a new folder here, a one-line row in the table above and a screenshot from a real TV in the PR description. Keep the dock list generic (the big streaming apps) unless the theme is for a specific TV, and say which TV you tried it on.