Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

51 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Dash Documentation Boilerplate β€” the 2plot network's template

2plot

dash-documentation-boilerplate β€” the markdown-driven documentation template every *.2plot.dev component site is forked from. By Pip Install Python.

CI CD Dash DMC Backends Python License: MIT

Live: boilerplate.2plot.dev Β· the template every 2plot.dev component documentation site is built from.

A comprehensive boilerplate for creating beautiful, interactive documentation for your Dash components, data science workflows, and applications. Features markdown-driven content, live code examples, and automatic theme persistence.

Documentation Preview


✨ Features

πŸ“ Markdown-Driven Documentation

  • Write documentation in Markdown with Python integration
  • Custom directives for interactive examples, code highlighting, and component props
  • Automatic page generation from markdown files with frontmatter metadata
  • Table of contents generation for easy navigation

🎨 Modern UI/UX

  • Built with Dash Mantine Components
  • Responsive design for mobile, tablet, and desktop
  • Dark and light theme support with automatic preference persistence
  • Smooth transitions and professional styling
  • Customizable color schemes and theming

πŸ” Developer Experience

  • Hot reload during development
  • Searchable component navigation
  • Syntax highlighting for multiple languages
  • Interactive code examples with live callbacks
  • Component props documentation auto-generation

πŸ€– AI/LLM & SEO Integration

  • LLMS_DOC pattern β€” write a module-level prose string per page; served verbatim at /<page>/llms.txt
  • Multi-backend β€” add_llms_routes(app) auto-detects Flask, FastAPI, or Quart and dispatches to the matching adapter
  • MCP bridge β€” each page's prose registers as a dash.mcp resource on Dash 4.3+ (silent no-op otherwise)
  • SEO β€” sitemap.xml with intelligent priority inference; respects mark_hidden()
  • Bot management β€” training crawlers blocked (configurable), AI search citations allowed, browsers untouched
  • Privacy controls β€” mark_hidden() to exclude pages from sitemap, robots, MCP, and crawler prerender
  • Share with AI β€” paste the app URL into ChatGPT/Claude/etc.; they fetch the prose docs directly
  • Cross-host network directory β€” lib/network_directory.py publishes the sibling sites so an agent landing on one satellite can find the rest (docs)
  • Powered by dash-improve-my-llms 2.3.4

πŸ”Œ Pluggable Backends (Dash 4.x)

  • Run the same app on Flask, FastAPI, or Quart β€” switch with a single DASH_BACKEND environment variable
  • Backend selection centralized in lib/backend.py; a live badge shows which backend is serving the page
  • FastAPI/Quart (ASGI) unlock async callbacks, websocket callbacks, OpenAPI docs, a native JSON API (/api/backend, /api/pages, /healthz), and ASGI middleware
  • Dedicated docs: Pluggable Backends, Backend Deep Dive, and a FastAPI Showcase

πŸ‹ Production Ready

  • Docker and docker-compose support
  • Gunicorn (WSGI) and Uvicorn (ASGI) production servers
  • Optimized for deployment
  • Environment-based configuration

πŸš€ Built With Latest Technologies

  • Dash 4.2.0 - Modern Plotly Dash framework with pluggable backends
  • DMC 2.7.0 - Dash Mantine Components
  • Mantine 8.3.6 - Beautiful React UI library
  • React 18 - Latest React features
  • Python 3.11+ - Modern Python

πŸ“‹ Requirements

System Requirements

  • Python: 3.11 or higher
  • Node.js: 14+ (for npm dependencies)
  • npm: 6+

Python Dependencies

  • dash ~=4.4.1 β€” see the support matrix below; not 4.3.0
  • dash-mantine-components >= 2.7.0
  • dash-ag-grid
  • dash-improve-my-llms >= 2.3.4 (the 2plot network standard β€” see below)
  • flask >= 3.0.0 (default backend)
  • plotly >= 5.0.0
  • pandas >= 1.2.3
  • pydantic >= 2.3.0
  • python-frontmatter >= 1.0.0
  • markdown2dash (installed --no-deps β€” see below)
  • gunicorn >= 23.0.0 (WSGI production server; 21.x carried two request-smuggling CVEs)

