Building a Serverless E-commerce Storefront with React, Next.js, and Stripe
Introduction
This article will guide you through building a basic e-commerce storefront using React, Next.js for server-side rendering, and Stripe for handling payments. We'll focus on the core components: displaying products and processing payments. This is a simplified example suitable for learning purposes.
Prerequisites
- Node.js and npm or yarn installed
- Stripe account (for API keys)
Setting up Next.js
First, create a new Next.js project:
npx create-next-app my-ecommerce-store
cd my-ecommerce-store
Displaying Products
Create a components
directory and a ProductCard.js
file:
// components/ProductCard.js
import React from 'react';
const ProductCard = ({ product }) => {
return (
<div>
<h3>{product.name}</h3>
<p>${product.price}</p>
<button>Add to Cart</button>
</div>
);
};
export default ProductCard;
In your pages/index.js
:
// pages/index.js
import ProductCard from '../components/ProductCard';
const products = [
{ id: 1, name: 'Awesome T-Shirt', price: 25 },
{ id: 2, name: 'Cool Mug', price: 15 },
];
const Home = () => {
return (
<div>
<h1>Our Products</h1>
{products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
};
export default Home;
Integrating Stripe
Install the Stripe library:
npm install @stripe/stripe-js @stripe/react-stripe-js
Create a .env.local
file and add your Stripe publishable key:
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_YOUR_STRIPE_PUBLISHABLE_KEY
Create a pages/api/checkout_sessions.js
file to handle creating Stripe checkout sessions:
// pages/api/checkout_sessions.js
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
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: 'Your Product',
},
unit_amount: 2000, // Amount 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) {
res.status(err.statusCode || 500).json(err.message);
}
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
}
Important: You need to set STRIPE_SECRET_KEY
in your environment variables. Never expose your secret key in your client-side code!
Update ProductCard.js
to include a checkout button:
// components/ProductCard.js
import React from 'react';
const ProductCard = ({ product }) => {
const handleCheckout = async () => {
const response = await fetch('/api/checkout_sessions', {
method: 'POST',
});
const data = await response.json();
if (response.status === 303) {
window.location.href = data.url;
} else {
console.error("Checkout failed");
}
};
return (
<div>
<h3>{product.name}</h3>
<p>${product.price}</p>
<button onClick={handleCheckout}>Buy Now</button>
</div>
);
};
export default ProductCard;
Create pages/success.js
and pages/cancel.js
for handling the success and cancel URLs. These can be simple pages that display a message to the user.
Conclusion
This provides a foundational understanding of building a serverless e-commerce storefront. You can expand on this by adding features like:
- Shopping cart functionality
- User authentication
- Database integration for product management
- More robust error handling