Vercel Edge Middleware
Why this is important
When customers look to achieve fast performance, elastic scale, enhanced security, and infrastructure efficiency of their web properties, they turn to Jamstack. The static websites provide this promise. Where static sites typically fail to deliver is when you need to alter the web experience of each individual visitor. The marketing users want to keep personalization and A/B testing capabilities, so they can continuously optimize the web experience and increase the conversions.
While there are client-side tools that work on the DOM-level, this approach predates the modern virtual DOM-based front-end libraries and frameworks, like React and Vue. This causes constant conflict for DOM (HTML), which results in flicker, content swaps, poor UX for your visitors in general, as well as a negative impact on Core Web Vitals.
This is when the digital architects turn back to the server-side rendering. Depending on the specific parameters of the solution, this may set you back in terms of infrastructure overhead and even performance. Going back from the Jamstack paradigm to more traditional server-side rendering can come with some trade-offs.
This is where the edge-side processing of static sites comes to the rescue. Powered by the edge compute capability of a Content Delivery Network, this functionality allows to continue generating static pages at build-time (Jamstack) but also provides the ability to modify page contents before it reaches the users' browser.
This allows keeping the best of both worlds: stellar performance, scale, and security characteristics that Jamstack is great for, and run personalization and A/B testing.
Enter Vercel Edge Middleware
Vercel supports the concept of Edge Middleware, which can act as the edge transformation layer for your static site. To learn more about Vercel Edge Middleware, visit this official documentation.
Next.js v12.2 is not supported yet.
At this moment, the current approach works with Next.js 12.1 and not compatible with Next.js 12.2. Stay tuned, we are updating our implementation to support the updated approach in 12.2.
Uniform and Vercel Edge Middleware
Uniform Context comes with the edge-side SDK and plugs natively into Vercel Edge Middleware allowing business users to manage both personalization and A/B testing without developer involvement. The personalization and A/B testing runs in front of the statically generated pages, outside of the browser, which conquers the flicker, content swaps and Cumulative Layout Shift issues. This capability is what we will be referring to as Edge-side personalization.
To learn more about Edge-side vs. Server-side personalization, check out this doc.
Blazing fast page load without flicker
This is a real webpagetest.org test showing 0.6 second page load without any UX issues:

Quick demo
Open this pre-deployed demo site to experience Uniform personalization running on Vercel Edge Middleware, check it out:

Experience these scenarios
- Open the For Developers page and go back home. Notice the hero changed to show a different message.
- Do a full page reload. Notice the page is stable, and no flicker!
- Now, try disabling JavaScript in your browser dev tools. Refresh the page. Notice the personalization still occurs? This is edge-side execution in action.
- Re-enable JavaScript to continue with the demo.
- Click Forget me to reset the Uniform signal scores. Visit For marketers and return to the home page, notice a different variant. This is personalization based on behavior collected at the edge.
- Go to Registration and complete fake registration. Go back to home. Notice a different hero is shown. This is a cookie-based signal in action. Click Forget me to reset the Uniform signal scores.
- Now visit the Campaign page. Notice
?utm_campaign=unfrmconfis added to the URL and a different hero is shown? This is a query string-based signal in action.
Use cases
The following use cases are possible with Uniform Context + Vercel Edge Middleware:
- GEO-based personalization based on the Geo data available within the Edge Middleware.
- Personalize on any data present on the HTTP request:
utm_campaignor any query string-based personalization- Cookie-based personalization
- Uniform A/B testing
- Personalization based on session context (user preferences, profile, shopping history, etc.).
- CDP-based personalization (or any API-based data context provider for that matter).
This will require fetching this data from the Edge Functions and supplying the values into Uniform Context quirks.
Pre-requisites
- An account with Vercel.
- Access to Github.
- Node.js installed locally.
Deploying the app to Vercel
This sample app is using a "fake CMS", so it's easy to get started.
It's a sample app
This is a sample app geared towards this specific tutorial. It setup with the essentials only, therefore not recommended to be used as a foundation to build a production site.
Clone this repo:
git clone https://github.com/uniformdev/examples.gitcd examples/context-edge-vercelnpm installPrivate npm packages needed
This guide requires access to private Uniform npm packages, requiring an npm token issued by one of the Uniform representatives. Set the token as
NPM_TOKENenvironment variable (recommended), or replace the token reference in.npmrcfile in application root.- If you are an existing customer, please contact support.
- If you are evaluating Uniform, please contact us here.
Install Vercel CLI if you haven't already with
npm i -g vercelRun this command to deploy your site to your Vercel account:
vercel --build-env NPM_TOKEN=<INSERT_NPM_TOKEN_HERE> --prodThis command adds the
NPM_TOKENenvironment variable while deploying your site. The value is the npm token that one of our Uniform representatives provided you with.The CLI will ask you a few questions. Your answers may vary. When asked which directory - hit "enter":
? Set up and deploy “~/code/examples/examples/context-edge-vercel”? [Y/n] y
? Link to different existing project? [Y/n] n
? What’s your project’s name? whatever
? In which directory is your code located? ./After the successful deployment, you may open up the site URL and go through the same scenarios as before to test drive personalization.
- Try disabling the JS in your browser dev tools to see personalization taking place on the Vercel edge side.
Success!
Congratulations, you have your edge-side personalizable site up and running on Vercel Edge Middleware!
Next steps:
If you'd like to understand the internals more, proceed to the deep dive section below.
Optional deep dive
If you would like to reconstruct this whole setup from scratch, this section walks through all the moving pieces. You can use this section to review the sample app we cloned earlier. After going through this doc, you should be able to integrate this capability into your own web application.
Step 1: Get a Next.js app running
You would need a vanilla Next.js app instrumented to Uniform Context SDK basics. If you don't have one running yet, we recommend completing this tutorial here.
Step 2: Enable the edge-side mode
Follow the steps in this doc.
Don't forget
Make sure you set outputType="edge" on your <UniformContext />:
<UniformContext outputType="edge" ...>
...
</UniformContext>
Step 3: Add Uniform edge context SDK
Install the edge specific packages from Uniform as dependencies in your Next.js app:
npm install @uniformdev/context-edge @uniformdev/context-edge-vercel bufferPrivate npm package
This package is private and requires an npm token issued by one of the Uniform representatives.
- If you are an existing customer, please contact support.
- If you are evaluating Uniform, please contact us here.
Create your middleware function under
/pagesas_middleware.ts. The purpose of this middelware is to register Uniform Context middleware and ensure it is processing all pages:import { NextResponse, NextRequest } from "next/server";
import { createEdgeContext } from "@uniformdev/context-edge";
import { createUniformEdgeMiddleware } from "@uniformdev/context-edge-vercel";
import manifest from "../lib/uniform/context-manifest.json";
import { ManifestV2 } from "@uniformdev/context/*";
const IGNORED_PATHS = /^\/.*\.(ico|png|jpg|jpeg|svg)$/g;
export default async function middleware(request: NextRequest) {
if (process.env.NODE_ENV === "development") {
console.log("Middleware disabled in development");
return;
}
if (!process.env.VERCEL_URL) {
console.error("VERCEL_URL environment is not defined");
return new Response("Configuration Error", {
status: 500,
});
}
if (
request.method.toUpperCase() !== "GET" ||
request.nextUrl.pathname.match(IGNORED_PATHS)
) {
return NextResponse.next();
}
const context = createEdgeContext({
manifest: manifest as ManifestV2,
request,
});
const middleware = createUniformEdgeMiddleware();
const response = await middleware({
context,
origin: new URL(`https://${process.env.VERCEL_URL}`),
request,
});
return new Response(response.body, {
...response,
headers: {
...response.headers,
"Cache-Control": "no-store, must-revalidate",
Expires: "0",
},
});
}
That's it! You made it to the end of this walkthrough.