Optional backends (install the matching extra to switch off Flask):

pip install "dash[fastapi]"   # FastAPI (ASGI) backend
pip install "dash[quart]"     # Quart (ASGI) backend
# then run with: DASH_BACKEND=fastapi python run.py  (needs uvicorn)

See requirements.txt for the complete list.

Dash support matrix

Verified against real apps on each backend, with the failure reproduced on a stock Dash app with dash-improve-my-llms uninstalled:

Dash Flask FastAPI Quart
4.1.0 βœ… β€” no pluggable backends β€”
4.2.0 βœ… βœ… βœ…
4.3.0 βœ… ❌ every non-root page 500s βœ…
4.4.0 βœ… βœ… βœ…
4.4.1 βœ… βœ… βœ…

4.3.0 added an early-return path guard to the ASGI middleware that returns before set_current_request, while the page catch-all still calls get_current_request() β€” so it raises RuntimeError: No active request in context. The catch-all is byte-identical between 4.2.0 and 4.3.0; only the middleware changed. 4.4.0 fixed it by setting the context inside the catch-all too.

That distinction matters for the pin: 4.2.0 works only because a single upstream code path happens to cover it, whereas 4.4.x sets the context in both places, so a future middleware guard can't reintroduce the bug. 4.4.x isn't just currently-passing, it's structurally safer.

~=4.4.1 lets 4.4.2 patches flow without twenty pull requests but blocks 4.5.0, so a minor bump goes through the matrix deliberately. The pin is for the most constrained backend network-wide, including Flask-only apps β€” DASH_BACKEND is an environment variable and this repo is a shared template, so a Flask deployment becomes a FastAPI deployment with one env change and no code change.

Note on dash-improve-my-llms. The floor is 2.3.4, the version 2plot.ai and 2plot.dev both run. It is what resolves this site's published identity: resolve_site_title takes the /llms.txt H1 and the llms viewer's brand chip from the home page's registered name, and skips generic candidates (Home, Index, and Dash's default title Dash) instead of publishing them. On a pre-2.3.4 build this host's viewer chip read a bare "Dash". There is no vendored copy of the package any more; vendor/ holds dash_clerk_auth alone. See Network Standard.

Note on markdown2dash. Version 0.1.2 declares gunicorn>=21.2.0,<22.0.0 β€” a markdown parser pinning a WSGI server, and directly against the CVE-driven gunicorn>=23 floor. pip cannot resolve both, so it is installed without its dependency graph. Its real dependencies (docutils, jsonpath, mistune) are listed in requirements.txt instead. Every install path does the same two commands:

pip install -r requirements.txt
pip install --no-deps markdown2dash==0.1.2

πŸš€ Quick Start

1. Clone the Repository

git clone https://github.com/pip-install-python/Dash-Documentation-Boilerplate.git
cd Dash-Documentation-Boilerplate

2. Install Dependencies

Python packages:

pip install -r requirements.txt
pip install --no-deps markdown2dash==0.1.2   # see the note above

Node packages (for DMC frontend components):

npm install

3. Run the Development Server

./scripts/dev.sh              # backend from .env (default flask)
./scripts/dev.sh fastapi      # override for one run

Visit http://localhost:8559 in your browser.

scripts/dev.sh resolves the interpreter from its own location, so it always uses this project's .venv. python run.py works too β€” but an IDE run configuration pointing at another project's virtualenv starts the app against that project's dependency versions, which is silent and expensive: on dash-improve-my-llms 2.0.0 there is no viewer module at all, so /<page>/llms.txt serves plain Markdown to everyone and nothing looks broken. The app now refuses to boot below the pinned floors and prints sys.executable, but the launcher avoids the question entirely.

