Building a Serverless E-commerce Storefront with Next.js and Stripe
Introduction
This article demonstrates how to build a basic serverless e-commerce storefront using Next.js and Stripe. We'll focus on the core components: displaying products and processing payments.
Setting up Next.js
First, create a new Next.js project:
npx create-next-app my-ecommerce-store
cd my-ecommerce-store
Displaying Products
Let's create a simple product listing. For simplicity, we'll hardcode product data. In a real application, you'd fetch this from a database or CMS.
Create a file components/ProductList.js
:
// components/ProductList.js
const products = [
{ id: 1, name: "T-Shirt", price: 20 },
{ id: 2, name: "Mug", price: 10 },
{ id: 3, name: "Sticker", price: 5 },
];
const ProductList = () => (
<ul>
{products.map((product) => (
<li key={product.id}>
{product.name} - ${product.price}
</li>
))}
</ul>
);
export default ProductList;
Update pages/index.js
:
// pages/index.js
import ProductList from '../components/ProductList';
const Home = () => {
return (
<div>
<h1>Welcome to our Store!</h1>
<ProductList />
</div>
);
};
export default Home;
Integrating Stripe
Install Stripe's JavaScript library:
npm install @stripe/stripe-js
Creating a Checkout Session
We'll need a serverless function (API route in Next.js) to create a Stripe Checkout Session. Create pages/api/checkout_sessions.js
:
// pages/api/checkout_sessions.js
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: '2023-10-16',
});
export default async function handler(req, res) {
if (req.method === 'POST') {
try {
const session = await stripe.checkout.sessions.create({
line_items: [
{
price_data: {
currency: 'usd',
product_data: {
name: 'T-shirt', // Replace with dynamic product data
},
unit_amount: 2000, // Price in cents
},
quantity: 1,
},
],
mode: 'payment',
success_url: `${req.headers.origin}/success`,
cancel_url: `${req.headers.origin}/cancel`,
});
res.redirect(303, session.url);
} catch (err) {
console.error(err);
res.status(500).json({ statusCode: 500, message: err.message });
}
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
}
Important:
- Set
STRIPE_SECRET_KEY
in your.env.local
file. Obtain this from your Stripe dashboard. - The
success_url
andcancel_url
should point to pages you create in your Next.js application to handle successful and canceled payments.
Implementing the Checkout Button
Add a checkout button to your product list:
// components/ProductList.js (updated)
import { loadStripe } from '@stripe/stripe-js';
const products = [
{ id: 1, name: "T-Shirt", price: 20 },
{ id: 2, name: "Mug", price: 10 },
{ id: 3, name: "Sticker", price: 5 },
];
const ProductList = () => {
const handleCheckout = async () => {
const stripe = await loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);
const response = await fetch('/api/checkout_sessions', {
method: 'POST',
});
const session = await response.json();
if (response.ok) {
stripe.redirectToCheckout({ sessionId: session.id });
} else {
console.error('Checkout failed:', session.message);
alert('Checkout failed. Please try again.');
}
};
return (
<ul>
{products.map((product) => (
<li key={product.id}>
{product.name} - ${product.price}
<button onClick={handleCheckout}>Checkout</button>
</li>
))}
</ul>
);
};
export default ProductList;
Important:
- Set
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
in your.env.local
file. Obtain this from your Stripe dashboard. Make sure this key is prefixed withNEXT_PUBLIC_
so that Next.js will expose it to the browser.
Conclusion
This is a basic implementation of a serverless e-commerce storefront using Next.js and Stripe. You can expand this by adding features like:
- Fetching product data from a database or CMS.
- Implementing user authentication.
- Adding a shopping cart.
- Handling shipping and taxes.
Remember to handle errors and security considerations carefully when building a production application.