Appearance
Sidebar & Groups: The Complete sidebar.toml Reference
Audience: anyone authoring or maintaining a document directory (a folder with its own ude_doc_config.json) — the person who decides what a project's sidebar looks like and how its classes are grouped.
This page is the single consolidated reference for sidebar.toml. Target Settings and Migration Guide (v1.0 → v2.0) each cover a slice of this material in passing; this page is the full picture, and the one to trust if the others ever drift.
Why this file exists
sidebar.toml carries two independent tables for a single document directory:
[[sidebar]]— the navigation entries (an array of tables).[groups]— the folder taxonomy used to group classes/structs/enums/etc. inside that navigation.
Both are read by resolve_config() (engine/ude/orchestrator.py:330, via load_sidebar_toml()), and both are mandatory, with no cascade and no default at any tier. That is the one fact worth memorizing about this file: nothing here is optional, and nothing here falls back to a shared or engine-provided default.
[[sidebar]] — navigation entries
An array of tables, each describing one sidebar entry. A minimal, real example (ude_projects/Kernel/kernel_api_cpp/sidebar.toml):
toml
[[sidebar]]
type = "api_reference"
label = "API Reference (C++)"
url = "index.html"
[[sidebar]]
type = "static"
label = "License and Copyright"
url = "license_copyright.html"
source_file = "../../../workspace/dev_guides/Kernel/tkernel_license_copyright.html"A type = "static" entry's source_file is resolved by the orchestrator into an absolute path and, at render time, read via BaseRenderer._load_static_file_from_path() (engine/ude/interfaces.py) — see Target Settings for the static_source_path search-path mechanics.
If [[sidebar]] is missing, empty, or sidebar = [], the build fails:
text
sidebar.toml in <dir> declares no [[sidebar]] entries. There is no default
navigation to fall back on — every document directory must define its own
[[sidebar]] table.(engine/ude/orchestrator.py:339-344)
[groups] — folder taxonomy
[groups] controls which virtual folders classes, structs, enums, and similar entities are grouped into on the generated site. A real example, again from Kernel:
toml
[groups]
namespace_level = [
"Classes",
"Fields,_Structures_and_Enums",
"Functions",
"Types",
]GroupsConfig (engine/ude/config.py:56-68, model_config = ConfigDict(extra="forbid")) declares exactly one field:
python
namespace_level: List[str] = Field(default_factory=list)There is no class_level key. Older material in this documentation set (and one now-fixed example in the v1.0 → v2.0 migration guide) described a class_level key alongside namespace_level. That was never valid — the schema only ever declared namespace_level, and extra="forbid" rejects anything else, class_level included, exactly as hard as a genuine typo like namespac_level.
If [groups] is missing, or namespace_level is empty, the build fails — exactly the same treatment as [[sidebar]], no asymmetry:
text
sidebar.toml in <dir> declares no [groups] namespace_level entries. There is no
default taxonomy to fall back on — every document directory must define its
own [groups] table.(engine/ude/orchestrator.py:346-357)
A known-wrong error message
If you put an unrecognized key in [groups] (a typo, or a stray class_level), Pydantic validation fails and the engine raises:
text
UdeException: Invalid [groups] configuration: only 'namespace_level' and 'class_level' are permitted keys. Details: ...WARNING
This message is quoted verbatim from engine/ude/config.py:89 and is itself wrong: it names class_level as a permitted key, but the schema one line above (config.py:56-68) only ever declares namespace_level, and rejects class_level exactly as hard as it rejects the message's own claim would suggest it shouldn't. This is a tracked engine defect, not a documentation ambiguity — see ToDo/v3.0/EngineDefects_ToDo.md. Trust the schema, not the exception text: only namespace_level is valid.
No cascade, anywhere, for either table
Unlike almost every other configuration key in this system, [[sidebar]] and [groups] are not part of the global → SDK → doc-config deep-merge cascade described in Target Settings. There used to be a per-Lang×Output engine-tier default taxonomy; it was removed outright ([IMP-32.10]) along with its template fixtures — searching engine/ude/templates/ today turns up only Doxyfile, class_layout.html, csharp/, java/, python/, and css/, no sidebar-taxonomy directory of any kind.
The document's own sidebar.toml is the only source for both tables, at every tier. As a direct consequence, groups and sidebar are forbidden keys in all three JSON config layers:
_reject_forbidden_sidebar_keys()(engine/ude/orchestrator.py:164-186) rejects either key found in the global config (:263), the SDK config (:297), or the doc config (:310).GlobalConfig._reject_sidebar_keys()(engine/ude/config.py:125-162) rejects them again at theGlobalConfiglevel — alongside the removedsidebar_structures_dirkey (see Global Settings).
Putting "groups": {...} or "sidebar": [...] in ude_global_config.json, ude_sdk_config.json, or ude_doc_config.json is a hard configuration error, not a legitimate override — there is nothing here for deep_merge() to combine.
Checklist for a new document directory
- Create
sidebar.tomlnext to that document'sude_doc_config.json. - Add at least one
[[sidebar]]entry. - Add a
[groups]table with a non-emptynamespace_levellist. - Do not add a
class_levelkey, and do not addgroupsorsidebarto any of the three JSON config files. - Re-run
ude compile(orude audit, if you just want to check the config resolves) — a missing, empty, or malformedsidebar.tomlfails immediately, before any parsing happens.
Related Docs
(Paths below are repository-root-relative.)
user-docs/docs/target-settings.md— where[groups]fits among the other doc-config keysuser-docs/docs/migration-v2.md— whysidebar.tomlbecame mandatory in v2.0user-docs/docs/adding-a-new-sdk.md—sidebar.tomlas part of adding a whole new document
