In this article I am going to talk about nopCommerce themes or as many call them nopCommerce templates and how we can create one. Please note that the content in this blog post will be presented from the perspective of a .NET MVC nopCommerce developer. However front end developers will also be able to benefit from it and learn how to create a nopCommerce theme\template.
What is a nopCommerce theme?
A nopCommerce theme is just a collection of files which define how a nopCommerce web site looks like, its layout and appearance, as well as how a web site behaves, its functionality. It is important to understand that not every functionality can be achieved via a nopCommerce theme. This is where nopCommerce plugins come to fill the gap. So it is not uncommon for a nopCommerce theme to be accompanied by a nopCommerce plugin, created specifically for the theme in order to achieve certain more advanced functionality. However nopCommerce plugins are a topic for another blog post and in this article we will deal mainly with nopCommerce themes.
What you need to create a nopCommerce theme?
First of all to be able to create a nopCommerce theme you will need:
1. The nopCommerce source code or a nopCommerce web site installation. You can download the source code from the nopCommerce codeplex page. Working off the source code is not obligatory, you can also work directly with a nopCommerce web site installation. To install nopCommerce without the source code please go to the nopCommerce download page.
2. Visual Studio or any text editor.
3. A good working knowledge of html and css.
4. A knowledge of ASP.NET MVC is not mandatory but will be a huge benefit.
The file structure of nopCommerce themes
To be able to work with themes in nopCommerce you will need know a little bit of the nopCommerce file and folder structure and particularly this related to the themes.
If you are working with the source code the nopCommerce themes are located in: Presentation\Nop.Web\Themes.
If you are working with a nopCommerce web site installation you can find the themes in the Themes folder located in your nopCommerce web site root directory.
Before creating a nopCommerce theme\template you need to understand the file structure of a nopCommerce theme. A theme contains:
1. A Content folder. All the styles sheets and images (in the Content\Images folder) of the theme are located here.
2. A Views folder. All the MVC razor views of a theme are located here. Front end developers can think of MVC razor views as web pages, which contain HTML markup and server side code. Pretty much the equivalent of a .php file. So if you are a front end developer you should at the very least be able to edit the html markup of the various views\pages of the theme.
3. A theme.config file. The theme.config file contains information about the theme such as name and description. This information is read and used by nopCommerce when populating for example the "Store theme" dropdown list on the Configuration -> Settings -> General And Miscellaneous Settings page in the administration panel or when populating the theme selector control, which allows a nopCommerce customer to select a theme.
How to install a nopCommerce theme?
A nopCommerce theme or template defines the layout, the appearance as well as the functionality of a nopCommerce web site. We could argue that nopCommerce themes\templates are standalone software modules and they can be installed or uninstalled from a nopCommerce web site by simply copying them to or removing them from the nopCommerce Themes folder. Once a nopCommerce theme is installed you can switched it on by going to the administration panel of nopCommerce and opening the Configuration -> Settings -> General And Miscellaneous Settings page. The "Store theme" dropdown list contains all the currently installed themes and shows the currently active theme.
How to get started with a nopCommerce theme?
The easiest way to get started with your nopCommerce theme is to copy the default DarkOrange theme folder from the nopCommerce Themes directory and paste it in the same Themes directory. Rename it to whatever your theme will be called, this is usually the name of your web site, for example NopTemplates. Edit the information in the theme.config file to reflect at least your theme name. Once this is done you can go to the Configuration -> Settings -> General And Miscellaneous Settings administration page and select your Theme as the currently active one. In this way any changes you make to the theme will take effect immediately and you will be able to preview them in the public part of the web site.
Where is the html markup and how to change it in a nopCommerce theme?
You have just created your nopCommerce theme. Now in order to be able to do some meaningful modifications to the theme we will elaborate a bit more on the Views folder in your theme. The Views folder in you nopCommerce theme\template is a reflection of the Views folder which is located in the Presentation\Nop.Web directory if you are working with the nopCommerce source code or in the root directory of your web site if you are working directly with a nopCommerce web site installation. This nopCommerce Views folder contains directories named after different so called MVC actions, for example Catalog, Blog, Checkout, etc. MVC actions are just pieces of server side code (methods), which server different views\pages. The .cshtml files in these action folders are the views\pages themselves. These views\pages contain razor code and HTML markup. Razor views is a topic outside the scope of this article. What is important to understand thought is that when a nopCommerce view\page is requested\visited it is served from the respective Views\[Action] folder. Moreover, nopCommerce will first look into the Views folder of the currently active Theme and if it cannot find it in the theme then it will look into its own Views folder. So in this way, in your theme you are able to override the default nopCommerce pages. For example if you would like to change the recently viewed products page in your nopCommerce web site, just create a Catalog folder in the Views directory of your theme, copy the RecentlyViewedProducts.cshtml view from the nopCommerce Views directory and edit it to your requirements. Now when a web site visitor requests the recently viewed products page, the RecentlyViewedProducts.cshtml view from your theme is returned. In most cases, when developing your nopCommerce theme, you would not need to override all the nopCommerce views\pages. So the best way to create your nopCommerce theme\template is to take an incremental approach and override the views one by one, when simple css changes will not suffice.
This is especially true for partial Views. It is very likely that you would need to override most of the default nopCommerce partial views. Partial views are just like regular views but they are not allowed to be served as pages as they are considered not to be complete (partial). Rather they are used in normal views by including them into the normal views markup via server side code. For example the RecentlyViewedProducts.cshtml view includes the _ProductBox.cshtml view using this line of code: @Html.Partial("_ProductBox", @item). What this code means is outside the scope of this article, but what is important is that you are aware of partial views and their usage in main views. When a partial view is included into a main view, the markup of the partial view is put into the place of the include call. You can recognize partial views by the leading underscore in their names. This is not mandatory, a partial view name might not begin with an underscore. However it is a convention that is well accepted and recommended. Please note however that nopCommerce uses another ASP.NET MVC concept know as childonly views. These views are pretty much the same as partial views, they cannot be served as web site pages but they are included in normal views via a different server code. For example: @Html.Action("CategoryNavigation", "Catalog", new { currentCategoryId = currentCategoryId, currentProductId = currentProductId }). I am mentioning this because childonly views do not start with an underscore and you might be mislead to think of a childonly view as a normal view. How to recognize childonly views then? Without looking at the nopCommerce c# code you would not be able to do that with an absolute certainty. However a good rule of thumb is if the view does not have a layout view and does not start with an underscore it is most probably a childonly view. Layout views are explained next.
How to change the layout of a nopCommerce web site by using a nopCommerce theme?
Now that you understand how nopCommerce views work combined with a nopCommerce theme you are ready to make modifications to the html of a nopCommerce web site. Most probably you would want to start with the layout views\pages of the web site or as most ASP.NET developers know them the master pages. Layout views allow you to define a common look and structure of your web site and inherit this in your pages. The nopCommerce Views folder as well as your theme Views folder contain a folder named Shared. This is where common views (not bound to a particular action) can be found and this is also the place where all the nopCommerce layout views reside. Please note that layout views can be inherited in a hierarchical manner. And this is exactly what nopCommerce uses to define its web site structure and layout.
At the top of the layout hierarchy is the _Root.cshtml view. The razor code and html markup defined in this view is inherited by every page in your nopCommerce web site. How is this so? Below the _Root.cshtml view in the layout hierarchy sit the following views: _ColumnsOne.cshtml, _ColumnsTwo.cshtml, _ColumnsThree.cshtml, _ColumnsFluid.cshtml. This means that all these views inherit the _Root.cshtml layout. And because every view\page in nopCommerce inherits one of these views, they also inherit the _Root.cshtml view. So if you would like to change something in the _Root.cshtml view or any other of the layout views below it in the layout hierarchy, you need to first copy the respective view into the Views\Shared folder in your theme.
You would rarely have to change the markup in the _Root.cshtml view because this view as well as the other layout views are built upon partial and childonly views and these views are the one you would most probably work with. For example the _Root.cshtml view includes the Header.cshtml and HeaderMenu.cshtml partial views. The _ColumnThree.cshtml view, which is the default layout view in nopCommerce, includes the CategoryNavigation.cshtml, ManufacturerNavigation.cshtml, PopularProductTags.cshtml and many other partial and childonly views, which define the content of the left and right columns of a nopCommerce web site. However, note that this is by default. Should you need to change the layout of every page, which inherits the _ColumnThree.cshtml view or any other layout view, you will have to copy the _ColumnThree.cshtml view or any other layout view you intend to use, into your nopCommerce theme Views\Shared folder and change the view there. Again I would like to repeat that changes in a layout view will be inherited by every page, which inherits the view.
Layout Sections with Razor
If you want to keep the layout as it is by default and just change the layout for individual pages, the nopCommerce team has provide a hook for you via razor section blocks. Razor sections can be thought of as layout sections. Razor sections are beyond the scope of this article but you can read more about them in this excellent blog post by Scott Guthrie. All you need to know about the razor sections defined by the nopCommerce layout views is that you have a "left" razor section in the _ColumnTwo.cshtml view and also a "right" razor section in the _ColumnThree.cshtml view. So for example say that in your nopCommerce theme the BlogPost.cshtml view\page inherits the _ColumnTwo.cshtml layout view. You would like to get rid of the product category and manufacturer navigation blocks in the left column of the blog page, because these are not very relevant to a blog page. Instead you would like to use custom content in the left column of the blog page and put the blog months and tags navigation there. In order to do this in your BlogPost.cshtml view, you have to define a "left" section (@section left) and put your custom content in it. Now the default content in the left column of your BlogPost.cshtml view\page will be overridden by your custom content. I am giving you this example because this is exactly how the nopCommerce team has implemented the BlogPost.cshtml view. So you can open the view (Views\Blog\BlogPost.cshtml) and have a look at the details.
How to add custom CSS styles sheets and Javascript files to a nopCommerce theme?
Going back to the _Root.cshtml view, I said that you would rarely have to change this view. One case it would seem necessary to do so is when you would like to add your own css style sheets or javascript files. In the _Root.cshtml you can see that nopCommerce is adding by default a bunch of Javascript links. You might be tempted to add your own script links or css links in the same place. But you would be wrong to do so. Notice that in fact there are no css links in the head tag of the _Root.cshtml. Why is this so? Because only core nopCommerce files should be linked there and these are files which are used by absolutely every view\page in nopCommerce no matter if it is a layout view\page, a normal view, a partial one or a childonly. Most importantly these are files not specific to a nopCommerce theme. And there are no style sheets, that can be classified as common to all and not specific to a nopCommerce theme. That is why you would not see css links in the head tag of the _Root.cshtml.
You will notice that the _Root.cshtml includes a partial view named Head.cshtml and you can find this partial view in the Presentation\Nop.Web\Views\Shared folder of your nopCommerce source code or in the Views\Shared folder of your nopCommerce web site. The Head.cshtml view is empty. However if you look in the Views\Shared folder of the DarkOrange theme for example you will notice that it includes a link to the style.css of the theme. The Head.cshtml view from your nopCommerce theme will override the default Head.cshtml view and this is what you should use in order to include your custom CSS stylesheets and Javascript files.
So in order to include your custom CSS stylesheets and Javascript files you do not have to change the _Root.cshtml view as you might have thought at the beginning. You need to have a Head.cshtml view in the Views\Shared folder of your nopCommerce theme and in this view you need to include your files.
Where are the CSS styles and how to change them in a nopCommerce theme?
The css stylesheets of a nopCommerce theme should be located in the Content folder of the nopCommerce theme. As you learned in the previous section, the css stylesheets are linked via the Head.cshtml view, which can be found in the Views\Shared folder of a nopCommerce theme. So basically you can locate your css files wherever you want to as long as you synchronize the location with the links in the Head.cshtml view. But it is a good idea to put them into the Content folder for the sake of consistency, especially if you intend to distribute your nopCommerce theme. The default nopCommerce themes come with a default style.css file. It might be a good idea, to copy the style.css file from the DarkOrange or Classic theme in your nopCommerce theme Content folder and work with it. However this depends a lot on your nopCommerce theme and how different it is from the default nopCommerce themes. If your theme is quite different and the markup and styles have almost nothing to do with the default ones, then it might be a good idea to create your CSS styles from scratch. Again for the sake of consistency I would recommend that you have a style sheet called style.css. I prefer to have one style sheet for all styles, as it makes searching for a particular style easier. But this is a matter of personal preference.
So now that you know where the styles of your nopCommerce theme are located you can start making some changes to your nopCommerce theme. I would not go through the default style.css of any of the default nopCommerce themes as every theme has its own styles and this is a topic that concerns front end development rather than the creation of nopCommerce themes. However going through the more important styles, especially the ones that have to do with the layout of the web site is useful. For that the nopCommerce team have put out a Designer's Guide article in their documentation. You can read more in the "Customizing nopCommerce Themes" section in the article.
Summary
In this article we have looked at how to create a nopCommerce theme and more particularly:
1. What is a nopCommerce theme and what the structure of a theme is?
2. How a nopCommerce theme can be installed?
3. How nopCommerce views relate to a nopCommerce theme?
4. How to work with the html markup, layout and styles of a nopCommerce web site in the context of a nopCommerce theme?
The most important point to take from this article is that when working on a nopCommerce project, although you might be tempted to make modifications directly to the default nopCommerce views and styles you should not do this. You should rather create a nopCommerce theme, which essentially would be your nopCommerce project. If you fail to do so, upgrading your theme to the latest versions of nopCommerce would be so difficult and you would incur a huge technical debt, which will greatly affect your competitiveness as a nopCommerce solutions provider.
Hope you will find the information in this blog post useful!
Nop-Templates.com Development Team
Thanks for the great article.
Tony
Question. I want to "extend" theme.config to add a couple additional items, such as listing the primary colors. Do you think I will need to modify any nop core files to support this?
If you want to have strongly typed properties for you data you can inherit the ThemeConfiguration class and implement them based on the information in the XmlNode. But this needs to be implemented in a plugin if you would like not to change the nopCommerce core.
I hope this is useful!