Skip to main content
RapidDev - Software Development Agency
v0-integrationsNext.js API Route

How to Integrate Magento with V0

To integrate Magento with V0 by Vercel, generate a Next.js storefront UI with V0, create API routes that call the Magento REST API using an admin or customer access token, store your Magento base URL and credentials in Vercel environment variables, and deploy. Your app can display product catalogs, shopping carts, and order histories from a Magento or Adobe Commerce backend.

What you'll learn

  • How to generate Magento admin and integration tokens for secure API authentication
  • How to generate a headless e-commerce storefront UI with V0 including product listings and cart components
  • How to create Next.js API routes that fetch Magento product catalog, cart, and order data
  • How to handle Magento's token-based authentication in server-side API routes
  • How to connect a V0-generated frontend to a live Magento or Adobe Commerce backend
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read45 minutesE-commerceApril 2026RapidDev Engineering Team
TL;DR

To integrate Magento with V0 by Vercel, generate a Next.js storefront UI with V0, create API routes that call the Magento REST API using an admin or customer access token, store your Magento base URL and credentials in Vercel environment variables, and deploy. Your app can display product catalogs, shopping carts, and order histories from a Magento or Adobe Commerce backend.

Build a Headless Magento Storefront with V0 and Next.js on Vercel

Magento powers over 250,000 e-commerce sites and is the dominant choice for enterprise B2B and large retail operations. Many businesses want the reliability of Magento as a backend combined with the performance and developer experience of a modern Next.js frontend — this is the headless commerce pattern. V0 can generate high-quality e-commerce UI components (product grids, filter sidebars, product detail pages, cart drawers, checkout flows) that you connect to your Magento backend via Next.js API routes.

Magento's REST API is comprehensive, covering the entire e-commerce lifecycle: product catalog management, category navigation, product search, shopping cart operations, customer accounts, order history, and checkout. The API supports both admin-level access (for fetching and managing catalog data) and customer-level access (for cart operations and order history tied to specific customer accounts). For a headless storefront, you typically use admin tokens server-side for catalog data and generate customer tokens server-side after customer authentication.

The Next.js and Magento combination is increasingly popular as the headless storefront pattern matures. Next.js's ISR (Incremental Static Regeneration) is ideal for product pages — you can statically generate product pages at build time and revalidate them periodically as Magento product data changes, combining the speed of static generation with the freshness of server-side rendering. V0 is particularly strong at generating the product listing page, product detail page, and shopping cart components that form the core of a headless storefront.

Integration method

Next.js API Route

Magento integrates with V0-generated Next.js apps through server-side API routes that call the Magento REST API or GraphQL API using admin tokens or customer tokens. Your Magento admin credentials and base URL are stored as server-only Vercel environment variables. The V0-generated storefront UI calls your Next.js routes, which proxy requests to your Magento instance and return structured product, cart, and order data for rendering.

