For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Change the homepage feed from the latest 5 posts to the latest 5 distinct publishing dates with posts, rendered as a grouped left-rail timeline.
Architecture: Keep the change local to index.html. Add one small verification script in scripts/verify_homepage_day_timeline.py that proves both the grouping logic and the built homepage output, then replace the flat feed markup and styles in the homepage with grouped Liquid and timeline CSS. No archive work, no shared include extraction, and no JavaScript rendering changes in this pass.
Tech Stack: Jekyll, Liquid, HTML, CSS, Python 3 stdlib
scripts/verify_homepage_day_timeline.py
Responsibility: verify the built homepage renders exactly 5 day groups, includes all posts from those 5 days, excludes the 6th day, and keeps a small fixture test for multi-post grouping behavior.index.html
Responsibility: replace the flat homepage feed with grouped Liquid markup and page-scoped timeline CSS.Files:
Step 1: Add the verifier script
#!/usr/bin/env python3
from __future__ import annotations
from pathlib import Path
import re
import sys
POST_PATTERN = re.compile(r"(\d{4})-(\d{2})-(\d{2})-(.+)\.md$")
GROUP_PATTERN = re.compile(r'class="[^"]*\bfeed-day-group\b[^"]*"')
LABEL_PATTERN = re.compile(r'<div class="feed-day-label">\s*([^<]+?)\s*</div>')
def slug_to_url(name: str) -> tuple[str, str]:
match = POST_PATTERN.match(name)
if not match:
raise ValueError(f"Unsupported post filename: {name}")
year, month, day, slug = match.groups()
return f"{year}-{month}-{day}", f"/blog/{year}/{month}/{day}/{slug}/"
def group_posts_by_day(rows: list[tuple[str, str]], max_days: int = 5) -> list[dict[str, list[str] | str]]:
groups: list[dict[str, list[str] | str]] = []
current_day = None
for day, url in rows:
if day != current_day:
if len(groups) == max_days:
break
groups.append({"day": day, "urls": []})
current_day = day
groups[-1]["urls"].append(url)
return groups
def fixture_self_test() -> None:
rows = [
("2026-04-13", "/blog/2026/04/13/a/"),
("2026-04-12", "/blog/2026/04/12/b/"),
("2026-04-12", "/blog/2026/04/12/c/"),
("2026-04-11", "/blog/2026/04/11/d/"),
("2026-04-10", "/blog/2026/04/10/e/"),
("2026-04-09", "/blog/2026/04/09/f/"),
("2026-04-08", "/blog/2026/04/08/g/"),
]
groups = group_posts_by_day(rows, max_days=5)
assert [group["day"] for group in groups] == [
"2026-04-13",
"2026-04-12",
"2026-04-11",
"2026-04-10",
"2026-04-09",
]
assert groups[1]["urls"] == [
"/blog/2026/04/12/b/",
"/blog/2026/04/12/c/",
]
assert all(group["day"] != "2026-04-08" for group in groups)
def expected_homepage_groups(posts_dir: Path) -> list[dict[str, list[str] | str]]:
rows: list[tuple[str, str]] = []
for path in sorted(posts_dir.iterdir(), reverse=True):
if not path.name.endswith(".md"):
continue
day, url = slug_to_url(path.name)
rows.append((day, url))
return group_posts_by_day(rows, max_days=5)
def day_label(day: str) -> str:
year, month, date = day.split("-")
month_name = {
"01": "JAN",
"02": "FEB",
"03": "MAR",
"04": "APR",
"05": "MAY",
"06": "JUN",
"07": "JUL",
"08": "AUG",
"09": "SEP",
"10": "OCT",
"11": "NOV",
"12": "DEC",
}[month]
return f"{month_name} {date}"
def verify_rendered_homepage(site_index: Path, groups: list[dict[str, list[str] | str]]) -> None:
html = site_index.read_text(encoding="utf-8")
group_count = len(GROUP_PATTERN.findall(html))
if group_count != 5:
raise AssertionError(f"Expected 5 timeline groups, found {group_count}")
labels = LABEL_PATTERN.findall(html)
expected_labels = [day_label(group["day"]) for group in groups]
if labels[:5] != expected_labels:
raise AssertionError(f"Expected labels {expected_labels}, found {labels[:5]}")
for group in groups:
for url in group["urls"]:
if url not in html:
raise AssertionError(f"Missing expected post URL in homepage output: {url}")
all_expected_urls = [url for group in groups for url in group["urls"]]
outside_group_urls = []
posts_dir = Path("_posts")
for path in sorted(posts_dir.iterdir(), reverse=True):
if not path.name.endswith(".md"):
continue
_, url = slug_to_url(path.name)
if url in all_expected_urls:
continue
outside_group_urls.append(url)
if outside_group_urls and outside_group_urls[0] in html:
raise AssertionError(f"Found a post from the 6th day or later in homepage output: {outside_group_urls[0]}")
def main() -> int:
fixture_self_test()
groups = expected_homepage_groups(Path("_posts"))
verify_rendered_homepage(Path("_site/index.html"), groups)
print(f"Verified homepage timeline for {len(groups)} distinct publish dates.")
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except AssertionError as error:
print(f"FAIL: {error}", file=sys.stderr)
raise SystemExit(1)
Run:
bundle exec jekyll build
python3 scripts/verify_homepage_day_timeline.py
Expected:
FAIL: Expected 5 timeline groups, found 0
git add scripts/verify_homepage_day_timeline.py
git commit -m "test: add homepage day timeline verifier"
Files:
index.htmlIn index.html, replace the existing .feed-item, .feed-item.loaded, .feed-item:hover, .feed-item:focus-visible, .feed-item-title, and .feed-item-date rules with this block:
.feed-timeline {
display: flex;
flex-direction: column;
gap: 28px;
}
.feed-day-group {
display: grid;
grid-template-columns: 84px minmax(0, 1fr);
column-gap: 22px;
align-items: start;
}
.feed-day-rail {
display: flex;
flex-direction: column;
align-items: flex-start;
min-height: 100%;
}
.feed-day-label {
font-family: var(--font-ui);
font-size: 0.58rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 3px;
color: var(--text-muted);
white-space: nowrap;
}
.feed-day-thread {
width: 1px;
min-height: 52px;
flex: 1;
margin-top: 10px;
margin-left: 10px;
background: linear-gradient(
to bottom,
var(--border-subtle) 0%,
rgba(0, 0, 0, 0) 100%
);
}
html[data-theme="black"] .feed-day-thread {
background: linear-gradient(
to bottom,
var(--border-subtle) 0%,
rgba(255, 255, 255, 0) 100%
);
}
.feed-day-posts {
display: flex;
flex-direction: column;
}
.feed-post-link {
display: block;
text-decoration: none;
color: var(--text-primary);
padding: 12px 0;
border-bottom: 1px solid var(--border-subtle);
transition: color 0.3s ease, transform 0.3s ease, padding-left 0.3s ease;
}
.feed-post-link:hover {
padding-left: 10px;
color: var(--interaction-emphasis);
}
.feed-post-link:focus-visible {
padding-left: 10px;
color: var(--interaction-emphasis);
outline: 2px solid var(--interaction-emphasis);
outline-offset: 4px;
}
.feed-post-title {
display: block;
font-family: var(--font-ui);
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
line-height: 1.25;
}
In the existing @media (max-width: 768px) block in index.html, add these rules before the closing brace:
.blog-feed {
max-width: 560px;
}
.feed-timeline {
gap: 24px;
}
.feed-day-group {
grid-template-columns: 1fr;
row-gap: 10px;
}
.feed-day-thread {
width: 48px;
min-height: 1px;
height: 1px;
margin-top: 8px;
margin-left: 0;
}
In index.html, replace the current contents of #feed-container with this grouped timeline markup:
<div id="feed-container" class="feed-timeline">
<section class="feed-day-group">
<div class="feed-day-rail">
<div class="feed-day-label">APR 18</div>
<div class="feed-day-thread" aria-hidden="true"></div>
</div>
<div class="feed-day-posts">
<a href="/blog/2026/04/18/mark-of-the-mature-man/" class="feed-post-link">
<span class="feed-post-title">the mark of the mature man</span>
</a>
</div>
</section>
<section class="feed-day-group">
<div class="feed-day-rail">
<div class="feed-day-label">APR 17</div>
<div class="feed-day-thread" aria-hidden="true"></div>
</div>
<div class="feed-day-posts">
<a href="/blog/2026/04/17/john-price-quotes/" class="feed-post-link">
<span class="feed-post-title">john price quotes</span>
</a>
</div>
</section>
<section class="feed-day-group">
<div class="feed-day-rail">
<div class="feed-day-label">APR 16</div>
<div class="feed-day-thread" aria-hidden="true"></div>
</div>
<div class="feed-day-posts">
<a href="/blog/2026/04/16/the-resonant-computing-manifesto/" class="feed-post-link">
<span class="feed-post-title">π The Resonant Computing Manifesto</span>
</a>
<a href="/blog/2026/04/16/we-found-a-ticking-time-bomb-in-macos-tcp-networking/" class="feed-post-link">
<span class="feed-post-title">we found a ticking time bomb in macos tcp networking</span>
</a>
</div>
</section>
<section class="feed-day-group">
<div class="feed-day-rail">
<div class="feed-day-label">APR 15</div>
<div class="feed-day-thread" aria-hidden="true"></div>
</div>
<div class="feed-day-posts">
<a href="/blog/2026/04/15/so-you-want-to-live-to-be-81/" class="feed-post-link">
<span class="feed-post-title">π So You Want To Live To Be 81?</span>
</a>
<a href="/blog/2026/04/15/pi-monopackagescoding-agentchangelogmd-at-main/" class="feed-post-link">
<span class="feed-post-title">π pi-mono/packages/coding-agent/CHANGELOG.md at main</span>
</a>
<a href="/blog/2026/04/15/banksy-satoshi-the-unmasking-impulse/" class="feed-post-link">
<span class="feed-post-title">banksy, satoshi & the unmasking impulse</span>
</a>
</div>
</section>
<section class="feed-day-group">
<div class="feed-day-rail">
<div class="feed-day-label">APR 14</div>
<div class="feed-day-thread" aria-hidden="true"></div>
</div>
<div class="feed-day-posts">
<a href="/blog/2026/04/14/dense-discovery-383-why-we-defend-whats-failing-us/" class="feed-post-link">
<span class="feed-post-title">π Dense Discovery #383: Why we defend whatβs failing us</span>
</a>
<a href="/blog/2026/04/14/if-you-thought-the-speed-of-writing-code-was-your-problem-you-have-bigger-problems/" class="feed-post-link">
<span class="feed-post-title">if you thought the speed of writing code was your problem - you have bigger problems</span>
</a>
</div>
</section>
</div>
</section>
</div>
Run:
bundle exec jekyll build
python3 scripts/verify_homepage_day_timeline.py
Expected:
Verified homepage timeline for 5 distinct publish dates.
git add index.html scripts/verify_homepage_day_timeline.py
git commit -m "feat: group homepage posts by day"
Files:
index.html if QA reveals a real issueRun:
bundle exec jekyll serve --host 127.0.0.1 --port 4000
Expected:
Server address: http://127.0.0.1:4000/
Verify:
spacing between day groups is larger than spacing between post links
At roughly 390px wide, verify:
post titles do not collide with the date or viewport edge
Using Tab, verify:
the focus outline is readable in both Chrome and Black theme finishes
Run:
bundle exec jekyll build
python3 scripts/verify_homepage_day_timeline.py
Expected:
Verified homepage timeline for 5 distinct publish dates.
git add index.html scripts/verify_homepage_day_timeline.py
git commit -m "fix: polish homepage day timeline layout"
index.html.feed-day-groupfeed-day-labelfeed-day-threadfeed-post-linkfeed-post-titleIf gh auth is still broken in the execution environment, create the issue and later the PR manually with these commands after re-auth:
gh auth login -h github.com
gh issue create \
--title "Homepage timeline groups latest posts by day" \
--body "Implement the approved homepage-only day timeline design from docs/superpowers/specs/2026-04-06-homepage-day-timeline-design.md."
Plan complete and saved to docs/superpowers/plans/2026-04-06-homepage-day-timeline-implementation-plan.md. Two execution options:
1. Subagent-Driven (recommended) - I dispatch a fresh subagent per task, review between tasks, fast iteration
2. Inline Execution - Execute tasks in this session using executing-plans, batch execution with checkpoints
Which approach?