Compile-Time Data in LWR on Node.js

After you understand the basics about templating and layouts with LWR, you can use the various data provided by LWR for more complex scenarios. The place to start is with context objects.

Understand Context Objects 

LWR uses a route’s templates and context to render the response for a page request.

The context object that LWR passes into HTML and Nunjucks templates contains data from several locations. This data is merged into a single object in this order:

When it comes to context objects, Markdown templates are a little different from HTML and Nunjucks templates. Context isn’t passed into Markdown templates unless you use a route handler, which is a way of customizing the page response. “Route Handler Functions” in Server-Side Routing in LWR discusses this advanced topic.

Note

Global Data 

From the file system, you can pass any static global context data into your app’s content and layout templates. This data is available to all HTML or Nunjucks templates within your application. It is not available to component HTML templates, however.

1src/
2  └── data/     // global template context data
3      ├── site/
4      │   └── navbar.json
5      └── global.json
1// $rootDir/src/data/global.json
2{
3  "siteTitle": "LWR Docs"
4}
1// $rootDir/src/data/site/navbar.json
2[
3  {
4    "id": "guide",
5    "name": "Guide",
6    "url": "/guide/introduction"
7  },
8  {
9    "id": "recipes",
10    "name": "Recipes",
11    "url": "/recipes"
12  }
13]

This global data is then added to the context.

1// context object
2{
3  "global": {
4    "siteTitle": "LWR Docs"
5  },
6  "site": {
7    "navbar": [
8      {
9        "id": "guide",
10        "name": "Guide",
11        "url": "/guide/introduction"
12      },
13      {
14        "id": "recipes",
15        "name": "Recipes",
16        "url": "/recipes"
17      }
18    ]
19  }
20}

Front Matter 

LWR reads any front matter out of a template and adds it to the context object. Front matter values are local to the template.

LWR uses the gray-matter parser to process front matter. This allows you to use YAML, JSON, TOML, or CoffeeScript to format front matter, or you can even set custom delimiters. The following is a YAML front matter example:

