Needs tutorial¶
This tutorial builds a small but complete traceability model, step by step, for the engineering programme behind an autonomous parcel-delivery drone. Along the way you will declare your own need types, write need items and connect them with links, refer to them from ordinary prose, and finally summarise and measure the whole set with tables, diagrams, and counts.
Every example below is shown twice —
first as the source you would type,
then as the result it produces —
using the syntax-example directive
(see Directives).
The need items, roles, tables, and counts in those result panes are live —
the ubCode engine resolves and renders them as you edit —
and this published site renders every example, diagram views included,
with Sphinx-Needs.
(Where the two engines differ, the tutorial says so; see the note by the flow
diagram below.)
Before you start
You will get the most from this walkthrough with ubCode already installed (Installation) and the vocabulary from Key concepts fresh in mind. A little reStructuredText helps too, though the examples are short enough to follow without it.
How ubCode handles a need¶
ubCode keeps a live model of your project and refreshes it on every keystroke, rather than computing everything once at the end of a build. Three things happen in the background as you type: it reads each need directive out of your source files and captures the fields you wrote; it connects the needs — matching links to their targets, resolving variant and dynamic values, and filling in back-links; and it checks the result — validating IDs, field values, and link targets against your configuration, and surfacing anything inconsistent as a diagnostic.
Running this loop continuously is what sets ubCode apart from a batch build: a broken link or a duplicate ID appears the instant you introduce it, not after a build. The table and count views you meet later read straight from this live model, so they always reflect the project’s current state.
Defining need types¶
A need type is a category of need that becomes a directive of the same name.
ubCode does not assume a fixed set of types;
you declare exactly the ones your project uses in ubproject.toml.
For the drone programme we want three types —
a top-level Project, the Requirements it drives,
and the Specifications that realise them.
Each entry gives the directive name, a human-readable title,
and a prefix for automatically generated IDs;
the optional style and color keys control how the type appears
in flow diagrams:
[[needs.types]]
directive = "dr-project"
title = "Project"
prefix = "P_"
style = "folder"
color = "#E8DAEF"
[[needs.types]]
directive = "dr-req"
title = "Requirement"
prefix = "R_"
color = "#D4EFDF"
[[needs.types]]
directive = "dr-spec"
title = "Specification"
prefix = "S_"
color = "#D6EAF8"
To make IDs predictable across the team, you can also require them explicitly and constrain their shape:
[needs]
id_required = true
id_regex = "^[A-Z]_[A-Z0-9]{4,}$"
With id_required set, ubCode reports any need that is missing an ID,
and id_regex rejects IDs that do not match the pattern —
both while you type, long before a build.
See also
Need types for every option a need type accepts, and Core options for the ID controls.
Creating a need item¶
With the types declared, a need is just a directive: its title is the argument, its fields are options, and its description is the body. Here is the programme’s root item:
The project need
.. dr-project:: Autonomous delivery drone
:id: P_DRONE
:tags: tutorial
:status: open
A rotor-based drone that carries small parcels between local depots
and customer drop-points without a human pilot,
planning its own route and holding station in wind.
A rotor-based drone that carries small parcels between local depots and customer drop-points without a human pilot, planning its own route and holding station in wind. |
Every field you add becomes part of the need’s metadata,
so you can later filter, sort, and report on it.
The tags field, in particular, is a convenient handle
for selecting a related group of needs, as we will do below.
Referring to a need¶
Once a need has an ID, you can point at it from anywhere in your prose
with the need role.
By default it renders the need’s title and ID as a clickable link;
supply an explicit label in angle brackets to show your own wording instead:
The need role
The overall goal is captured by :need:`P_DRONE`.
When the sentence reads better with your own words, label the reference
yourself, as in :need:`the delivery-drone programme <P_DRONE>`.
The overall goal is captured by Autonomous delivery drone (P_DRONE).
When the sentence reads better with your own words, label the reference yourself, as in the delivery-drone programme (P_DRONE).
ubCode resolves these references as you type, and flags the role if the ID does not exist — so a renamed or deleted need never leaves a dangling reference behind.
Linking needs together¶
Individual needs become a model once you connect them.
The built-in links option records a generic relationship,
and you can define named link types for relationships
that read better in both directions.
For the drone programme we add one custom link type,
dr_supports, so that each requirement records the programme objective
it exists to serve:
[needs.links.dr_supports]
outgoing = "supports"
incoming = "supported by"
color = "#1A5276"
Now we can write the two requirements, each pointing at the project through the custom link:
Requirements with links
.. dr-req:: Collision-free flight
:id: R_SAFE
:tags: tutorial
:status: open
:dr_supports: P_DRONE
The drone must detect and avoid obstacles in its flight path —
buildings, wires, birds, and other aircraft —
and hold a safe separation at all times.
.. dr-req:: Reliable telemetry link
:id: R_LINK
:tags: tutorial
:status: open
:dr_supports: P_DRONE
The drone must stay in contact with the control centre throughout a
flight, reporting position and health, and land safely if the link drops.
The drone must detect and avoid obstacles in its flight path — buildings, wires, birds, and other aircraft — and hold a safe separation at all times. |
The drone must stay in contact with the control centre throughout a flight, reporting position and health, and land safely if the link drops. |
Because dr_supports has an incoming label of supported by,
the project need automatically gains a “supported by” back-link to each
requirement — you write the relationship once, from the requirement,
and see it from both sides.
Next we add the specifications that realise the safety requirement.
Here we use the plain links option rather than a custom type,
to show the generic form:
Specifications realising a requirement
.. dr-spec:: Vision-based obstacle detection
:id: S_VISION
:tags: tutorial
:status: in_progress
:links: R_SAFE
Forward and downward cameras feed a model that segments obstacles from
the background and estimates their distance, driving avoidance manoeuvres.
.. dr-spec:: Geofence enforcement
:id: S_GEOFEN
:tags: tutorial
:status: open
:links: R_SAFE
The flight controller refuses commands that would take the drone outside
its approved corridor or above its permitted altitude.
Forward and downward cameras feed a model that segments obstacles from the background and estimates their distance, driving avoidance manoeuvres. |
The flight controller refuses commands that would take the drone outside its approved corridor or above its permitted altitude. |
See also
Link types for the full set of link-type options, and Roles for the other need reference roles.
Conditional content¶
Sometimes part of a document only applies to a particular build —
a specific platform, market, or review stage.
The if directive includes its body only when a condition holds,
evaluated against the project’s variant data:
A conditional block
.. if:: var.stage == "review"
.. note::
This section is only shown while the ``stage`` variant is ``review``.
Use it for notes that should not reach the published manual.
Note
This section is only shown while the stage variant is review.
Use it for notes that should not reach the published manual.
The if directive is not specific to needs —
it conditionally includes any block, needs included —
which makes it the basis for building several product variants
from a single “150 %” source
(see Variant builds).
Summarising the model¶
With a handful of needs in place, we can start to view them as a whole. The Sphinx-Needs summary directives each select a subset of needs with a shared filter syntax and present it in a different form; this tutorial uses a table and a flow diagram.
A needtable lays the selected needs out as a sortable table.
Here we select everything tagged tutorial and choose the columns to show:
A needs table
.. needtable::
:tags: tutorial
:columns: id, type, title, status
:sort: id
:style: table
A needflow draws the same needs as a diagram, so the links between them become visible. Starting the flow at the project need and following the links outward gives a top-down picture of the programme:
A needs flow
.. needflow:: Drone programme overview
:root_id: P_DRONE
:show_link_names:

