This repository contains the sources for the Shiny for Python web site.
git clone https://github.com/posit-dev/py-shiny-site.git
cd py-shiny-site
make ai-setup # submodules, Python deps, generated API docs, component previews
make serve # live preview at http://localhost:1414make ai-setup is a one-command initialization for any fresh checkout or git
worktree. It also seeds heavy gitignored artifacts (_build/, render caches)
from a sibling checkout when one exists — on a machine that already has a
built copy of the site, a new worktree is ready in seconds. Prerequisites it
doesn't install for you:
- uv — the
Python package/venv manager.
makeruns every Python tool through it; if uv isn't on yourPATH,makestops immediately with the install link above. - Homebrew — used to install qvm, which pins the Quarto version.
git.
The Python venv and Quarto itself are still installed by make on demand.
Running make by itself lists all targets.
| Command | What it does |
|---|---|
make serve |
Live preview. If _build/ is missing it first runs a parallel full build (~7–10 min); after that, startup is instant and only pages you edit are re-rendered. |
make serve-serial |
Live preview with a full serial initial render (~35 min). Use this after changing _quarto.yml, the SCSS theme, includes, or extensions — make serve intentionally skips the up-front full render, so site-wide config changes won't propagate to unedited pages there. |
make site-parallel |
Full site build into _build/ using local parallel shards (SHARDS=6 by default). The honest full rebuild, several times faster than make site on multi-core machines. |
make site |
Full serial site build (what CI's shards run under the hood; the reference for fidelity). |
make quartodoc |
Regenerate API reference qmds from the py-shiny submodule. Skips itself when nothing relevant changed (submodule commit, _renderer.py, quartodoc configs, requirements.txt). |
make docs |
Rebuild component static previews and Shinylive links. |
make clean |
Remove build outputs and render caches. |
- The vendored shinylive Quarto extension is patched to memoize its subprocess
calls in
.quarto/shinylive-cache/(see the note inCLAUDE.mdandscripts/patches/shinylive-cache.patch). If you edit_extensions/quarto-ext/shinylive/shinylive.lua, regenerate the patch file somake quarto-extensionscan re-apply it after extension upgrades. scripts/ci-shard.py/scripts/ci-merge.pysplit a full render into balanced slices and merge the outputs; both CI andmake site-paralleluse them. Known cosmetic limitation: the navbar section-highlight is missing on a few dozen pages in sharded builds.
make runs everything through uv inside a uv-managed virtualenv at .venv/.
To run commands in it yourself, prefix them with uv run — it auto-discovers
.venv, so there's nothing to activate:
uv run python -c "import shiny; print(shiny.__version__)"
uv run pytest components/layout/accordion/test_accordion.pyEvery example app under components/ is exercised by Playwright tests
(reusing py-shiny's public testing API — no custom runner):
make test-components-smoke # does every app-*.py boot?
make test-components-examples # do the per-component example apps behave?
# non-browser checks, one target per test file
make test-components-pages # every page ships a runnable app
make test-components-exist # every public ui export has a doc page
make test-components-relevant-functions # relevant-functions generator helpers
make test-components-conftest # conftest.py helpers
make test-site-links-checker # the internal-link checkerpytest.ini defaults to the chromium browser and xdist (-n auto); narrow a
run with PYTEST_ARGS, e.g. make test-components-smoke PYTEST_ARGS='-k "layout/accordion"'.
See the testing-example-apps skill for how to add tests for a component.
git pull
make submodules # sync py-shiny submodule to the referenced commit
make all # quartodoc + components + siteIf something looks stale, make clean (or make distclean to also remove
extensions and the venv) and rebuild.
Note: submodules check out a specific commit in detached-HEAD mode. If you
develop inside py-shiny/, check out a branch there and keep it in sync with
the commit this repo references.
Extensions are checked into _extensions/ so no install step is needed. To
update them:
make clean-extensions quarto-extensionsthen commit the result. This re-downloads the extensions and re-applies the
local shinylive cache patch — it fails loudly if upstream changed in a way
that breaks the patch (see scripts/patches/shinylive-cache.patch for how to
re-port or retire it).
- Every push to a PR builds the site on GitHub Actions: six parallel shard
jobs render slices of the site, a combine job merges them, then a deploy job publishes
a preview to Netlify (
pr-<N>--pyshiny.netlify.app, ~12 minutes end to end). Superseded runs are cancelled automatically. - Commits to
maindeploy to production the same way. - Escape hatch: run the workflow manually (
workflow_dispatch) withfull_render = trueto build in a single unsharded job. - Two more workflows run on every PR, each covering one concern and reporting
one required check:
test-apps— everything that boots an app in a browser: the per-component interaction tests and the smoke sweep, both sharded 6 ways (make test-components-examples/make test-components-smoke). They use a cached Docker Playwright browser, so no per-job browser download. Check:done-test-apps / verify.test-docs— browserless checks over doc content: the component Shinylive links andrelevant-functionsfields are regenerated and the job fails if the committed values are out of date, plus unit tests for the the helper scripts inscripts/. So after editing anyapp-*.py, runmake docs-update-shinylive-links(optionally scoped withFILES="...") and commit the updatedindex.qmd. Check:done-test-docs / verify.
- Broken internal links are checked in the site workflow rather than
test-docs, since the checker needs the rendered site that workflow'scombinejob produces (make test-site-linkslocally). - Each workflow exposes exactly one required check, a
done-*aggregator that calls the reusable.github/workflows/_done.ymland fails if any job it covers did not succeed. Jobs can be added or re-sharded inside a workflow without touching branch protection. - Other shared workflow setup lives in local composite actions under
.github/internal/(setup-uv,setup-py-shiny-site,setup-playwright-remote).
make compare-versions runs a viewport comparison between production and a
local build (Playwright + vision model). Run it before merging changes that
could affect rendered output site-wide. See CLAUDE.md for details and
filtering options.