Lab - Build Basic Catalog Pages
Lab - Build Basic Catalog Pages
Lab - Build Basic Catalog Pages
Your basic Next.js storefront build currently features only a store logo. Let’s expand it with basic catalog pages.
This exercise builds on the basic Next.js application begun in the previous lab and has the same technical requirements.
Your store should have the following catalog data associated with your headless channel:
This exercise continues where you left off previously in your basic Next.js project. Simply start the dev server from the project root if it’s not currently running:
If you need a fresh start, you can follow the instructions below to set up a new project complete with previous exercise code.
.env.example as .env.local and modify .env.local with configuration details for your store.pnpm output and verify your home page loads successfully.You may choose to download or clone the completed version of this lab in a separate location to serve as a reference for the final state.
Let’s add a simple nav menu to the storefront header, consisting of links to top-level categories. This will require querying additional data from the GraphQL Storefront API, specifically categoryTree. Note that, since this data is to be made available to all pages like the store settings you’re already fetching, we’re going for maximum efficiency by including it in the same query. This is part of the power of GraphQL.
components/header/_data/component-data.ts, modify the GraphQL query to include categoryTree data, and add corresponding details to the response type.getHeaderSettings to add nav categories to the result object.components/header/index.tsx. Add navCategories to the destructuring of getHeaderSettings.You should be able to verify that the menu now displays on your home page!
The categories in the main nav menu each link to a URL path like /category/someCategorySlug. Let’s flesh out the page route for this pattern. You’ll first need to implement the right GraphQL query to fetch the needed category information, including the category’s products.
types/catalog.ts. Fill in the details of the CategoryProductand BasicCategory interfaces as shown below.These two definitions will help facilitate the right response type in the next step, where the basic category and product fields are the same but the structure of products is not as flat.
app/category/[...catPath]/page-data.ts and add the following code to define the query and the various necessary types.This is a verbose block of code, but mainly because we’ve created two different versions of the query: getCategoryWithBeforeQuery and getCategoryWithAfterQuery. These support the GraphQL variables necessary for “previous” and “next” pagination, which you’ll make use of in subsequent steps. To avoid as much duplication as possible, GraphQL fragments are used for the fields selected for category and product records.
Note the GetCategoryWithProductsResp interface, defining the expected GraphQL response. The products field, rather than directly returning a list, has the sub-field edges, and each item in that list contains the field node. We’ve injected the BasicCategory and CategoryProduct interfaces separately into this structure.
Finally, note that the GraphQL queries already support the before and after arguments even though we’re not yet implementing pagination. This will avoid the need for major refactoring in the following steps.
getCategoryWithProducts to accept the proper input, perform the query, and parse the category and product data.Just as we’re not implementing pagination yet, we also won’t be performing this fetch with any specific customer context. Nevertheless, the function supports a customerToken parameter that it passes in the GraphQL fetch, supporting this option for the future.
getCategoryWithProducts to return the appropriate values.app/category/[...catPath]/page.tsx, the route file that will actually handle page requests like “/category/{category-name}”. Note that the file path segment in square brackets is a “catch-all” segment that will capture everything after “/category” in the URL.CategoryPage component as follows.params is a standard Next.js convention and will contain the values of any dynamic URL segments (in this case, catPath). With the URL path, we have what we need to call getCategoryWithProductsto fetch the data.
app/category/[...catPath]/page.tsx, remove the console.log statement and add code to return a 404 response if no category is found.This JSX content utilizes a separate component - ProductCard- for each product on the category page. This component is currently empty and doesn’t even accept the props being passed to it, so let’s flesh it out.
components/product-card/index.tsx and update the component as follows.Your category page displays one page of a category’s products, but currently there is no way to see more results. Let’s add this support for pagination.
The getCategoryWithProducts query already supports arguments for filtering the product list, but for full pagination support you also need to query data about the current “page” of results.
app/category/[...catPath]/page-data.ts, add a fragment string defining pageInfo fields, then utilize that fragment in both versions of the category query.getCategoryWithProducts to include info about the current page.Now the function returns data including the startCursor from the current result set only if there is a previous page and the endCursor if there is a next page.
Next, you’ll modify the category page component to use URL querystring information for paging. The expected URL pattern will be /category/someCategorySlug?before={productCursor} or /category/someCategorySlug?after={productCursor}.
app/category/[...catPath]/page.tsx to use the page field on the category to conditionally output paging links.before or after querystring params and pass them into the query.If your category doesn’t contain enough products for multiple pages, temporarily set the limit value passed to getCategoryWithProducts to 1 or a sufficiently small value to see the effect.
The process of creating a product detail page will look similar to that of creating the category page, starting with crafting the GraphQL query.
Product interface definition in types/catalog.ts.app/product/[...productPath]/page-data.ts and add the GraphQL query and vars/response types.getProduct function to perform the query and return the product.pnpm run dev was executed.app/product/[...productPath]/page.tsx, remove the logging statement, and add an early return if no product was found.What you have so far is a basic but still incomplete catalog implementation. If you want to continue to flesh out your Next.js storefront on your own, below are some possibilities for expansion.
categoryTree query and utilize this data to build a multi-level main nav with drop-downs for subcategories.