Table of Contents

Getting started with DW10 implementations

An introduction to server-side rendering using Razor templates

An implementation in DynamicWeb is the process of setting up the platform and creating the frontend experience that customers and users interact with. DynamicWeb brings together CMS, eCommerce, PIM, and Marketing into one platform. But every project needs a storefront: the visible layer where content, product data, and commerce functionality come together.

This part of the documentation focuses on building that storefront - and outlines the different implementation directions available in DynamicWeb 10. Each approach balances speed, flexibility, and customization in different ways, making it possible to choose the right fit for each project.

There are four different implementation directions to take:

Method Description Effort & Skillset Advantages & Considerations
Swift A prebuilt, configurable storefront accelerator designed for quick deployment. Provides a mobile-first, performance-optimized template set for standard B2B and B2C sites. Low to moderate effort. Most setup is configuration-based rather than code-heavy. Editors can manage layout and design visually; developers extend where needed. Fastest time to market and includes best practices for SEO, accessibility, and performance. Ideal for standard webshops and rapid implementation. Less suited for deeply custom designs - customizations may require in-depth Swift knowledge. Low maintenance compared to Core or From Scratch.
Core Uses DynamicWeb’s standard template foundation with Razor and ViewModels to speed up development while maintaining flexibility. Serves as a base for creating a tailored but conventional solution. Moderate to high effort. Requires knowledge of Razor templating and the DynamicWeb architecture. Developers should be comfortable extending and maintaining server-side templates. Faster to implement than starting from scratch while still offering flexibility. Good balance between control and efficiency, but still requires significant design and coding work. Ideal if you want a custom foundation without reinventing everything.
From Scratch Build a design from the ground up - templates and layouts - without using prebuilt designs or components. Ideal when you need a completely unique storefront or have very specific design and behavior requirements. High effort. Requires advanced front-end (HTML, CSS, JavaScript) and Razor skills, as well as an understanding of DynamicWeb’s template system and ViewModels. Offers complete flexibility and control over layout, design, and functionality. However, cam be time-consuming, lacks prebuilt conveniences. Best suited for teams with strong technical expertise and large, custom projects.
Headless A fully decoupled, API-driven approach that separates the frontend (e.g., React, Vue, Next.js) from the DynamicWeb backend. Uses APIs to deliver data for total freedom in presentation and user experience. High effort. Requires advanced frontend development, API integration, and state management skills. Developers must handle e.g. routing, cart logic, and user context manually. Maximum flexibility and scalability, perfect for omnichannel and app-driven projects. Can be complex to build and maintain, with more responsibilities for caching, performance, and integration. Best for advanced teams or large-scale digital ecosystems.

This section focuses on the two implementation methods which uses the DW10 Template Engine:

  • From scratch - a clean-slate starting point where you create a template set from scratch
  • Core - a developer-focused template foundation

The other two implementation methods are documented elsewhere:

Setting up a developer environment

To implement a DynamicWeb 10 solution using the DW10 templates system you need:

  • A DynamicWeb 10 solution installed locally
  • An IDE for template development which supports Razor, e.g. VS Code or Visual Studio
  • Experience with HTML, CSS, Javascript
  • Experience with Razor
  • A basic understanding of DynamicWeb and its concepts

Apart from that, the frontend stack can be anything you desire and you can use build tools, GIT, Node.js, NPM, bundlers, TypeScript, minifiers, etc.

To install a solution locally you can follow one of our guides...

...and then the local frontend development section under each guide to get set up.

For more advanced setups see the Environments article.

The template hierarchy

All templates are physically store on disc and are organized in the Templates-folder of your solution. A collection of templates and static files which control how the frontend of a website looks is called a design. You can have multiple designs on a solution, each of them represented by a folder under Files/Templates/Designs:

/Files/
├── Templates/
│   ├── Designs/
│   │   ├── myDesign/
│   │   │   ├── Paragraph/
│   │   │   │   ├── image.cshtml
│   │   │   │   ├── text.cshtml
│   │   │   ├── Navigation/
│   │   │   │   ├── topNavigation.cshtml
│   │   │   │   ├── leftNavigation.cshtml
│   │   │   ├── myLayout1.cshtml
│   │   │   ├── myLayout2.cshtml
│   │   │   ├── myMaster.cshtml

If you're new to templates, designs and DynamicWeb we recommend that you check out our Designs and Templates tutorial, which will provide you with a good introduction to all the moving parts which constitute a design in DynamicWeb 10.

When DynamicWeb 10 serves a page, multiple templates which belong to different parts of the page are rendered individually and then combined. How many templates are combined like this depends on you content model - but typically:

  • A Master-template contains markup common to most pages - e.g. the <head>-section, references to static resources like JS and CSS, and usually also a navigation
  • A Page-template (or layout) contains the main markup, sections and columns of a particular page type – e.g. blogpost, shop or frontpage
  • A Paragraph-template controls how content - text, images, app output - from a paragraph type is organized
  • An App-template (or module template) controls how content from a paragraph app is shown, e.g. a product list or a login form

They typically fit together like this: template-hierarchy

When a page is requested for the first time, the various templates are parsed, merged into one, and saved to a _parsed-folder inside the design-folder. They are recompiled whenever we detect a change to them.

Using Razor in templates

Razor is a markup syntax for embedding .NET based code into webpages. The Razor syntax consists of Razor markup, C#, and HTML. Files containing Razor generally have a .cshtml file extension.

Here is an example Razor template:

@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@Model.Title</title>
  </head>
  <body>
    <h1>Welcome to the page '@Model.Name'</h1>
  </body>
</html>

In the example above, most of the code is markup - and a ViewModel from DynamicWeb is injected and can be used to fetch content dynamically from the DynamicWeb 10 solution. In this example, we call it to fetch the Name property of the PageViewModel, making the h1-content dynamic - *@Model.Name* will be replaced with whatever the name of the page being shown to the visitor is called.

The result of the rendering would be this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DynamicWeb - CMS, PIM and Ecommerce</title>
  </head>
  <body>
    <h1>Welcome to the page 'Home'</h1>
  </body>
</html>

Showing dynamic content

Building on the previous paragraph, there are two ways to fetch dynamic content to a template:

  • ViewModels - type safe, perform better, allows you to have IntelliSense/code prediction in your IDE
  • TemplateTags - older, being phased out, sometimes still used in some template contexts

ViewModel templates

A ViewModel-based template starts by inheriting a context-specific ViewModel - here a ProductListViewModel. You can then use the @Model-directive to access the properties of the ViewModel, making the template dynamic:

@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Ecommerce.ProductCatalog.ProductListViewModel>

<h1>@Model.Group.Name</h1>

<ul>
@foreach (var product in Model.Products)
{
    <li>@product.Name (@product.Price.PriceWithVatFormatted)</li>
}
</ul>

You can find all our ViewModels in the API reference - and many of them are also described and explained in the articles which form this part of the developer documentation.

TemplateTag templates

A tag-based template uses various loops and Get-methods to fetch content based on TemplateTags:

@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>

<h1>@GetString("Ecom:ProductList:Page.GroupName")</h1>

<ul>
@foreach (LoopItem product in GetLoop("Products"))
{
    <li>@product.GetString("Ecom:Product.Name") (@product.GetString("Ecom:Product.Price.PriceWithVATFormatted"))</li>
}
</ul>

To see which TemplateTags are available you can use the @TemplateTags() helper method somewhere in the template; it will render a table in frontend with a list of available tags, loops, and values for the context. You can read more about the TemplateTags-system on our old documentation site.

Extensibility

By default, ViewModels contain all the properties which we regard as necessary to do whatever you need to do in each template. If you need to add custom properties to a ViewModel, please see Extending ViewModels.

Please note, however, that you risk making the ViewModel perform at an unacceptable level. To avoid this, keep these guidelines in mind:

  • Be careful not to add 'business logic' in the template, e.g. price calculations and the like. Use other extensibility points for that, e.g. custom providers
  • Creating extension methods for code only used once compiles the code away so it is harder to update and harder to understand how the template work.
  • Templates are rendered and the code in them executed many times - too many API-calls or too much C#-code can cause performance issues if you're not careful

Read more about extensibility here.

To top