diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e889c6..3254956 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,45 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- **Documentation pages now carry Open Graph and Twitter card tags.** A link to + any page pasted into Slack, Reddit or a chat rendered as a bare url, because + the theme emits no such tags and nothing supplied them. Each page now declares + its title, description and canonical url. The card is the text-only `summary` + kind: Zensical ships no social-card generation and the documentation carries + no image asset. + +- **The documentation site is verified with Google Search Console.** Every + generated page carries the ownership tag for the property, so the maintainers + can finally see which pages are indexed and which searches reach them — + previously a blind spot. Nothing about the library itself changes. Removing + the tag silently un-verifies the property. + +### Changed + +- **Every link in the PyPI sidebar now goes somewhere different.** `Homepage` + and `Repository` both pointed at the GitHub repository, so a reader arriving + on the package page got two identically-targeted links and no obvious route + to the documentation. `Homepage` now points at the documentation site and the + redundant `Documentation` entry is gone; the repository stays reachable + through `Repository`. + +- **Page titles now describe the page to someone who has not arrived yet.** + Titles were written for a reader already inside the site — `Comparison`, + `httpx`, `Timeout` — which tells someone meeting the project in a search + result or a pasted link nothing about what they are looking at. A + `seo_titles` map in `zensical.toml` gives each page a self-describing title; + a page left out of the map keeps the theme default. + +### Fixed + +- **The documentation landing page was titled `interlock - interlock`.** + Zensical does not populate `page.is_homepage`, so the theme fell through to + the generic "page title - site name" branch and duplicated the project name + on the one page that is linked and ranked the most, leaving it without a + single word describing what the project is. + ## [2.6.0] - 2026-08-12 ### Added diff --git a/overrides/main.html b/overrides/main.html index e0a1aa4..4c9c81b 100644 --- a/overrides/main.html +++ b/overrides/main.html @@ -1,5 +1,43 @@ {% extends "base.html" %} +{# Page titles are written for someone already inside the site — "Comparison", + "httpx", "Timeout" — which says nothing to someone meeting the project in a + search result or a pasted link. `seo_titles` in zensical.toml maps a page url + to the title that page should carry outside the site. It also covers the + landing page: Zensical never populates `page.is_homepage`, so the theme falls + through to "{{ page.title }} - {{ site_name }}" and titles it + "interlock - interlock". A page absent from the map keeps the theme default. #} +{% set seo_titles = config.extra.seo_titles | d({}) %} + +{% block htmltitle %} + {% if page.url in seo_titles %} + {{ seo_titles[page.url] }} · {{ config.site_name }} + {% else %} + {{ super() }} + {% endif %} +{% endblock %} + +{# Without these a link to the docs pasted into Slack, Reddit or a chat renders + as a bare url. Zensical ships no social-card generation and the docs carry no + image asset, so this is the text-only `summary` card, not a large one. #} +{% block extrahead %} + {# Proves ownership of https://bagowix.github.io/interlock/ to Google Search + Console. Public by design, not a secret. Google only reads it from the + property root, but emitting it everywhere costs nothing and does not depend + on detecting the landing page — the very thing Zensical gets wrong above. + Removing this tag silently un-verifies the property. #} + + {% set og_title = seo_titles[page.url] if page.url in seo_titles else (page.title | striptags) %} + + + + + + + + +{% endblock %} + {% block scripts %} {{ super() }} diff --git a/pyproject.toml b/pyproject.toml index 20cde5b..e886830 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,8 +39,7 @@ requests = ["requests>=2.31.0"] aiohttp = ["aiohttp>=3.12.0"] [project.urls] -Homepage = "https://github.com/bagowix/interlock" -Documentation = "https://bagowix.github.io/interlock/" +Homepage = "https://bagowix.github.io/interlock/" Repository = "https://github.com/bagowix/interlock" Changelog = "https://github.com/bagowix/interlock/blob/main/CHANGELOG.md" Issues = "https://github.com/bagowix/interlock/issues" diff --git a/zensical.toml b/zensical.toml index 7be33b5..23b7085 100644 --- a/zensical.toml +++ b/zensical.toml @@ -67,3 +67,35 @@ custom_fences = [ alternate_style = true [project.markdown_extensions.pymdownx.tasklist] custom_checkbox = true + +# Titles for readers who have not arrived yet: search results, pasted links, +# social cards. Keyed by page url ("" is the landing page), consumed by the +# htmltitle and extrahead blocks in overrides/main.html, which append the site +# name. Keep each under ~60 characters or search engines truncate it. A page +# left out of this map keeps the theme's " - interlock". +[project.extra.seo_titles] +"" = "A modern circuit breaker for Python" +"getting-started/" = "Getting started with a Python circuit breaker" +"comparison/" = "Python circuit breaker libraries compared" +"migration/" = "Migrating from pybreaker or circuitbreaker" +"demo/" = "A runnable Python circuit breaker demo" +"correctness/" = "How the circuit breaker is tested for correctness" +"reference/" = "Python circuit breaker API reference" +"guides/configuration/" = "Configuring a Python circuit breaker" +"guides/states/" = "Circuit breaker states and manual control" +"guides/failure-classification/" = "Which failures should trip a circuit breaker" +"guides/observability/" = "Circuit breaker metrics and OpenTelemetry" +"guides/timeout/" = "Timeouts with a Python circuit breaker" +"guides/retries/" = "Retries and circuit breakers in Python" +"guides/pipeline/" = "Resilience pipeline: timeout, retry, bulkhead" +"integrations/" = "Circuit breaker integrations for Python clients" +"integrations/fastapi/" = "FastAPI circuit breaker with 503 and Retry-After" +"integrations/litestar/" = "Litestar circuit breaker with 503 and Retry-After" +"integrations/httpx/" = "httpx circuit breaker transport" +"integrations/httpx2/" = "httpx2 circuit breaker transport" +"integrations/aiohttp/" = "aiohttp circuit breaker middleware" +"integrations/requests/" = "requests circuit breaker adapter" +"integrations/redis/" = "Distributed circuit breaker state in Redis" +"integrations/tenacity/" = "tenacity retries with a circuit breaker" +"integrations/llm/" = "Circuit breaker for OpenAI and Anthropic calls" +"integrations/frameworks/" = "Circuit breaker for Flask and Django"