Prerequisites

  • A running Magento or Adobe Commerce instance — either self-hosted, Magento Cloud, or Adobe Commerce Cloud — with the REST API accessible from the internet
  • Magento admin access to generate an Integration token — navigate to System → Integrations → Add New Integration, set required permissions, and note the Access Token provided
  • Your Magento store base URL (e.g., https://your-magento-store.com) — the REST API is at {baseUrl}/rest/V1/
  • A V0 account at v0.dev and a Vercel account for deploying the Next.js storefront
  • Basic understanding of headless commerce — the Next.js frontend handles all rendering while Magento serves as the data API, with no Magento theme or frontend code deployed

Step-by-step guide

1

Generate the Storefront UI Components with V0

Open V0 at v0.dev and describe the e-commerce components you want to build. Magento data maps well to standard e-commerce patterns — product listings, category navigation, product detail pages, and cart management. The key advantage of V0 for headless Magento is that you can describe exactly the UX you want without being constrained by Magento's Luma theme or PWA Studio defaults. Be specific about product card layouts, filter sidebar behavior, variant selectors (size/color pickers for configurable products), and cart drawer animation. Magento product objects include fields like name, sku, price, special_price (sale price), media_gallery_entries (images), extension_attributes (stock status), and custom_attributes (any configurable attributes your store has defined). Describe these fields to V0 so it generates components with the right data bindings. For the product listing page, mention that you want ISR-compatible rendering — the page component fetches products server-side rather than client-side, which works with Next.js ISR for fast, cacheable responses. For the cart, describe a slide-in drawer pattern that persists cart state in localStorage (or a cookie) and syncs with Magento's cart API. After generating, push to GitHub via V0's Git panel and connect to Vercel.

V0 Prompt

Create a headless Magento product listing page component. The component receives a 'products' prop (array of product objects) and 'total' count. Render products in a responsive grid (4 columns desktop, 2 tablet, 1 mobile). Each product card: product image, product name, 'by {brandName}' subtitle, original price, sale price in red (if different), stock badge ('In Stock'/'Out of Stock'), star rating, and 'Add to Cart' button that calls addToCart(product.sku) prop function. Show a loading skeleton grid while products are undefined. Include a no-results empty state. Export as ProductGrid component.

Paste this in V0 chat

Pro tip: Ask V0 to generate a separate CartDrawer component that slides in from the right — this is the standard e-commerce cart pattern and V0 generates it well with Tailwind CSS animations and a semi-transparent overlay background.

Expected result: A ProductGrid component renders in V0's preview with product cards, sale price display, stock badges, and Add to Cart buttons. The component accepts a products array prop and handles loading and empty states.

2

Create the Magento Authentication and Product API Routes

Create the Next.js API routes that authenticate with Magento and fetch product catalog data. Magento's REST API uses bearer token authentication — for admin operations like fetching the full catalog, you use an Integration access token generated in the Magento admin. For customer-specific operations (cart, orders), you generate a customer token by calling the customer token endpoint with the customer's email and password credentials. For a headless storefront, the most common pattern is using the Integration token server-side for all catalog operations (since these are public data) and handling customer authentication separately through your Next.js auth layer. The Magento product search endpoint (GET /rest/V1/products) supports complex filtering using searchCriteria parameters — you can filter by category, price range, attribute values, and text search using a URL query string format that Magento parses into its search framework. Product responses include all configured attributes, images, pricing rules, and stock information. The response is paginated with total_count for building pagination controls. For configurable products (products with size/color variants), additional calls to /rest/V1/configurable-products/{sku}/options and /rest/V1/configurable-products/{sku}/children fetch the variant options and child product SKUs.

app/api/magento/products/route.ts
1// app/api/magento/products/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3
4const MAGENTO_BASE_URL = process.env.MAGENTO_BASE_URL;
5const MAGENTO_TOKEN = process.env.MAGENTO_INTEGRATION_TOKEN;
6
7interface MagentoProduct {
8 id: number;
9 sku: string;
10 name: string;
11 price: number;
12 status: number;
13 type_id: string;
14 media_gallery_entries?: Array<{ file: string; position: number; disabled: boolean }>;
15 custom_attributes?: Array<{ attribute_code: string; value: string }>;
16 extension_attributes?: { stock_item?: { qty: number; is_in_stock: boolean } };
17}
18
19function getMagentoImageUrl(baseUrl: string, file: string) {
20 return `${baseUrl}/pub/media/catalog/product${file}`;
21}
22
23export async function GET(request: NextRequest) {
24 if (!MAGENTO_BASE_URL || !MAGENTO_TOKEN) {
25 return NextResponse.json(
26 { error: 'Magento is not configured' },
27 { status: 500 }
28 );
29 }
30
31 const { searchParams } = new URL(request.url);
32 const page = parseInt(searchParams.get('page') ?? '1', 10);
33 const pageSize = parseInt(searchParams.get('pageSize') ?? '20', 10);
34 const categoryId = searchParams.get('categoryId') ?? '';
35 const searchQuery = searchParams.get('q') ?? '';
36
37 // Build Magento searchCriteria query parameters
38 const params = new URLSearchParams({
39 'searchCriteria[currentPage]': page.toString(),
40 'searchCriteria[pageSize]': pageSize.toString(),
41 'searchCriteria[filter_groups][0][filters][0][field]': 'status',
42 'searchCriteria[filter_groups][0][filters][0][value]': '1',
43 'searchCriteria[filter_groups][0][filters][0][condition_type]': 'eq',
44 fields:
45 'items[id,sku,name,price,extension_attributes,media_gallery_entries,custom_attributes],total_count',
46 });
47
48 if (categoryId) {
49 params.set('searchCriteria[filter_groups][1][filters][0][field]', 'category_id');
50 params.set('searchCriteria[filter_groups][1][filters][0][value]', categoryId);
51 params.set('searchCriteria[filter_groups][1][filters][0][condition_type]', 'eq');
52 }
53
54 if (searchQuery) {
55 params.set('searchCriteria[filter_groups][2][filters][0][field]', 'name');
56 params.set('searchCriteria[filter_groups][2][filters][0][value]', `%${searchQuery}%`);
57 params.set('searchCriteria[filter_groups][2][filters][0][condition_type]', 'like');
58 }
59
60 try {
61 const response = await fetch(
62 `${MAGENTO_BASE_URL}/rest/V1/products?${params.toString()}`,
63 {
64 headers: {
65 Authorization: `Bearer ${MAGENTO_TOKEN}`,
66 'Content-Type': 'application/json',
67 },
68 next: { revalidate: 300 }, // Cache for 5 minutes
69 }
70 );
71
72 if (!response.ok) {
73 throw new Error(`Magento API error: ${response.status}`);
74 }
75
76 const data = await response.json() as { items: MagentoProduct[]; total_count: number };
77
78 const products = (data.items ?? []).map((item) => {
79 const salePrice = item.custom_attributes?.find(
80 (a) => a.attribute_code === 'special_price'
81 )?.value;
82
83 const image = item.media_gallery_entries?.find((e) => !e.disabled && e.position === 1);
84
85 return {
86 id: item.id,
87 sku: item.sku,
88 name: item.name,
89 price: item.price,
90 salePrice: salePrice ? parseFloat(salePrice) : null,
91 imageUrl: image ? getMagentoImageUrl(MAGENTO_BASE_URL!, image.file) : null,
92 inStock: item.extension_attributes?.stock_item?.is_in_stock ?? true,
93 stockQty: item.extension_attributes?.stock_item?.qty ?? 0,
94 };
95 });
96
97 return NextResponse.json({
98 products,
99 totalCount: data.total_count,
100 page,
101 pageSize,
102 });
103 } catch (error) {
104 const message = error instanceof Error ? error.message : 'Unknown error';
105 console.error('Magento API error:', message);
106 return NextResponse.json(
107 { error: 'Failed to fetch products', details: message },
108 { status: 500 }
109 );
110 }
111}

Pro tip: Use the Magento 'fields' query parameter to request only the product fields your storefront needs — by default Magento returns all product attributes which can make responses very large. Specifying fields like 'items[id,sku,name,price,media_gallery_entries]' dramatically reduces payload size.

Expected result: GET /api/magento/products returns a normalized array of product objects with name, price, sale price, image URL, and stock status from your Magento catalog. Pagination and category filtering work via query parameters.

3

Implement Cart Operations with Magento Guest Cart API

Create the cart API routes that handle add-to-cart, update quantity, and checkout operations. Magento supports two cart types: guest carts (for anonymous shoppers) and customer carts (for authenticated customers). For a public storefront, start with guest carts — the flow is to create a cart (POST /rest/V1/guest-carts which returns a cart ID token), then add items to the cart using that token (POST /rest/V1/guest-carts/{cartId}/items). Store the cart ID in a browser cookie or localStorage so it persists across page loads. The cart ID is not sensitive data, but treat it with reasonable care since anyone with the cart ID can access and modify that cart. For the cart display, GET /rest/V1/guest-carts/{cartId} returns the full cart with items, quantities, prices, and totals. For checkout, the Magento REST API supports a complete checkout flow including shipping address collection, shipping method estimation, payment information submission, and order placement. For most V0 storefront projects, a simplified flow that directs customers to the Magento checkout page (at your Magento store URL) after adding items to the cart is the fastest path to a working checkout — deep Next.js checkout integration with Magento requires implementing the full checkout API sequence which is complex to build and test correctly. The cart REST API also supports coupon code application (PUT /rest/V1/guest-carts/{cartId}/coupons/{couponCode}) for promotion codes.

V0 Prompt

Create a CartDrawer component that slides in from the right. It receives: isOpen (boolean), onClose (function), cartItems (array of {name, sku, price, quantity, imageUrl}), and cartTotal (number). Show cart items as a list with image thumbnail, product name, quantity control (+/-), item price, and a remove button. Show the cart subtotal at the bottom. Add a 'Proceed to Checkout' button and a 'Continue Shopping' link that closes the drawer. Show an empty cart message with a shopping bag icon when cartItems is empty. Add a semi-transparent dark overlay behind the drawer. Animate the drawer sliding in from the right using CSS transitions.

Paste this in V0 chat

Pro tip: For a simpler implementation, redirect customers to your Magento store's cart page (e.g., https://your-magento-store.com/checkout/cart) after adding items rather than building a full custom checkout. This lets V0 handle the product discovery UI while Magento handles the trusted checkout experience.

Expected result: The CartDrawer component slides in when items are added, showing product details, quantity controls, and the subtotal. The Proceed to Checkout button routes to the Magento checkout flow.

4

Configure Environment Variables and Deploy to Vercel

Push your code to GitHub and configure Magento credentials in Vercel. Open the Vercel Dashboard, select your project, and navigate to Settings → Environment Variables. Add MAGENTO_BASE_URL with your Magento store's base URL (without a trailing slash, e.g., https://your-magento-store.com), and MAGENTO_INTEGRATION_TOKEN with the Integration access token from Magento's admin panel (System → Integrations → your integration → Access Token). Neither variable should have the NEXT_PUBLIC_ prefix — Magento API calls should always be server-side to protect your integration token and avoid CORS issues. If you need the Magento URL accessible in client-side code (for image URLs), you can expose only the base URL as NEXT_PUBLIC_MAGENTO_BASE_URL since it's not sensitive. After adding environment variables for Production (and Preview if you want to test against a staging Magento instance), save and redeploy. Verify the deployment by opening your Vercel URL and checking that the product catalog loads from Magento. If you see CORS errors, confirm that all API calls are going through your Next.js API routes and not directly from the browser to Magento. Magento's REST API may need to have CORS configured if you're calling it from the client side, but the Next.js API route pattern avoids CORS entirely.

Pro tip: Test your Magento integration token by calling your Magento REST API directly in a browser: {MAGENTO_BASE_URL}/rest/V1/store/storeConfig with an Authorization: Bearer header. If you get a 200 response with store config data, your token and URL are correct.

Expected result: The Vercel deployment succeeds and the product catalog loads real products from your Magento backend with images, prices, stock status, and working Add to Cart functionality.

Common use cases

Headless Product Catalog

A Next.js product listing page that fetches the Magento catalog via API routes and renders products with filtering, sorting, and pagination. ISR keeps product data current without full page rebuilds on every request.

V0 Prompt

Create a product catalog page for an e-commerce store. Left sidebar has category filters (Electronics, Clothing, Accessories), price range slider, and brand checkbox filters. Main area shows products in a 4-column grid. Each product card has: product image placeholder, product name, brand name, price with a sale price crossed out if applicable, star rating with count, 'Add to Cart' button, and a wishlist heart icon. Top bar shows product count and sort dropdown (Price: Low to High, Newest, Best Sellers). Include pagination at the bottom. Use a clean modern e-commerce design.

Copy this prompt to try it in V0

Product Detail Page

A rich product detail page pulling Magento's full product data including images, attributes, configurable options (size/color), stock status, and related products. Customers can select variants and add to cart directly from the page.

V0 Prompt

Build a product detail page. Left side: large image with 4 thumbnail images below. Right side: product name (h1), SKU in gray, star rating row, price and sale price, a size selector with buttons (XS S M L XL), a color selector with colored circles, quantity input with +/- buttons, a large 'Add to Cart' button in blue, and an 'Add to Wishlist' link. Below the fold: a tabbed section with Product Description, Specifications (table), and Reviews. At the bottom: 'You Might Also Like' horizontal scroll of related product cards. Clean white design with bold typography.

Copy this prompt to try it in V0

Customer Order History Dashboard

An authenticated customer portal showing past Magento orders with status tracking, order details, and reorder functionality. Customers can view their complete purchase history and track shipments without navigating Magento's own account portal.

V0 Prompt

Design a customer account order history page. Header shows customer name and member-since date. Below: a list of orders sorted newest first. Each order row shows: order number, order date, total price, status badge (Processing/Shipped/Delivered in different colors), number of items, and 'View Details' and 'Reorder' buttons. Clicking 'View Details' expands an accordion showing individual line items with product names, quantities, and prices. Include a search bar to filter orders by order number. Use account dashboard styling with a left nav showing Account, Orders, Addresses, and Payment Methods.

Copy this prompt to try it in V0

Troubleshooting

Magento API returns 401 Unauthorized despite correct token

Cause: The Magento Integration token may have been regenerated, the integration may be inactive, or the token was created with insufficient API permissions. Token permissions in Magento are granular — the integration must have access to the specific API resources you're calling.

Solution: Log into Magento admin and navigate to System → Integrations. Find your integration and check that it's Active and that the Resource Access is set to 'All' or includes Products, Categories, and Cart endpoints. If the token was regenerated, update MAGENTO_INTEGRATION_TOKEN in Vercel. Trigger a redeployment after updating environment variables.

Product images return 404 or broken image errors

Cause: The Magento image URL is constructed incorrectly, the media base URL is different from the store base URL, or the Magento media files are served from a CDN with a different domain.

Solution: Fetch the media base URL from the Magento store config endpoint (GET /rest/V1/store/storeConfig) — the response includes a base_media_url field that is the correct URL prefix for product images. Use this value instead of constructing image URLs manually from your MAGENTO_BASE_URL.

typescript
1// Fetch actual media URL from Magento:
2const config = await fetch(`${MAGENTO_BASE_URL}/rest/V1/store/storeConfig`, headers);
3const { base_media_url } = await config.json();
4const imageUrl = `${base_media_url}catalog/product${item.media_gallery_entries[0].file}`;

searchCriteria filters return all products instead of filtering correctly

Cause: Magento's searchCriteria URL parameter format is complex and uses indexed arrays — incorrect indexing causes filters to be ignored silently rather than throwing errors.

Solution: Verify your searchCriteria URL parameters are correctly structured. The format uses bracketed notation: searchCriteria[filter_groups][0][filters][0][field]=status. Each filter group is ANDed together, filters within a group are ORed. Use a URL debugger to confirm the parameter string is correctly encoded before sending to Magento.

typescript
1// Correct searchCriteria structure for category filter:
2params.set('searchCriteria[filter_groups][0][filters][0][field]', 'category_id');
3params.set('searchCriteria[filter_groups][0][filters][0][value]', categoryId);
4params.set('searchCriteria[filter_groups][0][filters][0][condition_type]', 'eq');

Product prices show as 0 or undefined for configurable products

Cause: Configurable products in Magento have a price of 0 at the parent level — the actual prices live on the child simple products. The parent configurable product's price field is often 0 or the minimum child price.

Solution: For configurable products (type_id === 'configurable'), fetch the child products using GET /rest/V1/configurable-products/{sku}/children to get individual variant prices and SKUs. Display the price range (min to max child price) or the minimum price as the starting price.

typescript
1// Fetch children for configurable products:
2if (item.type_id === 'configurable') {
3 const children = await fetchMagento(`/rest/V1/configurable-products/${item.sku}/children`);
4 const prices = children.map((c: {price: number}) => c.price).filter(Boolean);
5 item.priceMin = Math.min(...prices);
6 item.priceMax = Math.max(...prices);
7}

Best practices

  • Use Magento's Integration token for server-side catalog reads — never expose this token in client-side code or prefix it with NEXT_PUBLIC_
  • Use the Magento 'fields' query parameter to limit API response data to only the fields you need — this significantly reduces response size and improves performance
  • Implement ISR (Incremental Static Regeneration) for product pages using Next.js generateStaticParams and revalidate — product data changes infrequently and static generation provides the best performance for product catalog pages
  • Cache product API route responses with Next.js fetch revalidation (next: { revalidate: 300 }) to reduce Magento API load while keeping catalog data reasonably fresh
  • Handle Magento's configurable products separately from simple products — configurable products have child SKUs with individual pricing and stock that must be fetched from the children endpoint
  • Always route Magento API calls through Next.js API routes — calling Magento directly from the browser would require CORS configuration on Magento and expose your integration token
  • For checkout, redirect to the native Magento checkout URL rather than building a custom checkout unless you need deep customization — Magento's checkout handles complex tax, shipping, and payment scenarios reliably

Alternatives

Frequently asked questions

Should I use Magento's REST API or GraphQL API for a headless storefront?

For a new V0-generated headless storefront, Magento's GraphQL API is often better than REST — you can request exactly the fields you need in a single query, avoiding multiple REST calls and over-fetching. However, GraphQL support varies by Magento version and extension — Magento 2.4+ has good core GraphQL coverage, while older versions or heavily customized stores may have more complete REST coverage. This guide uses REST for compatibility, but you can use the same Next.js API route pattern with a POST to your Magento GraphQL endpoint instead.

What's the difference between a Magento Integration token and a customer token?

An Integration token is generated in the Magento admin panel and provides server-to-server access with the permissions you configure. It's used for admin-level operations like catalog reads. A customer token is generated by calling the /rest/V1/integration/customer/token endpoint with a customer's email and password — it provides access to that specific customer's account data (orders, cart, wishlist). Your Next.js app uses Integration tokens server-side for catalog data and generates customer tokens server-side during customer login for account-specific operations.

How do I handle Magento product images in a Next.js app?

Magento stores product images at {base_media_url}catalog/product{file_path}. Fetch the base_media_url from the Magento store config endpoint (GET /rest/V1/store/storeConfig) — don't assume it's the same as your store URL since many stores serve media from a CDN. Add your Magento image domain to the images.domains array in next.config.js to enable Next.js Image optimization for Magento product photos.

Can V0 generate a complete Magento storefront, or only individual components?

V0 can generate all the individual page components you need — product listing pages, product detail pages, category navigation, shopping cart, and account pages — but wiring them together into a complete routing structure and connecting them to the Magento API requires manual configuration. V0 excels at generating the UI layer; use this guide's API route patterns to connect those components to live Magento data.

Does Magento's API support product search with full-text search?

Yes — Magento's product search endpoint (GET /rest/V1/products/search or GET /rest/V1/products with searchCriteria) supports full-text search queries using Elasticsearch or OpenSearch as the search backend. Use the searchCriteria with name like '%query%' for simple name matching, or use the dedicated search endpoint for Elasticsearch-powered full-text search that covers product descriptions and attributes.

How do I keep product pages fast with ISR and Magento as the backend?

Configure Next.js generateStaticParams to pre-generate your most important product pages at build time using Magento's product list API. Set a revalidate interval (e.g., 300 seconds for 5 minutes) on your product detail pages so they automatically refresh from Magento periodically. For large catalogs, focus ISR on your top-traffic products and use on-demand revalidation (revalidatePath or revalidateTag) to refresh pages immediately when Magento sends a webhook notification of product changes.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.