CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
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.
| a6dc91c | 1 | /** |
| 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 | * | |
| eed4684 | 17 | * Tiers (pass 2 — "do it all", near-full-bleed): |
| 18 | * >= 1300px -> 1680 (dashboards, lists, tables, admin, explore, insights) | |
| 19 | * 1080..1299 -> 1320 (medium pages) | |
| 20 | * 1000..1079 -> 1200 (settings, repo-settings, import, forms) | |
| 21 | * 740..819 -> 900 (small confirm/detail cards, gentle nudge) | |
| 22 | * else -> unchanged (tiny claim/dialog views < 740px stay compact) | |
| a6dc91c | 23 | * |
| 24 | * Run once: `bun scripts/widen-layout.ts` | |
| 25 | */ | |
| 26 | ||
| 27 | import { Glob } from "bun"; | |
| 28 | ||
| 29 | const ROOT = new URL("..", import.meta.url).pathname; | |
| 30 | ||
| 31 | function widen(old: number): number | null { | |
| eed4684 | 32 | if (old >= 1300) return 1680; |
| 33 | if (old >= 1080) return 1320; | |
| 34 | if (old >= 1000) return 1200; | |
| 35 | if (old >= 740 && old < 820) return 900; | |
| 36 | return null; // leave tiny intentional widths alone | |
| a6dc91c | 37 | } |
| 38 | ||
| 39 | // Matches a single-line page-container declaration, capturing the px width. | |
| 40 | // Example: ` .admin-wrap { max-width: 1080px; margin: 0 auto; }` | |
| 41 | const LINE_RE = | |
| 42 | /^(\s*\.[A-Za-z0-9_-]*(?:wrap|container|page)\b[^\n{]*\{[^\n}]*max-width:\s*)(\d+)(px[^\n]*margin:\s*0 auto[^\n]*)$/; | |
| 43 | ||
| 44 | const glob = new Glob("src/**/*.tsx"); | |
| 45 | let filesChanged = 0; | |
| 46 | let linesChanged = 0; | |
| 47 | ||
| 48 | for await (const rel of glob.scan({ cwd: ROOT })) { | |
| 49 | if (!rel.startsWith("src/routes/") && !rel.startsWith("src/views/")) continue; | |
| 50 | const path = ROOT + rel; | |
| 51 | const src = await Bun.file(path).text(); | |
| 52 | const lines = src.split("\n"); | |
| 53 | let touched = false; | |
| 54 | ||
| 55 | for (let i = 0; i < lines.length; i++) { | |
| 56 | const m = lines[i].match(LINE_RE); | |
| 57 | if (!m) continue; | |
| 58 | const old = parseInt(m[2], 10); | |
| 59 | const next = widen(old); | |
| 60 | if (next === null || next === old) continue; | |
| 61 | lines[i] = `${m[1]}${next}${m[3]}`; | |
| 62 | console.log(`${rel}:${i + 1} ${old}px -> ${next}px`); | |
| 63 | touched = true; | |
| 64 | linesChanged++; | |
| 65 | } | |
| 66 | ||
| 67 | if (touched) { | |
| 68 | await Bun.write(path, lines.join("\n")); | |
| 69 | filesChanged++; | |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | console.log(`\nDone: ${linesChanged} container(s) widened across ${filesChanged} file(s).`); |