Code Review Videos > JavaScript & TypeScript > Gov UK Frontend Express Project Starting Point

Gov UK Frontend Express Project Starting Point

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.0Code 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-frontendCode 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-frontendCode 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 expressCode 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-devCode 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 --initCode 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 srcCode 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 tscCode 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 3300Code language: PHP (php)

Your server should now be running and serving content.

We can test this by visiting http://localhost:3000/

express gov uk starter first boot firefox

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.

gov uk error summary nunjucks macro example

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/nunjucksCode 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:

gov uk example project after installing nunjucks in webstorm

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 specify autoescape to protect against cross-site scripting (XSS) attacks and set express to our Express app.
  • Inside the / route handler, we use res.render('index.njk') to render the index.njk template.

Testing the Nunjucks Template

Now that Nunjucks is configured, we need to do three things:

  1. Stop the Express server, if it is still running: press ctrl + c in the terminal to stop the server.
  2. Re-compile your TypeScript to JavaScript: run npx tsc from your project root directory.
  3. 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.jsCode 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.

basic html page with express and nunjucks

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-frontendCode language: Shell Session (shell)

Once that finishes successfully, run this command also:

npm install sass --save-devCode 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:

gov uk front end before sass import

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-mapCode language: Shell Session (shell)

That looks fairly intense. But let’s break it down line by line.

  1. ./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’s node_modules directory. It ensures that we use the Sass version installed as a dependency in our project.
  2. --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 the node_modules/govuk-frontend directory. This is used to access styles from the Gov UK Frontend package.
    gov uk front end assets
  3. --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.
  4. 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.
  5. 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 as main.css in the dist/public/stylesheets directory.
  6. --style=compressed: This flag sets the output style for the compiled CSS. In our case, it’s set to compressed, which means that our CSS will be minified and optimised for production, resulting in a smaller file size.
  7. --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:

gov uk sass 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:

generated gov uk main css file result

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:sassCode 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)
  1. 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 the govuk-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 the govuk-frontend package, which contains additional assets and stylesheets needed for the Gov UK frontend components.
  2. assets.forEach(dir => { ... }): This code iterates over the assets array and sets up Express middleware to serve static files from each of the specified directories.
  3. app.use('/assets', express.static(path.join(process.cwd(), dir))): This line configures Express to serve static files under the /assets route. It uses the express.static middleware to serve files from the specified directory, and path.join is used to construct the full path to the directory based on the current working directory (process.cwd()) and the directory path in the assets 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:

gov uk front end after build

We can see that the reference to the stylesheet worked – it returns a 200 status code.

We can also browse directly to that file:

gov uk css loaded in browser

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:

testing express static assets path

In the browser we can immediately see (i.e. without having to stop / restart express):

express static asset browser view

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:

node modules gov uk favicon

And in the browser:

gov uk favicon served by express

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.jsCode language: Shell Session (shell)

After which you should see:

gov uk front end website with styles applied

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.njkCode language: Shell Session (shell)
gov uk default nunjucks template

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.

gov uk styled page in firefox

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.

gov uk accordion example

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.jsCode language: Shell Session (shell)

After which you should see:

gov uk accordion added to the page but needs javascript

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:

gov uk site working with javascript

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!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.