Configuring a project with ubproject.toml¶
The ubproject.toml file is a TOML configuration file
that tells ubCode how to analyse and validate your project.
Every setting — need types, link types, custom fields, linting rules,
formatting preferences — lives in this single declarative file.
You can find the schema at https://ubcode.useblocks.com/ubproject.schema.json, and it is recommended that you add this to the top of your file for use with the taplo toolkit:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
Please also see the detailed ubproject.toml schema reference.
For a complete example, see the Sphinx-Needs Demo project.
Configuration sections¶
The ubproject.toml file is organized into logical sections.
Each section controls different aspects of ubCode’s behaviour:
Needs — need types, link types, custom fields, statuses, tags, external needs, variants, dynamic functions,
filter_data, andimport_keysSchema validation — schema validation with
schemas.json, local and network validation rulesDeprecated needs options — deprecated options retained for backward compatibility with older sphinx-needs versions
Parsing — custom directives, roles, and ignore lists
Linting — ignore codes, per-file-ignores, and message-ignores
Formatting — reStructuredText formatting options
Server — language server behaviour and performance settings
Project, source & scripts — project metadata, source file discovery, scripts, and
needs_json
Each section includes sensible defaults, so you only need to specify the options you want to customise.
Configuration file discovery¶
Hierarchical configuration is supported, such that the “closest” config file in the directory hierarchy is used for every individual file, with all paths in the config file being resolved relative to the directory containing that config file.
For example, given the following directory structure:
project/
├── docs1/
│ ├── doc1.rst
│ └── ubproject.toml
├── docs2/
│ └── doc2.rst
└── ubproject.toml
The configuration for doc1.rst will be read from
project/docs1/ubproject.toml,
whereas for doc2.rst it will be read from
project/ubproject.toml.
See also the source configuration for how file-discovery works for reStructuredText source files.
Configuration redirect with ubproject.redirect.toml¶
When processing files that are “outside” the documentation project folder
(e.g. source code files referenced via the code links feature),
the normal directory walk may fail because no ubproject.toml exists
in any ancestor directory.
To handle this,
you can place a redirect file called ubproject.redirect.toml
in a directory.
When found during the configuration file search,
it tells ubCode to continue looking for ubproject.toml
from a different location.
The redirect file has a minimal TOML schema:
path = "../docs"
The path value is resolved relative to the directory containing the redirect file.
It can point to either:
A directory — the search continues from that directory, looking for
ubproject.tomlthere.A file — the file is used directly as the
ubproject.toml.
For example, given the following directory structure:
project/
├── docs/
│ ├── doc1.rst
│ └── ubproject.toml
└── src/
├── main.py
└── ubproject.redirect.toml # contains: path = "../docs"
When processing main.py,
the search finds ubproject.redirect.toml in src/,
follows the redirect to docs/,
and uses the ubproject.toml there.
Note
If a ubproject.toml file exists in the same directory as a redirect file,
the ubproject.toml takes precedence and the redirect is ignored.
Circular redirects (two redirect files pointing at each other) are detected and treated as if no configuration was found.
Top-level options¶
The configuration file supports several top-level options that control the overall behaviour:
# Extend another configuration file
extend = "path/to/ubproject.toml"
# Virtual configurations do not correspond to an actual project.
# They are used for providing shared configuration defaults.
virtual = true
# Tags describing the current build target (e.g. builder, environment)
build_tags = ["html"]
- extend
Type:
string(optional)The path to another
ubproject.tomlfile to extend. This allows you to create a hierarchy of configuration files where child configurations can inherit settings from parent configurations. Paths are resolved relative to the current configuration file.# Extend the configuration from the parent directory extend = "../ubproject.toml" # Or extend from a specific shared configuration extend = "~/.config/ubcode/base.toml"
- virtual
Type:
boolean(default:false)When set to
true, this configuration is marked as virtual and does not correspond to an actual project. Virtual configurations are used for providing shared configuration defaults or for workspaces that are not themselves projects. This is particularly useful when creating base configurations that will be extended by other projects.# In a shared base configuration file virtual = true [needs] id_required = true id_regex = "^[A-Z0-9_]{5,}"
- build_tags
Type:
array of strings(default:[])A list of tags describing the current build target or environment. This replicates Sphinx’s tags configuration, making the same set of tags available as the
build_tagsvariable inside variant filter expressions (see Variants), enabling build-target-conditional field values.For example, you can use
build_tagsto vary need fields depending on the output format or deployment stage:build_tags = ["html", "draft"] [needs.variants] is_html = "'html' in build_tags"
Tags can also be overridden from the CLI without modifying
ubproject.toml:ubc build index -c "build_tags = ['html', 'production']"
Complete configuration examples¶
This section provides complete, real-world configuration examples for different types of projects.
Basic documentation project¶
A minimal configuration for a simple documentation project:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
[project]
name = "My Documentation"
version = "1.0.0"
description = "User documentation for our product"
[needs]
id_required = true
id_regex = "^[A-Z]{3}_[0-9]{3}$" # Format: ABC_123
[[needs.types]]
directive = "requirement"
title = "Requirement"
prefix = "REQ_"
color = "#BFD8D2"
Software development project¶
Configuration for a software project with comprehensive need tracking:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
[project]
name = "MyApp"
version = "2.1.0"
description = "Mobile application requirements"
srcdir = "docs"
[needs]
id_required = true
id_regex = "^[A-Z0-9_]{5,}$"
id_length = 8
# Define comprehensive need types
[[needs.types]]
directive = "epic"
title = "Epic"
prefix = "EPIC_"
color = "#FF6B6B"
[[needs.types]]
directive = "story"
title = "User Story"
prefix = "STORY_"
color = "#4ECDC4"
[[needs.types]]
directive = "task"
title = "Task"
prefix = "TASK_"
color = "#45B7D1"
[[needs.types]]
directive = "bug"
title = "Bug"
prefix = "BUG_"
color = "#F39C12"
# Define relationships (dict-based, sphinx-needs v7+)
[needs.links.implements]
incoming = "implemented by"
outgoing = "implements"
color = "#2ECC71"
[needs.links.blocks]
incoming = "blocked by"
outgoing = "blocks"
color = "#E74C3C"
# Constrain status values via field schema (sphinx-needs v7+)
[needs.fields.status]
schema = {enum = ["draft", "review", "approved", "done"]}
default = "draft"
predicates = [
["type == 'bug'", "review"],
["priority == 'critical'", "review"]
]
# Custom fields (dict-based, sphinx-needs v7+)
[needs.fields.priority]
description = "Priority level"
default = "medium"
[needs.fields.effort]
description = "Story points"
schema = {type = "integer", minimum = 1, maximum = 13}
[needs.fields.assignee]
description = "Assigned team member"
Multi-team enterprise configuration¶
Configuration for large organisations with multiple teams and external dependencies:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
extend = "../shared/base-config.toml"
[project]
name = "Platform API"
version = "3.2.0"
description = "Core platform API requirements"
[needs]
# Import from other team's exports
[needs.import_keys]
backend = "../backend-team/needs.json"
frontend = "../frontend-team/needs.json"
# Load external needs from other projects
[[needs.external_needs]]
json_path = "../security-team/security-requirements.json"
id_prefix = "SEC"
base_url = "https://security-docs.company.com"
target_url = "requirements/{{ id }}.html"
[[needs.external_needs]]
json_url = "https://compliance.company.com/api/needs.json"
id_prefix = "COMP"
base_url = "https://compliance.company.com"
css_class = "compliance-need"
# Relationships (dict-based, sphinx-needs v7+)
[needs.links.validates]
incoming = "validated by"
outgoing = "validates"
color = "#9B59B6"
[needs.links.derives_from]
incoming = "parent of"
outgoing = "derives from"
color = "#34495E"
# Rich metadata with schema validation
[needs.fields.component]
description = "System component"
parse_variants = true
[needs.fields.risk_level]
description = "Security risk assessment"
default = "low"
predicates = [
["compliance_level == 'strict'", "medium"],
["environment == 'production'", "high"]
]
[needs.fields.environment]
parse_variants = true
[needs.fields.test_coverage]
description = "Test coverage percentage"
# Additional context for conditional defaults
filter_data = {environment = "production", compliance_level = "strict"}
[format_rst]
# Enforce consistent formatting
paragraph_line_length = 88
paragraph_semantic_wrap = true
validate = true
fail_on_warning = ["rst.malformed_table"]
[lint]
# Project-specific linting rules
ignore = ["needs.id_not_found"] # Allow forward references
lsp_select = ["needs.title_missing", "rst.malformed_table"]
[server]
# Optimize for large project
index_on_save = false
hover_need_refs = true
[source]
# Multi-format support
extend_include = ["*.md"]
extend_exclude = ["archive/**", "drafts/**"]
[scripts]
# Team workflows
validate = "ubc lint --fail-on-error"
export = "ubc build needs-json --output needs.json"
"docs:build" = { chain = ["validate", "export"], terminal = "docs-build" }
Sphinx integration example¶
Configuration optimised for Sphinx documentation projects:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
[project]
name = "API Documentation"
srcdir = "source"
[needs]
# Integrate with Sphinx-Needs
external_needs = []
[[needs.types]]
directive = "requirement"
title = "Requirement"
prefix = "R_"
color = "#BFD8D2"
[[needs.types]]
directive = "specification"
title = "Specification"
prefix = "S_"
color = "#FEDCD2"
# Link to API documentation
[needs.links.api]
incoming = "documented by"
outgoing = "documents API"
[parse]
# Sphinx directive support
[parse.extend_directives.automodule]
argument = true
options = true
description = "Auto-document Python module"
extension = "sphinx.ext.autodoc"
[parse.extend_directives.automodule.named_options]
members = {description = "Include module members"}
undoc-members = {description = "Include undocumented members"}
[parse.extend_roles.py-func]
description = "Reference to Python function"
extension = "sphinx.domains.python"
[format_rst]
# Sphinx-friendly formatting
paragraph_line_length = 79 # PEP 8 line length
directive_indent = 3
field_list_indent = 2
[scripts]
# Sphinx build commands
html = "sphinx-build -b html {{confdir}} {{confdir}}/_build/html"
linkcheck = "sphinx-build -b linkcheck {{confdir}} {{confdir}}/_build/linkcheck"
"docs:live" = { cmd = "sphinx-autobuild {{confdir}} {{confdir}}/_build/html --host 0.0.0.0", terminal = "docs-server" }