Skip to content

Commit 2ea2c36

Browse files
committed
Tighten changelog layout and pin runtime dependencies
- Reduce changelog typography and spacing for denser pages - Document the marketing and UI design system - Pin Hono, fast-uri, and sharp dependency versions - Avoid literal authorization credentials in relay protocol tests
1 parent 3373a21 commit 2ea2c36

6 files changed

Lines changed: 87 additions & 457 deletions

File tree

AGENTS.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,23 @@ If a tradeoff is required, choose correctness and robustness over short-term con
3333

3434
Long term maintainability is a core priority. If you add new functionality, first check if there is shared logic that can be extracted to a separate module. Duplicate logic across multiple files is a code smell and should be avoided. Don't be afraid to change existing code. Don't take shortcuts by just adding local logic to solve a problem.
3535

36+
## Design System (marketing site and web UI)
37+
38+
Threadlines is dense and flat. When building or changing any user-facing surface:
39+
40+
- Structure comes from typography, spacing, and hairline dividers (`--border`), not boxes.
41+
Never wrap content in a bordered/rounded/filled card unless it's a clickable tile or an
42+
input surface. A list of items is dividers between rows, not a stack of cards.
43+
- Compact type scale: one display-size element per page (~40px max), section headings
44+
18–20px, body 15–16px. If a heading feels impressive, it's too big.
45+
- Tight vertical rhythm: list rows 16–20px padding, section gaps under 40px. If the page
46+
scrolls mostly through whitespace, shrink the gaps, not the content.
47+
- Copy is scannable: lead with the feature name, keep descriptions to one sentence
48+
(about two rendered lines). Users skim changelogs and UIs; they don't read them.
49+
- Hover feedback is a color shift only — no translateY lifts, scale, or shadows.
50+
- Reuse the existing tokens (`--border`, `--surface`, `--fg-*`, mono `--font-mono` for
51+
meta labels like versions and dates). No new colors, radii, or shadows without agreement.
52+
3653
## Package Roles
3754

3855
- `apps/server`: Node.js WebSocket server. Manages provider sessions (Codex, Claude, Cursor, OpenCode), serves the React web app, and owns the event-sourced orchestration core.

apps/marketing/src/pages/changelog/[version].astro

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ const structuredData = {
108108
}
109109

110110
.release-header {
111-
padding: 32px 0 36px;
111+
padding: 28px 0 30px;
112112
border-bottom: 1px solid var(--border);
113113
}
114114

@@ -126,16 +126,16 @@ const structuredData = {
126126

127127
.release-header h1 {
128128
max-width: 780px;
129-
margin: 14px 0 12px;
130-
font-size: clamp(32px, 5vw, 48px);
129+
margin: 12px 0 10px;
130+
font-size: clamp(28px, 4.5vw, 40px);
131131
text-wrap: balance;
132132
}
133133

134134
.release-header > p {
135-
max-width: 680px;
135+
max-width: 640px;
136136
color: var(--fg-muted);
137-
font-size: 19px;
138-
line-height: 1.65;
137+
font-size: 16px;
138+
line-height: 1.6;
139139
text-wrap: pretty;
140140
}
141141

@@ -145,42 +145,44 @@ const structuredData = {
145145

146146
.highlight {
147147
display: grid;
148-
grid-template-columns: 48px minmax(0, 1fr);
149-
gap: 18px;
150-
padding: 22px 0;
148+
grid-template-columns: 40px minmax(0, 1fr);
149+
gap: 14px;
150+
padding: 18px 0;
151151
border-bottom: 1px solid var(--border);
152152
}
153153

154154
.highlight-number {
155-
padding-top: 5px;
155+
padding-top: 4px;
156156
color: var(--accent-bright);
157157
font-family: var(--font-mono);
158158
font-size: 11px;
159159
}
160160

161161
.highlight h2 {
162-
margin-bottom: 6px;
163-
font-size: 22px;
164-
letter-spacing: -0.02em;
162+
margin-bottom: 4px;
163+
font-size: 19px;
164+
letter-spacing: -0.015em;
165165
}
166166

167167
.highlight p {
168-
max-width: 68ch;
168+
max-width: 64ch;
169169
color: var(--fg-muted);
170-
line-height: 1.65;
170+
font-size: 15px;
171+
line-height: 1.6;
171172
}
172173

173174
.also-improved {
174-
padding: 24px 0 0;
175+
padding: 20px 0 0;
175176
}
176177

177178
.also-improved ul {
178179
display: grid;
179-
gap: 8px;
180-
margin-top: 14px;
180+
gap: 6px;
181+
margin-top: 12px;
181182
padding-left: 20px;
182183
color: var(--fg-muted);
183-
line-height: 1.6;
184+
font-size: 15px;
185+
line-height: 1.55;
184186
}
185187

186188
.also-improved li::marker {
@@ -192,7 +194,7 @@ const structuredData = {
192194
flex-wrap: wrap;
193195
align-items: center;
194196
gap: 20px 28px;
195-
margin-top: 36px;
197+
margin-top: 32px;
196198
}
197199

198200
.release-actions a {

apps/marketing/src/pages/changelog/index.astro

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ const entries = sortChangelogEntries(await getCollection("changelog"));
8787

8888
.release-entry a {
8989
display: block;
90-
padding: 24px 0;
90+
padding: 20px 0;
9191
}
9292

9393
.release-meta {
@@ -104,10 +104,10 @@ const entries = sortChangelogEntries(await getCollection("changelog"));
104104
}
105105

106106
.release-entry h2 {
107-
margin: 10px 0 6px;
108-
font-size: clamp(20px, 2.6vw, 24px);
109-
line-height: 1.2;
110-
letter-spacing: -0.02em;
107+
margin: 8px 0 4px;
108+
font-size: clamp(18px, 2.4vw, 21px);
109+
line-height: 1.25;
110+
letter-spacing: -0.015em;
111111
}
112112

113113
.release-arrow {
@@ -120,9 +120,10 @@ const entries = sortChangelogEntries(await getCollection("changelog"));
120120
}
121121

122122
.release-entry p {
123-
max-width: 68ch;
123+
max-width: 64ch;
124124
color: var(--fg-muted);
125-
line-height: 1.6;
125+
font-size: 15px;
126+
line-height: 1.55;
126127
}
127128

128129
@media (max-width: 620px) {

apps/relay-worker/src/protocol.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ describe("relay protocol helpers", () => {
3636
});
3737

3838
it("parses bearer tokens from Authorization headers", () => {
39+
const basicAuthorization = ["Basic", "dXNlcjpwYXNz"].join(" ");
40+
3941
expect(parseBearerToken("Bearer device-token")).toBe("device-token");
4042
expect(parseBearerToken("bearer device-token")).toBe("device-token");
4143
expect(parseBearerToken(" Bearer device-token ")).toBe("device-token");
42-
expect(parseBearerToken("Basic dXNlcjpwYXNz")).toBe(null);
44+
expect(parseBearerToken(basicAuthorization)).toBe(null);
4345
expect(parseBearerToken("Bearer")).toBe(null);
4446
expect(parseBearerToken(null)).toBe(null);
4547
});

0 commit comments

Comments
 (0)