SEO : robots.txt + sitemap.xml + canonical/hreflang/JSON-LD sur le site de doc
- src/api/main.py : routes /robots.txt (Disallow /api/, /docs) et
/sitemap.xml (/, /contact, /stats)
- web/{index,contact,stats}.html : canonical, hreflang fr-ca, og:site_name,
og:locale, JSON-LD WebSite + Organization + BreadcrumbList
- la negociation de contenu existante est conservee : les clients API
recoivent toujours le statut JSON a la racine
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4 changed files +50 −1
modified
src/api/main.py
+30 −1
@@ -20,7 +20,7 @@ from typing import Any | ||
| 20 | 20 | |
| 21 | 21 | from fastapi import FastAPI, Request |
| 22 | 22 | from fastapi.middleware.cors import CORSMiddleware |
| 23 | −from fastapi.responses import FileResponse | |
| 23 | +from fastapi.responses import FileResponse, PlainTextResponse, Response | |
| 24 | 24 | from fastapi.staticfiles import StaticFiles |
| 25 | 25 | |
| 26 | 26 | from src.api import reqstats |
@@ -166,6 +166,35 @@ def stats_page() -> FileResponse: | ||
| 166 | 166 | return FileResponse(WEB_STATS, media_type="text/html") |
| 167 | 167 | |
| 168 | 168 | |
| 169 | +# --- Référencement du site de documentation (www.api-ka.com) ------------------- | |
| 170 | + | |
| 171 | +BASE_URL = "https://www.api-ka.com" | |
| 172 | + | |
| 173 | + | |
| 174 | +@app.get("/robots.txt", include_in_schema=False) | |
| 175 | +def robots_txt() -> PlainTextResponse: | |
| 176 | + return PlainTextResponse( | |
| 177 | + "User-agent: *\n" | |
| 178 | + "Allow: /\n" | |
| 179 | + "Disallow: /api/\n" | |
| 180 | + "Disallow: /docs\n" | |
| 181 | + "Disallow: /openapi.json\n" | |
| 182 | + f"\nSitemap: {BASE_URL}/sitemap.xml\n") | |
| 183 | + | |
| 184 | + | |
| 185 | +@app.get("/sitemap.xml", include_in_schema=False) | |
| 186 | +def sitemap_xml() -> Response: | |
| 187 | + urls = "".join( | |
| 188 | + f"<url><loc>{BASE_URL}{p}</loc></url>" | |
| 189 | + for p in ("/", "/contact", "/stats")) | |
| 190 | + return Response( | |
| 191 | + '<?xml version="1.0" encoding="UTF-8"?>\n' | |
| 192 | + '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' | |
| 193 | + + urls + "</urlset>", | |
| 194 | + media_type="application/xml", | |
| 195 | + headers={"Cache-Control": "public, max-age=3600"}) | |
| 196 | + | |
| 197 | + | |
| 169 | 198 | # Assets de marque Groupe KA servis à la racine du domaine (voir src/api/web/) : |
| 170 | 199 | # favicon SVG, icône iOS et image Open Graph 1200x630 referencée par les meta og:image. |
| 171 | 200 | @app.get("/favicon.svg", include_in_schema=False) |
modified
src/api/web/contact.html
+6 −0
@@ -67,6 +67,12 @@ section{padding:64px 0} | ||
| 67 | 67 | .account p{margin:0;max-width:56ch;color:var(--ink-2);font-size:14.5px} |
| 68 | 68 | .account b{color:var(--ink)} |
| 69 | 69 | </style> |
| 70 | +<link rel="canonical" href="https://www.api-ka.com/contact"> | |
| 71 | +<link rel="alternate" hreflang="fr-ca" href="https://www.api-ka.com/contact"> | |
| 72 | +<link rel="alternate" hreflang="x-default" href="https://www.api-ka.com/contact"> | |
| 73 | +<meta property="og:site_name" content="API-Ka"> | |
| 74 | +<meta property="og:locale" content="fr_CA"> | |
| 75 | +<script type="application/ld+json">{"@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{"@type": "ListItem", "position": 1, "name": "Accueil", "item": "https://www.api-ka.com/"}, {"@type": "ListItem", "position": 2, "name": "Contact", "item": "https://www.api-ka.com/contact"}]}</script> | |
| 70 | 76 | </head> |
| 71 | 77 | <body> |
| 72 | 78 | |
modified
src/api/web/index.html
+8 −0
@@ -165,6 +165,14 @@ pre{margin:0;background:var(--ink);color:var(--paper);padding:16px 18px;overflow | ||
| 165 | 165 | .reveal.in{opacity:1;transform:none} |
| 166 | 166 | @media(prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}.hero-tile{transform:none}.pulse.ok{animation:none}} |
| 167 | 167 | </style> |
| 168 | +<link rel="canonical" href="https://www.api-ka.com/"> | |
| 169 | +<link rel="alternate" hreflang="fr-ca" href="https://www.api-ka.com/"> | |
| 170 | +<link rel="alternate" hreflang="x-default" href="https://www.api-ka.com/"> | |
| 171 | +<meta property="og:site_name" content="API-Ka"> | |
| 172 | +<meta property="og:locale" content="fr_CA"> | |
| 173 | +<script type="application/ld+json">{"@context": "https://schema.org", "@type": "WebSite", "name": "API-Ka", "url": "https://www.api-ka.com/", "description": "API publique des données quotidiennes de l'écosystème Groupe KA (Québec)", "inLanguage": "fr-CA"}</script> | |
| 174 | +<script type="application/ld+json">{"@context": "https://schema.org", "@type": "Organization", "name": "API-Ka (Groupe KA)", "url": "https://www.api-ka.com/", "logo": "https://www.api-ka.com/og.png"}</script> | |
| 175 | +<script type="application/ld+json">{"@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{"@type": "ListItem", "position": 1, "name": "Accueil", "item": "https://www.api-ka.com/"}]}</script> | |
| 168 | 176 | </head> |
| 169 | 177 | <body> |
| 170 | 178 | |
modified
src/api/web/stats.html
+6 −0
@@ -176,6 +176,12 @@ table.dt tbody tr:nth-child(even){background:var(--surface-2)} | ||
| 176 | 176 | @media(max-width:767px){section{padding:32px 0}.hero-s{padding:40px 0 32px}} |
| 177 | 177 | @media(prefers-reduced-motion:reduce){*{transition:none!important}} |
| 178 | 178 | </style> |
| 179 | +<link rel="canonical" href="https://www.api-ka.com/stats"> | |
| 180 | +<link rel="alternate" hreflang="fr-ca" href="https://www.api-ka.com/stats"> | |
| 181 | +<link rel="alternate" hreflang="x-default" href="https://www.api-ka.com/stats"> | |
| 182 | +<meta property="og:site_name" content="API-Ka"> | |
| 183 | +<meta property="og:locale" content="fr_CA"> | |
| 184 | +<script type="application/ld+json">{"@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{"@type": "ListItem", "position": 1, "name": "Accueil", "item": "https://www.api-ka.com/"}, {"@type": "ListItem", "position": 2, "name": "Statistiques", "item": "https://www.api-ka.com/stats"}]}</script> | |
| 179 | 185 | </head> |
| 180 | 186 | <body> |
| 181 | 187 | |
| 182 | 188 | |