4. Start Documenting!

Create your documentation in the docs folder:

docs/
β”œβ”€β”€ your-component/
β”‚   β”œβ”€β”€ your-component.md     # Markdown documentation
β”‚   └── examples.py           # Python code examples (optional)

πŸ“ Project Structure

dash-documentation-boilerplate/
β”œβ”€β”€ assets/                      # Static assets and CSS
β”‚   β”œβ”€β”€ m2d.css                 # Markdown-to-Dash styling (theme-aware)
β”‚   β”œβ”€β”€ main.css                # Custom styles (theme-aware)
β”‚   └── llms_copy.js            # "Copy for LLM" button handler
β”‚
β”œβ”€β”€ components/                  # Reusable UI components
β”‚   β”œβ”€β”€ appshell.py             # Main app layout with MantineProvider
β”‚   β”œβ”€β”€ header.py               # Header with search and theme toggle
β”‚   β”œβ”€β”€ navbar.py               # Navigation sidebar and drawer
β”‚   └── backend_badge.py        # Badge showing the active backend
β”‚
β”œβ”€β”€ docs/                        # Documentation content
β”‚   β”œβ”€β”€ example/                # Getting Started guide
β”‚   β”œβ”€β”€ directives/             # Custom Directives guide
β”‚   β”œβ”€β”€ interactive-components/ # Callback patterns guide
β”‚   β”œβ”€β”€ data-visualization/     # Theme-aware charts guide
β”‚   β”œβ”€β”€ ai-integration/         # AI/LLM integration (dash-improve-my-llms 2.2)
β”‚   β”œβ”€β”€ networks/               # Multi-site network wiring for satellites
β”‚   β”œβ”€β”€ backends/               # Pluggable Backends guide
β”‚   β”œβ”€β”€ backend-comparison/     # Flask vs FastAPI vs Quart deep dive
β”‚   └── fastapi-showcase/       # What the FastAPI backend unlocks
β”‚
β”œβ”€β”€ lib/                         # Utility libraries
β”‚   β”œβ”€β”€ constants.py            # BASE_URL + guard, APP_VERSION, colors
β”‚   β”œβ”€β”€ network_directory.py    # Cross-host directory shared by every satellite
β”‚   β”œβ”€β”€ backend.py              # Backend selection (DASH_BACKEND)
β”‚   β”œβ”€β”€ asgi_middleware.py      # ASGI middleware (FastAPI/Quart)
β”‚   β”œβ”€β”€ asgi_routes.py          # Showcase routes (/healthz, /api/*)
β”‚   β”œβ”€β”€ analytics_tracker.py    # Lightweight visitor analytics
β”‚   └── directives/             # Custom markdown directives
β”‚       β”œβ”€β”€ kwargs.py           # Component props table generator
β”‚       β”œβ”€β”€ source.py           # Source code display directive
β”‚       β”œβ”€β”€ toc.py              # Table of contents directive
β”‚       β”œβ”€β”€ headings.py         # Heading ids that survive inline formatting
β”‚       └── llms_copy.py        # "Copy for LLM" button directive
β”‚
β”œβ”€β”€ pages/                       # Dash multi-page app pages
β”‚   β”œβ”€β”€ home.md                 # Home page content
β”‚   β”œβ”€β”€ home.py                 # Home page layout (exports LLMS_DOC)
β”‚   └── markdown.py             # Dynamic markdown page loader
β”‚
β”œβ”€β”€ scripts/
β”‚   └── smoke_live.py           # Post-deploy checks against a live site
β”‚
β”œβ”€β”€ tests/                       # pytest suite (runs on all three backends)
β”‚   β”œβ”€β”€ conftest.py             # Boots run.py once; one client per backend
β”‚   β”œβ”€β”€ test_pages.py           # Every page loads and serves real content
β”‚   β”œβ”€β”€ test_llms_routes.py     # llms.txt, sitemap, robots, canonicals
β”‚   β”œβ”€β”€ test_network_directory.py
β”‚   β”œβ”€β”€ test_docs_content.py    # Frontmatter, directives, heading anchors
β”‚   β”œβ”€β”€ test_config.py          # BASE_URL guard, index.html metadata
β”‚   β”œβ”€β”€ test_internal_traffic.py # The analytics contract, both directions
β”‚   β”œβ”€β”€ test_network_smoke.py   # The battery, run against this app
β”‚   β”œβ”€β”€ test_site_identity.py   # One brand, every surface
β”‚   └── test_smoke_live.py      # The CD script, run against this app
β”‚
β”œβ”€β”€ templates/
β”‚   └── index.html              # SEO-optimized HTML template
β”‚
β”œβ”€β”€ vendor/                      # dash-clerk-auth sdist (not on PyPI)
β”‚
β”œβ”€β”€ .github/
β”‚   β”œβ”€β”€ dependabot.yml          # dash-network update group
β”‚   └── workflows/
β”‚       β”œβ”€β”€ ci.yml              # Lint, matrix, image build + boot + battery
β”‚       └── cd.yml              # Render deploy + live verification
β”‚
β”œβ”€β”€ .flake8
β”œβ”€β”€ .gitignore
β”œβ”€β”€ CHANGELOG.md                # Version history and changes
β”œβ”€β”€ Dockerfile                  # Docker container definition
β”œβ”€β”€ docker-compose.yml          # Docker compose configuration
β”œβ”€β”€ package.json                # Node.js dependencies
β”œβ”€β”€ package-lock.json           # Locked npm versions
β”œβ”€β”€ pytest.ini
β”œβ”€β”€ README.md                   # This file
β”œβ”€β”€ render.yaml                 # Render Blueprint for boilerplate.2plot.dev
β”œβ”€β”€ requirements.txt            # Python dependencies
└── run.py                      # Application entry point

