Routes
There are 3,378 possible pathways to qualifications for education roles. A route is useful only when it matches an individual’s situation and ambition.
To help users navigate these possibilities, we built the route discovery tool:
By answering four questions about their current situation and career ambitions, users receive an overview of the pathways that are relevant to them.
To power this functionality, the system uses four collections:
| Collection | Purpose |
|---|---|
route_questions | Stores the questions presented in the route discovery tool |
route_answers | Stores the individual answer options for each question |
route_steps | Stores the individual steps that make up a route |
routes | Stores the complete pathways into roles in education |
The questionnaire and the results logic rely on these collections in different ways. The following sections describe both parts of the system.
Build the questionnaire
The route_questions collection is relatively simple: it contains the four questions used by the route discovery tool.
The route_answers collection is more complex. The available answer options are dynamic, meaning that the answers shown depend on earlier selections made by the user.
For example:
- The role a user can select (question 2) depends on the type of school selected in question 1.
- The qualification a user wants to obtain (question 4) depends on the role selected in question 2.
Because of these dependencies, the questionnaire must be implemented dynamically.
An alternative approach is to fetch all route_answers at once and implement the conditional logic on the client side. This is the approach used in the Onderwijsloket application.
While this results in a slightly heavier initial request, it reduces subsequent API calls and provides a smoother user experience.
Return matching routes
After the user has answered all four questions, you can fetch the relevant routes using the routes collection.
const selectedAnswers = ["abc-123", "def-456", "ghi-789", "jkl-012"];
const data = directus.request(
readItems("routes", {
fields: [
"id",
"duration_in_months",
"title",
"path",
{
route_steps: [
{
route_steps_id: ["id", "short_title", "duration_in_months"]
}
]
}
],
filter: {
requires_answers: {
_none: {
route_answers_id: {
_nin: selectedAnswers
}
}
}
},
sort: ["duration_in_months"]
})
);
Each route in the routes collection contains a list of answers in the requires_answers field. These represent the answers a user must have selected for the route to be relevant.
filter: {
requires_answers: {
_none: {
route_answers_id: {
_nin: selectedAnswers,
}
}
}
}
In simple terms, this means:
Only return routes where all required answers are included in the answers the user selected.
How it works in practice:
- After the user answers the four questions, their selections are stored in
selectedAnswers. - Each route has a set of required answers (
requires_answers). - The filter removes any route that requires an answer the user did not select.
Example:
- User selected answers:
[A, B, C, D] - Route requires:
[A, C]→ included - Route requires:
[A, E]→ excluded, because the user didn’t selectE.
This way the API only returns routes that match the user’s situation and ambitions based on the answers they provided.
Keep in touch with the latest
Sign up for our monthly deep dives - straight to your inbox.