RAFT

Simulate a realistic search interaction with data

Prototype a search flow using structured data and basic filtering.

Goal

Make a prototype search feel real without building a full backend.

When to use

Use this when UR needs a believable dataset + search UI (not just a static list).

Steps

  1. Create a small dataset (JSON) with realistic fields.
  2. Build a search form that submits with GET (query string).
  3. Filter the dataset server-side and render the results list.
  4. Handle edge cases: empty query, no results, too many results.

Code (minimal example)

A) Dataset

js
// app/data/things.json (example)
[
  { "id": "A1", "name": "Alpha House", "postcode": "LS1 1AA" },
  { "id": "B2", "name": "Beta House", "postcode": "LS2 2BB" }
]

B) Route handler (filter)

js
// routes.js
const things = require('./data/things.json')
 
router.get('/search/results', function (req, res) {
  const q = String(req.query.q || '').trim().toLowerCase()
 
  const results = q
    ? things.filter(x =>
        String(x.name).toLowerCase().includes(q) ||
        String(x.postcode).toLowerCase().includes(q)
      )
    : []
 
  return res.render('search/results', { q, results })
})

C) Template

njk
<form method="get" action="/search/results">
  <div class="govuk-form-group">
    <label class="govuk-label" for="q">Search</label>
    <input class="govuk-input" id="q" name="q" value="{{ q }}" />
  </div>
  <button class="govuk-button" type="submit">Search</button>
</form>
 
{% if q and results.length === 0 %}
  <p class="govuk-body">No results</p>
{% endif %}
 
<ul class="govuk-list">
  {% for r in results %}
    <li>{{ r.name }} ({{ r.postcode }})</li>
  {% endfor %}
</ul>

Common mistakes

  • Doing search with POST (makes URLs non-shareable; GET is usually better here).
  • Not preserving the query value in the input.
  • Not handling the empty query state.

Next units

Notes

Source inspiration: hippo-prototyping discussion https://github.com/hippo-digital/hippo-prototyping/discussions/63