Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 0 additions & 56 deletions .github/workflows/deploy.yml

This file was deleted.

59 changes: 25 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,12 @@
A minimal, installable PyScript application for the portable
[PyDevices](https://github.com/PyDevices/pydevices) display stack.

Use this repository as a GitHub template, edit `main.py`, and enable GitHub
Pages with **GitHub Actions** as the source. The included workflow
(`.github/workflows/deploy.yml`) vendors PyScript, deploys the repository root
(the app lives there, not in a subdirectory) to GitHub Pages on every push to
`main`, and the service worker caches both the application shell and the
pinned PyScript interpreter for offline launches after the first successful
visit. The template also pins PyDevices source files to release `v0.7.0`, so
a new app does not silently change when the product's default branch
advances.

> The live demo for this template is hosted from the
> [PyDevices.github.io](https://github.com/PyDevices/PyDevices.github.io)
> repository, not from Pages on this repo — this repo's own Pages setting is
> for template users who click "Use this template."
Use this repository as a GitHub template, edit `main.py`, and run it on your
own machine with Python's built-in web server ([below](#run-it-locally)). The
service worker caches the application shell and the pinned PyScript
interpreter, so after one visit the app launches offline too. The template
pins PyDevices source files to release `v0.7.0`, so a new app does not
silently change when the product's default branch advances.

## Starter Example: Interactive Touch / Paint

Expand Down Expand Up @@ -61,14 +53,14 @@ app.run()

1. **HTML5 Canvas Backend**: `board_config.display_drv` binds to the `<canvas>` element through the supported PyScript/Pyodide `PSDisplay` backend. This template is intentionally Pyodide-only; direct MicroPython WebAssembly applications use the Gallery host instead.
2. **Browser Event Loop**: `app.run()` integrates cooperatively with the browser's native JavaScript event loop to dispatch pointer/touch events.
3. **Automated PWA Caching**: The included GitHub Actions workflow and service worker cache the PyScript interpreter and application shell so users can install and run the app offline on desktop or mobile browsers.
3. **Installable and offline**: the service worker caches the PyScript interpreter and application shell, so the app installs and runs offline on desktop and mobile browsers. A small note near the top right tells visitors how their browser installs it, and an installed app opens in a window sized to the display `board_config` asks for. [The PWA guide](docs/pwa-guide.md) has the details.

## Documentation

- [Newcomer's guide](docs/newcomers.md) — how the template becomes a browser app, and which generated/deployed boundaries to preserve.
- [Make your PyScript app a PWA](docs/pwa-guide.md) — host/install matrix,
manifest, service worker, cross-origin isolation, deployment, and offline
caching. The template already ships everything that guide describes.
- [Newcomer's guide](docs/newcomers.md) — how the template becomes a browser app, and which generated boundaries to preserve.
- [Make your PyScript app a PWA](docs/pwa-guide.md) — where it installs, the
manifest, the service worker, the app window, and edits that don't show.
The template already ships everything that guide describes.

What's planned next is in [ROADMAP.md](ROADMAP.md).

Expand All @@ -86,29 +78,28 @@ What's planned next is in [ROADMAP.md](ROADMAP.md).
and confirm `https://pyscript.net/releases/<version>/offline_<version>.zip`
returns 200 before committing the change.

## Preview locally
## Run it locally

From the repository root:

```bash
./scripts/vendor_pyscript.sh
python3 -m http.server 8000
```

Then open <http://localhost:8000>. Do not open `index.html` directly from the filesystem; PyScript and service workers require an HTTP origin.

## Deploy

Template users deploy with GitHub Pages:
Then open <http://localhost:8000>. The first command downloads the pinned
PyScript release into `vendor/` (it is `.gitignore`d, so run it once per
checkout and again after you change the pin).

1. In your GitHub repository, go to **Settings → Pages** and set
**Build and deployment → Source** to **GitHub Actions**.
2. Push to `main` (or run the workflow manually from the **Actions** tab).
`.github/workflows/deploy.yml` runs `scripts/vendor_pyscript.sh`, stamps
`sw.js`'s cache name with the commit SHA so every deploy busts old
caches, and publishes the repository root — including the generated
`vendor/` directory — to Pages.
Use that `localhost` address rather than opening `index.html` from disk or
browsing to the machine's LAN IP. Service workers, which make the app
installable and offline, only run on `http://localhost` or over `https://`.

`vendor/` is `.gitignore`d; it does not live in the repository, it's produced
fresh by the vendor script on every local checkout and every deploy.
The service worker serves every file from its cache once it has one, so an
edit to `main.py` can look as if it did nothing. While you work, reload with
**Ctrl+Shift+R** (**Cmd+Shift+R** on a Mac), or open DevTools → Application →
Service workers and tick **Bypass for network**. [Edits that don't
show](docs/pwa-guide.md#edits-that-dont-show) has the rest.

## Verify

Expand Down
5 changes: 3 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
- [Newcomer's guide](newcomers.md) — codebase map, browser execution path, and safe customization.
- [Bringing in a bigger app](packages.md) — wheels for sound, pygraphics and
LVGL; piano and the drum machine as worked examples.
- [Make your PyScript app a PWA](pwa-guide.md) — where PWAs run, manifest,
service worker, cross-origin isolation, deploy, and troubleshooting.
- [Make your PyScript app a PWA](pwa-guide.md) — where it installs, the
manifest and service worker, the app window, running it locally, and edits
that don't show.

Start with the [root README](../README.md) for the template itself.
55 changes: 27 additions & 28 deletions docs/newcomers.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Newcomer's guide to the PyDevices PyScript template

This repository is a GitHub template for an installable browser application,
not a shared PyDevices library and not a site to deploy as-is. Start by using
the template to create your own repository, then make that repository's
not a shared PyDevices library. Start by using the template to create your own
repository, then make that repository's
`main.py`, application name, icons, and styling yours.

The template runs Python in the browser through PyScript/Pyodide and renders
Expand All @@ -14,7 +14,7 @@ an application architecture on the copied project.
## A mental model

```text
GitHub Pages HTTP origin
http://localhost:8000 (python3 -m http.server)
|
v
index.html
Expand All @@ -35,26 +35,26 @@ main.py
sw.js caches the shell and later GET responses for offline reuse
```

The application must be served over HTTP(S). Opening `index.html` directly
from the filesystem does not provide the origin that PyScript and service
workers require.
The application must be served over HTTP. Opening `index.html` directly
from the filesystem does not provide the origin that PyScript needs, and the
service worker only runs on `http://localhost` or `https://`. The root
README's [Run it locally](../README.md#run-it-locally) has the commands.

## Repository map

| Path | Purpose |
|---|---|
| `index.html` | Application shell: canvas, status text, install button, PyScript loader, and the Python entrypoint declaration. |
| `index.html` | Application shell: canvas, status text, PyScript loader, and the Python entrypoint declaration. |
| `main.py` | Starter Python application. It constructs `appdev.App(board_config)`, paints the demo, and handles pointer events. |
| `pyscript.json` | Exact remote-file map for the PyDevices modules available to PyScript. |
| `manifest.json` | Browser PWA identity: names, icons, scope, and display mode. |
| `pwa.js` | Registers the service worker and manages the browser's install prompt. |
| `pwa.js` | Registers the service worker, sizes an installed app's window to the display, and shows the note that says how to install. |
| `sw.js` | Caches the app shell and runtime, then caches successful GET responses for offline reuse. |
| `style.css` | Shell and canvas presentation. |
| `scripts/vendor_pyscript.sh` | Downloads the pinned offline PyScript release into generated `vendor/pyscript/`. |
| `.github/workflows/deploy.yml` | Template-user Pages deployment: vendors PyScript, stamps the cache version, and publishes the repository root. |
| `.github/workflows/tests.yml` | Vendors PyScript and runs the template's unit tests. |
| `tests/test_template.py` | Checks JSON, source pins, local shell assets, and the Pyodide-only contract. |
| `docs/pwa-guide.md` | Detailed PWA host, cache, deployment, and troubleshooting reference. |
| `docs/pwa-guide.md` | Where the app installs, the service worker's cache, the app window, and edits that don't show. |

## Follow the starter application

Expand All @@ -68,33 +68,32 @@ workers require.
`appdev.App(board_config)` supplies event dispatch and refresh coordination.
4. The demo draws its colour strip, converts pointer events into a selected
colour or paint stroke, and calls `display_drv.show()` to present updates.
5. `pwa.js` registers `sw.js`. On a deployed copy, the workflow substitutes
the commit SHA into the cache name so a new deployment replaces stale shell
assets. After an initial online visit, cached shell/runtime and fetched
assets enable offline launches.
5. `pwa.js` registers `sw.js`. After an initial online visit, the cached
shell, runtime and fetched assets enable offline launches. The cache is
named after `VERSION` in `sw.js`; changing it replaces the old cache.

The template is Pyodide-only: its HTML uses a `type="py"` script. It is not a
direct MicroPython WebAssembly host; use the PyDevices examples Gallery when
that is the target runtime.

## Boundaries worth preserving

- Change the copied application's `main.py`, titles, icons, manifest, and CSS;
do not try to make this upstream template repository its own deployed app.
Its Pages workflow intentionally skips `PyDevices/pyscript-template`.
- Change the copied application's `main.py`, titles, icons, manifest, and CSS.
- Keep `pyscript.json` source URLs pinned. Updating the PyDevices release is a
deliberate dependency change: update the complete file map and verify the
copied application, rather than mixing versions casually.
- `vendor/pyscript/` is generated and ignored by Git. Never hand-edit it;
change the pinned version in `scripts/vendor_pyscript.sh` and regenerate it.
- The service worker cache version is stamped only during deployment. While
developing locally, hard-refresh or unregister the service worker when a
browser appears to serve an old application shell.
- Keep the app at the repository root. The deploy workflow publishes that root
and its service-worker paths assume it.
- Browser installation and offline behavior need a deployed HTTP(S) site and
at least one successful online load. They cannot be proven by opening a file
from disk.
- The service worker serves cached files first. While developing, hard-reload
(Ctrl+Shift+R) or tick DevTools' **Bypass for network** when a browser
appears to serve an old file, and change `VERSION` in `sw.js` when you want
browsers that already have the app to pick up a change. See
[Edits that don't show](pwa-guide.md#edits-that-dont-show).
- Keep the app at the repository root. The service worker's scope and its
cached paths assume it.
- Browser installation and offline behavior need `http://localhost` or an
`https://` origin and at least one successful online load. They cannot be
proven by opening a file from disk.

## Start a safe application change

Expand All @@ -107,8 +106,8 @@ For normal work in a repository created from this template:
`pyscript.json`.
4. Run the local HTTP preview described in the root README; do not use a
`file:` URL.
5. Enable GitHub Pages with GitHub Actions in the copied repository, push to
`main`, and verify install/offline behavior on the deployed site.
5. Install it from Chrome or Edge on localhost and check that its window fits
the display and that it launches with the server stopped.

The template tests can be run with:

Expand All @@ -125,7 +124,7 @@ browser test of pointer input, installation, or offline caching.
- Read `main.py` and `pyscript.json` together for the Python application
boundary and pinned dependency set.
- Read [the PWA guide](pwa-guide.md) before changing service-worker behavior,
deployment, hosting, or installation instructions.
caching, the app window, or installation instructions.
- Read `tests/test_template.py` before moving a shell file or adding a generated
asset to the cache list.
- For display/event APIs, follow the linked PyDevices source release rather
Expand Down
13 changes: 6 additions & 7 deletions docs/packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,12 @@ ordinary wheel works):

## Things you will want to change

- **Canvas size.** `style.css` draws the canvas at most 320 CSS pixels wide.
The app sets the canvas's real size; the CSS only scales it. Piano (480×320)
and the drum machine (720×480) are easier to use wider: raise the `320px`
in the `canvas` rule to the app's width. That also sidesteps a pydevices
0.5.2 bug where a mouse click on a shrunken canvas lands in the wrong place
([pydevices#69](https://github.com/PyDevices/pydevices/pull/69); touch is
not affected).
- **Canvas size.** The template's `main.py` sets the display to 500×500
with `env_set("PYDEVICES_WIDTH", ...)` and `PYDEVICES_HEIGHT` before it
imports `board_config`. Set them to your app's size (piano is 480×320, the
drum machine 720×480); the canvas takes whatever size the display is. The
template uses 500 because Chrome won't make an installed app's window any
narrower.
- **Name and icon.** `manifest.json` (`name`, `short_name`), the `<title>` and
heading in `index.html`, and the two icons.
- **Sound.** Browsers start audio only after a click or tap on the page, so
Expand Down
Loading
Loading