diff --git a/README.md b/README.md
index d71b3511..8ffd8ce2 100644
--- a/README.md
+++ b/README.md
@@ -182,6 +182,58 @@ Each top-level component receives a `url` property with the following API:
- `pushTo(url)` - performs a `pushState` call that renders the new `url`. This is equivalent to following a ``
- `replaceTo(url)` - performs a `replaceState` call that renders the new `url`
+### Prefetching Pages
+
+When you are switching between pages, Next.js will download new pages from the server and render them for you. So, it'll take some time to download. Because of that, when you click on a page, it might wait few milliseconds (depending on the network speed) before it render the page.
+
+> Once the Next.js has download the page, it'll reuse it in the next time when you navigate to that same page.
+
+This is a problem specially in UX wise. "Prefetching Pages" is one of our solutions for this problem. With this, Next.js will prefetch pages behind the scene using the support of [Service Workers](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers).
+
+#### Declarative API
+
+You can simply ask Next.js to prefetch pages using `next/prefetch`. See:
+
+```jsx
+import Link from 'next/prefetch'
+
+// This is the header component
+export default () => (
+
+ Home
+ Home
+ Home
+
+)
+```
+
+Here you are using `` from `next/prefetch` instead of `next/link`. It's an extended version of `next/link` with prefetching support.
+
+Then Next.js will start to prefetch all the pages behind the scene. So, when you click on any of the link it won't need to do a network hit to fetch the page.
+
+If you need, you could stop prefetching like this:
+
+```jsx
+Home
+```
+
+#### Imperative API
+
+You can get started with prefetching using `` pretty quickly. But you may want to prefetch based on your own logic. (You may need to write a custom prefetching `` based on [premonish](https://github.com/mathisonian/premonish).)
+
+Then you can use the imperative API like this:
+
+```jsx
+import { prefetch } from 'next/prefetch'
+
+prefetch('/')
+prefetch('/features')
+```
+
+When you simply run `prefetch('/page_url')` we'll start prefetching that page.
+
+> We can only do this, if `prefetch` is called when loading the current page. So in general, make sure to run `prefetch` calls in a common module all of your pages import.
+
### Error handling
404 or 500 errors are handled both client and server side by a default component `error.js`. If you wish to override it, define a `_error.js`:
diff --git a/client/next-prefetcher.js b/client/next-prefetcher.js
new file mode 100644
index 00000000..be56830c
--- /dev/null
+++ b/client/next-prefetcher.js
@@ -0,0 +1,100 @@
+/* global self */
+
+const CACHE_NAME = 'next-prefetcher-v1'
+
+self.addEventListener('install', () => {
+ console.log('Installing Next Prefetcher')
+})
+
+self.addEventListener('activate', (e) => {
+ console.log('Activated Next Prefetcher')
+ e.waitUntil(Promise.all([
+ resetCache(),
+ notifyClients()
+ ]))
+})
+
+self.addEventListener('fetch', (e) => {
+ e.respondWith(getResponse(e.request))
+})
+
+self.addEventListener('message', (e) => {
+ switch (e.data.action) {
+ case 'ADD_URL': {
+ console.log('CACHING ', e.data.url)
+ sendReply(e, cacheUrl(e.data.url))
+ break
+ }
+ case 'RESET': {
+ console.log('RESET')
+ sendReply(e, resetCache())
+ break
+ }
+ default:
+ console.error('Unknown action: ' + e.data.action)
+ }
+})
+
+function sendReply (e, result) {
+ const payload = { action: 'REPLY', actionType: e.data.action, replyFor: e.data.id }
+ result
+ .then((result) => {
+ payload.result = result
+ e.source.postMessage(payload)
+ })
+ .catch((error) => {
+ payload.error = error.message
+ e.source.postMessage(payload)
+ })
+}
+
+function cacheUrl (url) {
+ const req = new self.Request(url, {
+ mode: 'no-cors'
+ })
+
+ return self.caches.open(CACHE_NAME)
+ .then((cache) => {
+ return self.fetch(req)
+ .then((res) => cache.put(req, res))
+ })
+}
+
+function getResponse (req) {
+ return self.caches.open(CACHE_NAME)
+ .then((cache) => cache.match(req))
+ .then((res) => {
+ if (res) {
+ console.log('CACHE HIT: ' + req.url)
+ return res
+ } else {
+ console.log('CACHE MISS: ' + req.url)
+ return self.fetch(req)
+ }
+ })
+}
+
+function resetCache () {
+ let cache
+
+ return self.caches.open(CACHE_NAME)
+ .then((c) => {
+ cache = c
+ return cache.keys()
+ })
+ .then(function (items) {
+ const deleteAll = items.map((item) => cache.delete(item))
+ return Promise.all(deleteAll)
+ })
+}
+
+function notifyClients () {
+ return self.clients.claim()
+ .then(() => self.clients.matchAll())
+ .then((clients) => {
+ const notifyAll = clients.map((client) => {
+ return client.postMessage({ action: 'NEXT_PREFETCHER_ACTIVATED' })
+ })
+ return Promise.all(notifyAll)
+ })
+}
diff --git a/examples/with-prefetching/README.md b/examples/with-prefetching/README.md
new file mode 100644
index 00000000..5f5725be
--- /dev/null
+++ b/examples/with-prefetching/README.md
@@ -0,0 +1,13 @@
+# Example app with prefetching pages
+
+This example features:
+
+* An app with four simple pages
+* It will prefetch all the pages in the background except the "contact" page
+
+## How to run it
+
+```sh
+npm install
+npm run dev
+```
diff --git a/examples/with-prefetching/components/Header.js b/examples/with-prefetching/components/Header.js
new file mode 100644
index 00000000..264c7aeb
--- /dev/null
+++ b/examples/with-prefetching/components/Header.js
@@ -0,0 +1,32 @@
+import React from 'react'
+import Link, { prefetch } from 'next/prefetch'
+
+// Prefetch using the imperative API
+prefetch('/')
+
+const styles = {
+ a: {
+ marginRight: 10
+ }
+}
+
+export default () => (
+