feat(design): Phase 3 — home page layout (#194)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Juan Manuel Servera committed
May 25, 2026 at 21:50 UTC
63a4417ce658443992ddc29e0b59dbebb307610a
6 files changed
+229
-99
.squad/agents/amy/history.md
+2
@@ -14,3 +14,5 @@
14
- 2026-05-25 Inter and JetBrains Mono are loaded with preload + stylesheet links; existing PaperMod variables are mapped to new `--color-*`, `--text-*`, and `--space-*` tokens for compatibility.
15
- 2026-05-25 Phase 2 chrome: `layouts/partials/header.html` now owns the tokenized brand/nav/GitHub/theme-toggle header, and `layouts/partials/footer.html` overrides PaperMod's footer while preserving its scroll/theme/copy-code scripts.
16
- 2026-05-25 PaperMod gotcha: adding a skip-to-content link requires overriding `layouts/_default/baseof.html`; keep the theme submodule untouched and place site-level chrome overrides in root `layouts/partials/`.
17
+- 2026-05-25 Phase 3 homepage: use `layouts/index.html` for editorial entry-point structure; keep home-specific styling in `assets/css/extended/squadscope.css` and reuse token variables only.
18
+- 2026-05-25 Home visual verification runs through `node scripts/design/verify-visual.mjs --base http://localhost:1313/SquadScope/` after starting `/tmp/hugo server -D --bind 0.0.0.0 --port 1313 --baseURL http://localhost:1313/SquadScope/`.
assets/css/extended/squadscope.css
+143
-33
@@ -7,23 +7,31 @@
7
.home-latest,
8
.home-empty-state,
9
.home-report-card,
10
-.home-nav-card,
10
+.home-quick-links,
11
.metric-card,
12
.report-shortcuts {
13
- border: var(--size-border-thin) solid var(--color-border);
13
+ border: 1px solid var(--color-border);
14
border-radius: var(--radius-md);
15
background: var(--color-surface);
16
}
17
18
.home-hero,
19
.home-latest,
20
-.home-empty-state {
20
+.home-empty-state,
21
+.home-quick-links {
22
padding: var(--space-4);
23
}
24
25
+.home-hero {
26
+ display: grid;
27
+ gap: var(--space-4);
28
+}
29
+
30
.home-eyebrow,
31
.section-topline,
26
-.metric-label {
32
+.metric-label,
33
+.home-report-week,
34
+.home-tag-label {
35
display: block;
36
color: var(--color-text-muted);
37
font-size: var(--text-sm);
@@ -31,42 +39,100 @@
39
text-transform: uppercase;
40
}
41
34
-.home-description {
42
+.home-hero h1 {
43
+ margin: var(--space-2) 0;
44
+ font-size: clamp(var(--text-3xl), 10vw, var(--text-4xl));
45
+ line-height: var(--leading-tight);
46
+}
47
+
48
+.home-description,
49
+.home-latest-hook {
50
+ max-width: var(--prose-measure);
51
+ color: var(--color-text);
52
font-size: var(--text-lg);
36
- margin: var(--space-2) 0 var(--space-3);
53
+ line-height: var(--leading-relaxed);
54
}
55
39
-.home-nav-grid,
40
-.report-metrics,
41
-.home-report-list {
42
- display: grid;
43
- gap: var(--space-3);
56
+.home-copy {
57
+ max-width: var(--prose-measure);
58
+ color: var(--color-text-muted);
59
}
60
46
-.home-nav-grid {
47
- grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
61
+.home-cadence {
62
+ display: grid;
63
+ gap: var(--space-3);
64
+ align-content: start;
65
+ padding: var(--space-3);
66
+ border: 1px solid var(--color-border);
67
+ border-radius: var(--radius-md);
68
+ background: var(--color-bg);
69
}
70
50
-.home-nav-card {
71
+.home-cadence ul,
72
+.home-cadence dl {
73
display: grid;
74
gap: var(--space-2);
53
- padding: var(--space-3);
54
- text-decoration: none;
75
+ margin: 0;
76
}
77
57
-.home-nav-title {
78
+.home-cadence ul {
79
+ padding-inline-start: var(--space-4);
80
+}
81
+
82
+.home-cadence dt,
83
+.home-report-title,
84
+.home-quick-links a,
85
+.home-tag-strip a {
86
color: var(--color-text);
87
font-weight: 700;
88
}
89
62
-.home-nav-copy {
90
+.home-cadence dd {
91
+ margin: var(--space-1) 0 0;
92
+ color: var(--color-text-muted);
93
+}
94
+
95
+.home-latest {
96
+ display: grid;
97
+ gap: var(--space-3);
98
+}
99
+
100
+.home-latest-kicker,
101
+.home-report-meta,
102
+.home-tag-strip {
103
+ display: flex;
104
+ flex-wrap: wrap;
105
+ gap: var(--space-2);
106
+ align-items: center;
107
color: var(--color-text-muted);
108
font-size: var(--text-sm);
109
}
110
111
+.home-latest h2 {
112
+ max-width: var(--prose-measure);
113
+ margin: 0;
114
+ font-size: clamp(var(--text-2xl), 6vw, var(--text-3xl));
115
+ line-height: var(--leading-tight);
116
+}
117
+
118
+.home-latest h2 a,
119
+.home-report-title,
120
+.home-quick-links a,
121
+.home-tag-strip a {
122
+ text-decoration-thickness: 1px;
123
+ text-underline-offset: var(--space-1);
124
+}
125
+
126
+.report-metrics,
127
+.home-report-list,
128
+.home-content-grid,
129
+.home-quick-links {
130
+ display: grid;
131
+ gap: var(--space-3);
132
+}
133
+
134
.report-metrics {
68
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
69
- margin: var(--space-4) 0;
135
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, calc(var(--space-15) + var(--space-3))), 1fr));
136
}
137
138
.metric-card {
@@ -79,8 +145,9 @@
145
146
.metric-value {
147
display: block;
82
- font-size: var(--text-lg);
148
margin-top: var(--space-1);
149
+ font-size: var(--text-lg);
150
+ line-height: var(--leading-tight);
151
}
152
153
.home-actions,
@@ -97,7 +164,7 @@
164
display: inline-flex;
165
align-items: center;
166
justify-content: center;
100
- min-height: 2.5rem;
167
+ min-height: calc(var(--space-5) + var(--space-2));
168
padding: 0 var(--space-3);
169
border-radius: var(--radius-full);
170
text-decoration: none;
@@ -110,11 +177,24 @@
177
178
.home-action-secondary,
179
.report-shortcuts a {
113
- border: var(--size-border-thin) solid var(--color-border);
180
+ border: 1px solid var(--color-border);
181
+}
182
+
183
+.home-tag-strip {
184
+ padding: var(--space-2) var(--space-3);
185
+ border-block: 1px solid var(--color-border);
186
+}
187
+
188
+.home-tag-strip a {
189
+ padding: var(--space-1) var(--space-2);
190
+ border-radius: var(--radius-full);
191
+ background: var(--color-accent-muted);
192
+ color: var(--color-accent);
193
+ text-decoration: none;
194
}
195
196
.home-report-list {
117
- grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
197
+ margin-top: var(--space-3);
198
}
199
200
.home-report-card,
@@ -122,18 +202,41 @@
202
padding: var(--space-3);
203
}
204
125
-.home-report-card h3,
126
-.squad-archive-entry h4 {
127
- margin-top: 0;
128
- margin-bottom: 0.5rem;
205
+.home-report-card {
206
+ display: grid;
207
+ gap: var(--space-2);
208
}
209
131
-.home-report-meta {
132
- display: flex;
133
- flex-wrap: wrap;
134
- gap: var(--space-2);
210
+.home-report-title {
211
+ display: grid;
212
+ gap: var(--space-1);
213
+ text-decoration: none;
214
+}
215
+
216
+.home-report-card p {
217
+ margin: 0;
218
color: var(--color-text-muted);
136
- font-size: var(--text-sm);
219
+}
220
+
221
+.home-quick-links {
222
+ align-content: start;
223
+}
224
+
225
+.home-quick-links a {
226
+ display: flex;
227
+ justify-content: space-between;
228
+ gap: var(--space-3);
229
+ padding: var(--space-2) 0;
230
+ border-bottom: 1px solid var(--color-border);
231
+}
232
+
233
+.home-quick-links a::after {
234
+ content: "→";
235
+ color: var(--color-accent);
236
+}
237
+
238
+.home-quick-links a:last-child {
239
+ border-bottom: 0;
240
}
241
242
.squad-report .report-shortcuts {
@@ -349,6 +452,13 @@ summary:focus-visible,
452
}
453
}
454
455
+@media (min-width: 769px) {
456
+ .home-hero,
457
+ .home-content-grid {
458
+ grid-template-columns: minmax(0, 2fr) minmax(calc(var(--space-16) + var(--space-10)), 1fr);
459
+ }
460
+}
461
+
462
@media (max-width: 640px) {
463
.metric-card-wide {
464
grid-column: span 1;
layouts/index.html
+84
-66
@@ -1,84 +1,102 @@
1
{{- define "main" -}}
2
{{- $weeklyPages := (where site.RegularPages "Type" "weekly").ByDate.Reverse -}}
3
+{{- $latest := cond (gt (len $weeklyPages) 0) (index $weeklyPages 0) nil -}}
4
5
<div class="home-shell">
5
- <section class="home-hero">
6
- <p class="home-eyebrow">Weekly tech signal from GitHub</p>
7
- <h1>{{ .Title }}</h1>
8
- {{- with .Params.description }}
9
- <p class="home-description">{{ . }}</p>
10
- {{- end }}
11
- <div class="post-content md-content">
12
- {{ .Content }}
6
+ <section class="home-hero" aria-labelledby="home-title">
7
+ <div class="home-hero-main">
8
+ <p class="home-eyebrow">Weekly tech signal from GitHub</p>
9
+ <h1 id="home-title">{{ .Title }}</h1>
10
+ <p class="home-description">
11
+ {{- with .Params.description -}}
12
+ {{ . }}
13
+ {{- else -}}
14
+ {{ site.Params.homeInfoParams.Content }}
15
+ {{- end -}}
16
+ </p>
17
+ <div class="home-copy md-content">
18
+ {{ .Content }}
19
+ </div>
20
</div>
14
- </section>
21
16
- <section class="home-nav-grid" aria-label="Primary views">
17
- <a class="home-nav-card" href="{{ `archive/` | absLangURL }}">
18
- <span class="home-nav-title">Archive</span>
19
- <span class="home-nav-copy">Browse every weekly summary in reverse chronological order.</span>
20
- </a>
21
- <a class="home-nav-card" href="{{ `monthly/` | absLangURL }}">
22
- <span class="home-nav-title">Monthly</span>
23
- <span class="home-nav-copy">Step back and review the strongest themes across each month.</span>
24
- </a>
25
- <a class="home-nav-card" href="{{ `yearly/` | absLangURL }}">
26
- <span class="home-nav-title">Yearly</span>
27
- <span class="home-nav-copy">Follow broader platform shifts and long-running trend lines.</span>
28
- </a>
29
- <a class="home-nav-card" href="{{ `tags/` | absLangURL }}">
30
- <span class="home-nav-title">Tags</span>
31
- <span class="home-nav-copy">Jump into recurring topics like AI, security, and developer tooling.</span>
32
- </a>
33
- <a class="home-nav-card" href="{{ `categories/` | absLangURL }}">
34
- <span class="home-nav-title">Categories</span>
35
- <span class="home-nav-copy">Move between weekly, monthly, and yearly reporting cadences.</span>
36
- </a>
37
- <a class="home-nav-card" href="{{ `search/` | absLangURL }}">
38
- <span class="home-nav-title">Search</span>
39
- <span class="home-nav-copy">Use Pagefind to search by keyword, filter, date, or repository name.</span>
40
- </a>
41
- <a class="home-nav-card" href="{{ `index.xml` | absLangURL }}">
42
- <span class="home-nav-title">RSS</span>
43
- <span class="home-nav-copy">Subscribe to the newest reports in your feed reader.</span>
44
- </a>
22
+ <aside class="home-cadence" aria-label="What readers get">
23
+ <p class="section-topline">What readers get</p>
24
+ <ul>
25
+ <li>Signal-first weekly GitHub trend analysis.</li>
26
+ <li>Monthly and yearly rollups for longer arcs.</li>
27
+ <li>Noise calls on spam, star farming, and blind spots.</li>
28
+ </ul>
29
+ <dl>
30
+ <div>
31
+ <dt>Cadence</dt>
32
+ <dd>Weekly on Mondays, with rollups as the archive grows.</dd>
33
+ </div>
34
+ </dl>
35
+ </aside>
36
</section>
37
47
- {{- if gt (len $weeklyPages) 0 -}}
48
- {{- $latest := index $weeklyPages 0 -}}
49
- <section class="home-latest" aria-labelledby="latest-report-heading">
50
- <div class="section-topline">Latest weekly summary</div>
38
+ {{- if $latest -}}
39
+ <article class="home-latest" aria-labelledby="latest-report-heading">
40
+ <div class="home-latest-kicker">
41
+ <span class="section-topline">Latest report</span>
42
+ {{- with $latest.Params.week }}<span>{{ . }}</span>{{- end }}
43
+ </div>
44
<h2 id="latest-report-heading"><a href="{{ $latest.RelPermalink }}">{{ $latest.Title }}</a></h2>
52
- <p>{{ $latest.Params.summary | default $latest.Summary }}</p>
45
+ <p class="home-latest-hook">{{ $latest.Params.summary | default $latest.Summary }}</p>
46
{{ partial "report-metrics.html" $latest }}
47
<div class="home-actions">
55
- <a class="home-action-primary" href="{{ $latest.RelPermalink }}">Read summary</a>
56
- <a class="home-action-secondary" href="{{ `archive/` | absLangURL }}">Open archive</a>
48
+ <a class="home-action-primary" href="{{ $latest.RelPermalink }}">Read this week</a>
49
+ <a class="home-action-secondary" href="{{ `archive/` | absLangURL }}">Browse archive</a>
50
</div>
58
- </section>
51
+ </article>
52
{{- else -}}
60
- <section class="home-empty-state">
61
- <div class="section-topline">Latest weekly summary</div>
62
- <h2>No weekly report published yet</h2>
63
- <p>The homepage will automatically feature the newest report as soon as the first weekly summary lands in <code>content/weekly/</code>.</p>
53
+ <section class="home-empty-state" aria-labelledby="latest-report-heading">
54
+ <div class="section-topline">Latest report</div>
55
+ <h2 id="latest-report-heading">No weekly report published yet</h2>
56
+ <p>The homepage will feature the newest report as soon as the first weekly summary lands in <code>content/weekly/</code>.</p>
57
</section>
58
{{- end -}}
59
67
- <section class="home-recent" aria-labelledby="recent-reports-heading">
68
- <div class="section-topline">Recent weekly reports</div>
69
- <h2 id="recent-reports-heading">Browse the latest entries</h2>
70
- <div class="home-report-list">
71
- {{- range first 5 $weeklyPages -}}
72
- <article class="home-report-card">
73
- <h3><a href="{{ .RelPermalink }}">{{ .Title }}</a></h3>
74
- <p>{{ .Params.summary | default .Summary }}</p>
75
- <div class="home-report-meta">
76
- <span>{{ .Date.Format "2006-01-02" }}</span>
77
- {{- with .Params.categories }}<span>{{ delimit . ", " }}</span>{{- end }}
78
- </div>
79
- </article>
80
- {{- end -}}
81
- </div>
82
- </section>
60
+ {{- if site.Taxonomies.tags -}}
61
+ <nav class="home-tag-strip" aria-label="Top tags">
62
+ <span class="home-tag-label">Track</span>
63
+ {{- range first 6 site.Taxonomies.tags.ByCount }}
64
+ <a href="{{ printf "tags/%s/" (.Name | urlize) | absLangURL }}">{{ .Name }}</a>
65
+ {{- end }}
66
+ </nav>
67
+ {{- end -}}
68
+
69
+ <div class="home-content-grid">
70
+ <section class="home-recent" aria-labelledby="recent-reports-heading">
71
+ <div class="section-topline">Recent issues</div>
72
+ <h2 id="recent-reports-heading">Weekly archive</h2>
73
+ <div class="home-report-list">
74
+ {{- range first 6 $weeklyPages -}}
75
+ <article class="home-report-card">
76
+ <a class="home-report-title" href="{{ .RelPermalink }}">
77
+ <span class="home-report-week">{{ .Params.week | default (.Date.Format "2006-01-02") }}</span>
78
+ <span>{{ .Title }}</span>
79
+ </a>
80
+ <p>{{ .Params.summary | default .Summary }}</p>
81
+ <div class="home-report-meta">
82
+ <span>{{ .Date.Format "Jan 2, 2006" }}</span>
83
+ {{- with .Params.repos_featured }}<span>{{ . }} repos featured</span>{{- end }}
84
+ </div>
85
+ </article>
86
+ {{- end -}}
87
+ </div>
88
+ </section>
89
+
90
+ <nav class="home-quick-links" aria-labelledby="quick-links-heading">
91
+ <div class="section-topline">Quick links</div>
92
+ <h2 id="quick-links-heading">Move through the report</h2>
93
+ <a href="{{ `weekly/` | absLangURL }}">Weekly reports</a>
94
+ <a href="{{ `monthly/` | absLangURL }}">Monthly rollups</a>
95
+ <a href="{{ `yearly/` | absLangURL }}">Yearly rollups</a>
96
+ <a href="{{ `archive/` | absLangURL }}">Full archive</a>
97
+ <a href="{{ `search/` | absLangURL }}">Search</a>
98
+ <a href="{{ `index.xml` | absLangURL }}">RSS feed</a>
99
+ </nav>
100
+ </div>
101
</div>
102
{{- end -}}
screenshots/design-verification/2026-05-25/home-desktop-light.png
Binary files a/screenshots/design-verification/2026-05-25/home-desktop-light.png and b/screenshots/design-verification/2026-05-25/home-desktop-light.png differ
screenshots/design-verification/2026-05-25/home-mobile-dark.png
Binary files /dev/null and b/screenshots/design-verification/2026-05-25/home-mobile-dark.png differ
screenshots/design-verification/2026-05-25/home-wide-light.png
Binary files /dev/null and b/screenshots/design-verification/2026-05-25/home-wide-light.png differ