Revision code

Changes Version 2.0.0
Released on June 17, 2021 with 1255 commits

Unpoly 2 ships with many new features and API improvements, unlocking many use cases that were not possible with Unpoly 1.

For an in-depth guide to all changes, see our Unpoly 2 presentation (150 slides).

If you're upgrading from an older Unpoly version you should load unpoly-migrate.js to enable deprecated APIs. Also see below for an overview of breaking changes.

Change overview

Less need for boilerplate configuration

  • Fragment links often replace the primary content element of your application layout. For this purpose you can now define default targets that are automatically updated when no target selector is given.
  • Unpoly can be configured to handle all links and forms, without any [up-...] attributes.
  • We have examined many real-world Unpoly apps for repetitive configuration and made these options the new default.

New Layer API


  • Overlays allow you to break up a complex screen into subinteractions.
  • Subinteractions take place in overlays and may span one or many pages. The original screen remains open in the background.
  • Once the subinteraction is done, the overlay is closed and a result value is communicated back to the parent layer.
  • You can now define whether a framgent update constitutes a user navigation. Switching screens needs other defaults than updating a tiny box.
  • User navigation aborts earlier requests, fixing race conditions on slow connections.


  • New overlays are focused automatically and trap focus in a cycle. Closing the overlay re-focuses the link that opened it.
  • Focus is automatically managed when rendering major new content. A new [up-focus] attribute allows you to explicitly move the user's focus as you update fragments.
  • Keyboard navigation is supported everywhere.
  • Focus, selection and scroll positions are preserved within an updated fragment.

Reworked Bootstrap integration

  • The Bootstrap integration is now minimal and as unopinionated as possible. Little to no Bootstrap CSS is overridden.
  • Bootstrap versions 3, 4 and 5 are now supported.

Quality of live improvements

  • Unpoly now ships with a bandwidth-friendly polling implementation that handles many edge cases.
  • The position of a clicked link is considered when deciding which element to replace. If possible, Unpoly will update an selector in the region of the link that triggered the fragment update. This helps with multiple self-contained components (with the same selector) on the same page.
  • The log output is more much more compact and has a calmer formatting.
  • New fragments are no longer revealed by default. Instead Unpoly scrolls to the top when the main target has changed, but does not scroll otherwise.
  • History is no longer changed by default. Instead Unpoly updates history only when a main target has changed.
  • All scroll-related options have been unified in a single [up-scroll] attribute.
  • Many optimizations have been made to preserve bandwidth on slow connections. For example, Unpoly stops preloading and polling whenthe connection has high latency or low throughput.
  • The client-side cache can be carefully managed by both the client and server.
  • Unpoly 1 had many functions for updating fragments (up.replace(), up.extract(), up.modal.extract(), etc.). Unpoly 2 has unified these into a single function up.render().
  • Event handlers to up:link:follow, up:form:submit etc. may change the render options for the coming fragment update.
  • Added more options to handle unexpected server responses, including the new up:fragment:loaded event.

Extended server protocol

The optional server protocol has been extended with additional headers that the server may use to interact with the frontend. For example:

See up.protocol for a full list of features.

If you are using Ruby on Rails, the new protocol is already implemented by the unpoly-rails gem.

If you are using Elixir / Phoenix, the new protocol is already implemented by the ex_unpoly package.

Overview of breaking changes

Please use unpoly-migrate.js for a very smooth upgrade process from Unpoly 0.x or 1.x to Unpoly 2.0.

By loading <code>unpoly-migrate.js</code>, calls to most old APIs will be forwarded to the new version. A deprecation notice will be logged to your browser console. This way you can upgrade Unpoly, revive your application with a few changes, then replace deprecated API calls under green tests.

There's a short list of changes that we cannot fix with aliases.

Overlays (modals, popups) have different HTML

But it's similar. E.g. <div class="modal"> becomes <up-modal>.

Unpoly only sees the current layer

You can target other layers with { layer: 'any' }.

Async functions no longer wait for animations

You might or might not notice. In cases where you absolutely do need to wait, an { onFinished } callback can be used.

Tooltips are no longer built-in

But there are a million better libraries.

Unpoly 1 maintenance

  • With the release of Unpoly we're ending maintenance of Unpoly 1. Expect little to no changes to Unpoly 1 in the future.
  • GitHub issues that have been fixed in Unpoly 2 will be closed.
  • The documentation for Unpoly 1 has been archived to
  • The code for Unpoly 1 can be found in the 1.x-stable branch.


If you're upgrading from an older Unpoly version you should load unpoly-migrate.js to polyfill deprecated APIs. Changes handled by unpoly-migrate.js are not considered breaking changes.

See our upgrading guide for details.