Add a new page

Front-Commerce comes with a classic set of pages for an e-commerce application. It has URLs for Catalog routes (Categories, Product, Search…), Checkout routes, Account routes, Cms pages…

But when building your own e-commerce experience you will most likely need to add your own pages/routes. And that’s what we will focus on in this guide.

We will take the example of a shop that is selling ingredients. It might make sense for such a website to also present a bunch of recipes to inspire their customers. Thus, we will add the needed routes to display:

  • a page containing the list of all the recipes
  • a page containing the details of one recipe

Add a page using a static URL

First, let’s add the page containing the list of all recipes. To do so you will need to:

  • Create the route file that will be mapped to a URL
  • Declare your module as a web module
This system is inspired by JavaScript frameworks like Next.js, Gatsby, Sapper, Nuxt, etc. If you understand how these work, implementing routing within Front-Commerce will be easier. See Routing reference for more advanced information.

Create the route file that will be mapped to a URL

Create a route file in the folder web/theme/routes/ of your module. If you don’t have a module yet, please refer to Extend the theme.

The url of your route will then depend on the name of the file you’ve created in the web/theme/routes/ folder. Thus, if we want to display a page at the URL /recipes, we will create a file in web/theme/routes/recipes.js which will export the component you want to display on this page.

import React from "react";
import { H1 } from "theme/components/atoms/Typography/Heading"
import RecipesList from "theme/modules/Recipes/List"

const Recipes = () => <div>
  <H1>Discover our recipes</H1>
  <RecipesList />
</div>;

export default Recipes;
Note that there is a RecipesList component here. It’s a business component that you can create by referring to Create a business component.

We have decided here to put the file under web/theme/routes/recipes.js, but it would have still worked if we’ve put it under web/theme/routes/recipes/index.js. The page would still be displayed at the URL /recipes.

Declare your module as a web module

You have now declared that if your module’s routes are loaded, it will display the Recipes component at the URL /recipes. However, your module routes are not loaded yet. You need to declare it in your .front-commerce.js file.

To do so, create an empty file in web/index.js. This is useful for module resolution at the build level. Then add it as a webModule in your .front-commerce.js file.

module.exports = {
  name: "Front Commerce DEV",
  url: "http://www.front-commerce.test",
  modules: ["./my-module"],
  serverModules: [
    { name: "FrontCommerce", path: "server/modules/front-commerce" },
    { name: "Magento2", path: "server/modules/magento2" }
  ],
  webModules: [
    { name: "FrontCommerce", path: "front-commerce/src/web/index.js" },
+   { name: "MyWebModule", path: "./my-module/web/index.js" },
  ]
};

Once you’re done, you can refresh your application (npm run start), and you should see your new route if you go to the /recipes URL. 🎉

Warning: If several web modules are registered in your application and several of them define the same route, the route of the last web module in .front-commerce.js will be displayed. This can be useful if you want to override a default feature of Front-Commerce.

Add a page using a URL with parameters

Now, let’s add a RecipeDetails page that should be mapped to the /recipes/my-recipe-slug. You will need to create the route file that will match the URL. Since you have a parameter in the URL, you will need to put brackets around it.

Thus, create a RecipeDetails component in web/theme/routes/recipes/[slug].js. This will allow you to display the RecipeDetails component in any url looking like /recipes/.*.

import React from "react";
import { H1 } from "theme/components/atoms/Typography/Heading"
import Recipe from "theme/modules/Recipes/Details"

const RecipeDetails = (props) => <div>
  <H1>You are looking at the recipe matching the slug {props.match.params.slug}</H1>
  <Recipe slug={props.match.params.slug} />
</div>;

export default RecipeDetails;

What’s interesting to note here is that:

  • anything that is between brackets in your file path will be transformed into a parameter available in props.match.params.slug
  • you can create sub folders in your web/theme/routes folder if you want to have deeper URLs

You can now restart your application (npm run start) and you should see your route RecipeDetails displayed at /recipe/baguette. 🎉

Note: Internally, this works by transforming any /recipes/[slug] kind of routes to /recipes/:slug, which is then used by React-Router, a major routing library in React’s ecosystem.

What about dynamic URLs?

If your URL can’t be mapped to a pattern that can be transformed into filenames, do not worry, we have got you covered! There is a second extension point in Front-Commerce that allows you to achieve this: the Dispatcher.

You can learn more about it in our advanced documentation.

How can I share layouts between routes?

You might also wonder how can a route use the same layout as the other routes. Front-Commerce handles this by using files like _layout.js or _inner-layout.js in your routes.

You can learn more about it in our advanced documentation.

Edit on GitHub