# BookReader v5 is a jQuery core wrapped in web components, and the AGPL is the real adoption decision

> The Internet Archive's book viewer, deployed on archive.org, rebuilt as a hybrid architecture where LitElement side panels listen to custom events emitted by a jQuery core. The public API can still change while v5 is in beta, and the licence is AGPL-3.0, which matters more than either.

**internetarchive/bookreader** — The Internet Archive BookReader

- Repository: https://github.com/internetarchive/bookreader
- Website: https://openlibrary.org/dev/docs/bookreader
- Stars: 1,183 · Forks: 496
- Language: JavaScript
- License: AGPL-3.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/internetarchive-bookreader

## The hybrid architecture is a migration, and it is described honestly

Starting at v5, BookReader introduces a hybrid architecture that merges the core code written in jQuery with its evolution as a web component. The README describes the approach as event driven, and the roadmap is stated plainly: as BookReader moves toward being a web component, the two halves are connected through events.

The mechanism is a split of responsibilities. The core emits custom events reporting the actions it takes, covering UI changes through the core events in `src/BookReader/events.js` and API returns through the search API in the same file. BookNavigator, described as BookReader's web components controller, listens to those events and reacts in order to populate the side menu panels. The reverse direction works through public methods: when BookNavigator reacts to an event it can directly control the core using public functions, and the stated plan is that as the UI is decoupled from the drawing and calculating logic, those logical methods will become easier to spot, will be raised as public methods, and will get unit tests.

That last part is the important one. This is not a rewrite, it is an incremental decoupling with a stated mechanism for growing a testable public surface.

The state of the project is stated in the same spirit. BookReader v5 is currently in beta, it is described as stable enough for production use, and it is actively deployed on archive.org. The warning is that future updates while v5 is in beta may introduce breaking changes to public BookReader APIs, although these will be noted in the CHANGELOG. That is a fair contract, and the release tags show a project moving steadily: v5.0.0-119 on 2026-10-14, v5.0.0-118 on 2026-10-06 and v5.0.0-117 on 2026-08-17, with the last push on 2026-10-14 and the repository not archived.

## The core is jQuery, the panels are LitElement

The division of labour inside the reader is explicit.

The core functionality is in jQuery, and it includes drawing and resizing the book and the various modes, the horizontal navigation, the search API service, and plugins. The side navigation is powered by LitElement flavoured web components.

So the reader is not a single paradigm. The part that touches pixels, the page canvas, the modes such as 1up, 2 page spread and gallery view, the horizontal scroll and the search request, is jQuery code. The part that is the menu and its panels is modern web components. The seam between them is the custom event stream.

This is the part of the design that generates the most discussion, and rightly so. A jQuery core in a project like this is a deliberate choice about what to rewrite and when, and the hybrid arrangement means both the old and the new conventions are in the codebase at once. A contributor has to know which half they are in.

The dependency list makes the same point from the packaging side. Most of the direct dependencies are Internet Archive's own scoped packages: a long series of `@internetarchive/icon-*` packages for the individual icons, `@internetarchive/modal-manager`, `@internetarchive/shared-resize-observer`, `@internetarchive/ia-item-navigator`, `@internetarchive/ia-activity-indicator` and `@internetarchive/bergamot-translator`. On top of that sit third party packages such as `interactjs` for the drag and resize interactions, `iso-language-codes` and the rest.

The icons being separate packages is a scale decision. An interface has hundreds of icons, and shipping each as its own versioned package lets them be consumed independently and updated without a full reader release, at the cost of a very long dependency list for anyone installing the package.

## The plugin system is mixins on the BookReader prototype

The extension mechanism is unusual enough to be worth describing precisely, because it is the main way to add behaviour to the reader without forking it.

The README says a basic plugin system is used, that the general idea is that plugins are mixins that augment the BookReader prototype, and points at the plugins directory for the included files. The named examples show the range.

`plugin.autoplay.js` adds autoplay mode, flipping pages at set intervals. `plugin.chapters.js` renders chapter markers. `plugin.search.js` adds the search user interface and callbacks. `plugin.tts.js` adds text to speech, read aloud, with a sound library and callbacks. `plugin.url.js` automatically updates the browser URL. `plugin.resume.js` uses cookies to remember the current page. `plugin.vendor-fullscreen.js` replaces the fullscreen mode with the vendor's native fullscreen.

Because the mechanism is prototype mixins rather than a class hierarchy or an event subscription, a plugin can add a method to the BookReader object directly. That flexibility is also why the event architecture matters: the mixin surface and the event surface are what a plugin author has to reason about, and the project is trying to shift the balance toward events so the two halves stay decoupled.

The properties side of the core is less finished. The README has a TODO pointing at `src/BookReader/options.js` for the properties, which is a useful indicator of where the documentation lags the code. The options file is where the `data`, `bookTitle`, `thumbnail`, `metadata` and `ui` keys from the usage example are handled.

## Embedding in an iframe is the integration path most adopters want

BookReader can be embedded within an iframe, and this is documented in enough detail to be usable without reading the source.

If you use the IFrame Plugin inside the iframe, the reader sends notifications about changes in the state of the reader via `window.postMessage()`. The parent window can send messages of its own, also via `window.postMessage()`, and the IFrame Plugin handles updating the reader to match.

The message format is specified. The Fragment Change message is sent to the parent window when the embedded BookReader moves between pages or modes, and when the iframe receives it, it moves to the specified page or mode. The fragment is formatted in accordance with the BookReader URL spec.

```json
{
  "type": "bookReaderFragmentChange",
  "fragment": "page/n1/mode/2up"
}
```

