The open-source engine for building reading apps in the browser.
Render EPUB3, comics, and PDF with a single, framework-agnostic SDK — and ship your own reader, your way.
🚀 Live demo · 📖 Documentation · Website · Report a bug · Request a feature
prose is a free, open-source Reading System Engine — the hard part of an ebook reader, packaged as a modern SDK. It takes care of parsing, layout, pagination, navigation, and rendering so you can focus on building your own reading experience.
It strictly follows the EPUB 3.3 specification and, in theory, can render anything: its enhancer system lets you teach the engine new media types and behaviors. Comics (CBZ/CBR), PDF, and plain text already ship as enhancers — and you can write your own for any format you need.
Developers and teams building reading apps, ebook stores, document viewers, or comic readers for the web (and, via a WebView bridge, React Native). If you'd otherwise glue together a parser, a paginator, and a renderer by hand, prose gives you that foundation out of the box.
No install required — open the live demo and load your own EPUB, CBZ, or PDF.
Ready to build? Follow the Getting started guide to create your first reader in a few minutes.
Issues and pull requests are welcome. CONTRIBUTING.md explains how to report a bug, what a pull request needs, and how it gets released. Everyone taking part follows the code of conduct.
prose is a pnpm workspace, with Lerna on top to run tasks and cut releases.
packages/: the libraries, published to npm as@prose-reader/*.apps/front: the website, with the demo under/demo.apps/docs: the documentation, built with Starlight and published at doc.prose-reader.com.apps/tests: the browser test suite, on Playwright.apps/metadata-fetcher-api: the metadata fetcher as an HTTP service, also published as a Docker image.prose-react-native-demo/: an Expo app. It is not a workspace member: it installs with npm, from its own lockfile, the way an app consuming the libraries would.
Use the Node version in .nvmrc and the pnpm version in the packageManager field of package.json. CI reads the same two pins.
nvm install
nvm use
npm install --global "$(node -p "require('./package.json').packageManager")"
pnpm install
pnpm run build:libBuild the libraries before you run a test or an app. Workspace packages resolve each other to their build output, so a fresh checkout fails on unresolved @prose-reader/* imports until the libraries are built. After you change a library, rebuild it, or keep pnpm run start:lib running to rebuild every library on change.
pnpm install also sets up a pre-commit hook. It runs biome check --write on the staged files: it formats them, applies safe lint fixes, and stops the commit on a lint error it cannot fix.
| Task | Command |
|---|---|
| Build the libraries | pnpm run build:lib |
| Build every project, the website and the documentation included | pnpm run build |
| Rebuild the libraries on every change | pnpm run start:lib |
| Run the website and the demo, on port 9000 | pnpm run start:front |
| Run the documentation, on port 4321 | pnpm run start:docs |
| Run the library watchers, the website and the documentation together | pnpm start |
CI runs these on every pull request, and also builds the metadata fetcher API's Docker image and checks that it starts.
| Check | Command |
|---|---|
| Formatting | pnpm run format |
| Lint | pnpm run lint |
Every AGENTS.md has its CLAUDE.md, every skill its symlink |
pnpm run check:agent-docs |
Internal @prose-reader/* dependency ranges |
pnpm run check:internal-ranges |
@prose-reader/react-native against its Expo SDK |
pnpm run check:expo-sdk |
Types, after pnpm run build |
pnpm run tsc |
| Documentation links and anchors | pnpm --filter prose-reader-docs build |
| Unit tests | pnpm exec lerna run test --ignore prose-reader-tests |
| Browser tests, set up as described below | pnpm --filter prose-reader-tests test |
React Native demo, after pnpm run build:lib |
cd prose-react-native-demo && npm ci && npm run typecheck && npm run bundle |
pnpm --filter @prose-reader/core testruns one package's unit tests.pnpm testruns the unit and browser tests together.pnpm exec biome check --write .fixes formatting and applies safe lint fixes.
The unit tests run in happy-dom or jsdom, which have no layout engine. Behaviour that depends on layout is tested in apps/tests, in real browsers: pagination, a CFI resolving to visible content, restoring a position after a resize, scrolling. apps/tests/AGENTS.md explains how the suite is built.
Install the browser builds that Playwright pins, once:
pnpm --filter prose-reader-tests exec playwright install --with-depsChromium alone is enough while you work on one spec:
pnpm --filter prose-reader-tests exec playwright install chromium
pnpm --filter prose-reader-tests test --project=chromium tests/<path>.spec.ts- The suite imports
@prose-reader/*fromdist/. Rebuild the library you changed before you run a spec again. - Run it on the browsers Playwright installs, not on one your machine already has. A pass on another build is not a pass in CI.
- CI runs the suite on Chromium, Firefox, WebKit and two mobile profiles, on macOS, where the screenshot baselines are rendered. On another OS, the specs that compare screenshots fail locally.
MIT © Maxime Bret
Built with prose: oboku, a modern and free reading app. Come take a look!