Joe Lanman - Designer

GOV.UK Prototype Kit - Data driven prototyping

One of the big advantages of using the GOV.UK Prototype Kit is the ability to use data.

For example take an admin system with a list of items and a page to view and edit each item. In other prototyping apps you might have to create a page for each item, and update both the list and the page separately if you want to change something.

Using the kit you can define the list as data, and design just the list page and the item page. You can now change the list, add or remove items and all the pages update automatically.

The kit tutorial is about getting a juggling licence (I recommend following that before this one). So for this tutorial, let’s design the admin side - where we can process the applications for a juggling licence.

About JSON

We’ll be using a format called JSON (JavaScript Object Notation) for our data.

Some JSON basics:

Array (a list)

[
  "Apples",
  "Blueberries",
  "Pears",
  "Strawberries"
]

Arrays begin and end with square brackets [ ]

Object, with name/value pairs

{
  "name": "Giulia",
  "age": 63
}

You can put arrays in objects, or objects in arrays:

[
  {
    "name": "Giulia",
    "age": 63
  },
  {
    "name": "Rhian",
    "age": 22
  }
]

1. Adding data

Open the session data defaults file:

app/data/session-data-defaults.js

Add our data:

module.exports = {

  // Insert values here

  "applications": [
    {
      "id" : 1,
      "name": "Giulia",
      "date": "1/2/2026",
      "how-many-balls": "1 or 2",
      "most-impressive-trick": "Juggling on a unicycle"
    },
    {
      "id" : 2,
      "name": "Rhian",
      "date": "2/2/2026",
      "how-many-balls": "3 or more",
      "most-impressive-trick": "Juggling chainsaws"
    },
    {
      "id" : 3,
      "name": "Maeve",
      "date": "4/2/2026",
      "how-many-balls": "1 or 2",
      "most-impressive-trick": "Upside down"
    }
  ]

}

Important note on changing the default data

Session data is created from this file and stored when you open the prototype in the browser. If you change the default data, you need to click the ‘Clear data’ link in the footer to reset it to the new defaults.

2. Applications list page

In the app/views folder create a new file called applications.html

Add this code:

{% extends "layouts/main.html" %}

{% set pageName="Applications" %}

{% block content %}

  <h1 class="govuk-heading-l">
    Juggling licence applications
  </h1>

  <table class="govuk-table">

    <thead>
      <tr>
        <th scope="col" class="govuk-table__header">
          Name
        </th>
        <th scope="col" class="govuk-table__header">
          Date sent
        </th>
      </tr>
    </thead>

    <tbody>

      {% for application in data['applications'] %}

        <tr>

          <th scope="row" class="govuk-table__header">
              <a href="/applications/{{ application['id'] }}">
                {{ application['name'] }}
              </a>
          </th>

          <td class="govuk-table__cell">
            {{ application['date'] }}
          </td>

        </tr>

      {% endfor %}

    </tbody>

  </table>

{% endblock %}

Open the applications page in the browser:

http://localhost:3000/applications

It should look like this:

Screenshot showing a table with 3 applications

3. Application view page

In the app/views folder create a new file called application-view.html.

Add this code:

{% extends "layouts/main.html" %}

{% set pageName="Application" %}

{% block beforeContent %}
  {{ govukBackLink({
    text: "Back",
    href: "/applications"
  }) }}
{% endblock %}

{% block content %}

<div class="govuk-grid-row">
  <div class="govuk-grid-column-two-thirds">

    <h1 class="govuk-heading-l">
      {{ application['name'] }}
    </h1>

    <dl class="govuk-summary-list">

      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          How many balls can you juggle?
        </dt>
        <dd class="govuk-summary-list__value">
          {{ application['how-many-balls'] }}
        </dd>
      </div>

      <div class="govuk-summary-list__row">
        <dt class="govuk-summary-list__key">
          Most impressive juggling trick?
        </dt>
        <dd class="govuk-summary-list__value">
          {{ application['most-impressive-trick'] }}
        </dd>
      </div>
      
    </dl>

  </div>
</div>

{% endblock %}

If you view the page in the browser, the details will be blank. We need to write a route to get the data.

4. Add a route

In app/routes.js add this code:

// Add your routes here

router.get('/applications/:id', function(request, response) {

  var id = request.params.id
  var data = request.session.data

  var application = data.applications.find(function(application){
    return application.id == id
  })

  response.locals.application = application
  response.render('application-view')

})

Let’s go through that code.

router.get('/application/:id', function(request, response) {

  var id = request.params.id

We get the id for the application from the path. :id means ‘store whatever comes here as a parameter’.

var data = request.session.data

We store the session data in data so it’s easier to refer to later.

var application = data.applications.find(function(application){
  return application.id == id
})

We get the applications from the session data, and use the find function to get the one where the id matches the one in the path.

response.locals.application = application

We are making the application available to the page, so now lines like this on the page work:

{{ application['name'] }}

You can find out more about routes in the kit documentation

If you go to the applications list page in the browser and click the links, you should now get a page with details for each application, like this:

Screenshot showing an application view with the name and other details

Change the data

Make a change to the session-data-defaults.js file - for example change a name or add another application, and save the file.

Click the ‘Clear data’ link in the footer to reset it to the new defaults.

Your changes will now appear on both the list of applications, and the relevant application page.

Last updated: 30/1/26