Skip to content
This repository was archived by the owner on Jun 8, 2026. It is now read-only.

Commit bc72326

Browse files
VdustRclaude
andauthored
docs: apply session retro improvements to magazine workflow (#4)
Learnings from 26-03 production session: CLAUDE.md: - Add name verification rule (never fabricate, always check Slack) - Add Co-Authored-By as primary AI stats metric (not labels) - Add WCAG AA contrast minimum requirement - Add Twemoji over native emoji rule - Add Claw'd mascot specification - Add post-publish announcement prompt magazine-collect.md: - Add Co-Authored-By commit query for AI stats - Add name verification requirement - Add Slack data preprocessing with jq (structured extraction of timestamp, user, first line, URLs — not raw truncation) magazine-design-reference.md (new): - WCAG contrast verification script (Python) - Twemoji CDN usage guide - Whitespace management strategies - Card design system (eyebrow tags, section-scoped styles) - CSS selector gotchas (descendant vs compound) - Overflow detection script - Pre-flight quality checklist Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f0e2eaf commit bc72326

3 files changed

Lines changed: 193 additions & 2 deletions

File tree

.claude/commands/magazine-collect.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,17 @@ For default channels and any user-provided Slack links:
9191
4. **Invoke `/agent-browser` skill** to browse links found within Slack messages (public URLs and Slack threads alike)
9292
5. If neither Slack MCP nor `/agent-browser` can access content, ask user to copy-paste the message text directly
9393

94-
### 2.4 Initial Processing
94+
### 2.4 Slack Data Preprocessing
95+
96+
Slack MCP returns large JSON payloads (100K-280K chars) that exceed subagent context limits. **Always preprocess with jq before dispatching to subagents**:
97+
98+
```bash
99+
cat {slack-output-file} | jq -r '.[0].text' | jq -r '.messages[] | select(.ts | tonumber >= {start_ts}) | "[\(.ts)] \(.user // "bot"): \(.text | split("\n")[0] | .[0:150])\n URLs: \([.text | scan("https?://[^>|\\s]+")] | join(" "))"'
100+
```
101+
102+
This extracts timestamp, user, first line (topic sentence), and all URLs — structured enough for subagents to identify topics without reading full JSON. URLs are the most important signal in sharing channels.
103+
104+
### 2.5 Initial Processing
95105
For each source, extract:
96106
- What it is (release, tool, article, discussion)
97107
- Core claim or announcement
@@ -135,8 +145,16 @@ gh issue list --repo chatbotgang/{repo} --state all --limit 30 --json title,numb
135145

136146
# Recent commits
137147
gh api repos/chatbotgang/{repo}/commits --jq '.[0:30] | .[] | {sha: .sha[0:7], message: .commit.message, author: .commit.author.name, date: .commit.author.date}'
148+
149+
# AI-assisted development rate (Co-Authored-By, NOT labels)
150+
gh api "repos/chatbotgang/{repo}/commits?per_page=100&since={start}&until={end}" \
151+
--jq '. as $all | ($all | length) as $total | ($all | map(select(.commit.message | test("Co-[Aa]uthored-[Bb]y.*[Cc]laude"))) | length) as $cc | "\($cc)/\($total) co-authored (\(if $total > 0 then ($cc * 100 / $total) else 0 end)%)"'
138152
```
139153

154+
**IMPORTANT**: Use `Co-Authored-By` commit metadata as the primary AI-assisted development metric, not `claude-code` labels. Labels are repo-specific and many repos don't use them. Paginate with `page=2` if the first page returns exactly 100 results.
155+
156+
**IMPORTANT**: All person names (skill authors, contributors) must be verified from Slack profiles (`mcp__slack__slack_get_user_profile`) or GitHub. Never guess or fabricate names.
157+
140158
### 3.2 Insight Filtering
141159

142160
**INCLUDE** (Technical Focus):
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Magazine Design Reference
2+
3+
Reference document for `/magazine-edit`. Contains design standards, validation scripts, and patterns learned from session retrospectives.
4+
5+
## WCAG Color Contrast Verification
6+
7+
### Requirements
8+
9+
| Level | Normal text (<18pt) | Large text (≥18pt or ≥14pt bold) |
10+
|-------|--------------------|---------------------------------|
11+
| AA (minimum) | 4.5:1 | 3.0:1 |
12+
13+
### Python Verification Script
14+
15+
Run this before finalizing any color pair on dark backgrounds:
16+
17+
```python
18+
import sys
19+
def lum(h):
20+
h=h.lstrip('#'); r,g,b=[int(h[i:i+2],16)/255 for i in(0,2,4)]
21+
f=lambda c:c/12.92 if c<=0.04045 else((c+.055)/1.055)**2.4
22+
return 0.2126*f(r)+0.7152*f(g)+0.0722*f(b)
23+
def contrast(a,b):
24+
l1,l2=lum(a),lum(b); mx,mn=max(l1,l2),min(l1,l2)
25+
return round((mx+.05)/(mn+.05),2)
26+
# Usage: python3 -c "..." '#ffffff' '#0f0d2e'
27+
fg,bg=sys.argv[1],sys.argv[2]
28+
r=contrast(fg,bg)
29+
print(f'{fg} on {bg}: {r}:1 {"PASS" if r>=4.5 else "FAIL (need 4.5:1)"}')
30+
```
31+
32+
### Known Borderline Colors (large text ONLY)
33+
34+
- `#e63946` on `#faf9f6` → 3.96:1 (large text only)
35+
- `#2ea043` on `#f6f8fa` → 3.17:1 (large text only)
36+
- `#7c3aed` on `#0d1b2a` → 3.05:1 (large text only)
37+
38+
## Emoji: Use Twemoji Images, Not Native Emoji
39+
40+
Native emoji render differently across platforms. Use Twemoji SVG images instead.
41+
42+
### CDN URL Pattern (pinned to last stable release)
43+
44+
```
45+
https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/svg/{CODEPOINT}.svg
46+
```
47+
48+
### HTML Usage
49+
50+
```html
51+
<img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/svg/1f680.svg"
52+
alt="rocket" style="width:1.2em;height:1.2em;vertical-align:-0.15em;display:inline-block;">
53+
```
54+
55+
### Codepoint Examples
56+
57+
| Emoji | Codepoint | Filename |
58+
|-------|-----------|----------|
59+
| 🚀 | U+1F680 | `1f680.svg` |
60+
|| U+26A1 | `26a1.svg` |
61+
| 🔥 | U+1F525 | `1f525.svg` |
62+
|| U+2B50 | `2b50.svg` |
63+
64+
Use manual `<img>` tags (not `twemoji.parse()`) for PDF reliability.
65+
66+
## Whitespace Management
67+
68+
### Dense Pages — Bottom Whitespace
69+
70+
| Whitespace | Strategy |
71+
|------------|----------|
72+
| < 15mm | Acceptable. Use `<div style="flex:1"></div>` spacer if desired |
73+
| 15–35mm | Add decorative rule or ornament |
74+
| > 35mm | Content problem — add more text, increase font size, or merge pages |
75+
76+
### Flex Column Pattern (recommended for all dense pages)
77+
78+
```css
79+
.page.dense {
80+
display: flex;
81+
flex-direction: column;
82+
padding: 14mm 18mm;
83+
}
84+
/* Content grids should NOT stretch cards */
85+
.grid-2, .grid-3 {
86+
align-content: start; /* prevents card stretching */
87+
}
88+
```
89+
90+
### Overflow Detection Script
91+
92+
Add to HTML `<script>` during development — shows red overlay on overflowing pages:
93+
94+
```javascript
95+
if (window.matchMedia('not print').matches) {
96+
document.querySelectorAll('.page').forEach((p, i) => {
97+
if (p.scrollHeight > p.clientHeight + 2) {
98+
p.style.outline = '3px solid red';
99+
const l = document.createElement('div');
100+
l.style.cssText = 'position:absolute;top:0;left:0;background:red;color:white;font:9px monospace;padding:2px 4px;z-index:9999';
101+
l.textContent = `OVERFLOW +${p.scrollHeight - p.clientHeight}px (p${i+1})`;
102+
p.style.position = 'relative'; p.appendChild(l);
103+
}
104+
});
105+
}
106+
```
107+
108+
## Card Design System
109+
110+
### Tag/Badge Placement: Eyebrow (Above Title)
111+
112+
Tags go ABOVE the title (eyebrow position), not inline or below:
113+
114+
```html
115+
<div class="card">
116+
<div class="card-eyebrow">
117+
<span class="tag tag-release">v6</span>
118+
</div>
119+
<h3>Astro 6</h3>
120+
<p>Dev server matches production...</p>
121+
</div>
122+
```
123+
124+
### Section-Scoped Card Styles
125+
126+
| Feature | Dark sections (eco/sec) | Light sections (tools/proj) |
127+
|---------|------------------------|----------------------------|
128+
| Card bg | Slightly lighter than page (#1a1d2e vs #0f1119) | White with shadow |
129+
| Border | Left 3px accent color | Full border thin gray |
130+
| Code bg | Dark (#252840) | Light (#f0f4f8) |
131+
132+
### Visual Monotony Prevention
133+
134+
1. No 3+ consecutive dense pages without a breather
135+
2. Each dense page should have at least 1 hero card (spanning full width)
136+
3. Adjacent pages should use different grid structures (2-col → asymmetric → 3-col)
137+
4. Alternate accent border direction between pages (left → top)
138+
139+
## CSS Selector Gotchas
140+
141+
### Same-Element vs Descendant Selectors
142+
143+
```css
144+
/* WRONG: descendant selector — won't match <div class="page s-eco dense"> */
145+
.s-eco .dense { padding: 14mm 18mm; }
146+
147+
/* RIGHT: same-element compound selector */
148+
.s-eco.dense { padding: 14mm 18mm; }
149+
```
150+
151+
Always verify CSS selectors match the actual HTML class structure.
152+
153+
## Verification Workflow
154+
155+
### Pre-Flight Checklist (before declaring "done")
156+
157+
1. **Export PDF** and read every page via `Read` tool — browser preview lies
158+
2. **WCAG contrast**: run Python script on all text-on-dark-background color pairs
159+
3. **Overflow**: check no content is clipped at page bottom edges
160+
4. **Whitespace**: no page has > 35mm unused bottom space
161+
5. **Selector audit**: grep for `.s-{section} .{class}` patterns — should be `.s-{section}.{class}` for same-element
162+
6. **Font loading**: verify custom fonts render (not fallback to system fonts)
163+
7. **Cross-page consistency**: all cards within same section use identical styles
164+
8. **Names**: all person names verified from Slack/GitHub, never fabricated

CLAUDE.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,22 @@ Use `/magazine` to run both in sequence within one session.
7575
- **Avoid product feature descriptions** — this is a tech digest, not a product changelog
7676
- **No filler content** — if there's no insight, don't write it
7777
- **Skip statistics** — no PR counts, contributor counts unless meaningful
78+
- **Never fabricate names** — all person names must be verified from Slack profiles (`mcp__slack__slack_get_user_profile`) or GitHub. If unknown, ask the user. Never guess.
79+
- **AI-assisted development stats** — use `Co-Authored-By` commit metadata as the primary metric, not labels (labels are repo-specific and inconsistent)
7880

7981
### Quality Standards
8082

8183
- All content in **American English**
82-
- Print-friendly layout (check for blank pages from page breaks)
84+
- **PDF is the source of truth** — always verify layout in exported PDF, not browser preview (browser has margins/gaps that don't appear in print)
85+
- **WCAG AA contrast minimum** — all text must meet 4.5:1 contrast ratio (normal text) or 3:1 (large text ≥18pt). Calculate and verify, don't eyeball.
86+
- **No native emoji** — use image-based emoji (Twemoji CDN or local assets) for cross-platform consistency
8387
- Accessible HTML structure
8488
- Distinctive typography (avoid generic fonts)
89+
- **Claw'd mascot** — use inline SVG pixel art (salmon #cc8b6e body, black eyes, blocky legs). Each appearance should have a different expression to reduce repetitiveness.
90+
91+
### After Publishing
92+
93+
After merging a new issue, always suggest: "Want to announce this issue? Run `/magazine-announce`"
8594

8695
## Language
8796

0 commit comments

Comments
 (0)