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
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Keep pinned GitHub Actions current. Nothing else here is managed by
# Dependabot: Python dependencies are pinned per docs/requirements.txt or
# Dependabot: Python dependencies are
# resolved at build time, not from a lockfile in this repo.
version: 2
updates:
Expand Down
50 changes: 50 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Contributing

Bug reports and fixes are welcome. Open an
[issue](https://github.com/PyDevices/pyscript-template/issues) first for
anything larger than a fix.

## Run the tests

```bash
./scripts/vendor_pyscript.sh
python3 -m unittest discover -s tests -v
```

The suite checks that the shell, service worker, manifest and `pyscript.json`
agree: the JSON parses, every local file `index.html` and `sw.js` mention
exists, the PyDevices source URLs are pinned to the release the test names, the
page uses the Pyodide interpreter, and `pwa.js` leaves the browser's own install
prompt alone. Two tests also run `tests/worklet_sim.mjs` under Node to check the
audio worklet's queue. It does not replace a real browser test of pointer
input, installation or offline caching.

Read `tests/test_template.py` before moving a shell file or adding a generated
asset to the cache list.

## Update a pin

- **PyScript.** Change `PYSCRIPT_VERSION` in `scripts/vendor_pyscript.sh`.
Check <https://pyscript.net/releases/> and confirm
`https://pyscript.net/releases/<version>/offline_<version>.zip` returns 200
before committing. Re-run `./scripts/vendor_pyscript.sh` and the tests.
The wheel tag in [Bring in a bigger
app](docs/guides/bring-in-a-bigger-app.md) depends on the Pyodide that
release ships.
- **PyDevices sources.** Every URL in `pyscript.json` names one PyDevices
release. Change them together and update the release string in
`tests/test_template.py`, then load the app in a browser.
- **Cache.** Change `VERSION` in `sw.js` whenever you change a cached file, so
browsers that already have the app pick the change up.

## Docs

The pages are plain Markdown under `docs/`, starting at
[docs/index.md](docs/index.md). There is no docs build. Check that any link you
add resolves.

## Releasing

The template has no packages and no version of its own: a change is released
by merging it to `main`, and users get it the next time they press **Use this
template** or pull.
124 changes: 31 additions & 93 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,112 +1,50 @@
# PyDevices PyScript template
![The paint demo running in a browser: a row of colour blocks above a canvas with four coloured wavy lines](docs/images/paint.png)

A minimal, installable PyScript application for the portable
[PyDevices](https://github.com/PyDevices/pydevices) display stack.
# PyScript 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.
PyScript template is a starter for an installable browser app that draws with
the PyDevices display stack: Python (Pyodide) on a canvas, working offline once
it has loaded.

## Starter Example: Interactive Touch / Paint
On GitHub, press **Use this template**, or clone it, then serve it from
localhost:

This is exactly what ships in `main.py` — an interactive paint application
demonstrating the PyDevices Board Contract (`board_config` and
`appdev.App`) running in the browser:

```python
import board_config
import appdev
```bash
git clone https://github.com/PyDevices/pyscript-template my-app
cd my-app
./scripts/vendor_pyscript.sh
python3 -m http.server 8000
```

display_drv = board_config.display_drv
app = appdev.App(board_config)
Open <http://localhost:8000>. Here is a paint app in 20 lines; it is a cut-down
`main.py`, which also sets a 500x500 display size:

```python
import board_config, appdev
from pyscript import document
display, app = board_config.display_drv, appdev.App(board_config)
colors = [0xFFFF, 0xF800, 0x07E0, 0x001F, 0x07FF, 0xF81F, 0xFFE0, 0x0000]
block_size = display_drv.width // len(colors)
selected = 0

def draw_palette():
for i, color in enumerate(colors):
x = i * block_size
display_drv.fill_rect(x, 0, block_size, 30, color)
display_drv.show()

draw_palette()

block, selected = display.width // len(colors), 0
for i, color in enumerate(colors):
display.fill_rect(i * block, 0, block, 30, color)
display.show()
document.querySelector("#status").textContent = "Pick a colour, then paint."
def on_touch(event):
global selected
x, y = event.pos
if y < 30:
selected = min(len(colors) - 1, x // block_size)
selected = min(len(colors) - 1, x // block)
else:
display_drv.fill_rect(x - 3, y - 3, 6, 6, colors[selected])
display_drv.show()

display.fill_rect(x - 3, y - 3, 6, 6, colors[selected])
display.show()
app.on(app.events.MOUSEBUTTONDOWN, on_touch)
app.on(app.events.MOUSEMOTION, on_touch)
app.run()
```

## How It Works

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. **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 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).

## Customize

- Edit `main.py` for application behavior.
- Edit `pyscript.json` to add PyDevices source files or Pyodide packages. For
an app that makes sound or uses LVGL, such as piano or the drum machine from
pydevices-examples, see [Bringing in a bigger app](docs/packages.md).
- Change the app name, colors, and icons in `index.html`, `manifest.json`, and `style.css`.
- Change `PYSCRIPT_VERSION` in `scripts/vendor_pyscript.sh` when you choose to
update the browser interpreter. Check the
[PyScript releases page](https://github.com/pyscript/pyscript/releases) or
<https://pyscript.net/releases/> for newer versions before bumping the pin,
and confirm `https://pyscript.net/releases/<version>/offline_<version>.zip`
returns 200 before committing the change.

## Run it locally

From the repository root:

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

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).

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://`.

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

```bash
python3 -m unittest discover -s tests -v
```
Click a colour block along the top, then move the pointer over the canvas to
paint. The picture at the top of this page is that app after four strokes.

The template uses only the `py` interpreter (Pyodide) for the broadest pip-wheel path. The same PyDevices source packages remain portable to MicroPython, CircuitPython, and CPython desktop; use the [direct MicroPython WebAssembly Gallery](https://pydevices.github.io/pydevices-examples/gallery/) for the first-party direct host and complete cross-interpreter examples.
[Docs](https://github.com/PyDevices/pyscript-template/blob/main/docs/index.md) · [Examples](https://pydevices.github.io/pydevices-examples/gallery/) · [Roadmap](ROADMAP.md)

MIT licensed. See `LICENSE`.
Made by [PyDevices](https://pydevices.com).
11 changes: 0 additions & 11 deletions docs/README.md

This file was deleted.

49 changes: 49 additions & 0 deletions docs/get-started/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Make your first app

## Use the template

On GitHub, press **Use this template** on the
[pyscript-template](https://github.com/PyDevices/pyscript-template)
page to make your own repository, or clone it:

```bash
git clone https://github.com/PyDevices/pyscript-template my-app
cd my-app
```

## Run it locally

From the repository root:

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

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). You should see a row of eight
colour blocks above a black canvas. Click a block, then click or drag on the
canvas to paint.

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://`.

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](../guides/make-it-installable.md#edits-that-dont-show) has the rest.

## Make it yours

1. Edit `main.py` to replace the paint demo with your application.
2. Rename the app in `index.html` and `manifest.json`, replace the two icons
and adjust `style.css`.
3. Add only the PyDevices source files or Pyodide packages the app needs to
`pyscript.json`. For an app that makes sound or uses LVGL, see
[Bring in a bigger app](../guides/bring-in-a-bigger-app.md).
4. Install it from Chrome or Edge on localhost, check that its window fits the
display, and check that it launches with the server stopped. The steps are in
[Make your app installable and offline](../guides/make-it-installable.md).
2 changes: 1 addition & 1 deletion docs/packages.md → docs/guides/bring-in-a-bigger-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ worked examples.

## Use the pydevices wheel instead of the file list

`audiodev` alone is fourteen files, so stop listing sources one by one.
`audiodev` alone is a dozen or more files, so stop listing sources one by one.
PyScript's `packages` takes wheel URLs, and the `pydevices` wheel carries the
whole core (`displaydev`, `audiodev`, `appdev`, `events`, `keys`,
`multimer`). Two files still come from the source tree: the browser board
Expand Down
21 changes: 5 additions & 16 deletions docs/pwa-guide.md → docs/guides/make-it-installable.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Progressive Web App (PWA) Guide for PyScript
# Make your app installable and offline

This template is already an installable, offline-capable app. Your PyScript
application can:
Expand Down Expand Up @@ -43,7 +43,7 @@ All of this lives at the repository root:

### The manifest

[`manifest.json`](../manifest.json) tells the browser how the app appears
[`manifest.json`](../../manifest.json) tells the browser how the app appears
once installed. `display: "standalone"` gives it a window with no address bar,
`theme_color` colours the title bar, `background_color` is the splash screen,
and the two icons cover home screens and launchers. Change the names, colours
Expand All @@ -54,7 +54,7 @@ The manifest can't say how big the window should be; there is no such member.

### The service worker

[`sw.js`](../sw.js) caches the shell (`SHELL`) when it installs, then serves
[`sw.js`](../../sw.js) caches the shell (`SHELL`) when it installs, then serves
every GET request from its cache first and caches anything new it fetches. On
the first visit the page starts loading before the worker controls it, so
`pwa.js` also hands the worker the URLs the page already loaded and the worker
Expand Down Expand Up @@ -92,20 +92,9 @@ Browsers decide whether a page may resize its window:

In a tab, `pwa.js` never touches the window.

## Run it locally
## Serve it from localhost

From the repository root:

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

Open <http://localhost:8000>. A service worker only runs on a secure origin:
`http://localhost` counts, `https://` counts, and a file opened from disk or a
LAN address like `http://192.168.1.20:8000` doesn't. On localhost Chrome and
Edge show their install icon, so you can install the app and try its window
from your own machine.
[Run it locally](../get-started/index.md#run-it-locally) has the commands. A service worker only runs on a secure origin: `http://localhost` counts, `https://` counts, and a file opened from disk or a LAN address like `http://192.168.1.20:8000` doesn't. On localhost Chrome and Edge show their install icon, so you can install the app and try its window from your own machine.

### Edits that don't show

Expand Down
2 changes: 1 addition & 1 deletion docs/workers.md → docs/guides/run-in-a-worker.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Python in Web Workers
# Run your Python in Web Workers

By default the template runs your Python on the page's main thread, which
is simple and fine for most apps. When your app redraws a lot *and* has to
Expand Down
Loading
Loading