1---
2custom: 9000
3someText: Good to meet you
4immutable: false
5layoutTemplate: $layoutsDir/main_layout.njk
6---
7
8{# $rootDir/src/content/home.njk #}
9<p>{{someText}}</p>
10<p>{{custom}}</p>
11It is now {{ now | date('dddd, MMMM Do YYYY, h:mm:ss a') }}
YAML
1---
2custom: 9000
3someText: Good to meet you
4immutable: false
5layoutTemplate: $layoutsDir/main_layout.njk
6---
7
8{# $rootDir/src/content/home.njk #}
9<p>{{someText}}</p>
10<p>{{custom}}</p>
11It is now {{ now | date('dddd, MMMM Do YYYY, h:mm:ss a') }}

LWR has predefined the following front matter variables:

VariableSupported Template LanguagesNotes
layoutTemplateHTML, Nunjucks, MarkdownSets the layout template inside a content template. This value is overridden by the layoutTemplate set on the route.
immutableNunjucksSet this variable to false if the template contents are mutable; the default is true. Nunjucks templating allows mutable constructs to be embedded in a template’s content, for example, random and cycler. Due to this capability, templates that use these features must mark the template as mutable so LWR can modify the cacheability of the page response.

Page Information 

LWR can pass information about the page from the current route and request.

  • id: route.id
  • title: set to the first defined value of the following:
    • properties.title from the route or viewParams.title from the route handler
    • filename from route.contentTemplate
    • “LWR App”
  • url: the request URL, relative to the origin

Example 1: When the current browser location is http://localhost:3000/ and the route is:

1// route in lwr.config.json
2{
3  "id": "home_page",
4  "path": "/",
5  "contentTemplate": "$contentDir/home.html",
6  "layoutTemplate": "$layoutsDir/main_layout.njk"
7}

Then, the page information is:

1// context object
2{
3  "page": {
4    "id": "home_page",
5    "title": "home",
6    "url": "/"
7  }
8}

Example 2: When the current browser location is http://localhost:3000/recipes?sort=desc and the route is:

1// route in lwr.config.json
2{
3  "id": "recipes",
4  "path": "/recipes",
5  "contentTemplate": "$contentDir/recipes.md",
6  "properties": {
7    "title": "Recipes Repository"
8  }
9}

Then, the page information is:

1// context object
2{
3  "page": {
4    "id": "recipes",
5    "title": "Recipes Repository",
6    "url": "/recipes?sort=desc"
7  }
8}

The object is accessible via the page context variable in the HTML/Nunjucks templates:

1{# $layoutsDir/layout.njk shows the page title and a logo on the home page #}
2<!DOCTYPE html>
3<html>
4  <head>
5    <title>{{page.title}}</title>
6  </head>
7  <body>
8    {% if page.id === 'home_page' %}
9    <img src="$assetsDir/images/logo.svg" alt="logo" />
10    {% endif %}{{ body | safe }}{{ lwr_resources | safe }}
11  </body>
12</html>

Markdown Metadata 

Markdown content templates produce context on their headings, which can be accessed from an HTML or Nunjucks layout template. Information on each heading starting with two or more # is included. For example, this Markdown:

1## Topic 1
2
3### Sub-Topic
4
5#### Grandchild

Produces this context object:

1// context object
2{
3  "headings": [
4    {
5      "text": "Topic 1",
6      "slug": "topic-1"
7    },
8    {
9      "text": "Sub-Topic",
10      "slug": "sub-topic"
11    },
12    {
13      "text": "Grandchild",
14      "slug": "grandchild"
15    }
16  ]
17}

The object is accessible via the headings context property in HTML/Nunjucks layout templates:

1{# $layoutsDir/partials/nav.njk shows a link for each heading #}
2<ul>
3    {% for mdHeading in headings %}
4        <li><a href="#{{mdHeading.slug}}">{{mdHeading.text}}</a></li>
5    {% endfor %}
6</ul>

Static Route Properties 

You can pass static context into HTML/Nunjucks templates from a route via its properties:

1// route with properties in lwr.config.json
2{
3  "id": "about",
4  "path": "/about",
5  "contentTemplate": "$contentDir/about.html",
6  "properties": {
7    "someText": "Lorem ipsum dolor sit amet"
8  }
9}
1<!-- $contentDir/about.html shows the route property -->
2<h2>About</h2>
3<p>{{someText}}</p>

Route Handlers 

Context objects can optionally contain route handlers. Route handlers are functions that allow you to customize the page response for a route. “Route Handler Functions” in Server-Side Routing in LWR discusses this advanced topic.

LWR 

LWR automatically passes two context object properties:

  • body: Available in layout templates, a string containing the rendered page content that is output from the route’s contentTemplate or rootComponent.
  • lwr_resources: A string containing all the scripts required to run your application, such as the Lightning Web Component library and LWR client resources. If this string is excluded from the page response, embedded Lightning web components don’t render.
    • Note: The lwr_resources property is optional. If you have purely static HTML content (no Lightning web components, module resolution, or other LWR features), you don’t require LWR resources in your layout. In the static site you created as your first project, the main_layout.njk file doesn’t include lwr_resources.

Here are examples of HTML and Nunjucks layout templates that use both LWR properties:

HTML:

1<!-- $layoutsDir/main.html -->
2<!DOCTYPE html>
3<html>
4  <head></head>
5  <body>
6    <!-- triple braces prevents HTML escaping -->
7    {{{body}}} {{{lwr_resources}}}
8  </body>
9</html>

Nunjucks:

1{# $layoutsDir/main.njk #}
2<!DOCTYPE html>
3<html>
4  <head></head>
5  <body>
6    {# the "safe" filter prevents HTML escaping #} {{ body | safe }}{{lwr_resources | safe }}
7  </body>
8</html>

Developer Preview Feature

Feature is available as a developer preview. Feature is not generally available unless or until Salesforce announces its general availability in documentation or in press releases or public statements. All commands, parameters, and other features are subject to change or deprecation at any time, with or without notice. Do not implement functionality developed with these commands or tools.