Skip to content

Commit bcb014d

Browse files
lesnik512claude
andcommitted
docs: implementation plan for docs-site og:image rollout
Eight tasks: a pilot PR (modern-di), five more docs repos, the that-depends special case (existing docs/overrides), and finalizing the .github bundle. Shared override template + per-repo procedure in Global Constraints. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 16ffa5b commit bcb014d

1 file changed

Lines changed: 300 additions & 0 deletions

File tree

  • planning/changes/2026-06-30.02-docs-ogimage-rollout
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
# docs-site og:image rollout — implementation plan
2+
3+
> **For agentic workers:** REQUIRED SUB-SKILL: Use
4+
> superpowers:subagent-driven-development (recommended) or
5+
> superpowers:executing-plans to implement this plan task-by-task. Steps
6+
> use checkbox (`- [ ]`) syntax for tracking.
7+
8+
**Goal:** Each of the 7 docs-site repos emits `og:image`/`twitter:image` pointing
9+
at its self-hosted social card, via a MkDocs Material `custom_dir` + `main.html`
10+
override — shipped as one PR per repo.
11+
12+
**Spec:** [`design.md`](./design.md)
13+
14+
**Branch (this `.github` bundle):** `docs-ogimage`. **Per docs-repo branch:** `docs-ogimage`.
15+
16+
**Commit strategy:** one PR per docs repo; a final PR lands this planning bundle in `.github`.
17+
18+
## Global constraints
19+
20+
- **The 7 repos and their sites** (all default branch `main`):
21+
| repo | site_url | custom_dir |
22+
|------|----------|-----------|
23+
| `modern-di` | `https://modern-di.modern-python.org` | none (add `overrides`) |
24+
| `lite-bootstrap` | `https://lite-bootstrap.modern-python.org` | none (add `overrides`) |
25+
| `httpware` | `https://httpware.modern-python.org` | none (add `overrides`) |
26+
| `faststream-redis-timers` | `https://faststream-redis-timers.modern-python.org` | none (add `overrides`) |
27+
| `faststream-outbox` | `https://faststream-outbox.modern-python.org` | none (add `overrides`) |
28+
| `semvertag` | `https://semvertag.modern-python.org` | none (add `overrides`) |
29+
| `that-depends` | `https://that-depends.modern-python.org` | **existing** `docs/overrides` |
30+
31+
- **Card source** (this `.github` checkout, already on disk):
32+
`/Users/kevinsmith/src/pypi/modern-python/brand/projects/<repo>/social-card.png`
33+
- **Clone work dir:** `/Users/kevinsmith/src/pypi/.ogimage-clones/<repo>` (create the
34+
parent once; it is outside the `.github` repo).
35+
- **The override file is byte-identical for all 7 repos** — this exact content
36+
(it reads everything from `mkdocs.yml`, so nothing is per-repo):
37+
38+
```jinja
39+
{% extends "base.html" %}
40+
{% block extrahead %}
41+
{{ super() }}
42+
{% set base = config.site_url if config.site_url.endswith('/') else config.site_url ~ '/' %}
43+
{% set card = base ~ 'assets/social-card.png' %}
44+
{% set title = (page.title ~ ' · ' ~ config.site_name) if (page.title and not page.is_homepage) else config.site_name %}
45+
{% set description = page.meta.description if page.meta and page.meta.description else config.site_description %}
46+
<meta property="og:type" content="website">
47+
<meta property="og:site_name" content="{{ config.site_name }}">
48+
<meta property="og:title" content="{{ title }}">
49+
<meta property="og:description" content="{{ description }}">
50+
<meta property="og:url" content="{{ page.canonical_url }}">
51+
<meta property="og:image" content="{{ card }}">
52+
<meta property="og:image:type" content="image/png">
53+
<meta property="og:image:width" content="1280">
54+
<meta property="og:image:height" content="640">
55+
<meta name="twitter:card" content="summary_large_image">
56+
<meta name="twitter:title" content="{{ title }}">
57+
<meta name="twitter:description" content="{{ description }}">
58+
<meta name="twitter:image" content="{{ card }}">
59+
{% endblock %}
60+
```
61+
62+
- **Per-repo procedure** (Tasks 1–6 follow it exactly with their `<repo>` /
63+
`<site>` / `<override-dir>` = `overrides`; Task 7 differs — see it):
64+
65+
1. `mkdir -p /Users/kevinsmith/src/pypi/.ogimage-clones`
66+
2. `gh repo clone modern-python/<repo> /Users/kevinsmith/src/pypi/.ogimage-clones/<repo>` (skip if dir exists; then `git -C … pull --ff-only`)
67+
3. `cd` into it; `git checkout -b docs-ogimage`
68+
4. `mkdir -p docs/assets <override-dir>`
69+
5. Copy the card: `cp /Users/kevinsmith/src/pypi/modern-python/brand/projects/<repo>/social-card.png docs/assets/social-card.png`
70+
6. Write `<override-dir>/main.html` with the exact override content above.
71+
7. Add `custom_dir: <override-dir>` under `theme:` in `mkdocs.yml` **only if absent** (Tasks 1–6 add `custom_dir: overrides`; Task 7 already has it).
72+
8. **Verify** (see "Verification" below).
73+
9. `git add -A && git commit -m "docs: add social card og:image meta"`
74+
10. `git push -u origin docs-ogimage`
75+
11. `gh pr create --base main --head docs-ogimage --title "Add social card og:image" --body "<body>"` (body: one line on what + that the card is self-hosted at `<site>/assets/social-card.png`, plus the 🤖 line).
76+
12. Watch CI: `gh pr checks <n>` until non-pending.
77+
78+
- **Verification (the task's "test"):** from the repo clone:
79+
- Build the docs. Try, in order: (a) `uv sync` then `uv run mkdocs build -d /tmp/ogbuild-<repo>`; (b) if that repo isn't uv-managed or deps fail, `uvx --with 'mkdocs-material[imaging]' --with mkdocs mkdocs build -d /tmp/ogbuild-<repo>` (add `--with` for any plugin the build complains is missing). If the docs toolchain genuinely cannot be assembled, STOP and report — do not open the PR on an unverified build.
80+
- Assert the built homepage carries the card:
81+
`grep -F '<meta property="og:image" content="<site>/assets/social-card.png">' /tmp/ogbuild-<repo>/index.html`
82+
must match exactly one line.
83+
- Assert the asset shipped: `test -f /tmp/ogbuild-<repo>/assets/social-card.png`.
84+
- Spot-check one interior page's built HTML contains the same `og:image` line.
85+
86+
- Do not touch anything else in the docs repos. No README changes here (separate spec).
87+
88+
---
89+
90+
### Task 1: modern-di (pilot)
91+
92+
**Repo:** `modern-python/modern-di` · **site:** `https://modern-di.modern-python.org` · **override-dir:** `overrides` (new) · **custom_dir:** add `overrides`.
93+
94+
This is the pilot — execute the per-repo procedure end to end and confirm the
95+
pattern before the rest.
96+
97+
- [ ] **Step 1: Clone + branch**
98+
99+
```bash
100+
mkdir -p /Users/kevinsmith/src/pypi/.ogimage-clones
101+
gh repo clone modern-python/modern-di /Users/kevinsmith/src/pypi/.ogimage-clones/modern-di
102+
cd /Users/kevinsmith/src/pypi/.ogimage-clones/modern-di && git checkout -b docs-ogimage
103+
```
104+
105+
- [ ] **Step 2: Add card + override + custom_dir**
106+
107+
```bash
108+
mkdir -p docs/assets overrides
109+
cp /Users/kevinsmith/src/pypi/modern-python/brand/projects/modern-di/social-card.png docs/assets/social-card.png
110+
```
111+
Write `overrides/main.html` with the exact override content from Global
112+
Constraints. Then add `custom_dir: overrides` under `theme:` in `mkdocs.yml`
113+
(it currently has none). Example (match the file's existing indentation):
114+
115+
```yaml
116+
theme:
117+
name: material
118+
custom_dir: overrides
119+
# …existing theme keys unchanged…
120+
```
121+
122+
- [ ] **Step 3: Build + verify (the test)**
123+
124+
```bash
125+
uv sync && uv run mkdocs build -d /tmp/ogbuild-modern-di
126+
grep -F '<meta property="og:image" content="https://modern-di.modern-python.org/assets/social-card.png">' /tmp/ogbuild-modern-di/index.html
127+
test -f /tmp/ogbuild-modern-di/assets/social-card.png && echo CARD_OK
128+
```
129+
Expected: the grep prints exactly one line; `CARD_OK`. If `uv sync`/`uv run`
130+
fails, use the `uvx --with …` fallback from Global Constraints. If the build
131+
cannot be assembled at all, STOP and report BLOCKED.
132+
133+
- [ ] **Step 4: Commit + push + PR**
134+
135+
```bash
136+
git add -A && git commit -m "docs: add social card og:image meta"
137+
git push -u origin docs-ogimage
138+
gh pr create --base main --head docs-ogimage \
139+
--title "Add social card og:image" \
140+
--body $'Adds a self-hosted social card and the og:image/twitter:image meta (Material custom_dir override). Card served at https://modern-di.modern-python.org/assets/social-card.png.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)'
141+
```
142+
143+
- [ ] **Step 5: Watch CI**
144+
145+
`gh pr checks <n>` until non-pending; report the result.
146+
147+
---
148+
149+
### Task 2: lite-bootstrap
150+
151+
**Repo:** `modern-python/lite-bootstrap` · **site:** `https://lite-bootstrap.modern-python.org` · **override-dir:** `overrides` (new) · **custom_dir:** add `overrides`.
152+
153+
Follow the Global Constraints per-repo procedure with these values. Card source:
154+
`…/brand/projects/lite-bootstrap/social-card.png`.
155+
156+
- [ ] **Step 1: Clone + branch**`gh repo clone modern-python/lite-bootstrap …/.ogimage-clones/lite-bootstrap`; `git checkout -b docs-ogimage`.
157+
- [ ] **Step 2: Add card + override + custom_dir** — copy `lite-bootstrap` card to `docs/assets/social-card.png`; write `overrides/main.html` (exact Global-Constraints content); add `custom_dir: overrides` under `theme:` in `mkdocs.yml`.
158+
- [ ] **Step 3: Build + verify** — build to `/tmp/ogbuild-lite-bootstrap`; assert one match of
159+
`grep -F '<meta property="og:image" content="https://lite-bootstrap.modern-python.org/assets/social-card.png">' /tmp/ogbuild-lite-bootstrap/index.html` and `test -f /tmp/ogbuild-lite-bootstrap/assets/social-card.png`.
160+
- [ ] **Step 4: Commit + push + PR** — commit `docs: add social card og:image meta`; PR `--base main` with body naming `https://lite-bootstrap.modern-python.org/assets/social-card.png` + the 🤖 line.
161+
- [ ] **Step 5: Watch CI**`gh pr checks <n>` to completion.
162+
163+
---
164+
165+
### Task 3: httpware
166+
167+
**Repo:** `modern-python/httpware` · **site:** `https://httpware.modern-python.org` · **override-dir:** `overrides` (new) · **custom_dir:** add `overrides`.
168+
169+
- [ ] **Step 1: Clone + branch** — clone to `…/.ogimage-clones/httpware`; `git checkout -b docs-ogimage`.
170+
- [ ] **Step 2: Add card + override + custom_dir** — copy `httpware` card to `docs/assets/social-card.png`; write `overrides/main.html` (exact content); add `custom_dir: overrides` under `theme:`.
171+
- [ ] **Step 3: Build + verify** — build to `/tmp/ogbuild-httpware`; assert one match of
172+
`grep -F '<meta property="og:image" content="https://httpware.modern-python.org/assets/social-card.png">' /tmp/ogbuild-httpware/index.html` and the card file exists.
173+
- [ ] **Step 4: Commit + push + PR**`docs: add social card og:image meta`; PR body names `https://httpware.modern-python.org/assets/social-card.png` + 🤖 line.
174+
- [ ] **Step 5: Watch CI.**
175+
176+
---
177+
178+
### Task 4: faststream-redis-timers
179+
180+
**Repo:** `modern-python/faststream-redis-timers` · **site:** `https://faststream-redis-timers.modern-python.org` · **override-dir:** `overrides` (new) · **custom_dir:** add `overrides`.
181+
182+
- [ ] **Step 1: Clone + branch** — clone to `…/.ogimage-clones/faststream-redis-timers`; `git checkout -b docs-ogimage`.
183+
- [ ] **Step 2: Add card + override + custom_dir** — copy `faststream-redis-timers` card; write `overrides/main.html`; add `custom_dir: overrides`.
184+
- [ ] **Step 3: Build + verify** — build to `/tmp/ogbuild-faststream-redis-timers`; assert one match of
185+
`grep -F '<meta property="og:image" content="https://faststream-redis-timers.modern-python.org/assets/social-card.png">' /tmp/ogbuild-faststream-redis-timers/index.html` and the card exists.
186+
- [ ] **Step 4: Commit + push + PR**`docs: add social card og:image meta`; PR body names the redis-timers card URL + 🤖 line.
187+
- [ ] **Step 5: Watch CI.**
188+
189+
---
190+
191+
### Task 5: faststream-outbox
192+
193+
**Repo:** `modern-python/faststream-outbox` · **site:** `https://faststream-outbox.modern-python.org` · **override-dir:** `overrides` (new) · **custom_dir:** add `overrides`.
194+
195+
- [ ] **Step 1: Clone + branch** — clone to `…/.ogimage-clones/faststream-outbox`; `git checkout -b docs-ogimage`.
196+
- [ ] **Step 2: Add card + override + custom_dir** — copy `faststream-outbox` card; write `overrides/main.html`; add `custom_dir: overrides`.
197+
- [ ] **Step 3: Build + verify** — build to `/tmp/ogbuild-faststream-outbox`; assert one match of
198+
`grep -F '<meta property="og:image" content="https://faststream-outbox.modern-python.org/assets/social-card.png">' /tmp/ogbuild-faststream-outbox/index.html` and the card exists.
199+
- [ ] **Step 4: Commit + push + PR**`docs: add social card og:image meta`; PR body names the outbox card URL + 🤖 line.
200+
- [ ] **Step 5: Watch CI.**
201+
202+
---
203+
204+
### Task 6: semvertag
205+
206+
**Repo:** `modern-python/semvertag` · **site:** `https://semvertag.modern-python.org` · **override-dir:** `overrides` (new) · **custom_dir:** add `overrides`.
207+
208+
- [ ] **Step 1: Clone + branch** — clone to `…/.ogimage-clones/semvertag`; `git checkout -b docs-ogimage`.
209+
- [ ] **Step 2: Add card + override + custom_dir** — copy `semvertag` card; write `overrides/main.html`; add `custom_dir: overrides`.
210+
- [ ] **Step 3: Build + verify** — build to `/tmp/ogbuild-semvertag`; assert one match of
211+
`grep -F '<meta property="og:image" content="https://semvertag.modern-python.org/assets/social-card.png">' /tmp/ogbuild-semvertag/index.html` and the card exists.
212+
- [ ] **Step 4: Commit + push + PR**`docs: add social card og:image meta`; PR body names the semvertag card URL + 🤖 line.
213+
- [ ] **Step 5: Watch CI.**
214+
215+
---
216+
217+
### Task 7: that-depends (special — existing `docs/overrides`)
218+
219+
**Repo:** `modern-python/that-depends` · **site:** `https://that-depends.modern-python.org` · **override-dir:** `docs/overrides` (**exists**; `custom_dir: docs/overrides` already set — do NOT add `custom_dir`).
220+
221+
- [ ] **Step 1: Clone + branch** — clone to `…/.ogimage-clones/that-depends`; `git checkout -b docs-ogimage`.
222+
223+
- [ ] **Step 2: Inspect existing overrides**
224+
225+
```bash
226+
ls -la docs/overrides
227+
cat docs/overrides/main.html 2>/dev/null || echo "no main.html"
228+
```
229+
- **If `docs/overrides/main.html` does NOT exist:** create it with the exact
230+
override content from Global Constraints.
231+
- **If it EXISTS:** merge — keep its `{% extends … %}` and existing blocks, and
232+
ensure an `extrahead` block contains the OG/Twitter `<meta>` lines from the
233+
Global Constraints template (with `{{ super() }}` first). If it already has an
234+
`extrahead` block, append the meta lines inside it; if not, add the
235+
`{% block extrahead %}{{ super() }} … {% endblock %}` block. Do not remove
236+
anything it already does.
237+
238+
- [ ] **Step 3: Add card (no mkdocs change)**
239+
240+
```bash
241+
mkdir -p docs/assets
242+
cp /Users/kevinsmith/src/pypi/modern-python/brand/projects/that-depends/social-card.png docs/assets/social-card.png
243+
```
244+
Do not edit `mkdocs.yml``custom_dir: docs/overrides` is already set.
245+
246+
- [ ] **Step 4: Build + verify**
247+
248+
Build to `/tmp/ogbuild-that-depends` (uv first, else the `uvx --with` fallback).
249+
Assert exactly one match of
250+
`grep -F '<meta property="og:image" content="https://that-depends.modern-python.org/assets/social-card.png">' /tmp/ogbuild-that-depends/index.html`
251+
and `test -f /tmp/ogbuild-that-depends/assets/social-card.png`. Spot-check one
252+
interior page. If a pre-existing override already emitted an `og:image`, confirm
253+
there is now exactly ONE `og:image` line (grep count) — if two, the merge
254+
duplicated it; fix so only our line remains.
255+
256+
- [ ] **Step 5: Commit + push + PR**`docs: add social card og:image meta`; PR `--base main`, body names `https://that-depends.modern-python.org/assets/social-card.png` + 🤖 line.
257+
258+
- [ ] **Step 6: Watch CI.**
259+
260+
---
261+
262+
### Task 8: finalize the `.github` planning bundle
263+
264+
**Files (in `.github`, branch `docs-ogimage`):**
265+
- Modify: `planning/changes/2026-06-30.02-docs-ogimage-rollout/design.md` (summary)
266+
267+
- [ ] **Step 1: Finalize the summary**
268+
269+
In `design.md`, set `summary:` to the realized result, e.g.:
270+
`summary: docs-site og:image shipped — all 7 docs repos serve a self-hosted social card via a Material override; one PR per repo.`
271+
272+
- [ ] **Step 2: Verify planning**
273+
274+
```bash
275+
cd /Users/kevinsmith/src/pypi/modern-python && just check-planning
276+
```
277+
Expected: `planning: OK`.
278+
279+
- [ ] **Step 3: Commit + open the bundle PR**
280+
281+
```bash
282+
git add planning/changes/2026-06-30.02-docs-ogimage-rollout/design.md
283+
git commit -m "docs: finalize og:image rollout bundle summary"
284+
git push -u origin docs-ogimage
285+
gh pr create --base main --head docs-ogimage \
286+
--title "Plan + record: docs-site og:image rollout" \
287+
--body $'Planning bundle (design + plan) for wiring og:image into the 7 docs repos. The implementation shipped as one PR per docs repo (linked).\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)'
288+
```
289+
290+
---
291+
292+
## Notes for the executor
293+
294+
- Each docs-repo task is a self-contained PR; verify the build (or STOP) before
295+
opening it. The 7 repo PRs are independent — order does not matter, but do the
296+
`modern-di` pilot first to shake out the docs-build command.
297+
- These tasks run in cloned repos under `/Users/kevinsmith/src/pypi/.ogimage-clones/`,
298+
NOT in the `.github` repo. Only Task 8 touches `.github`.
299+
- If a repo's docs build needs a plugin the fallback `uvx` line doesn't include,
300+
add another `--with <plugin>` rather than skipping verification.

0 commit comments

Comments
 (0)