Running the UI in a Browser¶
The devcontainer has no display, so the desktop window cannot open there.
Instead, the real UI runs in a browser and talks to the real backend
through the development HTTP server, picturesque-devserver
(ADR-0010).
The server is for development and tests only and is never shipped.
flowchart LR
browser[Browser] -- "/ (UI)" --> vite[Vite dev server<br/>127.0.0.1:5173]
vite -- "/api/* (proxy)" --> dev[picturesque-devserver<br/>127.0.0.1:5174]
dev --> api[picturesque-app Api]
Start both servers¶
make dev-web
Then open http://127.0.0.1:5173. Ctrl+C stops both servers. To reach
the page from the host, forward port 5173 from the devcontainer (VS Code
does this automatically).
The dev server stores its catalog in target/devserver-data/; set
PICTURESQUE_DATA_DIR to use another folder, or delete it to start
fresh. It listens on 127.0.0.1:5174. Set
PICTURESQUE_DEVSERVER_ADDR to change it; non-loopback addresses are
refused, because the server exposes file-system operations. If you change
the port, update the /api proxy in ui/vite.config.ts to match.
Set PICTURESQUE_MODEL_MANIFEST to a JSON file to replace the list of
downloadable AI models; the end-to-end tests use it to serve a tiny model
locally (ui/e2e/fixtures/models.json).
HTTP API¶
The server mirrors the Tauri command API exactly:
GET /api/healthReturns
ok.POST /api/commands/{name}Runs the command
name. The request body is the JSON arguments, or empty when the command takes none. A successful call returns the JSON result with status 200. A failed call returns an error body:{ "code": "unknown_command", "message": "unknown command `nope`" }
codeHTTP status
invalid_arguments400
unknown_command,not_found404
internal500
GET /api/images/{size}/{photo_id}A photo’s cached JPEG (see API).
GET /api/eventsServer-sent events: each backend event (for example import progress) is one
data:line holding a JSON object with atypefield. In the desktop app the same objects arrive as the Tauri eventapp-event.
For example:
$ curl -s -X POST http://127.0.0.1:5174/api/commands/app_info
{"name":"Picturesque","version":"0.1.0"}
End-to-end tests¶
Browser tests live in ui/e2e/ and use Playwright. They start the dev
server and Vite automatically (or reuse ones already running locally):
make ui-deps # once: npm packages and the Playwright Chromium build
make e2e
On failure, Playwright keeps a trace in ui/test-results/; open it with
npx playwright show-trace <path>/trace.zip.
Playwright browser tools for Claude Code¶
.mcp.json configures the Playwright MCP server to use headless
Chromium. Its version is pinned because each release expects a specific
Chromium build. After changing the version, install the matching browser
with that release’s playwright-core (npx playwright install
chromium run from the same package) and restart the session.