Getting Started
Learn how to create documentation pages with markdown and Python
Introduction
Welcome to the Dash Documentation Boilerplate! This guide will teach you how to create beautiful, interactive documentation pages using markdown and Python.
The boilerplate uses a markdown-driven approach where you write documentation in .md files and supplement them with interactive Python components. The framework automatically discovers your documentation and generates pages with routing.
Creating Your First Page
Step 1: Create a Folder
Create a new folder in the docs/ directory for your component or feature:
mkdir -p docs/my-component
Step 2: Create a Markdown File
Create a markdown file with frontmatter metadata at the top:
---
name: My Component
description: A description of my awesome component
endpoint: /components/my-component
package: my-component
icon: mdi:code-tags
---
## My Component
Your documentation content here...
Frontmatter Fields
- name (required): Display name in the navigation
- description (required): Short description for SEO and navigation
- endpoint (required): URL path for the page (e.g.,
/components/my-component) - package (optional): Package name for organization
- icon (optional): Material Design icon (from Iconify)
Step 3: Write Your Content
Use standard markdown syntax for your documentation:
## Features
This component provides:
- Feature 1
- Feature 2
- Feature 3
### Usage
Here's how to use it:
\`\`\`python
import dash_mantine_components as dmc
component = dmc.Button("Click me!")
\`\`\`
### Advanced Examples
More detailed examples below...
That's it! The page will automatically appear in the navigation when you restart the server.
Using Custom Directives
The boilerplate provides powerful custom directives to enhance your documentation:
Table of Contents - .. toc::
Automatically generate a table of contents from your headings:
.. toc::
### Section 1
Content here...
### Section 2
Content here...
Execute Python Components - .. exec::
Embed interactive Dash components from Python modules:
.. exec::docs.my-component.example
This will import and render the component variable from docs/my-component/example.py.
Tip: Use :code: false to hide the code and show only the rendered output:
.. exec::docs.my-component.example
:code: false
Display Source Code - .. source::
Show syntax-highlighted source code:
<!-- Error: File not found: docs/my-component/example.py -->
Tip: Make long code collapsible:
<!-- Error: File not found: docs/my-component/example.py -->
:defaultExpanded: false
:withExpandedButton: true
Component Props - .. kwargs::
Auto-generate a props documentation table:
.. kwargs::dmc.Button
Directive Options
The custom directives support options that control how content is displayed. Options are specified using a colon syntax after the directive.
Common Directive Options
Option: code false - Hide Source Code Display
Use with .. exec:: to show only the rendered component without the code:
.. exec::docs.my-component.example
:code: false
When to use:
- ✅ You want to show the interactive demo without cluttering the page
- ✅ The code will be shown separately with
.. source:: - ✅ The example is self-explanatory and code isn't needed inline
Example:
Here's an interactive demo:
.. exec::docs.data-visualization.basic_chart
:code: false
Source code:
File: docs/data-visualization/basic_chart.py
from dash import dcc, callback, Input, Output import dash_mantine_components as dmc import pandas as pd import plotly.express as px
Register Mantine templates
dmc.add_figure_templates(default="mantine_light")
Sample data
df = pd.DataFrame({ "Category": ["Product A", "Product B", "Product C", "Product D", "Product E"], "Sales": [120, 95, 180, 140, 165] })
Create initial figure
fig = px.bar( df, x="Category", y="Sales", title="Product Sales Comparison", color="Sales", color_continuous_scale="teal" )
fig.update_layout( xaxis_title="Product Category", yaxis_title="Sales (Units)", showlegend=False, height=400 )
component = dcc.Graph(figure=fig, id='figure-basic-chart', config={'displayModeBar': False})
@callback( Output('figure-basic-chart', "figure"), Input("color-scheme-storage", "data"), ) def update_figure_theme(theme): """Update chart template based on color scheme""" template = "mantine_dark" if theme == "dark" else "mantine_light"
# Recreate the figure with the correct template fig = px.bar( df, x="Category", y="Sales", title="Product Sales Comparison", color="Sales", color_continuous_scale="teal", template=template )
fig.update_layout( xaxis_title="Product Category", yaxis_title="Sales (Units)", showlegend=False, height=400 )
return fig
Option: defaultExpanded false - Collapse Code by Default
Use with .. source:: to show code in a collapsed state initially:
<!-- Error: File not found: docs/my-component/example.py -->
:defaultExpanded: false
When to use:
- ✅ Long source files that might overwhelm the page
- ✅ Optional/advanced code that users can view if interested
- ✅ Multiple code examples on one page
Option: withExpandedButton true - Add Expand/Collapse Button
Use with .. source:: to add an interactive expand/collapse button:
<!-- Error: File not found: docs/my-component/example.py -->
:defaultExpanded: false
:withExpandedButton: true
When to use:
- ✅ Combined with
:defaultExpanded: falsefor collapsible code - ✅ Giving users control over viewing source code
- ✅ Keeping documentation clean while making code accessible
Combining Options
You can combine multiple options for fine-grained control:
### Interactive Demo
The component in action:
.. exec::docs.components.advanced-example
:code: false
<Click to view source code>
<!-- Error: File not found: docs/components/advanced-example.py -->
:defaultExpanded: false
:withExpandedButton: true
This pattern creates a clean documentation flow:
- User sees the interactive demo first
- User can optionally expand to view the source code
- Page stays uncluttered for quick scanning
Complete Example
Here's a real-world example combining all these options:
---
name: My Component
description: An awesome interactive component
endpoint: /components/my-component
---
.. toc::
### Overview
This component provides interactive data filtering...
### Live Demo
Try it out below:
.. exec::docs.components.my-component.demo
:code: false
Want to see how it works? View the source:
<!-- Error: File not found: docs/components/my-component/demo.py -->
:defaultExpanded: false
:withExpandedButton: true
### API Reference
Component props documentation:
.. kwargs::dmc.MyComponent
Best Practices
✅ Do:
- Use
:code: falsewhen showing code separately with.. source:: - Collapse long code files with
:defaultExpanded: false - Add expand buttons for optional code viewing
- Keep the user experience in mind - don't overwhelm with code
❌ Don't:
- Hide code without providing a way to view it
- Use
:code: falsefor simple examples where seeing code helps understanding - Collapse very short code snippets (< 20 lines)
Creating Interactive Examples
Basic Example
Create a Python file in your docs folder (e.g., docs/my-component/example.py):
from dash import html, dcc
import dash_mantine_components as dmc
component = dmc.Button(
"Click Me!",
id="my-button",
variant="filled",
color="blue"
)
Then reference it in your markdown:
.. exec::docs.my-component.example
Example with Callbacks
You can create interactive examples with callbacks:
from dash import html, dcc, callback, Input, Output
import dash_mantine_components as dmc
component = html.Div([
dmc.Button("Click Me!", id="click-button", n_clicks=0),
html.Div(id="click-output")
])
@callback(
Output("click-output", "children"),
Input("click-button", "n_clicks")
)
def update_output(n_clicks):
return f"Button clicked {n_clicks} times!"
Interactive Example
Below is a working example showing a button that updates a graph. You can interact with it right here in the documentation!
:code: false The source code for this example is shown below:
# File: docs/example/introduction.py
from dash import dcc, html, Input, Output, callback
import dash_mantine_components as dmc
import pandas as pd
import plotly.express as px
# Register Mantine templates
dmc.add_figure_templates(default="mantine_light")
# Sample data
df1 = pd.DataFrame({
"Fruit": ["Apples", "Oranges", "Bananas", "Grapes"],
"Amount": [4, 1, 2, 2]
})
df2 = pd.DataFrame({
"Fruit": ["Apples", "Oranges", "Bananas", "Grapes"],
"Amount": [2, 4, 5, 1]
})
component = html.Div([
html.H1("Graph Update Example", style={'textAlign': 'center', 'marginBottom': '20px'}),
html.Div(
[
dcc.Graph(id='example-graph'),
html.Button(
'Update Graph',
id='update-button',
n_clicks=0,
style={'marginTop': '10px', 'padding': '10px 20px'},
),
],
id='interactive-section',
),
])
@callback(
Output('example-graph', 'figure'),
Input('update-button', 'n_clicks'),
Input("color-scheme-storage", "data"),
)
def update_graph(n_clicks, theme):
"""Update graph based on button clicks and theme."""
template = "mantine_dark" if theme == "dark" else "mantine_light"
if n_clicks % 2 == 0:
fig = px.bar(df1, x="Fruit", y="Amount", title="Fruit Amounts", template=template)
else:
fig = px.bar(df2, x="Fruit", y="Amount", title="Updated Fruit Amounts", template=template)
return fig
Documenting a Page for AI Assistants
When users paste your documentation URL into ChatGPT, Claude, or any MCP-aware client, the request hits /<page>/llms.txt. With dash-improve-my-llms 2.0, that endpoint serves a module-level string called LLMS_DOC verbatim — no layout walking, no extraction, no surprises:
# pages/my_feature.py
from dash import html, register_page
register_page(__name__, path="/my-feature", name="My Feature")
LLMS_DOC = """\
# My Feature
> One-line tagline that explains what this page is for.
## What this page does
A short narrative description: what controls exist, how they relate to
the data, and what the user is supposed to do here.
## What the user can do
- Type in the search box to narrow by name.
- Switch category to constrain by class.
## What the page does NOT do
This is a demo. No persistence, no edit/create, no per-item detail view.
"""
def layout():
return html.Div([...])
For pages that don't have a module (like the markdown-driven docs in this boilerplate), pass the prose explicitly:
from dash_improve_my_llms import register_page_metadata
register_page_metadata(
path="/my-feature",
name="My Feature",
description="Search and filter the catalog.",
llms_doc="""... your prose here ...""",
)
dash-improve-my-llms 2.0 will emit a UserWarning at startup naming any page that's missing prose, so you'll know exactly where to fill in. See the AI/LLM Integration page for the full LLMS_DOC pattern and the rest of the 2.0 toolkit.
File Structure Example
Here's a complete example of a documentation folder structure:
docs/
└── my-component/
├── my-component.md # Main documentation
├── basic-example.py # Basic usage example
├── advanced-example.py # Advanced usage example
└── callbacks-example.py # Interactive callback example
In your markdown file:
---
name: My Component
description: An awesome component
endpoint: /components/my-component
icon: mdi:star
---
.. toc::
### Overview
Description of the component...
### Basic Usage
.. exec::docs.my-component.basic-example
<!-- Error: File not found: docs/my-component/basic-example.py -->
### Advanced Usage
.. exec::docs.my-component.advanced-example
<!-- Error: File not found: docs/my-component/advanced-example.py -->
### Interactive Example
.. exec::docs.my-component.callbacks-example
:code: false
<!-- Error: File not found: docs/my-component/callbacks-example.py -->
### Component Props
.. kwargs::MyComponent
Markdown Formatting Tips
Code Blocks
Use triple backticks with language specification:
def hello_world():
print("Hello, World!")
function helloWorld() {
console.log("Hello, World!");
}
pip install dash-mantine-components
Emphasis
- Bold text with
**text** - Italic text with
*text* Inline codewith backticks
Links
Lists
Unordered:
- Item 1
- Item 2
- Nested item
Ordered:
- First item
- Second item
- Third item
Blockquotes
This is a blockquote
It can span multiple lines
Tables
| Feature | Support |
|---|---|
| Markdown | ✅ |
| Python | ✅ |
| Callbacks | ✅ |
Best Practices
1. Use Descriptive Names
Choose clear, descriptive names for your pages and components:
✅ Good: name: Button Component ❌ Bad: name: Comp1
2. Organize by Feature
Group related documentation together:
docs/
├── components/
│ ├── button/
│ └── input/
├── layouts/
│ ├── grid/
│ └── stack/
└── examples/
├── dashboard/
└── form/
3. Add Table of Contents
Always include .. toc:: at the top of long documentation pages.
4. Show Code and Results
Use .. exec:: and .. source:: together to show both the code and the result. Consider using :code: false with exec and :defaultExpanded: false with source for cleaner presentation.
5. Test Your Examples
Make sure your interactive examples actually work before documenting them!
Next Steps
Now that you know the basics, check out these example pages:
- Custom Directives - See all directives in action with examples
- Interactive Components - Advanced callback patterns and state management
- Data Visualization - Plotly charts and graphs integration
- AI Integration - Using the dash-improve-my-llms features
Need Help?
- Documentation: Check the README.md
- Issues: Report bugs on GitHub Issues
- Community: Join the Dash Community Forum
Happy documenting! 🚀
Source: /getting-started
Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs:
- /getting-started/llms.txt — LLM-friendly documentation
- /sitemap.xml
- /robots.txt