Basker Docs

Search

Query published content across your site for search-as-you-type and search results pages

The search endpoints run a full-text query across the published content on your site and return ranked matches. Use them to build a search-as-you-type box, a dedicated results page, or any widget that finds content from the browser.

Matching is both exact and fuzzy, so a query that is close but not exact still returns useful results. Basker applies the boosts and synonyms that editors configure.

Two endpoints are available. /api/search returns one ranked set of up to 200 results. /api/search/v2 pages through results and adds a date-aware filter for events. Use /api/search/v2 for a results page that needs paging or tab counts.

GET {your-domain}/api/search?q={query}

Unlike the content endpoints, search does not accept the .json suffix. Always call the bare path.

Query parameters

ParameterTypeDefaultDescription
qstringNoneThe search query. Required. A missing query returns a 400.
collectionstring(all types)Restricts results to one or more content types. Separate multiple values with commas. Valid values are pages, posts, events, and people. Omit to search all types. An unrecognized value returns a 400.
localestring(site default)Language to search and return, for example cy. An unknown or unavailable code returns a 400.

Response

A docs array of ranked matches plus list metadata. Each item carries a collectionType field naming the content type that matched, so you can group or filter results by type on the client.

{
  "docs": [
    {
      "id": "000000000000000000000002",
      "collectionType": "events",
      "title": "Moonclock",
      "slug": "moonclock",
      "url": "/events/moonclock"
    },
    {
      "id": "000000000000000000000004",
      "collectionType": "posts",
      "title": "How Moonclock was made",
      "slug": "making-moonclock",
      "url": "/blogs/remarkable-theatre-news/posts/making-moonclock"
    }
  ],
  "totalDocs": 2,
  "limit": 200,
  "totalPages": 1,
  "page": 1,
  "pagingCounter": 1,
  "hasPrevPage": false,
  "hasNextPage": false,
  "prevPage": null,
  "nextPage": null
}

This endpoint returns the full ranked set, up to 200 results, in one response. It does not page. Every result includes an id, a collectionType, a title, a slug, and a url you can render. The other fields depend on the content type:

collectionTypeFields
pagesdescription, image, meta
postsdescription, image, meta, data.publishDate, data.authors (each with id and title)
eventsdescription, image, meta, data.startDate, data.endDate, data.startDate_tz, data.endDate_tz, data.venue (with id and title)
peopleimage. The person's name is in title.

Dates sit under data. There is no top-level startDate, date, or publishDate. Results carry no excerpt, no event instances, and no template settings.

Examples

Search as the visitor types:

async function search(query) {
  if (!query) return [];
  const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`);
  const { docs } = await res.json();
  return docs;
}

Group results by content type for a tabbed results page:

const { docs } = await (await fetch(`/api/search?q=${encodeURIComponent(query)}`)).json();

const byType = docs.reduce((groups, result) => {
  (groups[result.collectionType] ??= []).push(result);
  return groups;
}, {});
// byType.events, byType.posts, byType.people, …
GET {your-domain}/api/search/v2?q={query}

This endpoint returns 10 results per page and adds a filter parameter that separates upcoming events from past events. Use it for a full results page. Use /api/search for a type-ahead box, where one ranked set is enough.

Query parameters

ParameterTypeDefaultDescription
qstringNoneThe search query. Required. It must be 1 to 256 characters. Anything else returns a 400.
filterstringALLOne of ALL, EVENTS, PAST_EVENTS, NEWS, PAGES, or PEOPLE. EVENTS returns events that have not finished. PAST_EVENTS returns events that have. An unrecognized value returns a 400.
pageinteger1Page number to return. A page above the last page returns the last page. A value that is not a positive integer returns a 400.
collectionstring(all types)Restricts results to one or more content types before the filter applies. Valid values are pages, posts, events, and people.
localestring(site default)Language to search and return, for example cy. An unknown or unavailable code returns a 400.

Response

The same paginated envelope the content endpoints use, with limit set to 10. Read totalPages and hasNextPage to build the pager.

{
  "docs": [
    {
      "id": "000000000000000000000002",
      "collectionType": "events",
      "title": "Moonclock",
      "slug": "moonclock",
      "url": "/events/moonclock",
      "excerpt": "...",
      "image": { "url": "https://..." }
    }
  ],
  "totalDocs": 42,
  "limit": 10,
  "totalPages": 5,
  "page": 1,
  "pagingCounter": 1,
  "hasPrevPage": false,
  "hasNextPage": true,
  "prevPage": null,
  "nextPage": 2
}

Result counts per tab

GET {your-domain}/api/search/v2/counts?q={query}

Returns the number of matches for each filter, plus an ALL total. Call it once alongside the first page to label the tabs on a results page.

{
  "EVENTS": 12,
  "PAST_EVENTS": 24,
  "NEWS": 4,
  "PAGES": 2,
  "PEOPLE": 0,
  "ALL": 42
}

Example

Render one page of results and the tab counts together:

const query = encodeURIComponent(term);

const [page, counts] = await Promise.all([
  fetch(`/api/search/v2?q=${query}&filter=EVENTS&page=1`).then(res => res.json()),
  fetch(`/api/search/v2/counts?q=${query}`).then(res => res.json()),
]);

// page.docs, page.hasNextPage, counts.EVENTS

Caching

Search responses are cacheable at the edge. Popular queries benefit from the cache, and long-tail queries fall through to a fresh response.

Date-aware responses hold for a shorter time, because the boundary between upcoming and past events moves. The EVENTS and PAST_EVENTS filters and the counts endpoint carry s-maxage=300. Other search responses carry s-maxage=3600.

Avoid query parameters that vary per visitor, such as cache-busters and timestamps, unless you need to bypass the cache.

See also

  • Event instances: list and fetch performances, filtered by date, venue, and category.
  • Content endpoints: fetch one content type directly when you already know what you want.

On this page