Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesPull RequestsActionsSecurityInsightsSettings
✨ AI
More
Blame · Line-by-line history

widen-layout.ts

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

widen-layout.tsBlame71 lines · 1 contributor
a6dc91cClaude1/**
2 * One-shot layout-widening sweep.
3 *
4 * The site felt "thin": `main` allowed 1440px but nearly every page wrapped its
5 * content in a much narrower centered column (880–1180px), leaving big empty
6 * gutters on modern wide screens. This script widens the per-page container
7 * declarations into consistent tiers so the whole site uses the available
8 * width the way GitHub / Linear / Vercel do.
9 *
10 * It is deliberately conservative: it only rewrites a CSS declaration line when
11 * that line is unmistakably a page-level container — i.e. the selector is a
12 * class whose name ends in `-wrap`, `-container`, or `-page`, AND the same line
13 * sets both `max-width: <N>px` and `margin: 0 auto`. Hero-inner / sub-heading /
14 * media-query widths never match (no `margin: 0 auto`), so prose measure and
15 * narrow confirm dialogs are left intact.
16 *
17 * Tiers (old -> new):
18 * >= 1000px -> 1320 (dashboards, lists, tables, admin, explore, insights)
19 * 900..999 -> 1120 (medium / form-heavy pages)
20 * 820..899 -> 1040 (settings, repo-settings, import)
21 * < 820 -> unchanged (intentionally small confirm / detail / claim views)
22 *
23 * Run once: `bun scripts/widen-layout.ts`
24 */
25
26import { Glob } from "bun";
27
28const ROOT = new URL("..", import.meta.url).pathname;
29
30function widen(old: number): number | null {
31 if (old >= 1000) return 1320;
32 if (old >= 900) return 1120;
33 if (old >= 820) return 1040;
34 return null; // leave small intentional widths alone
35}
36
37// Matches a single-line page-container declaration, capturing the px width.
38// Example: ` .admin-wrap { max-width: 1080px; margin: 0 auto; }`
39const LINE_RE =
40 /^(\s*\.[A-Za-z0-9_-]*(?:wrap|container|page)\b[^\n{]*\{[^\n}]*max-width:\s*)(\d+)(px[^\n]*margin:\s*0 auto[^\n]*)$/;
41
42const glob = new Glob("src/**/*.tsx");
43let filesChanged = 0;
44let linesChanged = 0;
45
46for await (const rel of glob.scan({ cwd: ROOT })) {
47 if (!rel.startsWith("src/routes/") && !rel.startsWith("src/views/")) continue;
48 const path = ROOT + rel;
49 const src = await Bun.file(path).text();
50 const lines = src.split("\n");
51 let touched = false;
52
53 for (let i = 0; i < lines.length; i++) {
54 const m = lines[i].match(LINE_RE);
55 if (!m) continue;
56 const old = parseInt(m[2], 10);
57 const next = widen(old);
58 if (next === null || next === old) continue;
59 lines[i] = `${m[1]}${next}${m[3]}`;
60 console.log(`${rel}:${i + 1} ${old}px -> ${next}px`);
61 touched = true;
62 linesChanged++;
63 }
64
65 if (touched) {
66 await Bun.write(path, lines.join("\n"));
67 filesChanged++;
68 }
69}
70
71console.log(`\nDone: ${linesChanged} container(s) widened across ${filesChanged} file(s).`);