Drone programme overview¶
Note
needflow draws as a Mermaid flowchart in
the ubCode preview and ubc build html alike — the same diagram this
published Sphinx-Needs site shows (Sphinx renders it with Graphviz; ubCode
renders it client-side with Mermaid, so the picture is equivalent rather than
pixel-identical). The other needs diagram views — the needpie and
needbar charts — still render as self-describing placeholders in ubCode
for now. See Differences from a Sphinx build for the full register.
For larger models it is often tidier to tuck a secondary view away behind a disclosure widget, so the page is not dominated by diagrams:
Counting and measuring¶
Beyond listing needs, you often want a single number —
how many items are in a given state.
The need_count role evaluates a filter expression
and renders the size of the matching set inline,
which is handy inside a status summary:
Counting needs
- Specifications in total: :need_count:`type == 'dr-spec'`
- Requirements still open: :need_count:`type == 'dr-req' and status == 'open'`
- Specifications in progress: :need_count:`status == 'in_progress'`
Specifications in total: 2
Requirements still open: 2
Specifications in progress: 1
Because the count is recomputed from the live model, the figures track your edits as you make them — add a specification and the total goes up on the next indexing pass.
Where to go next¶
You have now created a small traceable model — a project, its requirements, the specifications that realise them, and the links, references, tables, diagrams, and counts that tie them together. From here you can grow the model with confidence, because ubCode keeps every link and ID honest as you type.
Todo
Extend this tutorial with a section on importing existing needs from a JSON export, and on tracking progress over time with a metrics view.
Needs — the full
[needs]configuration reference.Writing a filter — the filter language used by the summary directives.
Coming from Sphinx-Needs — bringing an existing Sphinx-Needs project into ubCode.
Differences from a Sphinx build — where the live preview differs from a full Sphinx build.