1
Install Pixeltable
Make a folder for the project, with a virtual environment in it:The package installs the
- venv
- uv
pxt command. The [serve] extra adds FastAPI and uvicorn, which pxt service uses to serve your routes. If you only plan to insert from Python, pip install pixeltable is enough and you can skip the service steps below.2
Make the folder a project
pixeltable.toml, which makes my-app the project root. Pixeltable records each function you write for your columns by its module path from that root, app.excerpt for the one in the next step, so it can import the function again when it computes your columns.3
Write app.py
Docs is a table named docs. A line with a colon is a column you insert: every row needs a title, and body can be left out because its type allows None. A line with = is a computed column. Pixeltable fills in title_upper and summary on every insert, and again when an update changes title. summary calls excerpt(), an ordinary Python function that @pxt.udf lets a column call. id is a key Pixeltable generates on insert, and the update route uses it to find the row.ingest is a service with three routes over Docs. POST /docs inserts a row and returns its key and computed columns. POST /docs/update changes a row’s title. POST /titles computes title_upper for a title and stores nothing.4
Create the table
my_app, the last argument, is a catalog directory, and pxt schema update creates it along with the docs table. It isn’t a folder on disk.The first pxt command that needs the catalog starts the Pixeltable daemon, a background process that runs the local database. It keeps running after you close the terminal, and it reads your environment once, when it starts: export API keys before your first pxt command, or run pxt daemon restart after. The data lives in Pixeltable’s home directory, outside my-app. Infrastructure has the layout.5
Start the service
y:54140 here, something else for you. pxt service list prints the URL and the routes again whenever you need them. In a script or in CI, where nothing can answer the prompt, add -f.6
POST a row
Use your port in place of You sent
54140:title and body. Before it answered, Pixeltable stored the row, generated its id, and computed title_upper and summary. pxt rows my_app/docs shows the row, pxt dashboard opens a local UI over the catalog, and in Python pxt.get_table('my_app.docs').collect() returns it.7
Change a column
This is the loop you’ll repeat most. In See what that changes:New rows get the 3-character excerpt, like That reruns
app.py, cut the excerpt at 3 characters:pxt schema update changes the table, and pxt service update restarts the service so it picks up the new definition. Until you restart it, the service answers inserts with HTTP 409.Wor... for World. The Hello row keeps its old one until you recompute it:summary on every existing row, along with anything computed from it, and leaves the other columns alone. It asks before it starts, since on a column that calls a model, a recompute costs real money.8
Stop when you're done
pxt service update app.py my_app starts the service again, on a new port.Next
You now have the whole loop: editapp.py, run pxt schema update, then pxt service update. The README’s video example is the same pattern with model calls: a video column, then columns for its audio, transcript and summary. To call a real model, add a column like the ones in RAG and live APIs or Media pipelines. For complete apps, browse awesome-pixeltable-apps.
How it works
What each line of
app.py means, and what diff, update and prune do with it.Pixeltable Cloud
The same
app.py on a hosted database, from pxt login to a running service.