πŸ“– Usage Guide

Creating Documentation Pages

  1. Create a new folder in the docs/ directory:

    mkdir -p docs/my-component
  2. Create a markdown file with frontmatter:

    ---
    name: My Component
    description: A description of my component
    endpoint: /components/my-component
    icon: mdi:code-tags
    ---
    
    ## My Component
    
    Your documentation content here...
  3. Add interactive examples (optional):

    # docs/my-component/example.py
    import dash_mantine_components as dmc
    
    component = dmc.Button("Click Me!", id="my-button")
  4. Use directives in your markdown:

    .. toc::
    
    .. exec::docs.my-component.example
    
    .. source::docs/my-component/example.py

Custom Markdown Directives

.. toc::

Generates a table of contents from your markdown headings.

.. exec::module.path.to.component

Renders an executable Python component from a module.

.. source::path/to/file.py

Displays source code with syntax highlighting.

.. kwargs::ComponentName

Generates a props documentation table for a component.

.. llms_copy::Page Title

Adds a "Copy for LLM" button that copies the page's /<page>/llms.txt URL to the clipboard for sharing with ChatGPT, Claude, and other AI assistants.

Customizing Themes

Modify lib/constants.py to change the primary color:

PRIMARY_COLOR = "teal"  # Change to any Mantine color

Customize CSS in:

  • assets/main.css - General styling
  • assets/m2d.css - Markdown-specific styling

Theme Persistence

The boilerplate automatically saves user theme preference (light/dark) in localStorage:

  • First visit: Detects browser preference or defaults to light
  • Theme toggle: Saves preference automatically
  • Return visits: Restores saved theme preference

βœ… Testing

