Headless
How to approach headless in DynamicWeb 10.
Headless refers to a type of architecture in which the front-end and back-end of a website or application are decoupled. In a traditional architecture, the front-end (or "head") is tightly integrated with the back-end, meaning that changes to one will often require changes to the other, which can be time-consuming and costly. With a headless architecture, the front-end and back-end communicate with each other through web APIs.
A headless architecture allows for more efficient development and deployment, greater flexibility in terms of content delivery, and enables companies to be more agile, allowing them to quickly adapt to changes in the market and customer needs.
Headless in DynamicWeb
All content in DynamicWeb is exposed to the frontend via ViewModels - traditional DynamicWeb implementations are using Razor template to render the markup on the server.
Instead of injecting the ViewModels into a template and render the markup on the server, DynamicWeb also supports a full featured web-api that exposes all the same ViewModels and data in a REST based services.
As an example, let's say we have created and item type called "BlogPost" and create a page using this item type.
The BlogPost item type have these fields:
- Title
- Author
- Image
- Text
- Link
Creating a new page using the blog post item type will allow you to add the content on the page
The same piece of content can bed rendered in Razor based templates using ViewModels but can also bed fetched using the delivery API.
Rendering a Blogpost page in Razor
A ViewModel instance of a given page is injected into the template and rendered
@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
<div>
<h1>@Model.Item.GetString("Title")</h1>
<p>
Written by @Model.Item.GetString("Author")</p>
<p>
@Model.Item.GetString("Text")
</p>
<p>
<img src="@Model.Item.GetFile("Image").Path" />
</p>
<p>
<a href="@Model.Item.GetLink("Link").Url">Read more</a>
</p>
</div>
Retrieving a Blogpost page using the headless delivery endpoint
The same page is available on the delivery API by requesting the page by its ID
GET https://localhost:6001/dwapi/content/pages/13
The ViewModel is then returned as a json document that can be used to render the blogpost using a JS component.
{
"id": 13,
"name": "My blog post",
"createdDate": "2023-06-14T13:32:34.873",
"updatedDate": "2023-06-14T13:45:22.1844074+02:00",
"title": null,
"description": null,
"keywords": "",
"areaID": 1,
"path": [
{
"id": 3,
"name": "About us"
},
{
"id": 13,
"name": "My blog post"
}
],
"languages": [],
"item": {
"fields": [
{
"name": "Title",
"systemName": "Title",
"value": "My blog post"
},
{
"name": "Author",
"systemName": "Author",
"value": "Nicolai Pedersen"
},
{
"name": "Image",
"systemName": "Image",
"value": [
{
"extension": ".png",
"name": "contentarea.png",
"path": "/Files/Images/ExampleImages/contentarea.png",
"focalX": 0,
"focalPositionFromLeft": 50,
"focalY": 0,
"focalPositionFromTop": 50,
"pathUrlEncoded": "%2FFiles%2FImages%2FExampleImages%2Fcontentarea.png"
}
]
},
{
"name": "Text",
"systemName": "Text",
"value": "<h2>Simplify eCommerce</h2>\n<p>DynamicWeb is PIM, eCommerce, Marketing and CMS in one powerful Commerce Suite featuring standard integrations to Microsoft Dynamics ERP.</p>\n<div>\n<p>Create an omnichannel B2B, B2C or D2C commerce experience using a modern <a href=\"https://dynamicweb.com/technology/mach\">MACH based application</a>, enabling you to build, run and scale your business the way you want.</p>\n</div>"
},
{
"name": "Link",
"systemName": "Link",
"value": {
"pageId": 5,
"paragraphId": 0,
"url": "/contact",
"isExternal": false
}
}
],
"id": "1",
"systemName": "BlogPost",
"pageID": 13,
"paragraphID": 0,
"link": "/about-us/my-blog-post"
},
"propertyItem": null
}
Development and frameworks
In headless implementations you can use any JS framework and development tool stack you desire.
An example of development stack:
- Git
- VS Code
- Node
- NPM
- Webpack/Vite/Esbuild, ESlint etc.
Some of the more popular frameworks for implementing headless are:
- React
- Vue
- Next.js
- Nuxt.js
- Angular
- Flutter - for developing native apps using data from DynamicWeb
Things to consider
In a regular DynamicWeb implementation using server side rendered, you are operating in a stateful context
When implementing in headless you are operating in a stateless context.
The difference is that in the stateful context DynamicWeb will keep track of the context and state of the current visitor. When in the stateless context your JS app needs to keep track of the state of the current visitor.
Examples of state that needs to be handled in the JS app:
- URLs and History
- User logins
- Carts
- Chosen language
- Chosen currency
- Chosen delivery country
- Impersonation rules
Hosting headless implementations
A headless implementation consists of at least 2 parts.
- A DynamicWeb installation that holds all the content
- Your JS app with js files, components, css and static resources
Since the JS app is completely decoupled from DynamicWeb and is consuming data using DynamicWeb as a micro service, it is possible to host the actual app in a location that is not together with DynamicWeb files.
It can be hosted on a CDN like Heroku, Netlify, AWS, Azure and other cloud services. The benefit is that many of these services comes with a CDN making it possible to load the static assets and the app very fast and only get the actual data from DynamicWeb.
The alternative to using a CDN based cloud offering for the JS app, is to upload it into DynamicWeb file system.