The `type` and `fragment` fields are the whole contract, and the fragment encodes both the leaf and the mode, so `page/n1/mode/2up` means the first leaf in two page spread mode. That is a small, readable message format, and the fact that it follows a published URL spec means the parent's deep link handling and its postMessage handling can share a parser.

The live examples in the README show the three deployment shapes: the reader on a details page, the full window view with a `view=theater` query parameter, and an embedded URL for iframes at an `/embed/` path. Anyone building an embeddable book viewer should start by looking at what archive.org itself does with the same component.

## The AGPL-3.0 licence is the decision that cannot be deferred

The package metadata declares the licence as AGPL-3.0, and the LICENSE file at the repository root is the authoritative text. This is the single most consequential fact about the project for anyone embedding it.

The Internet Archive is a nonprofit whose mission is public access to knowledge, and shipping its viewer under the AGPL is consistent with that. The AGPL also reaches networked use, which the GPL does not, and it is that section that matters for a JavaScript component that runs in a browser. The AGPL was written with a specific problem in mind, a modified version of a program running as a service over a network, and a web component that every visitor of your site downloads is uncomfortably close to that case, depending on how the modification is distributed and whether the corresponding source is offered.

I am not offering a legal opinion on how any particular deployment lands, and the reader should not treat the paragraphs above as one. The practical advice is narrower. If you are using BookReader unmodified, which is the expected case, the obligations are far lighter than if you fork it. If you plan to modify it, which is exactly what a plugin-heavy integration often becomes, then the question of what you must publish becomes real and should be answered with your own counsel before you ship, not after.

The package is published publicly to npm as `@internetarchive/bookreader`, with `publishConfig.access` set to public, and the module entry is `dist/esm/ia-bookreader.js` with exports for the esm subpath and a wildcard for everything else. The version is 5.0.0-119.

The licence contrast is worth noting against the rest of the ecosystem. Most JavaScript component libraries are MIT, which is why this decision is easy to miss when you copy a script tag from a demo page. It is the one field in the package.json worth reading before anything else.

## Building the demos, and the two source trees

The development setup explains the hybrid structure better than the architecture section does.

The source JavaScript is written in ES6 and located in `src/js`, and in ES5 and located in `BookReader`. Two directories, two language levels, both shipping, which is the practical cost of supporting a core that predates modern build tooling and a new component layer that does not. The package `files` array includes `BookReader/`, `dist/`, `src/` and `jsconfig.json`, so all three forms are in the published tarball.

The demos live in the `BookReaderDemo` directory and can be tested by building the source files and starting a simple web server, with Node.js installed.

```bash
npm run build
```

```bash
npm run serve
```

Then you open `http://localhost:8000/BookReaderDemo/demo-simple.html`. The README also documents `npm run serve-dev` as an auto-reloading dev server that builds the edited JavaScript and CSS at the same address.

The test and tooling setup is thorough for a project of this age. There is an `.eslintrc.cjs`, a `babel.config.cjs`, a `webpack.config.js`, a `jsconfig.json`, a `.testcaferc.cjs` for browser based end to end tests, a `codecov.yml`, a `netlify.toml` for deploy previews and a `renovate.json` for dependency updates. The `tests/` directory holds the test suite, and there is an `AGENTS.md` at the root plus a `CONTRIBUTING.md`, with the topic list including hacktoberfest.

The icon development instructions are a good illustration of the modular structure. To see local icon package changes in the reader you need to install core-js into the icon package and link it into BookReader, and the README walks through confirming the icon package works in the iaux-icons demo first, then navigating into the icon package directory.

## Conclusion

Adopt BookReader if you are displaying scanned books or similar paginated media and you want the viewer that archive.org itself runs, and you are prepared to live with a v5 beta whose public APIs can still change. Do not adopt it if you cannot accept AGPL-3.0 obligations for a component shipped in a web page, because the licence is the constraint, not the code quality. Verify first that the version you pin has the plugin and event names you need, that your content can be expressed as page images in the data array shape it expects, and that you have read the CHANGELOG entry for every release between your version and the one you plan to deploy.

## FAQ

### What is the Internet Archive BookReader v5 architecture?

It is a hybrid: the core functionality, including drawing, resizing, the viewing modes, horizontal navigation, the search API and plugins, is written in jQuery, while the side navigation panels are LitElement flavoured web components. The core emits custom events and BookNavigator listens and reacts to them, with control flowing back through public methods.

### How do I embed BookReader in an iframe?

Use the IFrame Plugin inside the iframe. The reader then sends state change notifications via window.postMessage, and the parent window can send messages back the same way. The Fragment Change message has the type bookReaderFragmentChange and a fragment such as page/n1/mode/2up.

### How do plugins extend BookReader?

Plugins are mixins that augment the BookReader prototype, and the included examples cover autoplay, chapter markers, search, text to speech, automatic URL updating, remembering the current page with cookies and vendor native fullscreen. The plugin files live in the plugins directory.

### Can I rely on the BookReader public API being stable?

Not yet. The README states that BookReader v5 is in beta, that it is stable enough for production use and is actively deployed on archive.org, but that future updates while v5 is in beta may introduce breaking changes to public BookReader APIs, which will be noted in the CHANGELOG.

### What licence is BookReader released under?

AGPL-3.0, as declared in the package metadata and the LICENSE file at the repository root. The package is published to npm as @internetarchive/bookreader with public access.

## Sources

- [internetarchive/bookreader on GitHub](https://github.com/internetarchive/bookreader)
- [License: AGPL-3.0](https://github.com/internetarchive/bookreader/blob/master/LICENSE)
- [Project website](https://openlibrary.org/dev/docs/bookreader)
- [README](https://github.com/internetarchive/bookreader/blob/master/README.md)
- [Releases](https://github.com/internetarchive/bookreader/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/internetarchive-bookreader
