<!-- Generated from llms-txt-django/index.html. The canonical document is the HTML page. -->

- [ Home ](/) 
/
- [ How to create ](/how-to-create/) 
/
- Django guide            
# llms.txt for Django

Four approaches for Django: a static file (served via Nginx), a simple view returning HttpResponse, a dynamic view generated from your database models, or a cached view for high-traffic sites.

Last updated: April 22, 2026

ℹ Recommended approach

Use a  custom view  (Option 2) to serve  llms.txt  at the root path  /llms.txt . The static file approach (Option
1) places the file under  /static/llms.txt  
by default, which is the wrong path per the spec.

## Option 1: static file via STATICFILES_DIRS

Django's `staticfiles` framework copies files from `STATICFILES_DIRS` into `STATIC_ROOT` when you run `collectstatic`. You can then configure Nginx to serve the file directly, but note
that the URL will be under your `STATIC_URL` 
prefix (e.g. `/static/llms.txt`), not at the root.
static/llms.txt, approach notes   
Copy

```
# Django static file approach
#
# 1. Place llms.txt in one of your STATICFILES_DIRS:
#    myproject/
#    ├── static/
#    │   └── llms.txt   ← add this
#    └── myapp/
#
# 2. In settings.py, make sure STATICFILES_DIRS includes the static/ folder:
#    STATICFILES_DIRS = [BASE_DIR / "static"]
#
# 3. Run collectstatic to copy it to STATIC_ROOT:
#    python manage.py collectstatic
#
# NOTE: Django's staticfiles serve files under the STATIC_URL prefix (/static/ by default).
# This means the file will be at /static/llms.txt, NOT /llms.txt.
# Use the view approach below to serve at the root path /llms.txt.

```

To serve at `/llms.txt` from your static files, configure Nginx with an `alias` directive pointing to the collected file in `STATIC_ROOT`. See the Nginx snippet in the deployment section below.

## Option 2: custom view with HttpResponse

The cleanest Django approach is a minimal view that returns the file content with the correct `content_type`. This works with any deployment target and serves the file at exactly `/llms.txt`.
myapp/views.py   
Copy

```
# myapp/views.py
from django.http import HttpResponse

LLMS_TXT_CONTENT = """# My Site

> One-sentence description of what my site or product does.

## Documentation

- [Getting Started](https://mysite.com/docs/start/): Install and configure in minutes.
- [API Reference](https://mysite.com/docs/api/): Full endpoint catalog with examples.

## Product

- [Overview](https://mysite.com/product/): Core features and capabilities.
- [Pricing](https://mysite.com/pricing/): Plans and billing details.

## Optional

- [Changelog](https://mysite.com/changelog/): Release history.
- [GitHub](https://github.com/my-org/my-repo): Source code.
"""

def llms_txt(request):
return HttpResponse(
LLMS_TXT_CONTENT,
content_type="text/plain; charset=utf-8",
headers={
"Cache-Control": "public, max-age=3600, stale-while-revalidate=86400",
},
)

```

Wire it up in your root `urls.py`:
myproject/urls.py   
Copy

```
# myproject/urls.py
from django.urls import path
from myapp.views import llms_txt

urlpatterns = [
# Serve at /llms.txt (root path)
path("llms.txt", llms_txt, name="llms-txt"),
# ... your other URL patterns
]

```

The `path("llms.txt", ...)` pattern (no leading slash) matches the URL `/llms.txt`. Django strips the leading slash before matching.

## Option 3: dynamic generation from models

For sites where documentation pages are stored in the database, generate the file content from a
queryset. Use Django's built-in `cache_page` decorator to avoid hitting the database on every request.
myapp/views.py, dynamic   
Copy

```
# myapp/views.py
# Dynamic generation from database models
from django.http import HttpResponse
from django.views.decorators.cache import cache_page
from myapp.models import DocumentPage

# Cache for 1 hour, regenerated automatically when cache expires
@cache_page(60 * 60)
def llms_txt(request):
docs = DocumentPage.objects.filter(
published=True,
include_in_llms=True,
).order_by("order").values("title", "slug", "summary")

lines = ["# My Site", "", "> Documentation and API reference.", "", "## Documentation", ""]

for doc in docs:
url = f"https://mysite.com/docs/{doc['slug']}/"
lines.append(f"- [{doc['title']}]({url}): {doc['summary']}")

lines += [
"",
"## Optional",
"",
"- [Changelog](https://mysite.com/changelog/): Release history.",
]

return HttpResponse(
"\n".join(lines),
content_type="text/plain; charset=utf-8",
)

```

Add a boolean field `include_in_llms` to your model to let editors control which pages
appear in the file. Run the [validator](/validator/) after any content migration to catch formatting regressions.

✓ Use the sitemap framework as a data source

Django's  django.contrib.sitemaps  already knows which pages exist and their priority.
You can instantiate a sitemap class to get a list of URLs and feed them into your  llms.txt  view, ensuring the two files stay in sync automatically.

## WSGI/ASGI deployment (Gunicorn, uWSGI, Nginx)

The Django view works with all common deployment setups. The view itself is synchronous and
lightweight, no async needed.
nginx.conf, proxy to Gunicorn   
Copy

```
# nginx.conf snippet, proxy to Gunicorn upstream
server {
listen 80;
server_name mysite.com;

# Serve llms.txt directly from Gunicorn (Django view)
location = /llms.txt {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_cache_valid 200 1h;
add_header Cache-Control "public, max-age=3600";
}

# Optionally serve a pre-built static copy faster:
# location = /llms.txt {
#     alias /srv/mysite/static_root/llms.txt;
#     add_header Content-Type "text/plain; charset=utf-8";
# }
}

```

- **Gunicorn**, works out of the box. The view returns a 200 with `text/plain`; no special configuration required. 
- **uWSGI**, same as Gunicorn. If you use uWSGI static file serving, you can map `/llms.txt` directly to a file in `STATIC_ROOT` with `static-map = /llms.txt=/path/to/llms.txt`. 
- **ASGI (Daphne, Uvicorn)**, the view is compatible as-is. Django wraps
synchronous views in a thread executor automatically. 
- **Nginx cache**, add `proxy_cache_valid 200 1h` 
in your Nginx location block to cache the response at the proxy layer and avoid hitting Django on
every crawler request.   
## Verify

After deploying, confirm the file is served correctly:
Verification   
Copy

```
curl -I https://mysite.com/llms.txt
# Expected:
# HTTP/2 200
# content-type: text/plain; charset=utf-8

curl https://mysite.com/llms.txt | head -5
# Should print the first lines of your file
```

## Related guides

- [How to create llms.txt](/how-to-create/), templates and checklist. 
- [llms.txt format reference](/llms-txt-format/), spec details. 
- [Express.js guide](/llms-txt-express/), Node.js equivalent approach. 
- [Laravel guide](/llms-txt-laravel/), PHP equivalent approach. 
- [Validator](/validator/) · [Generator](/generator/).        
## Sources

- [ llmstxt.org, official spec ](https://llmstxt.org/)
- [ Django docs, writing views ](https://docs.djangoproject.com/en/stable/topics/http/views/)
- [ Django docs, URL dispatcher ](https://docs.djangoproject.com/en/stable/topics/http/urls/)           
On this page

- [ Option 1: static file via STATICFILES_DIRS ](#static)
- [ Option 2: custom view with HttpResponse ](#view)
- [ Option 3: dynamic generation from models ](#dynamic)
- [ WSGI/ASGI deployment (Gunicorn, uWSGI, Nginx) ](#deployment)
- [ Verify ](#verify)
