Add a new page
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 aRecipesList
component here. It’s abusiness 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.