![Pixbyt logo](logo.png)
Pixbyt is a self-hosted Tidbyt app server for advanced apps
that aren't supported by the official community app server
that you can access through Tidbyt's mobile app.
crossword |
jeopardy |
common-misconceptions |
owen-wilson-facts |
plex |
apple-tv |
letterboxd |
parcelapp |
homebridge-unifi |
guess-the-flag |
ffmpeg |
revolution |
hello-world |
dadjoke |
speedtest |
Your next Tidbyt app |
Your Tidbyt does not run apps directly; it depends on a server to periodically run apps and push the resulting images to the device. When you install a community app through Tidbyt's mobile app, the app runs on Tidbyt's official app server. For security reasons, there are a ton of limitations on what these apps are allowed to do, which means some awesome app ideas are impossible to implement.
Apps running on Pixbyt have none of these limitations:
Pixbyt lets you realize your wildest Tidbyt dreams by making it easy to:
Pixbyt's advanced features are enabled by tap-pixlet
, an unofficial Tidbyt app runner that extends Pixlet (the official Tidbyt app development framework) with an unofficial standard library named Pixlib, similar to how Starlib is the unofficial standard library for Starlark (the Python-like language Tidbyt apps are written in).
Pixlib comes with functions like
file.read
,
file.exec
,
font.height
,
html.unescape
, and
html.xpath
,
helpful constants like
const.WIDTH
,
const.HEIGHT
, and
const.FPS
, and
overloads load
to support local modules.
Pixbyt uses
tap-pixlet
to run apps,
target-tidbyt
and target-webp
to push the resulting images to your Tidbyt or WebP image files,
Airflow to run apps on a schedule, and
Meltano to tie these components together.
Pixbyt also includes resources to package your apps into a Docker image (locally or automatically on GitHub Actions) and launch it using Docker Compose.
This repo defines a Pixbyt app server with a single hello-world
app that shows off some of its advanced features.
It automatically builds a ghcr.io/douwem/pixbyt:main
Docker image that can be launched using Docker Compose to render the app to a Tidbyt device every hour:
To quickly see Pixbyt in action, you can open this repo in GitHub Codespaces and render the hello-world
app to a WebP image or your own Tidbyt before you add your own apps.
Codespaces will automatically install the necessary dependencies and launch you into a web-based VS Code editor.
HELLO_WORLD_NAME
environment variable in .env
to replace world
with your own name.Render app to a WebP image file:
TAP_PIXLET_MAGNIFICATION=8 meltano run hello-world--webp
The image will be created at output/hello-world/<timestamp>.webp
.
The exact path is also printed in the command output.
Render app to your Tidbyt:
TIDBYT_DEVICE_ID
and TIDBYT_KEY
environment variables in .env
.Render the hello-world
app and send it to your Tidbyt (in the foreground):
TAP_PIXLET_BACKGROUND=false meltano run hello-world
When you're ready to start using apps other than hello-world
, follow the steps below to build your own Pixbyt app server using this repo as a template:
If you've already opened this template repo in a codespace using the steps above:
If you haven't launched a codespace yet:
.env
configuration file doesn't exist yet, create it from the sample:
cp .env.sample .env
TZ
environment variable in .env
to your "TZ" timezone identifier. This is used by many apps that show the (relative) date and time.TIDBYT_DEVICE_ID
and TIDBYT_KEY
environment variables in .env
.The most important files in your Pixbyt repo (and likely the only ones you'll want to edit) are the following, which define the apps, their configuration, and their apps:
pixbyt
├─ .env # Configuration
├─ apps.yml # App schedules
├─ devices.yml # Optional: Devices
└─ apps
└─ <app> # One directory for each app
├─ <app>.star # Main Pixlet applet
├─ pixbyt.yml # Pixbyt metadata
├─ requirements.txt # Optional: Python packages (one `pip install` argument per line)
├─ apt-packages.txt # Optional: APT packages (one `apt-get install` argument per line)
├─ *.py # Optional: Python scripts to run using `file.exec`
├─ *.star # Optional: Starlark files to load using `load`
└─ * # Optional: Files to read using `file.read`
Out of the box, Pixbyt comes with a single hello-world
app that shows off some of its advanced features and can be used as an example to build your own.
If you're just trying out Pixbyt and don't yet have another app in mind that you'd like to run, you can keep hello-world
and skip ahead to step 4 to build and launch the app server.
If you don't want hello-world
on your Tidbyt, you can disable it by removing its entry from apps.yml
(and .env
), but DO NOT remove the apps/hello-world
directory as the GitHub Actions workflow that builds the Docker image uses it to test if the image works.
hello-world
appSkip ahead to step 4 to build and launch the app server.
Add the app and its update schedule to apps.yml
under apps:
:
apps:
# ...
- name: <app>
schedule: '<cron expression>'
# If you have multiple Tidbyts defined in `devices.yml`, you can optionally filter them by name:
# devices: [<device>]
<app>
with the name of the app.Replace <cron expression>
with an appropriate cron expression:
* * * * *
to update every minute, so that the displayed time is always as fresh as possible.*/5 * * * *
to update every 5 minutes, so that a fresh entry is shown on every app rotation.*/15 * * * *
to update every 15 minutes, or something else appropriate for your data source and the expected data freshness.Apps that will always generate the same image can use 0 0 * * *
to update every day at midnight, just to be sure.
A recommended schedule is typically documented in the app's README
.
<device>
with the name of a device defined in devices.yml
to only send the app to that device. By default, the app will be sent to all devices.For example:
apps:
# ...
- name: hello-world
schedule: '0/15 * * * *' # Every 15 minutes
devices: [office] # Optional
Note that examples in apps' README
s sometimes use schedules
and interval
keys instead of apps
and schedules
. They are equivalent and both are supported, but the latter is preferred.
If the app requires configuration, add its environment variables to .env
:
For any config key the app defines under app_config:
in its pixbyt.yml
file, add a value for the uppercase environment variable:
<APP>_<KEY>="<value>"
The exact environment variables are typically documented in the app's README
.
For example:
HELLO_WORLD_NAME="world"
If you're developing a new app, or you're not confident you've configured it correctly, you can test it without building and running the entire app server by following the Development instructions below.
To be able to easily run your app server using Docker Compose, you will build a Docker image from your repo containing Pixbyt and your apps.
During testing and development, you can do this on your local machine. In production, you'll likely want to do this on a NAS or other homelab, or on any other (virtual) server that has access to the required network resources.
Note that you'll need to do this each time your apps or their schedules change and a new Docker image is built, or whenever their configurations change.
.env
with your configuration, based on the sample or the configuration you used during development.Launch Pixbyt using Docker Compose:
docker compose up --pull --build -d
Your Pixbyt app server is now running, and your apps will update on schedule!
You can find logs for your apps under logs/apps/<app>/
.
During app development or debugging, you will not want to build the entire Docker image each time your apps, their schedules, or their configurations change, nor will you want to run the entire app server.
Instead, you can directly render a specific app to a WebP image file or your Tidbyt, and quickly iterate on your app based on what you see in the logs and the output image.
The quickest way to start developing is using GitHub Codespaces, which will automatically install the necessary dependencies and launch you into a web-based VS Code editor.
If you're already inside a codespace, continue to the next step.
If you've already created your own repo using this template repo:
<>
Code" button at the top of the pageIf you haven't created a new repo from this template yet:
The image will be created at output/<app>/<timestamp>.webp
.
The exact path is also printed in the command output.
meltano run <app>--webp
# Using Docker image:
docker compose run pixbyt run <app>--webp
For example:
meltano run hello-world--webp
# Using Docker image:
docker compose run pixbyt run hello-world--webp
TAP_PIXLET_MAGNIFICATION=8 meltano run <app>--webp
# Using Docker image:
docker compose run -e TAP_PIXLET_MAGNIFICATION=8 pixbyt run <app>--webp
For example:
TAP_PIXLET_MAGNIFICATION=8 meltano run hello-world--webp
# Using Docker image:
docker compose run -e TAP_PIXLET_MAGNIFICATION=8 pixbyt run hello-world--webp
The app will immediately show up on your Tidbyt. This is useful during development.
TAP_PIXLET_BACKGROUND=false meltano run <app>
# Using Docker image:
docker compose run -e TAP_PIXLET_BACKGROUND=false pixbyt run <app>
For example:
TAP_PIXLET_BACKGROUND=false meltano run hello-world
# Using Docker image:
docker compose run -e TAP_PIXLET_BACKGROUND=false pixbyt run hello-world
The app will be added to the Tidbyt app rotation. This is useful when you're running this command on a schedule, to make sure that the app will be up to date the next time it comes up in the app rotation.
meltano run <app>
# Using Docker image:
docker compose run pixbyt run <app>
For example:
meltano run hello-world
# Using Docker image:
docker compose run pixbyt run hello-world
If you're working with Pixbyt in GitHub Codespaces or locally, you can quickly iterate on apps and test your changes (this is not possible when you're debugging inside a Docker container). Changes to an app's source files are automatically picked up, but changes to APT and Python package dependencies aren't.
If an app defines Python packages in its requirements.txt
file, you'll need to manually do a clean install of the app's Meltano plugin every time it changes:
meltano install --clean extractor tap-pixlet--<app>
For example:
meltano install --clean extractor tap-pixlet--hello-world
If an app defines APT packages in its apt-packages.txt
file, you'll need to manually install them every time they change.