Building an Offline-Only Website

September 27, 2017

This summer I released a small personal project: Offline. It might be the only website that you forces you offline to view it. (I know, it’s weird.)

The project’s seed was planted a few years ago when I was having a really hard time concentrating while writing my thesis. I would routinely get lost on the internet, jumping from one Wikipedia page to the next, constantly engaged, but never productive. I got desperate for progress, so I finally tried simply disconnecting my WiFi. It worked. When I got a sudden urge to Google something or check Facebook I was met with a choice: did I really want to be distracted? Did I really want to admit defeat and reconnect?

I was able to write my thesis. And I kept the trick: if I really need to concentrate, I would try completely disconnecting.

Image telling user to go off-line in order to view application

This summer I decided to take it a step further: could I make a website that forced readers into that same disconnected and focused state? The "offline-first” movement in web development has been gaining momentum (following in the footsteps of the related “mobile-first” trend). Maybe those same principles could be taken further, from offline-first to offline-only.

In the end I pieced together a small offline-only page. Its logic is pretty simple:

  • download all the content
  • don’t display the content; instead, prompt the user to disconnect
  • wait for a disconnection, then display the content
  • if the page is refreshed while disconnected, fetch a cached local copy

The first step is trivial. The initial request returns HTML that, in turn, requires some scripts. I used React because I’m familiar with it, but any framework could be used to achieve this (including no framework at all). The important detail is that the all of the page’s contents are loaded into memory, but rendered only when the user is offline.

Next we have to detect if the user is offline. The navigator.onLine property is widely supported in modern browsers. But this is just a static value. In order to respond when the user goes offline, we’d either have to periodically check navigator.onLine, or listen for an event. Luckily browsers also provide "offline" and "online" events.

In React, this logic can be abstracted into Online and Offline components that only render their children when the browser is online or offline, respectively. I made react-detect-offline to do exactly this. (Check it out and let me know what you think!)

import { Online, Offline } from 'react-detect-offline'; const App = () => ( <div> <Online>Only shown when you're online</Online> <Offline>Only shown offline (surprise!)</Offline> </div> );

The last step is the most complex and the least obvious. If the user refreshes the page while disconnected, we’d like to load a local copy of the page rather than that try (and fail) to fetch a copy from the server. Enter service workers. Luckily, Create React App comes with full support for service workers right out of the box. I built Offline on top of Create React App and took advantage of service workers with zero extra effort.

Plug all the pieces together and you have a strange little piece of the internet that makes you leave the internet. I hope you enjoyed it (or at least got a laugh).