Ultimate Instruction to Build a NextJs Theme in Magento 2
Vinh Jacker | 10-01-2024
The Most Popular Extension Builder for Magento 2
With a big catalog of 224+ extensions for your online store
Having a modern, fast, and user-friendly interface will set you apart, helping you attract and retain customers successfully.
NextJS, with its powerful optimization capabilities, when combined with the Magento (Adobe Commerce) platform, offers a perfect solution for businesses aiming to enhance user experience and optimize website performance.
This article will guide you step-by-step on building a NextJs theme in Magento 2, helping you create an outstanding and efficient online store.
Introduction about NextJs
NextJs is a framework built on top of React, known for its SEO optimization capabilities, fast page loading performance, and smooth user experience. NextJs enables developers to easily build static and dynamic web applications thanks to features like SSR (Server-Side Rendering) and SSG (Static Site Generation).
Therefore, NextJs not only helps you create fast and efficient websites but also provides powerful tools and features to manage and optimize your website.
When combined with Magento 2, you’ll have a robust e-commerce platform that is easy to manage and optimize, delivering the best experience for users.
Overview of Magento 2 GraphQL API
Magento 2 provides a powerful GraphQL API that enables developers to easily query and manipulate data from the Magento system. GraphQL allows you to request precisely the data you need, optimizing performance and reducing bandwidth usage compared to traditional APIs like REST.
When building interfaces with NextJs, using Magento 2’s GraphQL API helps seamlessly connect the frontend and backend, providing the necessary data for pages and interface components.
Therefore, with GraphQL, developers can build applications more quickly, flexibly, and efficiently, significantly improving the user experience.
How to Build a NextJs Theme in Magento 2
To create a NextJS project within Magento 2, let’s delve into the detailed 6 steps below!
Step 1: Setup NextJs
First, you need to install NextJs and set up a new project. Open the terminal and run the following commands:
npx create-next-app my-magento-theme
cd my-magento-theme
npm run dev
Step 2: Setup Axios
Axios is a Promise-based HTTP client library for both Node.js and browsers. It offers codebase consistency, meaning the same codebase can run seamlessly in both environments.
Essentially, Axios is a powerful library that helps you easily connect to and query data from Magento 2’s GraphQL API. It’s used to fetch, cache, store, and modify application data.
Step 3: Add css to globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
Step 4: Create GraphQL file
You need to create an additional file productQuery.jsx to create a graphql query. Therefore, the following code will help you:
export const productQuery = `query ProductQuery($filters: ProductAttributeFilterInput) {
products(filter: $filters) {
items {
id
name
sku
description{
html
}
short_description{
html
}
image {
disabled
label
position
url
}
rating_summary
media_gallery{
url
position
label
disabled
}
}
}
}`
Step 5: Create API file to get data
Create a file helpers/api.jsx to get data from your Magento site.
import axios from 'axios';
export async function handleRequest({
url = null,
query = '',
method = 'POST',
params = {},
options = {},
variables = {},
clientConfig = {
baseURL: 'Your Magento base url',
timeout: 60000
}
}) {
const client = axios.create(clientConfig);
try {
return client
.request({
...options,
headers: {
accept: 'application/json',
...(options.headers || {})
},
url,
method,
data: {query, variables},
params
})
.then(({data: {data = {}, errors = []} = {}}) => ({data: data, errors}));
} catch (e) {
console.log('api error', e);
}
}
Step 6: To display the Product
Create a file named product.js in app
In this case, we’ll utilize the Static Site Generation (SSG) feature in Next.js, which is a powerful feature. It means that the HTML page will be generated at build time and reused on each request.
To pre-generate the paths based on the products, we use the asynchronous function Product.
Final Code and UI Design According to the API Response.
'use client'
import {useState} from "react";
import Image from "next/image";
export const Product = ({product = {}}) => {
const {thumbnail = {}, price_range = {}, sku} = product;
const [addtocart, setAddtocart] = useState(1);
const add = () => {
setAddtocart(addtocart + 1);
};
const sub = () => {
addtocart > 1 && setAddtocart(addtocart - 1);
};
return (
<div class="grid grid-cols-5 gap-4 w-[85%] mx-auto my-5">
<div className="col-span-2 border border-1 border-solid border-slate-400 rounded">
<Image src={thumbnail?.id} width={500} height={500}/>
</div>
<div className="col-span-3 mx-10">
<div className="">
<div display="grid">
<p className="font-[500] text-[2.5rem]">{product.name || ''}</p>
<div className="flex justify-between ">
<p className="text-price" sx=>
<span className="font-semibold">
$ {price_range?.minimum_price?.regular_price?.value}
</span>
<s className="pl-4 italic font-light text-fadedText">
{price_range?.discount?.amount_off}
</s>
</p>
<p variant="body1" className="mt-7">
Sku : {sku}
</p>
</div>
<div className="flex">
<button
onClick={sub}
aria-label="increment"
className="text-white w-10 rounded-l h-8 border-0 cursor-pointer bg-secondary hover:bg-brand hover:contrast-75"
>
-
</button>
<input
max={6}
type="text"
className="relative w-14 border-[1px] border-gray flex items-center px-3 font-semibold text-center text-gray-700 outline-none cursor-default -z-10 readonly focus:outline-none text-md hover:text-black focus:text-black md:text-base"
min={1}
value={addtocart}
id="quantity"
placeholder="0"
/>
<button
aria-label="increment"
className="text-white w-10 h-8 rounded-r border-0 cursor-pointer bg-secondary hover:bg-brand hover:contrast-75"
onClick={add}
>
+
</button>
</div>
<p className="pt-3 text-hoverEffect text-[16px] ">
{product.short_description?.html ||
''}
</p>
</div>
<button
color="secondary"
variant="contained"
className="w-full py-4 mx-auto"
type="submit"
>
Add to cart
</button>
</div>
</div>
</div>
);
};
Afterwards, call the Product in the page.tsx file to fetch data onto the page.
import styles from "./page.module.css";
import {Product} from "@/app/product";
import {handleRequest} from "@/helpers/api";
import {productQuery} from "@/app/productQuery";
async function Home() {
const {data: {products: {items}}} = await getProducts({urlKey: 'fusion-backpack'});
return (
<main className={styles.main}>
<Product product={items[0]} />
</main>
);
}
export default Home
export async function getProducts({urlKey = ''}) {
const data = await handleRequest({query: productQuery, variables: {filters: {url_key: {eq: urlKey}}},})
return data;
}
You can see the result on http://localhost:3000
Conclusion
Building a Next.js interface within Magento 2 (Adobe Commerce) brings numerous benefits in terms of performance, user experience, and SEO optimization. By utilizing Next.js alongside Magento 2’s GraphQL API, you can create modern, fast, and efficient e-commerce websites.
Hopefully, this guide has helped you understand the process of building and applying it to your project.
If you encounter any difficulties while building a NextJs theme in Magento 2, don’t hesitate to contact our experts for the best support.
Wishing you success!