This style guide provides conventions for writing and formatting content in the Learn OpenUSD repository. Following these guidelines ensures consistency across all lessons and makes the content easier to read and maintain.
All USD terminology should use the correct spelling as defined in the OpenUSD Glossary. Common terms include:
| Correct | Incorrect |
|---|---|
| prim | Prim, PRIM |
| stage | Stage |
| layer | Layer |
| attribute | Attribute |
| relationship | Relationship |
| composition | Composition |
| reference | Reference |
| payload | Payload |
| variant set | VariantSet, Variant Set |
| sublayer | Sublayer, sub-layer |
| metadata | Metadata, meta-data |
| scenegraph | scene graph, SceneGraph |
| primvar | PrimVar, prim var |
- USD terms should be lowercase unless at the start of a sentence or in a title/heading.
- Class and API names should use their exact casing (e.g.,
UsdGeom.Xform,Sdf.Layer). - File extensions should be lowercase (e.g.,
.usda,.usd,.usdc).
Examples:
- ✅ "A prim is the primary container in USD."
- ✅ "Prims can contain attributes and relationships."
- ❌ "A Prim is the primary container in USD."
- ✅ "The
UsdGeom.Xformclass defines transforms."
- USD and OpenUSD are always capitalized.
- LIVRPS (strength ordering mnemonic) is always capitalized.
- Spell out acronyms on first use, then use the acronym: "Universal Scene Description (USD)"
- Use
#for the page title (appears once at the top) - Use
##for major sections - Use
###for subsections - Use
####sparingly for sub-subsections
Link to glossary entries on first use in each lesson using the {term} role:
OpenUSD {term}`stages <Stage>` are the foundation of scene composition.The text before < is displayed; the text inside <> matches the glossary entry.
Use {code-cell} for Python code that executes during build:
```{code-cell}
from pxr import Usd
stage = Usd.Stage.CreateNew("example.usda")
print(stage.ExportToString(addSourceFileComment=False))
```Code cell options:
```{code-cell}
:tags: [remove-input]
# This code runs but input is hidden from output
```
```{code-cell}
:emphasize-lines: 7-10
# Lines 7-10 will be highlighted
```For non-executable code examples (API patterns, pseudocode):
```python
# This code is displayed but not executed
stage.DefinePrim("/path", "Type")
```Embed Kaltura videos using the custom {kaltura} directive:
```{kaltura} 1_cm4ehcvo
```For local video files:
Use admonitions to highlight important information:
```{seealso}
Read more about [USD File Formats](./usd-file-formats.md).
```
```{attention}
All exercises assume Visual Studio Code is open in the `usd_root/` directory.
```
```{caution}
Boolean operators like `and`/`or` will NOT combine predicates as intended.
```Available admonition types: note, warning, tip, caution, attention, seealso, important
Use grids for card-based layouts:
::::{grid} 1 1 2 2
:gutter: 2
:::{grid-item-card} Card Title
Card content here
:::
:::{grid-item-card} Another Card
More content
:::
::::Include reusable content snippets:
```{include} ../_includes/venv-table.md
```Link to other lessons using relative paths:
See the [Sublayers lesson](../creating-composition-arcs/sublayers/index.md).- Store images in
docs/images/<module-name>/ - Use descriptive filenames:
layer_Definition.webm,strength-ordering-diagram.png - Supported formats: PNG, JPG, GIF, WEBM, MP4
With alt text (preferred for accessibility):
Without alt text (for decorative images or videos):
- Capture only the relevant portion of the screen
- Use consistent window sizing when possible
- Avoid including or blur out personal information or unrelated UI elements
- Follow PEP 8 style guidelines
- Use type hints for clarity:
stage: Usd.Stage = ... - Include imports in every code cell (cells should be self-contained)
- Use descriptive variable names
- Use Google style docstrings for all functions and modules
Use Google style docstrings for all Python code:
Key sections (in order):
- Summary line: Brief one-line description ending with a period
- Extended description (optional): Additional context or details
- Args: Document each parameter with name and description
- Returns: Describe return value(s) and type
- Raises (optional): List exceptions that may be raised
For modules, include a module-level docstring with an overview and example usage:
"""Workshop preparation script for Learn OpenUSD.
This script transforms the documentation into a workshop version.
Example:
Run the script using uv::
$ uv run workshop_prep
"""- Add comments explaining each significant step
- Comments should explain "why" not just "what"
- Keep comments concise
Example:
# Import the Usd module from the pxr package
from pxr import Usd
# Create a new stage at the specified path
stage: Usd.Stage = Usd.Stage.CreateNew("_assets/example.usda")
# Define an Xform prim as the root of our scene
world = UsdGeom.Xform.Define(stage, "/World")
# Save changes to disk
stage.Save()- Print meaningful output for learner verification
- Use
ExportToString(addSourceFileComment=False)to avoid build-machine paths in output
- Save generated files to
_assets/subdirectories to avoid committing them to the repo. - Use relative paths from the lesson directory
- Use forward slashes even on Windows for consistency
- Use active voice: "We create a stage" not "A stage is created"
- Address the reader directly: "you will learn" not "learners will learn"
- Be concise but thorough
- Avoid jargon without explanation
- Use consistent terminology throughout
- Provide context for why something matters
- Include practical examples
- Connect sections with transitional sentences
- Preview what's coming: "In the next section, we will..."
- Summarize key points before moving on
- Store in
docs/exercise_content/<module-name>/ - Use
.usdafor human-readable examples - Use
.usdfor binary or format-agnostic files
- Include shebang and encoding if standalone
- Add docstrings explaining purpose
- Include license header
The notebook test harness runs notebook code cells in an isolated environment so tests can assert on variables and side effects. Use the run_notebook pytest fixture from tests/conftest.py.
run_notebook(path, cells=None, tags=None)executes code cells from the given notebook path. Paths undertests/are resolved from the repo root; other paths are resolved underdocs/_build/jupyter_execute/.- It returns a
Notebookobject: executed variables are available as attributes (e.g.nb.stage,nb.some_variable). Usenb._work_dirfor the temporary directory; files written to_assets/live undernb._work_dir / "_assets". - You can select cells by index (
cells=[0, 2]) or by label (tags=["setup", "stage-creation"]). Do not pass bothcellsandtags(raisesValueError). - Cells selected by
tagsrun in document order, not in the order tags are listed. - Invalid inputs raise: an out-of-bounds code cell index raises
IndexError. If any requested tag does not match at least one cell (e.g. a typo), the harness raisesValueErrorlisting the unmatched tags so tests fail instead of producing false positives.
Add a test-tags list to cell metadata so tests can run specific cells by semantic label.
In myst markdown (lesson .md notebooks), use the :test-tags: option on the {code-cell} directive:
```{code-cell}
:test-tags: [setup, stage-creation]
from pxr import Usd
stage = Usd.Stage.CreateInMemory()
```In .ipynb files (e.g. test fixtures), set metadata["test-tags"] on each code cell:
{
"cell_type": "code",
"metadata": {
"test-tags": ["setup", "stage-creation"]
},
"source": ["..."]
}Tags use OR semantics: a cell runs if it has any of the requested tags. Tagged cells always execute in document order.
def test_create_stage(run_notebook):
nb = run_notebook("stage-setting/stage.ipynb", tags=["setup"])
assert nb.stage is not NoneEvery new .md with executable code or .py file must include the Apache 2.0 SPDX license header:
---
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
---For Python files, use # comment syntax without the YAML delimiters.
If the lesson includes executable Python code, add Jupytext metadata after the license header:
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.17.2
kernelspec:
display_name: Python 3 (ipykernel)
language: python
name: python3
---For questions about style not covered here, refer to existing lessons as examples or open an issue for clarification.