Key Concepts

This page introduces the core ideas behind ubCode and Sphinx-Needs so you can start working without switching between multiple documentation sites. Each section links to the full reference for deeper exploration.

What are “needs”?

A need is a structured, traceable item inside your documentation. Think of it as a requirement, specification, test case, user story, or any other artefact you want to track — but written in plain text alongside your docs.

Every need has at least:

  • A unique ID (e.g. REQ_001) — used to reference it from other needs or from code.

  • A title — a short, human-readable summary.

  • A type — which kind of artefact it represents (see Need types below).

Needs can also carry fields — metadata such as a status, tags, links to other needs, and custom attributes that you define (see Fields below).

Here is a minimal need written in reStructuredText:

.. req:: User must log in before accessing the dashboard
   :id: REQ_001
   :status: open
   :tags: security

   The system shall redirect unauthenticated users
   to the login page.

In this example req is the directive (determined by the need type), REQ_001 is the ID, and status and tags are built-in metadata fields.

See also

Sphinx-Needs documentation for the full feature set of needs.

Need types

A need type defines a category of need and gives it its own RST directive. For example, you might define types like requirement, specification, test case, and user story — each with a different directive name, ID prefix, and diagram color.

Types are declared in ubproject.toml:

[[needs.types]]
directive = "req"          # use as ``.. req::`` in RST
title = "Requirement"
prefix = "REQ_"           # auto-generated IDs start with REQ_

[[needs.types]]
directive = "spec"
title = "Specification"
prefix = "SPEC_"

[[needs.types]]
directive = "test"
title = "Test Case"
prefix = "TC_"

When you write .. req:: in an RST file, ubCode knows this is a Requirement need because of the type definition.

See Needs for all type options.

Fields

Every need carries fields — named pieces of metadata such as status, tags, or any custom attribute you define. Some fields are built in (id, title, status, tags); you can add your own through the [needs.fields] configuration.

Custom fields

Define project-specific fields in ubproject.toml using [needs.fields]. Each key is the field name and the value describes its default, description, and optional validation schema:

[needs.fields.priority]
description = "Priority level"
default = "medium"

[needs.fields.assignee]
description = "Assigned team member"

[needs.fields.effort]
description = "Story points"
schema = {type = "integer", minimum = 1, maximum = 13}

Once declared, these fields can be used on any need:

.. req:: Encrypt data at rest
   :id: REQ_002
   :status: open
   :priority: high
   :assignee: alice
   :effort: 5

Schemas

The schema key on a field applies JSON Schema validation to every value entered for that field. Invalid data is caught at index time, before the docs are built.

Per-field schemas are set inside [needs.fields.<name>]:

[needs.fields.effort]
description = "Story points"
schema = {type = "integer", minimum = 1, maximum = 13}

[needs.fields.severity]
description = "Issue severity"
schema = {type = "string", enum = ["low", "medium", "high", "critical"]}

If a need sets :effort: 99, ubCode reports a validation error because 99 exceeds the maximum of 13.

For project-wide validation — for example constraining which types may link to which, or requiring certain fields per type — point schema_definitions_from_json to a JSON Schema file:

[needs]
schema_definitions_from_json = "schemas.json"

ubCode loads the definitions and validates every need against them as part of its indexing pipeline.

See Schema validation for the full schema reference.

Variants

Variants let a field or link value change depending on the current build context. You write a <<…>> expression inside a field value, and ubCode evaluates it at index time to pick the right result.

This is useful when a single set of docs must produce different outputs — for example one build for customer A and another for customer B, each with different priorities or statuses.

Named variants are defined in ubproject.toml together with build_tags that describe the current build:

build_tags = ["html", "draft"]

[needs.variants]
is_html = "'html' in build_tags"
is_open = "status == 'open'"

Then use the variant name in a field value:

.. req:: Encrypt data at rest
   :id: REQ_002
   :status: <<is_open: active, inactive>>
   :priority: <<is_html: web_critical, medium>>

The first matching expression’s value is used; the last comma-separated value is the fallback when nothing matches.

You can also write inline filter expressions without pre-defining a variant:

.. req:: Another requirement
   :id: REQ_003
   :status: <<[status == 'open']: active, inactive>>

See Variants for the full variant and build_tags reference.

What is reStructuredText?

reStructuredText (RST) is a lightweight markup language used by Sphinx to write documentation. If you have used Markdown, RST will feel similar — but it adds directives and roles for richer, structured content.

Directives

A directive is a block-level construct that starts with .., followed by the directive name and :::

.. note::

   This is a simple built-in directive.

Sphinx-Needs adds its own directives — every need type you define becomes a directive (.. req::, .. spec::, etc.).

Roles

A role is an inline construct written as :rolename:`text`. For example, Sphinx-Needs provides the :need: role to create a clickable reference to a need:

See :need:`REQ_001` for the authentication requirement.

ubCode understands a large set of Sphinx and Sphinx-Needs directives and roles out of the box. If your project uses additional directives from other extensions, you can register them in the configuration.

What is ubproject.toml?

ubproject.toml is the configuration file that tells ubCode about your project — which need types exist, what link types to use, where your source files are, and how linting should behave.

It uses the TOML format, which is declarative and human-readable.

Why TOML instead of ``conf.py``?

Sphinx projects are normally configured through a Python file (conf.py). ubCode cannot execute Python — that would be slow, insecure, and would require matching the user’s exact Python environment. A TOML file can be parsed in microseconds and gives ubCode everything it needs to index your project at language-server speed.

Starting from Sphinx-Needs 4.1 you can share configuration between conf.py and ubproject.toml via the needs_from_toml option, so you do not need to maintain two copies.

A minimal ubproject.toml looks like this:

"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"

[[needs.types]]
directive = "req"
title = "Requirement"
prefix = "REQ_"

See Needs for the full reference, or Coming from Sphinx-Needs for migration guidance.

Source code tracing

Note

Supported in ubcode added in v0.29

ubCode can go beyond RST documentation and trace into your source code. Powered by Codelinks, you embed traceability markers directly in code comments, and ubCode’s Rust engine picks them up in real time.

This lets requirements live right next to the code that implements them.

One-line need definitions

Create a complete need in a single comment line using a comma-separated format:

# @Function Bar, IMPL_4, impl, [SPEC_1]

This creates an impl need with:

  • Title: Function Bar

  • ID: IMPL_4

  • Type: impl

  • Links: SPEC_1

The field order and separators are configurable in ubproject.toml under [codelinks.projects.<name>.analyse.oneline_comment_style].

Need ID references

Reference existing needs without creating new ones. This records that a particular code location is related to specific needs:

# @need-ids: REQ_001, REQ_002

The marker keyword (@need-ids by default) is configurable in [codelinks.projects.<name>.analyse.need_id_refs].

The src-trace directive

The .. src-trace:: directive brings source-traced needs into your documentation:

.. src-trace:: my_app
   :directory: src/core

This tells ubCode to include all needs discovered in the src/core directory of the codelinks project named my_app. You can also use :file: to scope to a single file.

Configure the codelinks pipeline in the [codelinks] section of your ubproject.toml.

See also

Codelinks documentation for the full reference on source code tracing.

Where to go next