diff --git a/README.md b/README.md
index 60baf6aee2..10d4189b48 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
# Essential Next.js Build Plugin (beta)
-
-:warning: This is the beta version of the Essential Next.js plugin. For the stable version, see [Essential Next.js plugin v3](https://github.com/netlify/netlify-plugin-nextjs/tree/v3#readme) :warning:
+:warning: This is the beta version of the Essential Next.js plugin. For the stable version, refer to
+[Essential Next.js plugin v3](https://github.com/netlify/netlify-plugin-nextjs/tree/v3#readme) :warning:
@@ -16,16 +16,19 @@
## What's new in this version
-Version 4 is a complete rewrite of the Essential Next.js plugin. For full details of everything that's new, see [the v4 release notes](https://github.com/netlify/netlify-plugin-nextjs/blob/main/docs/release-notes/v4.md)
+Version 4 is a complete rewrite of the Essential Next.js plugin. For full details of everything that's new, check out
+[the v4 release notes](https://github.com/netlify/netlify-plugin-nextjs/blob/main/docs/release-notes/v4.md)
## Installing the beta
-
- Install the module:
+
```shell
npm install -D @netlify/plugin-nextjs@beta
```
-- Change the `publish` directory to `.next` and add the plugin to `netlify.toml` if not already installed:
+
+- Change the `publish` directory to `.next` and add the plugin to `netlify.toml` if not already installed:
+
```toml
[build]
publish = ".next"
@@ -34,16 +37,27 @@ publish = ".next"
package = "@netlify/plugin-nextjs"
```
-If you previously set a custom `distDir` in your `next.config.js`, or set `node_bundler` or `external_node_modules` in your `netlify.toml` these are no longer needed and can be removed.
+If you previously set a custom `distDir` in your `next.config.js`, or set `node_bundler` or `external_node_modules` in
+your `netlify.toml` these are no longer needed and can be removed.
+
+The `serverless` and `experimental-serverless-trace` targets are deprecated in Next 12, and all builds with this plugin
+will now use the default `server` target. If you previously set the target in your `next.config.js`, you should remove
+it.
-The `serverless` and `experimental-serverless-trace` targets are deprecated in Next 12, and all builds with this plugin will now use the default `server` target. If you previously set the target in your `next.config.js`, you should remove it.
+If you are using a monorepo you will need to change `publish` to point to the full path to the built `.next` directory,
+which may be in a subdirectory. If you have changed your `distDir` then it will need to match that.
-If you are using a monorepo you will need to change `publish` to point to the full path to the built `.next` directory, which may be in a subdirectory. If you have changed your `distDir` then it will need to match that.
+If you are using Nx, then you will need to point `publish` to the folder inside `dist`, e.g. `dist/apps/myapp/.next`.
-If you are using Nx, then you will need to point `publish` to the folder inside `dist`, e.g. `dist/apps/myapp/.next`.
+If you currently use redirects or rewrites on your site, see
+[the Rewrites and Redirects guide](https://github.com/netlify/netlify-plugin-nextjs/blob/main/docs/redirects-rewrites.md)
+for information on changes to how they are handled in this version.
-If you currently use redirects or rewrites on your site, see [the Rewrites and Redirects guide](https://github.com/netlify/netlify-plugin-nextjs/blob/main/docs/redirects-rewrites.md) for information on changes to how they are handled in this version.
+If you want to use Next 12's beta Middleware feature, this will mostly work as expected but please
+[read the docs on some caveats and workarounds](https://github.com/netlify/netlify-plugin-nextjs/blob/main/docs/middleware.md)
+that are currently needed.
## Beta feedback
-Please share any thoughts, feedback or questions about the beta [in our discussion](https://github.com/netlify/netlify-plugin-nextjs/discussions/706).
+Please share any thoughts, feedback or questions about the beta
+[in our discussion](https://github.com/netlify/netlify-plugin-nextjs/discussions/706).
diff --git a/docs/middleware.md b/docs/middleware.md
new file mode 100644
index 0000000000..c93ccbe97a
--- /dev/null
+++ b/docs/middleware.md
@@ -0,0 +1,76 @@
+# Using Next 12 middleware on Netlify
+
+Next 12 introduces a new feature called [Middleware](https://nextjs.org/docs/middleware), in which functions
+run before a request has finished processing. Middleware can be used to modify the request or replace the response. For
+example, it can change headers, rewrite the request path, or return a different response entirely.
+
+Next.js Middleware can run either in an edge function or at the origin. On Netlify, middleware runs at the origin as part
+of the normal Next.js server.
+
+## How to deploy Next 12 middleware
+
+Next 12 Middleware works out of the box with Netlify, and most functions will work unchanged. See
+[the middleware docs](https://nextjs.org/docs/middleware) for details of how to create them. There are however a few
+workarounds that are currently required for some features during the beta period:
+
+### `geo`
+
+When running at the origin, Next.js does not populate the `request.geo` object. Fortunately there is a one line fix to get
+the visitor's country:
+
+```typescript
+export async function middleware(req: NextRequest) {
+ // Add this line
+ req.geo.country = req.headers.get('x-country')
+
+ // The rest of your middleware goes here
+}
+```
+
+### `ip`
+
+Next.js also does not populate the `req.ip` value when running at the origin. There is another one line fix for this:
+
+```typescript
+export async function middleware(req: NextRequest) {
+ // Add this line
+ req.ip = req.headers.get('x-nf-client-connection-ip')
+
+ // The rest of your middleware goes here
+}
+```
+
+## Caveats
+
+Because the middleware runs at the origin, it is run _after_ Netlify rewrites and redirects. If a static file is served by the Netlify CDN
+then the middleware is never run, as middleware only runs when a page is served by Next.js. This means that middleware should not be used with the
+`EXPERIMENTAL_MOVE_STATIC_FILES` option, as this causes statically-generated pages to be served by the Netlify CDN
+before any middleware can be run.
+
+There is currently [a bug in Next.js](https://github.com/vercel/next.js/issues/31179) that causes a proxy loop if you
+try to rewrite to a URL with a host other than localhost. If you are using a pattern like this:
+
+```typescript
+export function middleware(req: NextRequest) {
+ // Change the `nextUrl` property in some way
+ req.nextUrl = req.nextUrl.replace('something', 'somethingelse')
+ // ...then rewrite to the changed URL
+ return NextResponse.rewrite(req.nextUrl)
+}
+```
+
+...then you need to set the `nextUrl.host` to `localhost`:
+
+```typescript
+export function middleware(req: NextRequest) {
+ // Change the `nextUrl` property in some way
+ req.nextUrl = req.nextUrl.replace('something', 'somethingelse')
+ req.nextUrl.host = 'localhost'
+
+ // ...then rewrite to the changed URL
+ return NextResponse.rewrite(req.nextUrl)
+}
+```
+
+If you have an issue with Next.js middleware on Netlify while it is beta, particularly if the issue cannot be reproduced when
+running locally, then please add a comment to [the Next plugin beta discussion](https://ntl.fyi/next-beta-feedback).