The suite boots run.py itself rather than a test app assembled for the occasion β€” almost everything worth catching here lives in the wiring (registration order, which middleware runs first, whether a page's prose survived to the response), and a test app that re-implements the wiring only tests the re-implementation.

pip install pytest
pytest                       # whichever backend DASH_BACKEND / .env selects

DASH_BACKEND=flask pytest    # the three backends, one at a time
DASH_BACKEND=fastapi pytest
DASH_BACKEND=quart pytest

flake8 lib components pages tests run.py

What it covers, and why each one is there:

Area The failure it catches
Page registration & reachability A markdown file that silently stops registering β€” invisible to any test that iterates whatever did register
Crawler bodies A page serving the JavaScript stub. This is the regression that cost the network 12 of 14 crawlable URLs
Rendered prose Links, tables, code fences and rules coming through as literal text instead of HTML
Canonical tags Exactly one per page, on this host. A wrong one deindexes the site and looks like nothing is wrong
sitemap / robots / llms.txt Missing pages, foreign hosts, a sitemap line pointing elsewhere
Network directory Self-listed peers, duplicate or overlapping tiers, entries missing from the published output
Docs content Broken .. exec:: / .. source:: targets, duplicate endpoints, incomplete frontmatter
Heading anchors A TOC link whose target id doesn't exist β€” clicking it does nothing, silently
BASE_URL guard A fork deploying with the boilerplate's own canonical host
scripts/smoke_live.py The CD script itself, run against the in-process app, so a typo can't turn every live check into a silent pass

CI

.github/workflows/ci.yml runs on every push and pull request:

  • lint β€” flake8, blocking
  • test β€” the full suite on Flask, FastAPI and Quart (Python 3.12), plus Python 3.11 and 3.13 on Flask. Asserts the installed Dash is β‰₯ 4.4 and dash-improve-my-llms is β‰₯ 2.1 before running anything
  • boot under gunicorn β€” a page can render under a test client and still fail under a real WSGI worker
  • docker β€” builds the image, boots it, and probes the live routes

πŸš€ Deployment

Render (how boilerplate.2plot.dev is hosted)

render.yaml is the Blueprint for the live deployment: gunicorn with two workers, /healthz as the health check, a persistent disk for the analytics ledger, and the custom domain attached.

render blueprint launch        # or point a new Render service at this repo

The one environment variable you must set is APP_BASE_URL. It drives <link rel="canonical">, sitemap.xml, and the absolute URLs in llms.txt. A fork that leaves it unset inherits https://boilerplate.2plot.dev and tells Google that every one of its pages is a duplicate of this one β€” traffic disappears and nothing in the app looks broken. lib/constants.py refuses to boot on Render without it, and rejects *.onrender.com values too, because those keep resolving after a custom domain is attached and quietly split link equity across two hosts.

APP_BASE_URL=https://yoursite.2plot.dev   # required in production
DASH_BACKEND=flask                        # flask | fastapi | quart
CROSS_APP_WEBHOOK_SECRET=...              # optional: network analytics
TRAFFIC_ANALYTICS_FILE=/var/data/visitor_analytics.json

CD

.github/workflows/cd.yml runs CI, POSTs to the Render deploy hook in the RENDER_DEPLOY_HOOK_URL secret, waits for the new instance to be reliably healthy, and then verifies the live site with scripts/smoke_live.py.

Without that secret the deploy step skips itself and the workflow still verifies whatever is currently live β€” so a fork doesn't fail CD on day one over a secret it was never given.

You can run the same checks by hand against any satellite:

python scripts/smoke_live.py https://emojimart.2plot.dev

It checks the four things that are silent in production: a canonical on the wrong host, a page serving the JavaScript stub, a missing network directory, and dead peer llms.txt links.

Docker

docker build -t dash-docs-boilerplate .
docker run -p 8550:8550 dash-docs-boilerplate     # http://localhost:8550
docker-compose up

The image serves with gunicorn and declares a HEALTHCHECK against /healthz. Note that vendor/ is copied in before the pip layer β€” while dash-improve-my-llms installs from the sdist, the build fails without it.


πŸ›°οΈ Forking this into a satellite site

This repo is the template the *.2plot.dev documentation sites are built from, so changes here propagate. Four things to change when you fork it:

  1. APP_BASE_URL in your host's environment, and DEFAULT_BASE_URL in lib/constants.py. See above for why this one matters more than everything else combined.
  2. lib/network_directory.py β€” keep it identical across every satellite. Twelve hand-maintained peer lists will drift, and a directory that disagrees with itself across hosts is worse than no directory. Only list hosts that are actually live.
  3. templates/index.html β€” title, description, Open Graph card, and the Schema.org blocks.
  4. docs/ β€” replace the example pages with your component's.

Leave warn_missing_llms_doc=True on. It names every page with no prose, which is exactly the list of pages serving a stub to crawlers. Turning it off hides the to-do list rather than shortening it. The full guide is at boilerplate.2plot.dev/networks.


πŸ› οΈ Development

Setting Up Development Environment

  1. Create virtual environment:

    python -m venv .venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
  2. Install dependencies:

    pip install -r requirements.txt
    pip install --no-deps markdown2dash==0.1.2
    npm install
  3. Run in debug mode:

    # Modify run.py
    app.run(debug=True, host='0.0.0.0', port='8553')

Adding New Components

  1. Create your component in a separate module
  2. Add documentation in docs/your-component/
  3. The app automatically discovers and registers pages from markdown files
  4. Restart the server to see your new documentation

Modifying the Layout

Main layout components:

  • Header: components/header.py - Logo, search, theme toggle
  • Navbar: components/navbar.py - Sidebar navigation
  • AppShell: components/appshell.py - Overall layout structure

πŸ”§ Configuration

Environment Variables

Create a .env file (optional):

DASH_DEBUG=False
DASH_HOST=0.0.0.0
DASH_PORT=8553
DASH_BACKEND=flask     # flask | fastapi | quart (requires the matching dash extra)

Network analytics (2plot.ai)

When deployed as a satellite of the 2plot network, this app reports its own traffic to the hub so the owner-only /traffic dashboard can chart it. Two signals, both hourly:

Signal How
Health The hub probes /healthz (served on every backend) and records up/down + latency.
Traffic lib/satellite_reporter POSTs a signed daily rollup to https://2plot.ai/api/satellite/traffic.
CROSS_APP_WEBHOOK_SECRET=...   # shared HMAC secret β€” without it, reporting is off
SATELLITE_APP_KEY=dev          # this app's key in the hub network directory
                               # (falls back to AD_APP_ID, then "dev")

# Optional
SATELLITE_TRAFFIC_URL=https://2plot.ai/api/satellite/traffic
SATELLITE_REPORT_INTERVAL_S=3600
ANALYTICS_GEO_LOOKUP=1         # 0 to skip ip-api.com (unnecessary behind Cloudflare)
ANALYTICS_RETENTION_DAYS=45    # local ledger retention; the hub keeps the history

Reporting is off by default β€” no secret, no POSTs, and the app logs that it is disabled. Check what would be sent without sending it:

python -m lib.satellite_reporter --dry-run

The numbers (visitors, sessions, median_session_s, top pages, countries) are computed in lib/traffic_rollup.py using the hub's own definitions β€” a visitor is an (IP, user-agent) pair, a session breaks on a 30-minute gap, and the median session length counts multi-page sessions only, so single pageviews are never padded in. Behind a proxy or CDN, the tracker reads CF-Connecting-IP / X-Forwarded-For for the client address and CF-IPCountry for the country; without that, every visitor would look like the proxy.

Deployment note β€” give the ledger a persistent disk. The hub takes the last report for a given (app, date). On an ephemeral filesystem (a plain Render/Heroku instance) a mid-day deploy wipes visitor_analytics.json, and the next hourly report overwrites today's correct total with the handful of hits collected since the restart. Mount a disk and point TRAFFIC_ANALYTICS_FILE at it (e.g. /var/data/visitor_analytics.json) so a deploy doesn't cost you a day of numbers.

Customization Points

File Purpose
lib/constants.py App-wide constants (colors, titles)
assets/main.css Custom CSS styles
templates/index.html HTML template (for analytics, meta tags)
components/appshell.py Theme configuration, MantineProvider settings

πŸ“š Documentation

User Documentation

  • Getting Started: This README
  • Changelog: See CHANGELOG.md
  • Examples: Check the /docs/example/ folder

🀝 Contributing

Contributions are welcome! Here's how you can help:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes
  4. Test thoroughly: Ensure the app runs without errors
  5. Commit your changes: git commit -m 'Add amazing feature'
  6. Push to the branch: git push origin feature/amazing-feature
  7. Open a Pull Request

Development Guidelines

  • Follow PEP 8 style guide for Python code
  • Add docstrings to functions and classes
  • Test your changes before submitting
  • Update documentation if adding new features
  • Keep commits atomic and well-described

πŸ› Known Issues & Troubleshooting

Common Issues

Issue: ModuleNotFoundError: No module named 'dash_html_components'

  • Solution: You're on an old version. Update to 1.0.0+ and import from the main package (from dash import html, dcc); 1.0.0 runs on Dash 4.x.

Issue: DASH_BACKEND=fastapi (or quart) fails to start

  • Solution: Install the matching extra β€” pip install "dash[fastapi]" (or [quart]) β€” and serve with an ASGI server (uvicorn). The app falls back to Flask if the backend is unavailable.

Issue: Theme doesn't persist

  • Solution: Check browser localStorage is enabled and not blocked

Issue: npm install fails

  • Solution: Update Node.js to 14+ and npm to 6+

Issue: Port already in use

  • Solution: Change port in run.py or stop the conflicting process

Issue: RuntimeError: APP_BASE_URL is not set on Render

  • Solution: Working as intended. Set APP_BASE_URL to this deployment's real origin. Without it the app would serve the boilerplate's canonical host on every page.

Issue: pip install -r requirements.txt fails with a gunicorn resolution conflict

  • Solution: markdown2dash 0.1.2 pins gunicorn<22 against this project's gunicorn>=23 floor. Install it separately: pip install --no-deps markdown2dash==0.1.2.

Issue: the llms.txt viewer's brand chip says "Dash", or /llms.txt opens with the wrong # line

  • Solution: You are on a pre-2.3.4 dash-improve-my-llms, or SITE_BRAND is unset. pip install -U "dash-improve-my-llms[flask]>=2.3.4" and see Network Standard.

Issue: the Docker container exits at boot with Could not import dash.backends._fastapi

  • Solution: A local .env was copied into the image. .dockerignore excludes it; make sure you have not removed that line.

Issue: Every non-root URL 500s with No active request in context

  • Solution: You're on Dash 4.3.0 with the FastAPI backend. Upgrade to 4.4.0+; requirements.txt already floors it there.

For more issues, check GitHub Issues


πŸ“Š Version Information

Current Version: 1.2.0

Component Version
Dash 4.4.0+ (4.3.0 excluded β€” broken FastAPI backend)
Dash Mantine Components 2.7.0+
Mantine 8.3.6
Python 3.11+
React 18.2.0
Flask / FastAPI / Quart pluggable backends
dash-improve-my-llms 2.3.4+

See CHANGELOG.md for version history.

What's New in 1.2.0

The 2plot network standard, landed on this template so every satellite can copy it. See Network Standard.

  • πŸͺͺ Explicit site identity (lib/constants.SITE_BRAND) on Dash(title=), register_page_metadata(path="/"), pages/home.md and templates/index.html. Before this, /llms.txt's viewer chip published Dash's default title β€” a bare "Dash" β€” as the name of this site.
  • πŸ“ˆ The internal-traffic contract: network machinery is counted nowhere. Token-carrying requests are dropped at write time before bot classification, /healthz is no longer stored, and every outbound call to another network host now sends INTERNAL_UA. The ad client had been fetching a campaign from 2plot.dev on every page view as python-requests β€” this satellite's readers were being charted as bots on the hub.
  • πŸ§ͺ CI on the network baseline: least-privilege permissions, per-job timeout-minutes, a buildx GHA cache, version fingerprints asserted inside the image, a secretless pytest suite, scripts/network_smoke.py run in three seats (container, production, in-process), Dependabot with a dash-network group, and an advisory pip-audit.
  • πŸ”’ gunicorn >= 23.0.0 (was 21.2.0, which carried CVE-2024-6827 and CVE-2024-1135). markdown2dash's spurious gunicorn<22 pin is dodged with a --no-deps install.
  • πŸ“¦ dash-improve-my-llms >= 2.3.4.
  • πŸ‹ .dockerignore β€” a local .env was being copied into the production image, which killed the container at boot on the first local run of the new battery. Secrets and dev config no longer reach an image layer.

What's New in 1.1.0

  • πŸ§ͺ CI/CD: a pytest suite that boots the real app on all three backends, flake8, a Docker build, and a CD workflow that deploys to Render and then verifies the live site.
  • πŸ›°οΈ Cross-host network directory (lib/network_directory.py) plus a Multi-Site Networks guide for satellite authors.
  • πŸ”’ APP_BASE_URL guard: production boots fail rather than silently serving another site's canonical host.
  • 🎯 dash-improve-my-llms 2.2: merge semantics for page metadata, universal prerender, a Markdown renderer that emits real anchors, tables and code fences, a navigation block so a page's llms.txt is no longer a dead end, and content negotiation on that URL β€” Markdown for agents, a rendered view with the network wordmark for browsers.
  • πŸ› Fixes: duplicate canonical tags on every page; a heading containing inline code crashing the renderer at startup; TOC anchors pointing at ids that didn't exist; MCP wiring that never ran because it imported a symbol that doesn't exist; dead /page.json and /architecture.txt links; a broken Open Graph image; piratesbagain.com.

What's New in 1.0.0

First stable release β€” a major architectural milestone:

  • πŸš€ Dash 4.x (4.2.0) and DMC 2.7.0 β€” modern framework with pluggable backends.
  • πŸ”Œ Pluggable backends: run the same app on Flask, FastAPI, or Quart by setting DASH_BACKEND β€” no code changes. ASGI backends add async/websocket callbacks, OpenAPI docs, a native JSON API, and ASGI middleware. New Pluggable Backends, Backend Deep Dive, and FastAPI Showcase docs.
  • 🎯 dash-improve-my-llms 2.0: the LLMS_DOC pattern (per-page prose served at /<page>/llms.txt), multi-backend AI/LLM surfaces, and an MCP resource bridge on Dash 4.3+.
  • 🧹 Removed the TOON format entirely β€” lib/toon_generator.py, the TOON docs/dashboard, and /llms.toon routes are gone (the package no longer exports TOONConfig, toon_encode, generate_*_toon).
  • ⚠️ Removed mark_important() / mark_component_hidden() (now no-ops) and the /page.json / /architecture.txt routes β€” Dash 4.3 MCP covers structured introspection. Write emphasis directly into a page's LLMS_DOC markdown.

πŸ“œ License

This project is licensed under the MIT License - see the LICENSE file for details.


πŸ™ Acknowledgments

Built With

Inspired By

  • dmc-docs - Documentation framework inspiration

Special Thanks

  • @AnnMarieW for suggested improvements
  • The Dash community for continuous support

πŸ“ž Support & Community

Get Help

Discord Invite

Stay Connected

GitHub: @pip-install-python GitHub Followers

YouTube: @2plotai β€” build-alongs and component walkthroughs


Want to Contribute?

Check out open issues labeled good first issue


⬆ Back to Top

Made with ❀️ by the Dash community

Pip Install Python LLC @ 2plot.ai

Star this repo if you find it useful! ⭐

About

This project is designed to help developers quickly create well-organized documentation for their Dash components, data science workflows, and entire Dash applications.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages