Site Project Settings

Contents

Environment variables

The site project uses dotenv to load environment variables from the .env file.

⚠️ Do not commit the .env file to your code repository!

SITE_LANGUAGE

SITE_LANGUAGE=en-US

The language of the site. This value will be passed in the Accept-Language HTTP header in requests to the Delivery API. It is also used to set the lang attribute of the html element in the base layout.

⚠️ Multi-lingual sites are not currently supported.

UMBRACO_BASE_URL

UMBRACO_BASE_URL=http://localhost:1111/

The base URL of the Umbraco CMS. Used to call the Delivery API and to download media files.

⚠️ This is a required variable. The build will fail if it is not set.

UMBRACO_DELIVERY_API_KEY

UMBRACO_DELIVERY_API_KEY=11111111-1111-1111-1111-111111111111

The Umbraco Delivery API key. Passed in the Api-Key header in all requests to the API. Can be left blank if the API is public.

⚠️ This is set to a randomly generated GUID when the solution is created. This needs to match the Delivery ApiKey setting in the CMS. Feel free to change it, but make sure to store it securely.

UMBRACO_DELIVERY_API_TAKE

UMBRACO_DELIVERY_API_TAKE=1111

The number of content nodes to retrieve at build time. Passed in the take parameter in calls to the Delivery API.

⚠️ This should be greater than the total number of nodes in the CMS. I haven't tested performance with large node trees.

Eleventy config

Eleventy is configured in eleventy.config.js. See the Eleventy configuration docs for full details about this file and the supported options.

The following sections detail the custom configurations and extensions included in the starter kit.

Directories

The Eleventy directory configuration is as follows:

dir: {
	input: "./content/",
	output: "./_site/",
	includes: "../_includes/",
	data: "../_data/",
}

input

The input directory is where Eleventy looks for templates to process.

At the moment this directory just contains UmbracoPage.11ty.js, a JavaScript template that automatically renders Nunjucks templates for Umbraco page nodes.

You can put any files that you want to be processed as Eleventy templates here and they will be combined with the content pages from the CMS in the output. Note that the Eleventy build will fail if there are permalink conflicts.

output

The output directory is where Eleventy writes the generated static site files.

includes

The includes directory is meant for Eleventy layouts, include files, extends files, partials or macros. The starter kit also places CSS files in this directory.

data

The data directory is where Eleventy's global data files reside. Global data is available to all templates. In the starter kit we use it to expose environment variables and Umbraco CMS data across templates.

Passthrough File Copy

Passthrough File Copy is used to copy the contents of the public directory to the output directory:

eleventyConfig.addPassthroughCopy({ "./public/": "/" });

Use this directory for static assets such as fonts that need to be publicly accessible on the front end.

Plugins

Id Attribute

The Id Attribute plugin is used to automatically add id attributes to heading tags within the HTML output. This allows for deep linking to sections within pages and automatically generating tables of contents. It is used in its default configuration:

eleventyConfig.addPlugin(IdAttributePlugin);

Render

The Render plugin is added to enable us to programmatically render Nunjucks templates for Umbraco content pages. It is also used in its default configuration:

eleventyConfig.addPlugin(EleventyRenderPlugin);

Image

The Image optimisation plugin is added with the following options:

eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
	formats: ["webp", "jpeg", "svg"],
	svgShortCircuit: true,
	htmlOptions: {
		imgAttributes: {
			loading: "lazy",
			decoding: "async",
		},
	},
	sharpOptions: {
		animated: true,
	},
	urlPath: "/images/",
});

Filters

A small number of custom filters are included in the filters directory.

subpageNavigation

The subpageNavigation filter is used in the generation of the subpage navigation menu in the webPage template. It returns an array of child pages, which themselves can contain children, for a given node ID and depth. This array is then used to render a nested list of links.

eleventyConfig.addFilter("subpageNavigation", subpageNavigation);

richText

The richText filter accepts some HTML, scans it for relative URLs starting with /media/ and prepends them with the UMBRACO_BASE_URL. This is so the Image plugin HTML transform will download and cache Umbraco media images embedded in rich text editors.

eleventyConfig.addFilter("richText", richText);

It uses @11ty/posthtml-urls under the hood.

sanitize

The sanitize filter uses DOMPurify to sanitise HTML markup and protect against XSS attacks. Rich text markup coming from the CMS is piped through this filter, just in case some malicious code has found its way in there.

eleventyConfig.addFilter("sanitize", sanitize);

If you are experiencing issues with certain HTML tags or attributes being stripped out, you can update the DOMPurify configuration in filters/sanitize.js.

Transforms

A small number of custom transforms are included in the transforms directory.

tableOfContents

The tableOfContents transform automatically generates a table of contents for a web page based on heading element IDs in the HTML.

eleventyConfig.addTransform("tableOfContents", tableOfContents);

It uses posthtml to parse the headings and posthtml-insert-at to inject the contents into the page.

htmlMinifier

The htmlMinifier transform minifies HTML and CSS in HTML output files.

eleventyConfig.addTransform("htmlMinifier", htmlMinifier);

It uses html-minifier-terser and is configured in transforms/htmlMinifier.js:

{
	collapseBooleanAttributes: true,
	collapseWhitespace: true,
	minifyCSS: true,
	removeAttributeQuotes: true,
	removeOptionalTags: true,
	removeRedundantAttributes: true,
	sortAttributes: true,
	sortClassName: true,
}

Watch targets

The uSync directory in the CMS project is added as a watch target so that any time Umbraco content is published (or content types/data types/etc. are modified), the dev site will be rebuilt/refreshed automatically:

eleventyConfig.addWatchTarget("../Thingy.Cms/uSync/");

We also wait a short time before triggering a new site build to give Umbraco a chance to index any published content:

eleventyConfig.setWatchThrottleWaitTime(500);

CSS

The starter kit uses a vanilla CSS approach based on the CUBE CSS methodology. CSS files are located in the _includes/css/ directory.

Some sensible global styles and variables have been defined (inspired by Andy Bell's excellent Complete CSS course), as well as some layout compositions from Every Layout.

However, in no way is this a complete CSS framework. It is meant as a basic starting point and something that can be built upon or easily ripped out and replaced with your favourite tools/frameworks.

Variables

Things like colours, fonts, borders, widths, and spacing are configured in CSS variables in these files:

  • global/scale.css: Utopia fluid type and space scales.

  • global/variables.css: colours, borders, fonts, gutters/wrappers, etc.

Changing the variables in these files should have a cascading effect across the entire site, helping to keep styling consistent.

Bundling

CSS bundling is handled by the Eleventy Bundle plugin. A single CSS bundle is defined named css:

eleventyConfig.addBundle("css");

If you want to add a new CSS file to the bundle you will need to include it in _includes/css/style.njk, or use the css shortcode in templates or partials (allowing for per-page bundles).

⚠️ This bundle is inlined in a <style> tag in the site head so should only be used for critical CSS styles. If you want some CSS to be deferred, use asset bucketing.

Minification

Note that the Bundle plugin does not do any minification. The inline CSS is minified by the htmlMinifier transform mentioned before. It uses clean-css under the hood with default options.