Improve Lighthouse Agentic Browsing readiness (#8)
## Summary - Add `robots.txt`, `sitemap.xml`, and `llms.txt` endpoints so crawlers and AI agents can discover public pages - Fix accessibility tree issues: contact form labels, semantic nav/profile dropdown buttons, cookie consent dialog ARIA, and dead `href="#"` links - Reduce layout shift on homepage/contact via hero min-heights, trusted-by marquee sizing, and fixed cookie banner - Add regression tests and `docs/agentic-browsing.md` for Lighthouse agentic-browsing audits Closes #5. Also addresses overlap with #3 (sitemap + robots.txt). ## Test plan - [x] `python manage.py test public.tests` (14 tests pass) - [ ] Verify `GET /robots.txt`, `/sitemap.xml`, `/llms.txt` return 200 in staging/prod - [ ] Confirm contact form labels visible and submittable on `/contact` - [ ] Run Lighthouse `--only-categories=agentic-browsing` on homepage and contact page - [ ] Smoke test mobile nav dropdown and cookie consent banner Reviewed-on: #8
This commit was merged in pull request #8.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
"""Machine-readable site discovery endpoints for crawlers and AI agents."""
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
|
||||
# Public marketing pages included in sitemap and llms.txt.
|
||||
PUBLIC_PAGE_ENTRIES = (
|
||||
("public_index", "Home", "weekly", "1.0"),
|
||||
("forward_deployed", "Forward-Deployed AI", "monthly", "0.9"),
|
||||
("bot", "AI Agents", "monthly", "0.9"),
|
||||
("ml_model", "ML Models", "monthly", "0.8"),
|
||||
("chat", "Secure AI Chat", "monthly", "0.8"),
|
||||
("ai_sensor", "AI Sensor Algorithms", "monthly", "0.7"),
|
||||
("ai_education", "AI Education", "monthly", "0.7"),
|
||||
("computers", "Computer Builds", "monthly", "0.7"),
|
||||
("file_hosting", "File Hosting", "monthly", "0.7"),
|
||||
("web_design", "Web Design and Hosting", "monthly", "0.8"),
|
||||
("contact", "Contact", "monthly", "0.9"),
|
||||
("terms_of_service", "Terms of Service and Privacy", "yearly", "0.3"),
|
||||
)
|
||||
|
||||
|
||||
def _absolute_url(request, url_name):
|
||||
return request.build_absolute_uri(reverse(url_name))
|
||||
|
||||
|
||||
def robots_txt(request):
|
||||
sitemap_url = _absolute_url(request, "sitemap_xml")
|
||||
content = render_to_string(
|
||||
"public/robots.txt",
|
||||
{"sitemap_url": sitemap_url},
|
||||
)
|
||||
return HttpResponse(content, content_type="text/plain; charset=utf-8")
|
||||
|
||||
|
||||
def sitemap_xml(request):
|
||||
pages = [
|
||||
{
|
||||
"loc": _absolute_url(request, url_name),
|
||||
"changefreq": changefreq,
|
||||
"priority": priority,
|
||||
}
|
||||
for url_name, _title, changefreq, priority in PUBLIC_PAGE_ENTRIES
|
||||
]
|
||||
content = render_to_string("public/sitemap.xml", {"pages": pages})
|
||||
return HttpResponse(content, content_type="application/xml; charset=utf-8")
|
||||
|
||||
|
||||
def llms_txt(request):
|
||||
pages = [
|
||||
{
|
||||
"title": title,
|
||||
"url": _absolute_url(request, url_name),
|
||||
}
|
||||
for url_name, title, _changefreq, _priority in PUBLIC_PAGE_ENTRIES
|
||||
]
|
||||
content = render_to_string(
|
||||
"public/llms.txt",
|
||||
{
|
||||
"site_url": request.build_absolute_uri("/"),
|
||||
"contact_url": _absolute_url(request, "contact"),
|
||||
"pages": pages,
|
||||
},
|
||||
)
|
||||
return HttpResponse(content, content_type="text/plain; charset=utf-8")
|
||||
Reference in New Issue
Block a user