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… When building your own e-commerce experience you will most likely need to add your own pages/routes. 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. Implementing routing within Front-Commerce will be easier if you understand how these work. 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. 🎉
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
. 🥖🎉
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.