This is a guide on getting the minimal amount of ‘things’ installed, configured, and working to kick off a project that uses Gov UK frontend components.
The truth of it is, the Gov UK docs are usually very good for this sort of thing. And you probably won’t have to do this very often. If you’re joining an existing team, the likelihood is that there is already an app (or several) waiting for your support.
However, once in while (or twice, in my Gov UK journey so far), I have had to kick off a new NodeJS / Express app from scratch. What follows is the absolute minimum necessary to get up and running. Everything else I would consider optional, and will be covered in further posts.
Make Sure You Have The Prerequisites
The standard way that Gov UK projects work, when working with server side JavaScript at least, is to use NodeJS and Express.
For the version of NodeJS, it is good practice to stick to the latest LTS (or Long Term Support) release.
You can download NodeJS to your machine – I’m running Linux here, so that’s why the screenshot above says ‘Download for Linux (x64)’, but the website is clever enough to direct you to the correct file for your operating system.
In my opinion, a better way to install NodeJS to your local machine is via NVM. However, that is a slightly more advanced topic and is outside the scope of this post.
Another approach is to use Docker, which again, is beyond the scope of this post.
If you are comfortable with either of those approaches, by all means use them. Or something else.
For now though, I’m going to assume you have NodeJS available on your machine somehow. You can validate this by opening a terminal (or command prompt on Windows), and typing node --version
(or node -v
for short), which should report the installed version:
node --version
v18.18.0
Code language: Shell Session (shell)
Create A Directory For Your Gov UK Frontend Project
As part of installing Node, you will also get the Node Package Manager, or npm
.
We will use npm
to install the various open source and publicly available software packages required to get our fledgling project off the ground.
In order to initialise a new Node JS project, we first need a directory somewhere on our system to contain all our files.
You can call this directory anything you like, but a suitable name is usually something like project-name-frontend
or similar. Keep it professional.
cd /some/directory/on/your/computer
mkdir example-gov-uk-frontend
Code language: Shell Session (shell)
I’m going to create my project directory under my /home/chris/Development
directory.
You don’t need to worry about this having any impact on other people who will work on your project. They will need to clone your files and run them on their own computer. That comes later. For now, you only need to think about your own setup.
# create a new directory for your project
mkdir example-gov-uk-frontend
# change into that directory
cd example-gov-uk-frontend
# here's my directory path as an example
# using 'pwd' to print the working directory path
pwd
/home/chris/Development/example-gov-uk-frontend
Code language: Shell Session (shell)
Initialising Your Gov UK NodeJS App
Now we have created our project directory, and have a terminal / command prompt open and we are in that directory, we can initialise our new Node JS project.
When you run npm init
, it guides you through a series of interactive prompts to create a package.json
file for your project.
The package.json
file is a critical metadata file that contains information about your project, its dependencies, and various configuration settings.
The package.json
file is crucial for Node.js projects because it lists project dependencies, scripts to run various tasks, and other project-specific settings. It serves as a central configuration file that helps developers and tools understand how to work with your project.
Let’s create our package.json
now using the interactive prompts:
npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (example-gov-uk-frontend)
version: (1.0.0)
description: The front end for an interesting Gov UK service
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /home/chris/Development/example-gov-uk-frontend/package.json:
{
"name": "example-gov-uk-frontend",
"version": "1.0.0",
"description": "The front end for an interesting Gov UK service",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this OK? (yes)
Code language: Shell Session (shell)
The process is intelligent enough to pick up the current directory name to be the suggested default for our package name
.
The package name
is essentially our project name.
The version
isn’t that important at this stage. You could argue for setting this to 0.0.1
to begin with. Better methodologies exist for managing the project version, so I personally don’t place that much emphasis on what this value is set too.
The description
is helpful, and is likely immediately obvious what this should be in your particular case.
For all the other fields I accept the blank defaults. These can be updated later.
You will then be shown a copy of the package.json
that will be generated for you, should you say “yes” to the “Is this OK?” prompt.
ls
package.json
cat package.json
# I believe on Windows you need to use
# type package.json
{
"name": "example-gov-uk-frontend",
"version": "1.0.0",
"description": "The front end for an interesting Gov UK service",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Code language: PHP (php)
OK, so now we have initialised our new project.
But right now it is a basic Node JS project. What turns it into a Gov UK project is the use of the Gov.UK Frontend components.
Creating A Frontend Webserver With Express
Now that we’ve initialised our project, the next step is to set up a web server using Express. Express is a minimal and flexible Node.js web application framework that’s well-suited for building web applications and APIs.
In our case, we’ll use it to serve our Gov UK frontend components.
Installing Express
Before we can create a web server, we need to install Express as a dependency for our project.
Open your terminal/command prompt, make sure you’re in the project directory (example-gov-uk-frontend
), and run the following command:
npm install express
# or
npm i express
Code language: Shell Session (shell)
This command installs Express and adds it as a dependency in your package.json
file.
Here’s what the package.json
file should look like immediately after running this command:
{
"name": "example-gov-uk-frontend",
"version": "1.0.0",
"description": "The front end for an interesting Gov UK service",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2"
}
}
Code language: JSON / JSON with Comments (json)
Your version of express
may be different. If it is different, it should be a greater value than 4.18.2
.
Adding TypeScript
Using TypeScript with Express in your Gov UK Frontend project is a great way to add static typing and enhanced developer tooling to your codebase. It’s also pretty much the expected base standard at this point.
Who doesn’t like reduced bugs and nicer IDE auto completion?
Here’s how to set up TypeScript with Express:
1. Install TypeScript and Required Dependencies
In your project directory, install TypeScript and the necessary TypeScript dependencies as development dependencies:
npm install typescript @types/node @types/express --save-dev
Code language: Shell Session (shell)
typescript
is the TypeScript compiler.@types/node
and@types/express
provide TypeScript type definitions for Node.js and Express, respectively. These help with auto-completion, and checking you are providing the right parameters when working with the various Express functions.
Here’s what the package.json
file should look like immediately after running this command:
{
"name": "example-gov-uk-frontend",
"version": "1.0.0",
"description": "The front end for an interesting Gov UK service",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"@types/express": "^4.17.18",
"@types/node": "^20.7.1",
"typescript": "^5.2.2"
}
}
Code language: JSON / JSON with Comments (json)
Again, the versions of these devDependencies
very likely will differ to the above, as these projects are updated frequently. However this should not affect the rest of this process.
2. Create a tsconfig.json File
Now we need to generate a TypeScript configuration file by running the following command in your project’s root directory:
npx tsc --init
Code language: Shell Session (shell)
This command will create a tsconfig.json
file in your project root. You can customise this file according to your project’s requirements.
Here’s an example of the tsconfig.json
file immediately after creation. I have removed all the disabled entries, and deleted the comments for brevity:
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Language and Environment */
"target": "es2016",
/* Modules */
"module": "commonjs",
/* Interop Constraints */
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
/* Type Checking */
"strict": true,
/* Completeness */
"skipLibCheck": true
}
}
Code language: JSON / JSON with Comments (json)
3. Modify your tsconfig.json File
Structuring your project with separate source and distribution directories enhances maintainability, collaboration, and project organisation.
It’s a widely adopted practice that simplifies development and deployment processes, particularly in larger and more complex projects which Gov UK projects tend to be.
We will create our TypeScript code under the src
directory, and TypeScript will automatically compile these files into plain old JavaScript which will end up in the dist
/ distribution directory.
In order for that to happen, we need to add two extra compiler options to the tsconfig.json
file:
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Language and Environment */
"target": "es2016",
/* Modules */
"module": "commonjs",
"rootDir": "./src",
/* Emit */
"outDir": "./dist",
/* Interop Constraints */
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
/* Type Checking */
"strict": true,
/* Completeness */
"skipLibCheck": true
}
}
Code language: JSON / JSON with Comments (json)
We can now create our first TypeScript file.
4. Create a TypeScript Entry File
Based on the above tsconfig.json
, we need to put all our TypeScript files in the src
directory of our project.
That directory does not yet exist, so let’s create it:
mkdir src
Code language: Shell Session (shell)
Our project structure should look something like this:
/node_modules
package.json
package-lock.json
/src
tsconfig.json
We do not need to create a dist
directory. TypeScript will do that for us in the next step.
Create a TypeScript entry file, typically named index.ts
, in your src
directory. This will be the entry point for your Express application.
// src/index.ts
import express from 'express';
const app = express();
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello from our Gov UK Frontend Express Starter with TypeScript!');
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Code language: TypeScript (typescript)
5. Run the TypeScript Compiler
In your terminal, compile your TypeScript code to JavaScript by running:
npx tsc
Code language: Shell Session (shell)
This will generate JavaScript files in the dist
directory, as specified in your tsconfig.json
file.
You should now have a new dist
directory, and a single file inside that directory, dist/index.js
.
6. Start Your Express Server
Let’s test out our progress so far.
To start your Express server with Node.js, use the following command:
node dist/index.js
# you should see something similar to:
Server is running on port 3000
# if you get a port conflict, try:
PORT=3300 <span style="background-color: initial; font-family: inherit; font-size: inherit; text-wrap: wrap; color: inherit;">node dist/index.js</span>
# and you should see the server running on the new port
Server is running on port 3300
Code language: PHP (php)
Your server should now be running and serving content.
We can test this by visiting http://localhost:3000/
Our basic Express webserver is now up and running.
Displaying Your Frontend Website With Nunjucks
Now that we have our basic Express web server set up, it’s time to move on to displaying a website with Nunjucks.
Nunjucks is a powerful templating engine that allows you to create dynamic web pages by combining HTML templates with data.
On UK Government projects, all the available front end components such as Accordions, Headers, Footers, Error messages, and many more are available through either plain HTML or Nunjucks macros. The standard, when working with NodeJS and Express is to use Nunjucks.
We will need to do a little further set up in order to be able to use those components. But we will be able to do so by the end of this post.
Installing Nunjucks
First, we need to install the Nunjucks library as a dependency for our project. Open your terminal or command prompt, ensure you’re in your project’s root directory (where your package.json
and tsconfig.json
files are located), and run the following command:
npm install nunjucks
This command installs Nunjucks and adds it as a dependency in your package.json
file.
To enable TypeScript support for Nunjucks, we also need to install TypeScript definitions for Nunjucks. Run the following command to do so:
npm install @types/nunjucks --save-dev
# or
npm i -D @types/nunjucks
Code language: CSS (css)
Here’s what the package.json
file should look like immediately after running this command:
{
"name": "example-gov-uk-frontend",
"version": "1.0.0",
"description": "The front end for an interesting Gov UK service",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
"nunjucks": "^3.2.4"
},
"devDependencies": {
"@types/express": "^4.17.18",
"@types/node": "^20.7.1",
"@types/nunjucks": "^3.2.4",
"typescript": "^5.2.2"
}
}
Code language: JSON / JSON with Comments (json)
Again, your versions may be slightly different. That should be absolutely fine.
Setting Up Nunjucks Templates
Next, let’s create a directory to store our Nunjucks templates. In your project’s src
directory, create a folder named views
:
mkdir src/views
Inside the views
directory, you can create your Nunjucks templates with the .njk
file extension. For example, let’s create a basic template named index.njk
:
touch src/views/index.njk
Here’s how this folder structure appears in WebStorm, my IDE of choice after running these commands:
Open the index.njk
file in a text editor and add some HTML content. Here’s a simple example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gov UK Frontend Express Starter</title>
</head>
<body>
<header>
<h1>Welcome to our Gov UK Frontend Express Starter</h1>
</header>
<main>
<p>This is a simple web page using Nunjucks templating.</p>
</main>
</body>
</html>
Code language: HTML, XML (xml)
Sadly, by default, neither WebStorm nor VSCode do a particularly good job of adding syntax highlighting to Nunjucks files, due to their .njk
extension.
For WebStorm, I suggest installing the Twig plugin. It suggests that this is a PHP plugin, but it works well for Nunjucks also.
For VSCode, there is a Nunjucks plugin.
Covering installation and configuration of those plugins is outside the scope of this post.
Configuring Nunjucks in Express
Now, we need to configure Express to use Nunjucks as the view engine. In your index.ts
file (located in the src
directory), make the following changes:
import express from 'express';
import nunjucks from 'nunjucks'; // Import Nunjucks
const app = express();
const port = process.env.PORT || 3000;
// Configure Nunjucks
nunjucks.configure('src/views', {
autoescape: true,
express: app,
});
app.get('/', (req, res) => {
// Render the 'index.njk' template
res.render('index.njk');
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Code language: JavaScript (javascript)
In this code:
- We import the Nunjucks library alongside Express.
- We configure Nunjucks to use the
views
directory as the location for our templates. We also specifyautoescape
to protect against cross-site scripting (XSS) attacks and setexpress
to our Expressapp
. - Inside the
/
route handler, we useres.render('index.njk')
to render theindex.njk
template.
Testing the Nunjucks Template
Now that Nunjucks is configured, we need to do three things:
- Stop the Express server, if it is still running: press
ctrl
+c
in the terminal to stop the server. - Re-compile your TypeScript to JavaScript: run
npx tsc
from your project root directory. - Start the Express server: run
node dist/index.js
from your project root directory.
That’s a little long winded.
Far better solutions to this problem exist, but as this is a deliberately minimal example, we will stick to this process.
However, we can short this to a two step process. You will still need to press ctrl
+ c
in the terminal to stop the server, but you can compile your TypeScript and start the Express server in one line with:
npx tsc && node dist/index.js
Code language: Shell Session (shell)
Visit http://localhost:3000/
in your web browser.
You should see the HTML content from your index.njk
template displayed in the browser.
Congratulations, you’ve successfully displayed a website using Nunjucks templating with Express!
Nunjucks offers powerful templating features, including data interpolation, conditionals, loops, and layout inheritance.
You will continue to build your Gov UK frontend project by creating more templates and adding dynamic content to your web pages using Nunjucks.
However, we are currently missing the necessary CSS to make our HTML look like a Gov UK site should do. Let’s fix that.
Adding govuk-frontend and Sass
Now that we’ve set up the basics for our Gov UK Frontend Express project, it’s time to bring in the core styles and components provided by govuk-frontend
. This package offers the necessary styling and components to align your project with the official UK government design system principles.
Installing govuk-frontend and Sass
Let’s start by adding govuk-frontend
to our project as a dependency. Open your terminal or command prompt, ensure you’re in the root directory of your project (where your package.json
file is located), and run the following commands:
npm install govuk-frontend
Code language: Shell Session (shell)
Once that finishes successfully, run this command also:
npm install sass --save-dev
Code language: Shell Session (shell)
govuk-frontend
contains the essential styles and components to make our web application look and feel like a Gov UK project.
sass
is used to compile Sass into CSS.
Sass, which stands for “Syntactically Awesome Style Sheets,” is a powerful and widely used CSS preprocessor. It extends the capabilities of standard CSS by introducing features like variables, nesting, mixins, and functions, making it easier and more efficient to write and maintain stylesheets for web development.
Sass code is compiled into standard CSS before being applied to web pages, allowing developers to write cleaner and more organised styles while benefiting from features that enhance re-usability and maintainability in large-scale projects.
Elements of the govuk-frontend
will end up in our final, production build. That is why, in our package.json
file, it is listed under the dependency
section.
However sass
is only used as part of our build process, and no part of sass
will be included in our final production build. That is why sass
is listed as a development dependency (devDependency
) in package.json
.
Writing Your Sass Styles
In my experience, having to write custom styles is rare on UK government projects primarily due to a strong emphasis on design consistency, adherence to user-centred principles, and strict accessibility standards.
Government websites prioritise a uniform user experience validated through extensive user research, making customisation less common to maintain accessibility and adherence to design systems.
However, we do need at least one custom Sass file so we can import the Gov UK frontend assets into our project.
We will create a new directory and file under the project root directory, ./assets/main.scss
. This will be our main Sass source file.
To make use of Gov UK Frontend styles, simply import them at the top of your main.scss
file like this:
@import "node_modules/govuk-frontend/govuk/all";
Code language: CSS (css)
This line imports all the styles from the Gov UK Frontend package, allowing you to leverage Gov UK’s consistent and user-friendly design principles in your project.
At this point we still need to compile the Sass file(s) down to a single CSS file that web browsers can actually use.
Using Sass From The Command Line
To start with, we will use Sass from the command line to better understand what is actually happening.
Once we have this process working from the command line, we will move this process into our package.json
file as a script, so that we don’t need to do anything this cumbersome on a regular basis.
Here’s how our project directory structure should look at this point:
Note that I have deleted all the files under the dist
directory, but you don’t have too.
OK, so the command we need to run is:
./node_modules/.bin/sass \
--load-path=node_modules/govuk-frontend \
--load-path=. \
assets/main.scss \
dist/public/stylesheets/main.css \
--style=compressed \
--no-source-map
Code language: Shell Session (shell)
That looks fairly intense. But let’s break it down line by line.
./node_modules/.bin/sass
: This is the command to execute the Sass compiler. The./node_modules/.bin
part specifies the path to the local binary executable for Sass within our project’snode_modules
directory. It ensures that we use the Sass version installed as a dependency in our project.--load-path=node_modules/govuk-frontend
: The--load-path
flag tells Sass where to look for imported files. In this case, it specifies that Sass should look for files in thenode_modules/govuk-frontend
directory. This is used to access styles from the Gov UK Frontend package.--load-path=.
: This flag adds the current directory (.
) to the list of paths where Sass will look for imported files. It allows us to include custom Sass files located in our project’s local directory.assets/main.scss
: This is the path to our main Sass source file. It’s the entry point for our Sass styles. We can then customise and import other stylesheets from here.dist/public/stylesheets/main.css
: This is the destination where the compiled CSS will be saved. It specifies the location and name of the output CSS file. In this case, the compiled CSS will be saved asmain.css
in thedist/public/stylesheets
directory.--style=compressed
: This flag sets the output style for the compiled CSS. In our case, it’s set tocompressed
, which means that our CSS will be minified and optimised for production, resulting in a smaller file size.--no-source-map
: This flag disables the generation of source maps. Source maps are used for debugging, but they are not needed in a production build. Disabling them helps keep the output CSS files smaller and more efficient.
If we run that now from the command line, we should get two interesting outcomes.
The first is that the command throws out lots of scary looking warnings:
Those warnings are coming from the Gov UK front end components directory, and we do not have an easy way to ‘fix’ them. This is a known issue and is due to the need for backwards compatibility with another Sass library called LibSass.
As the link above suggests, we can hide the warnings in their Sass, without silencing warnings in our own project.
In order to do this we need to add the --quiet-deps
flag:
./node_modules/.bin/sass \
--load-path=node_modules/govuk-frontend \
--load-path=. \
assets/main.scss \
dist/public/stylesheets/main.css \
--style=compressed \
--no-source-map \
--quiet-deps
Code language: Shell Session (shell)
I’d include a screenshot of running that command, but if all goes to plan, you actually won’t see any output.
In order to see the results of running this command we need to open up the path we provided as the output of running this command: dist/public/stylesheets/main.css
:
You can delete this file and re-run the command and it should be recreated.
Creating a Sass Build Script
Having to remember and run that long winded command isn’t ideal. Even less so if there are multiple people on your team, some of whom may not be particularly technical.
Fortunately we can hide this away behind a much smaller command, by creating a custom build script.
In the scripts
section of your package.json
file, add the following custom build script:
"build:sass": "sass --quiet-deps --load-path=node_modules/govuk-frontend --load-path=. assets/main.scss dist/public/stylesheets/main.css --style=compressed --no-source-map"
Code language: JavaScript (javascript)
This is practically identical to the command we ran by hand.
The one difference being that we do not need to provide the initial path of ./node_modules/.bin
to the sass
command, as this is implicitly where Node will look for our Sass binary file.
Compiling Your Sass
To compile your Sass code into CSS, run the following command in your terminal:
npm run build:sass
Code language: CSS (css)
This command will execute your custom Sass build script and generate a compressed CSS file located at dist/public/stylesheets/main.css
. You can now include this CSS file in your Express templates to apply the Gov UK styling to your web pages.
With Sass, you have the flexibility to define custom styles while benefiting from the Gov UK Frontend’s established design system. Your project will not only look polished but also adhere to the official UK government design principles.
Configuring Express to Serve Static Files
To utilise the CSS file we have just created, along with the images, fonts, and scripts provided by govuk-frontend
, we need to configure Express to serve static files from a specified directory.
The way this works is a little unintuitive, in my opinion.
In your index.ts
file (found in the src
directory), add the following lines of code to set up this configuration:
import express from 'express';
import nunjucks from 'nunjucks';
import path from 'path'; // Import the 'path' module
const app = express();
const port = process.env.PORT || 3000;
// Configure Express to serve static files from the 'assets' directory
const assets = [
'/dist/public/stylesheets',
'/node_modules/govuk-frontend/govuk/assets',
'/node_modules/govuk-frontend',
];
assets.forEach(dir => {
app.use('/assets', express.static(path.join(process.cwd(), dir)))
});
// Configure Nunjucks
nunjucks.configure('src/views', {
autoescape: true,
express: app,
});
app.get('/', (req, res) => {
// Render the 'index.njk' template
res.render('index.njk');
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Code language: TypeScript (typescript)
Here, we are importing the built-in Node.js module called path
.
The path
module provides utilities for working with file and directory paths. In this case, we are importing it so that we can construct a path to our assets
directory.
The added code is configuring Express to serve static files from specific directories, which is a crucial step in integrating govuk-frontend
styles and assets into your Express project. Let’s break down the additions:
// Configure Express to serve static files from the 'assets' directory
const assets = [
'/dist/public/stylesheets',
'/node_modules/govuk-frontend/govuk/assets',
'/node_modules/govuk-frontend',
];
assets.forEach(dir => {
app.use('/assets', express.static(path.join(process.cwd(), dir)))
});
Code language: TypeScript (typescript)
const assets
: This is an array that contains the paths to the directories where our static assets are located. These directories include:/dist/public/stylesheets
: This is the path to the stylesheets directory generated by our Sass build process. It should contain the compiled CSS file we created above./node_modules/govuk-frontend/govuk/assets
: This is the path to the assets directory within thegovuk-frontend
package. It contains various assets like images, JavaScript files, and fonts used by the Gov UK frontend components./node_modules/govuk-frontend
: This is the main directory of thegovuk-frontend
package, which contains additional assets and stylesheets needed for the Gov UK frontend components.
assets.forEach(dir => { ... })
: This code iterates over theassets
array and sets up Express middleware to serve static files from each of the specified directories.app.use('/assets', express.static(path.join(process.cwd(), dir)))
: This line configures Express to serve static files under the/assets
route. It uses theexpress.static
middleware to serve files from the specified directory, andpath.join
is used to construct the full path to the directory based on the current working directory (process.cwd()
) and the directory path in theassets
array.
With this configuration in place, any files in the specified directories can now be accessed by our Express application via the /assets
route. This allows us to include Gov UK frontend styles and assets in our templates and web pages.
For example, if we want to include a CSS file from govuk-frontend in your Nunjucks template, we can reference it like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gov UK Frontend Express Starter</title>
<link rel="stylesheet" href="/assets/main.css">
</head>
<body>
<header>
<h1>Welcome to our Gov UK Frontend Express Starter</h1>
</header>
<main>
<p>This is a simple web page using Nunjucks templating.</p>
</main>
</body>
</html>
Code language: HTML, XML (xml)
This will load the Gov UK frontend stylesheet from the specified path, and our web pages will have a valid reference to our custom stylesheet.
Note that this does not mean any custom styles will be immediately applied to our h1
and p
tags:
We can see that the reference to the stylesheet worked – it returns a 200
status code.
We can also browse directly to that file:
However, our favicon.ico
is showing as a 404
. Notice in our HTML / Nunjucks template we didn’t explicitly say where the favicon
should come from anyway.
I think it’s worthwhile adding an extra file in here just to be absolutely clear on how this pathing works. I’ve come unstuck by this myself, and as I said at the start of this section I find this particularly unintuitive.
If we add another sub-directory under dist/public/stylesheets
, and a file in there called test.txt
, let’s see what happens:
In the browser we can immediately see (i.e. without having to stop / restart express):
The important thing is that the path served by express:
/assets/some/nested/directory/test.txt
Is not a direct match with the directory structure in our project:
dist/public/stylesheets/some/nested/directory/test.txt
Essentially dist/public/stylesheets
is mapped to /assets
.
And why?
Because of this bit we added earlier:
// Configure Express to serve static files from the 'assets' directory
const assets = [
'/dist/public/stylesheets',
'/node_modules/govuk-frontend/govuk/assets',
'/node_modules/govuk-frontend',
];
assets.forEach(dir => {
app.use('/assets', express.static(path.join(process.cwd(), dir)))
});
Code language: TypeScript (typescript)
Which does mean that the assets provided by the govuk-frontend
are also immediately available, under /assets
, but not on a 1:1 path mapping.
Here’s the favicon
provided by the govuk-frontend
:
And in the browser:
Hopefully that makes a little more sense now. To me I think this is very confusing without an example to reference like the one above.
Anyway, let’s style up our page a little.
Styling Our HTML
As Fat Boy Slim told us back in 1998, we have come a long, long way together, through the hard times and the good.
It’s time to style our pages baby, it’s time to style them real good.
Or something.
To paraphrase, we’ve done a ton of work to get to this point and now we can, finally, see the benefit of our labour.
As I have already said, it’s rare to need to create your own styles when working on a Gov UK project. Instead you should first check out the documentation, and see if something already exists.
Let’s add the necessary styles to our page elements now and see the result:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gov UK Frontend Express Starter</title>
<link rel="stylesheet" href="/assets/main.css">
</head>
<body>
<header>
<h1 class="govuk-heading-xl">Welcome to our Gov UK Frontend Express Starter</h1>
</header>
<main>
<p class="govuk-body">This is a simple web page using Nunjucks templating.</p>
</main>
</body>
</html>
Code language: HTML, XML (xml)
For each element we have added the necessary Gov UK provided style.
Unfortunately you will still need to stop and restart Express to see your change in the browser:
npx tsc && node dist/index.js
Code language: Shell Session (shell)
After which you should see:
It’s looking nicer, but it’s not quite there yet.
Adding The Gov UK Page Layout
Up until this point, our HTML template was quite basic. It did the job but lacked the distinctive style and layout we associate with Gov UK projects. In a real-world scenario, Gov UK projects maintain a consistent look and feel across all web pages. They achieve this through the use of a common page layout that includes standardised headers, footers, navigation, and other components.
To bring our project in line with these design principles, we will make a key change: we updated our HTML template to extend the Gov UK page layout using Nunjucks’ inheritance feature.
Nunjucks Inheritance
Nunjucks provides a powerful feature called template inheritance. It allows you (or someone else) to create a base template (in this case, the Gov UK page layout) and extend it in other templates (our specific web pages) by defining content blocks that can be overridden.
The govuk front end provides a standard template that we should extend from. This template defines a number of block
that we can override to add in our specific page content, whilst maintaining the correct look and feel of a standard Gov UK website.
Here’s a screenshot of the template.njk
, which you can find in your own project at:
node_modules/govuk-frontend/govuk/template.njk
Code language: Shell Session (shell)
Let’s now extend that to add in our own content. It’s quite intuitive.
{% extends "govuk/template.njk" %}
{% block pageTitle %}Gov UK Frontend Express Starter<{% endblock %}
{% block head %}
<link rel="stylesheet" href="/assets/main.css">
{% endblock %}
{% block content %}
<h1 class="govuk-heading-xl">Welcome to our Gov UK Frontend Express Starter</h1>
<p class="govuk-body">This is a simple web page using Nunjucks templating.</p>
{% endblock %}
Code language: HTML, XML (xml)
Here’s an explanation of the changes we made to the template:
{% extends "govuk/template.njk" %}
Code language: JavaScript (javascript)
This line uses Nunjucks template inheritance to extend the base template provided by Gov UK Frontend. In other words, it means our page will inherit the structure and styles defined in the govuk/template.njk
template.
{% block pageTitle %}Gov UK Frontend Express Starter{% endblock %}
This block defines the title of our web page. In the base template, there’s a placeholder for the page title, and by using this block, we can set the title specific to our page.
{% block head %}
<link rel="stylesheet" href="/assets/main.css">
{% endblock %}
Code language: HTML, XML (xml)
Inside the “head” block, we include a link to our custom stylesheet (main.css
) located in the /assets
directory. This is where we could add the additional styles for our page.
{% block content %}
<h1 class="govuk-heading-xl">Welcome to our Gov UK Frontend Express Starter</h1>
<p class="govuk-body">This is a simple web page using Nunjucks templating.</p>
{% endblock %}
Code language: HTML, XML (xml)
Within the “content” block, we place the main content of your page. In this case, we have an h1
element for the page heading and a p
element for the page content. These elements are styled using Gov UK Frontend classes to maintain the consistent Gov UK look and feel.
By structuring our page in this way, we ensure that it adheres to the Gov UK design system and inherits the necessary styles and layout defined in the base template. This makes it easier to create Gov UK-compliant web pages while customising the content to suit our specific needs.
Typically we would create another ‘layer’, called layout.njk
where we provide common things such as our stylesheet and a default page title, Google Analytics, common JavaScripts and things, such that we do not have to add them to every single page on our site.
Testing A Gov UK Component
Lastly, we should test out one of the standard Gov UK components.
Any will do, take your pick from the docs.
I’ll go with the Accordion, simply because it is first in the list.
For each component we get a HTML and Nunjucks example.
Click the Nunjucks example and either manually copy the block, or click the handy ‘Copy code’ button to automatically set this to your clipboard.
Here’s how my template looks after doing this:
{% extends "govuk/template.njk" %}
{% from "govuk/components/accordion/macro.njk" import govukAccordion %}
{% block pageTitle %}Gov UK Frontend Express Starter<{% endblock %}
{% block head %}
<link rel="stylesheet" href="/assets/main.css">
{% endblock %}
{% block content %}
<h1 class="govuk-heading-xl">Welcome to our Gov UK Frontend Express Starter</h1>
<p class="govuk-body">This is a simple web page using Nunjucks templating.</p>
{{ govukAccordion({
id: "accordion-default",
items: [
{
heading: {
text: "Writing well for the web"
},
content: {
html: '<p class="govuk-body">This is the content for Writing well for the web.</p>'
}
},
{
heading: {
text: "Writing well for specialists"
},
content: {
html: '<p class="govuk-body">This is the content for Writing well for specialists.</p>'
}
},
{
heading: {
text: "Know your audience"
},
content: {
html: '<p class="govuk-body">This is the content for Know your audience.</p>'
}
},
{
heading: {
text: "How people read"
},
content: {
html: '<p class="govuk-body">This is the content for How people read.</p>'
}
}
]
}) }}
{% endblock %}
Code language: HTML, XML (xml)
Unfortunately we will still need to stop and restart Express to see your change in the browser:
npx tsc && node dist/index.js
Code language: Shell Session (shell)
After which you should see:
This looks sort of right, though not identical to the docs. Also clicking the links doesn’t work.
This is because the very last thing we need to do is ensure we have the Gov UK JavaScripts added and running.
{% extends "govuk/template.njk" %}
{% from "govuk/components/accordion/macro.njk" import govukAccordion %}
{% block pageTitle %}Gov UK Frontend Express Starter<{% endblock %}
{% block head %}
<link rel="stylesheet" href="/assets/main.css">
{% endblock %}
{% block content %}
<h1 class="govuk-heading-xl">Welcome to our Gov UK Frontend Express Starter</h1>
<p class="govuk-body">This is a simple web page using Nunjucks templating.</p>
{{ govukAccordion({
id: "accordion-default",
items: [
{
heading: {
text: "Writing well for the web"
},
content: {
html: '<p class="govuk-body">This is the content for Writing well for the web.</p>'
}
},
{
heading: {
text: "Writing well for specialists"
},
content: {
html: '<p class="govuk-body">This is the content for Writing well for specialists.</p>'
}
},
{
heading: {
text: "Know your audience"
},
content: {
html: '<p class="govuk-body">This is the content for Know your audience.</p>'
}
},
{
heading: {
text: "How people read"
},
content: {
html: '<p class="govuk-body">This is the content for How people read.</p>'
}
}
]
}) }}
{% endblock %}
{% block bodyEnd %}
<script src="/assets/govuk/all.js"></script>
<script>window.GOVUKFrontend.initAll()</script>
{% endblock %}
For the final time, stop and restart Express, and you should see the example working as expected:
Click any of the sections, or the ‘Show all sections’ link to see the accordion expand and contract.
Lovely.
Example Code
You can find the example code over on GitHub:
https://github.com/codereviewvideos/example-gov-uk-frontend
Conclusion
In this post, we’ve explored the world of web development through the lens of the Gov UK Frontend Express Starter. We began our journey by understanding the importance of adhering to design standards and user experience guidelines, which Gov UK Frontend provides in abundance.
We delved into the fundamentals of Nunjucks templating, a powerful tool for creating dynamic and consistent web pages. By extending the base template, we harnessed the structure and styling capabilities of Gov UK Frontend, ensuring our web pages seamlessly integrate into the broader Gov UK ecosystem.
Customisation was at the forefront of our exploration, with the inclusion of a custom stylesheet (main.css
) allowing us to tailor the appearance of our web pages to meet our unique requirements. Yet, we always remained faithful to the core principles of Gov UK design, delivering a user experience that is both accessible and user-friendly.
As we conclude our journey with the Gov UK Frontend Express Starter, it’s clear that this toolkit empowers developers to create web applications that not only look the part but also adhere to the highest standards of usability and accessibility. By combining the well understood Node JS framework of Express, the code structure of TypeScript, flexibility of Nunjucks with the structure and style of Gov UK Frontend, we’ve unlocked a powerful approach to web development.
Whether you’re a seasoned developer or just starting on your coding journey, Gov UK front end projects offer a robust foundation for building web applications that make a positive impact on users throughout the UK.
Happy coding!