PrairieLearn Review Desktop is a local Electron app for reviewing a PDF assessment next to a PrairieLearn instance running in Docker. The app lets you:
- choose a PDF on launch
- start a locally configured PrairieLearn container
- view the PDF and PrairieLearn side by side
- move between locally defined question records
- sync each question to a PrairieLearn URL and a PDF page
- flag questions, add notes, and resume later from local storage
This repo now uses npm workspaces. Current packages:
packages/pl-review-desktop: the Electron review apppackages/pl-puppeteer-sidecar: the terminal-first Puppeteer sidecar
The repo root acts as the workspace manager for these packages and any future siblings.
- Node.js 20+
- Docker Desktop or another local Docker runtime
npm installRun this from the repo root. npm will install dependencies for all workspace packages.
npm startThis root command forwards to the pl-review-desktop workspace package.
To run the Puppeteer sidecar from the workspace root:
npm run sidecar -- --url http://localhost:3000Arguments after the second -- are forwarded to the sidecar package.
To syntax-check the sidecar package:
npm run sidecar:checkTo run the desktop review app test suite:
npm run review:testDesktop tests live under packages/pl-review-desktop/test/.
npm run devIn dev mode, saving files under packages/pl-review-desktop/src/renderer/ reloads the window, while saving packages/pl-review-desktop/src/main.js or packages/pl-review-desktop/src/preload.js relaunches Electron.
If you want to target the package directly, you can also run commands like:
npm run dev --workspace pl-review-desktop- Click
Choose PDFor drag a PDF into the window. - Open the
PrairieLearn Connectionpanel. - Set
Base URLto the PrairieLearn URL you expect locally, such ashttp://127.0.0.1:3000. - Leave the connection mode on
Structuredand choose the local course directory to mount as/course. - The app automatically creates a temporary
pl_ag_jobsdirectory and maps it to/jobs. - If your container needs something different, switch to
Customand paste the full Docker start command instead.
Example:
docker run --rm -p 3000:3000 -v /path/to/course:/course -v /tmp/pl_ag_jobs-abc123:/jobs -e HOST_JOBS_DIR=/tmp/pl_ag_jobs-abc123 -v /var/run/docker.sock:/var/run/docker.sock --add-host=host.docker.internal:172.17.0.1 prairielearn/prairielearn:latestThe app does not modify PrairieLearn itself. Instead, it keeps a local question list where each item stores:
- a label
- a PrairieLearn path or full URL
- a PDF page number
- tags
- notes
- a flagged state
Use Capture Current View after navigating PrairieLearn in the embedded webview to save the current page into the selected question.
- PrairieLearn connection settings are stored in Electron's app data directory.
- Review sessions are stored in renderer
localStorage, keyed by the selected PDF path, so returning to the same file restores your question mappings, flags, notes, and last viewed page.
packages/pl-review-desktop/src/main/contains extracted services for config storage, CLI checks, PrairieLearn runtime orchestration, and webview attachment.packages/pl-review-desktop/src/renderer/now uses a module entrypoint with split state, service, UI, and controller files.- Desktop prerequisite behavior is:
dockerandgitare requiredghis optional and warned on when missing or unauthenticatedstructuredmode builds the Docker command from mounted course directoriescustommode uses the provided Docker command as-isreconnectmode attaches to an already running PrairieLearn container