Full documentation: https://llms.2plot.dev — the dedicated dash-improve-my-llms documentation site, with the complete API reference and deeper examples. This page is the quick-start overview.
Installation
pip install "dash-improve-my-llms[flask]" # Dash's default backend
pip install "dash-improve-my-llms[fastapi]" # Dash 4.2+
pip install "dash-improve-my-llms[quart]" # Dash 4.2+ async
Requires dash>=4.1. The backend is detected from app.server; your code is the same either way.
Introduction
A Dash app is a JavaScript application. Ask for any page without running JavaScript — which is what most crawlers, link previewers and LLM fetchers do — and every URL returns the same empty Loading... shell. To a search engine, a 30-page documentation site looks like 30 identical thin pages. To an agent, it looks like nothing at all.
dash-improve-my-llms fixes that at the framework level. You write each page's content once, as Markdown, and the package serves it everywhere a non-JavaScript consumer will look: rendered into the page's own initial HTML before React mounts, as /{page}/llms.txt, in the site-wide /llms.txt index, in sitemap.xml and robots.txt, and as an MCP resource on Dash 4.3+. One source of truth, six surfaces, and the interactive app is untouched.
This very site runs it — the /llms.txt index, the Markdown twin behind every page, and the cross-host network directory that links the *.2plot.dev satellites together are all this package at work.
Full Documentation
The complete documentation lives on its own site: llms.2plot.dev — every route, the access-control tiers, network configuration, the MCP bridge, and the machine-readable twin at llms.2plot.dev/llms.txt. This page is a summary; go there for the full reference.
Quick Start
import dash
from dash import Dash, html
from dash_improve_my_llms import add_llms_routes, RobotsConfig
app = Dash(__name__, use_pages=True)
# Absolute URLs in sitemap.xml, llms.txt and canonical tags come from this.
app._base_url = "https://myapp.com"
app._robots_config = RobotsConfig(block_ai_training=True)
app.layout = html.Div([dash.page_container])
add_llms_routes(app) # ← the whole integration
Then give each page prose — a module-level LLMS_DOC string, or register_page_metadata(path, name=..., description=..., llms_doc=...) when pages are generated in a loop.
What You Get
| Surface | What lands there |
|---|---|
| The page's own HTML | The prose, rendered into the initial response, before React mounts |
/{page}/llms.txt | The same prose as Markdown, with links back to the site and network indexes |
/llms.txt | An index of every page, plus the cross-host network directory |
/sitemap.xml | Every non-hidden page |
/robots.txt | Per-bot-class access policy |
dash.mcp | The same prose as an MCP resource (Dash 4.3+) |
Features
- Universal prerender — crawler-ready static HTML for every page, with the interactive app untouched.
llms.txteverywhere — a Markdown twin of every page, plus a rendered viewer for humans who open it in a browser.- Multi-backend — Flask, FastAPI and Quart, auto-detected from
app.server. - Per-request access control — visibility verdicts (
allow/gated/deny) applied consistently across llms.txt, crawler HTML, prerender, sitemap and MCP. - Cross-host network directory — publish sibling sites so an agent landing on one host can find the rest; this is how the 2plot network hangs together.
- Bot management — block AI-training crawlers while allowing AI-search citations, configurable per bot class.
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:
- /pip/dash_improve_my_llms/llms.txt — LLM-friendly documentation
- /sitemap.xml
- /robots.txt