惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
云风的 BLOG
云风的 BLOG
IT之家
IT之家
The Register - Security
The Register - Security
博客园_首页
博客园 - 聂微东
MongoDB | Blog
MongoDB | Blog
Blog — PlanetScale
Blog — PlanetScale
The GitHub Blog
The GitHub Blog
博客园 - 【当耐特】
腾讯CDC
F
Full Disclosure
F
Fortinet All Blogs
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
MyScale Blog
MyScale Blog
T
Tailwind CSS Blog
Jina AI
Jina AI
月光博客
月光博客
A
About on SuperTechFans
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Help Net Security
博客园 - Franky
Vercel News
Vercel News
美团技术团队
C
CERT Recently Published Vulnerability Notes
Security Latest
Security Latest
Scott Helme
Scott Helme
P
Proofpoint News Feed
博客园 - 三生石上(FineUI控件)
www.infosecurity-magazine.com
www.infosecurity-magazine.com
SecWiki News
SecWiki News
The Last Watchdog
The Last Watchdog
U
Unit 42
The Cloudflare Blog
N
News and Events Feed by Topic
T
Threat Research - Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
T
Tenable Blog
V
Vulnerabilities – Threatpost
GbyAI
GbyAI
B
Blog
Webroot Blog
Webroot Blog
A
Arctic Wolf
S
SegmentFault 最新的问题
aimingoo的专栏
aimingoo的专栏
AWS News Blog
AWS News Blog
I
Intezer
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

Vercel News

Vercel Open Source Program: Winter 2026 cohort How Notion Workers run untrusted code at scale with Vercel Sandbox How we run Vercel's CDN in front of Discourse From idea to secure checkout in minutes with Stripe Building Slack agents can be easy Scaling redirects to infinity on Vercel Advancing Python typing Gamma builds design-first agents with Vercel How Avalara turns pipe dreams into patent-pending with v0 Keeping community human while scaling with agents How OpenEvidence built a healthcare AI that physicians actually trust Security boundaries in agentic architectures Skills Night: 69,000+ ways agents are getting smarter Video Generation with AI Gateway We Ralph Wiggumed WebStreams to make them 10x faster How Stably ships AI testing agents in hours, not weeks How we built AEO tracking for coding agents Anyone can build agents, but it takes a platform to run them Introducing Geist Pixel The Vercel AI Accelerator is back with $6m in credits Making agent-friendly pages with content negotiation The Vercel OSS Bug Bounty program is now available Introducing the new v0 Run untrusted code with Vercel Sandbox, now generally available How Stripe built a game-changing app in a single flight with v0 How Sensay went from zero to product in six weeks AGENTS.md outperforms skills in our agent evals Agent skills explained: An FAQ Testing if "bash is all you need" AWS databases are now live on the Vercel Marketplace and v0 Use Perplexity Web Search with Vercel AI Gateway Introducing: React Best Practices Nick Bogaty joins Vercel as Chief Revenue Officer How Mux shipped durable video workflows with their @mux/ai SDK How to build agents with filesystems and bash How we made v0 an effective coding agent Stopping the slow death of internal tools Building AI-Generated Pixel Trading Cards with Vercel AI Gateway We removed 80% of our agent’s tools AI SDK 6 Our $1 million hacker challenge for React2Shell Cline now runs on Vercel AI Gateway How to prompt v0 Build smarter workflows with Notion and v0 Vercel launches partner certification Inside Workflow DevKit: How framework integrations work React2Shell Security Bulletin | Vercel Knowledge Base Billions of requests: Black Friday-Cyber Monday 2025 Investing in the Python ecosystem AWS Databases coming to the Vercel Marketplace How we built the v0 iOS app Workflow Builder: Build your own workflow automation platform Vercel Open Source Program: Fall 2025 cohort Self-driving infrastructure Vercel collaborates with Google for Gemini 3 Pro Preview launch Vercel: The anti-vendor-lock-in cloud How Nous Research used BotID to block automated abuse at scale How AI Gateway runs on Fluid compute What we learned building agents at Vercel Build and deploy data applications on Snowflake with v0 BotID Deep Analysis catches a sophisticated bot network in real-time Vercel achieves TISAX AL2 compliance to serve automotive partners Bun runtime on Vercel Functions David Totten Joins Vercel to Lead Global Field Engineering Vercel Ship AI 2025 recap You can just ship agents AI agents and services on the Vercel Marketplace Built-in durability: Introducing Workflow Development Kit Zero-config backends on Vercel AI Cloud Introducing Vercel Agent: Your new Vercel teammate Update regarding Vercel service disruption on October 20, 2025 Agents at work, a partnership with Salesforce and Slack Running Next.js in ChatGPT: How to Build ChatGPT Apps Talha Tariq joins Vercel as CTO of Security Just another (Black) Friday Server rendering benchmarks: Fluid Compute and Cloudflare Workers Towards the AI Cloud: Our Series F Collaborating with Anthropic on Claude Sonnet 4.5 to power intelligent coding agents Preventing the stampede: Request collapsing in the Vercel CDN BotID uncovers hidden SEO poisoning How we made global routing faster with Bloom filters What you need to know about vibe coding Scale to one: How Fluid solves cold starts Addressing security & quality issues with MCP tools - Vercel AI agents at scale: Rox’s Vercel-powered revenue operating system Agentic Infrastructure Zero Data Retention on AI Gateway Optimizing Vercel Sandbox snapshots How Waldium made a blog platform work for humans and AI alike How FLORA shipped a creative agent on Vercel's AI stack Agent responsibly Making Turborepo 96% faster with agents, sandboxes, and humans Unified reporting for all AI Gateway usage new.website joins forces with v0 SERHANT.'s playbook for rapid AI iteration Two startups at global scale without DevOps Chat SDK brings agents to your users 360 billion tokens, 3 million customers, 6 engineers Meet the 2026 Vercel AI Accelerator Cohort Build knowledge agents without embeddings
How to run A/B tests with Next.js and Vercel - Vercel – Vercel
Steven Tey · 2022-09-09 · via Vercel News

4 min read

Running A/B tests is hard.

We all know how important it is for our business–it helps us understand how users are interacting with our products in the real world.

However, a lot of the A/B testing solutions are done on the client side, which introduces layout shift as variants are dynamically injected after the initial page load. This negatively impacts your websites performance and creates a subpar user experience.

To get the best of both worlds, we built Edge Middleware: code that runs before serving requests from the edge cache. This enables developers to perform rewrites at the edge to show different variants of the same page to different users.

Today, we'll take a look at a real-world example of how we used Edge Middleware to A/B test our new Templates page.

Link to headingRedesigning the Template Marketplace

Earlier this year, we kickstarted the redesign of our Templates page.

Our old Templates page had a limited scope that focused mainly on the different frameworks that were supported on Vercel:

Old version: limited selection of templates that focused mainly on framework starters.Old version: limited selection of templates that focused mainly on framework starters.

Old version: limited selection of templates that focused mainly on framework starters.

For the new version, we wanted to build a marketplace to showcase all the different types of applications that can be built on Vercel – blogs, e-commerce storefronts, etc.

We also improved search to allow for partial matching of search terms and added category filters to make discovering new templates much easier:

New version: wider selection of templates with fuzzy search & filters.New version: wider selection of templates with fuzzy search & filters.

New version: wider selection of templates with fuzzy search & filters.

Since this was a major change of one of our most popular pages, we decided to break down the launch into multiple release phases:

  1. Early Access: Only 20% of visitors to /templates will see the new variant.

  2. Public Beta: An equal 50:50 split between the new and old variant.

  3. General Availability: Public launch–everyone gets the new variant.

We used Vercel's Edge Middleware to stagger our launch into 3 phases.We used Vercel's Edge Middleware to stagger our launch into 3 phases.

We used Vercel's Edge Middleware to stagger our launch into 3 phases.

We leveraged Edge Middleware to perform the A/B test at the edge, which allowed us to gather insightful user feedback without sacrificing performance.

Link to headingCatch-all Routes & On-demand Revalidation

Since we were using Next.js, we decided to create the new templates marketplace using the following optional catch-all route: /templates/[[...slug]].tsx.

This allowed us to programmatically generate new static pages when new templates are added using On-Demand Incremental Static Regeneration (ISR) and navigate between them using shallow-routing.

Here are some examples:

We also generated dynamic landing pages for each filter option to capture long-tail SEO traffic:

We then moved the old templates marketplace to the /templates-old.tsx route.

Link to headingExperimenting at the Edge

To perform the A/B test, we created a middleware.ts file with the following code:

middleware.ts

import { type NextRequest, NextResponse } from 'next/server';

// make sure the middleware only runs when

// the requested url starts with `/templates`

export const config = {

matcher: ['/templates(.*)'],

};

const THRESHOLD = 0.2; // initial threshold for the new variant (20%)

const COOKIE_NAME = 'tm_var'; // name of the cookie to store the variant

export function middleware(req: NextRequest) {

// get the variant from the cookie

// if not found, randomly set a variant based on threshold

const variant =

req.cookies.get(COOKIE_NAME) || (Math.random() < THRESHOLD ? 'new' : 'old');

const url = req.nextUrl.clone();

// if it's the old variant, rewrite to the old templates marketplace

if (variant === 'old') {

url.pathname = '/templates-old';

}

const res = NextResponse.rewrite(url);

// set the variant in the cookie if not already set

if (!req.cookies.get(COOKIE_NAME)) {

res.cookies.set(COOKIE_NAME, variant);

}

return res;

}

Middleware code to perform the A/B test at the edge.

Here's a step by step of what the middleware does:

  1. Tags each new visitor to the /templates page with either the old or new variant based on the current threshold (0.2 for the first stage)

  2. If the user is part of the old variant, performs a rewrite to the /templates-old.tsx route

  3. Saves the user's variant in the tm_var cookie to ensure the user gets served the same version in subsequent visits

Link to headingAvoiding layout shift with Edge Middleware

As we developed the new templates page, we ran into an interesting problem–data fetching had to be done on the client side for three reasons:

  1. We were using query parameters to preserve the filter state

  2. The pages were generated statically

  3. You can't read query parameters inside getStaticProps

To avoid layout shift, we decided to use skeleton loaders to buffer the loading state before showing the templates that match the configured filters.

For instance, if you go to vercel.com/templates?framework=svelte, you first receive a set of skeleton loaders while the data is fetched on the client side, and then the list of Svelte templates:

However, for the dynamic landing pages for each filter option (e.g. vercel.com/templates/svelte), we wanted to avoid skeleton loaders since we already know the set of templates that match the given filter at build time.

To get the best of both worlds, we used Edge Middleware. Since Edge Middleware is executed before a request is processed on a site, we are able to detect if there are any query parameters present right when the user requests the page.

Then, if there are query parameters present, we perform a rewrite to /templates/skeleton, which is a special route that shows a skeleton loader.

Here's the middleware code from earlier, with the addition of this logic:

middleware.ts

import { type NextRequest, NextResponse } from 'next/server';

// make sure the middleware only runs when

// the requested url starts with `/templates`

export const config = {

matcher: ['/templates(.*)'],

};

const THRESHOLD = 0.2; // initial threshold for the new variant (20%)

const COOKIE_NAME = 'tm_var'; // name of the cookie to store the variant

export function middleware(req: NextRequest) {

// get the variant from the cookie

// if not found, randomly set a variant based on threshold

const variant =

req.cookies.get(COOKIE_NAME) || (Math.random() < THRESHOLD ? 'new' : 'old');

const url = req.nextUrl.clone();

// if it's the old variant, rewrite to the old templates marketplace

if (variant === 'old') {

url.pathname = '/templates-old';

} else {

// for the new variant, we need to perform a rewrite to /template/skeleton

// if there are query paramters in the request URL

const hasQueryParams = req.nextUrl.search.length > 0;

if (hasQueryParams) {

url.pathname = `/templates/skeleton`;

}

}

const res = NextResponse.rewrite(url);

// set the variant in the cookie if not already set

if (!req.cookies.get(COOKIE_NAME)) {

res.cookies.set(COOKIE_NAME, variant);

}

return res;

}

Middleware code to perform an edge rewrite to avoid layout shift.

Then, on the client side, we detect when the data is finished fetching with SWR and render the final list of cards:

templates/[[...slug]].tsx

import useSWR from "swr"

import { useRouter } from "next/router"

import { Card, PlaceholderCard, CardProps } from '@/components/cards'

export default function Templates({ skeleton } : { skeleton: boolean }) {

const router = useRouter()

const { data } = useSWR<CardProps[]>("/api/templates")

// if skeleton is true and the router is still loading, show a skeleton

if (!data || (skeleton && !router.isReady)) {

return (

<div>

{[...Array(6).keys()].map((i: number) => (

<PlaceholderCard key={i}/>

))}

</div>

)

}

return (

<div>

{data.map((d: CardProps, i) => (

<Card key={i} data={d} />

))}

</div>

)

}

export function getStaticProps(context) {

const skeleton = context.params?.slug?.includes('skeleton')

return {

props: {

skeleton,

},

}

}

Simplified version of the code that shows how we use SWR and middleware to conditionally render loader skeletons on the client side if there are query parameters present in the request URL.

Link to headingCollecting data & iterating

Throughout our Early Access and Public Beta phases, we collected a series of data points that helped us understand how our new Templates Marketplace was performing in the real world.

Link to headingTracking conversion rates with Heap

We used Heap to track our conversion rates: how likely is a user to successfully deploy a template after seeing it on the new vs. old Templates pages.

Based on the data from Heap, we were able to make some tweaks to our implementation to increase conversion rates by 16% with the new variant.

Link to headingTracking search & filter usage Stats with Algolia

Algolia's Search Without Results feature was also instrumental for us to understand which templates users were interested in. Based on the data, we were getting >30 searches a week for WordPress templates that yielded no results.

This prompted us to add a few WordPress templates before releasing the Templates Marketplace to General Availability.

Link to headingEdge Middleware: Run A/B tests without the tradeoffs

Edge Middleware allowed us to streamline the release of our new Templates Marketplace by putting the new version behind a feature flag until it's fully tested and optimized.

Check out our Templates Marketplace today to jumpstart your app development process with our pre-built solutions.