OXYGENHUB

A trial GitHub-like look behind ?look=github (refs #74) 749d9a5fcd9f

assets/github.css, served at /static/github.css, restyles the hub close to
GitHub's: Primer colours light and dark, the system font stack, rounded
boxes with divided rows, the band and repository tabs as underline
navigation, grey buttons with green primary actions, sentence case, pill
labels and round avatars. Every rule is scoped to :root[data-look=github].
base.html loads it before first paint when the look cookie says so;
?look=github sets the cookie for a year and ?look=default clears it.
Author
Andy McCall @andymccall <[email protected]>
When
· 2026-10-01 18:24 UTC
Signature
✔ signed by Andy McCall
Hash
749d9a5fcd9f7c7bf40e2244f7186555ea327eb9b0993cfd7d80f8950eef35a5
Depends on
b5668108487f c40c2d3edb51 d23464c0ac60 d305b3b0afdc
Depended on by
84e3c09656b2 16ee5d19d220 61ecbd299f22 7f283f8e8b97 17ca6cddc534 f8cf54e99879 1656dc14c2ac c9aacc0e7dc1 8aafd2023dec 7edaff01d506 c987c86513df 554ccacfc123 6e7dfa0a42b9 8475176972e8 8ddebaa7e856 1f78655a0466 4d2e44d79b03 62ceb2eec18c 155cab142b63 206c1fc1b06a efd29a0033e8 83940d53664f 66fd9d6b1452 d0fbea2eb46e d1727c573f30 4ac01a732552 2a83f5303458 7d2eb590051f e71846aa07b9 3556d08e17f9 a6c241e8eba0 348f8c4baccf c889911bec12 0a56c5313bc0 5dead1f4f26d d7ce41acf22c 9e50caedf4db 4f37afcc3583 ea85398a51bc 8e96499f2705 4da8b828a822 cb71e18eb6f9 6a1780558353 2291f8cc9c96 bf5101d394c0 34f40eb4b205 739a763a558c eef677c48cd1 ced6d3afc5cf b0612e7dce30 070a7b64b368 d98a93c10a0d ae138eea7a71 f6346d875ee5 7493abf94a41
In bookmarks
api-unknown-fields cancel-landed-runs clear-waiting close-proposal-140 diffusion-pin-bookmark draft-ready image-check job-waits main oh-comment-body-file proposal-list-fast run-one-job wiki-says-so
In tags
v0.3.0 v0.3.1 v0.4.0 v0.4.1 v0.4.2 v0.5.0 v0.5.1 v0.5.2 v0.6.0 v0.6.1 v0.7.0 v0.8.0 v0.9.0 v0.9.1 v0.9.11 v0.9.15 v0.9.16 v0.9.19 v0.9.2 v0.9.20 v0.9.21 v0.9.22 v0.9.23 v0.9.24 v0.9.3 v0.9.4 v0.9.5 v0.9.6 v0.9.7 v0.9.8 v0.9.9
Edits
4 atoms, 1 tree operation, 4 files

Browse the tree at this change

added assets/github.css +167 −0
1 +
/* A trial look close to GitHub's (Primer colours, system fonts, rounded
2 +
   boxes, underline navigation), loaded over style.css only for a browser
3 +
   that asked for it with ?look=github (?look=default turns it off). Every
4 +
   rule is scoped to :root[data-look="github"], so the hub's own theme is
5 +
   unchanged for everyone else. Light and dark follow the theme toggle. */
6 +
7 +
:root[data-look="github"] {
8 +
  --bg:#ffffff; --panel:#ffffff; --soft:#f6f8fa; --ink:#1f2328; --mute:#59636e; --line:#d1d9e0; --dim:#818b98;
9 +
  --acc:#0969da; --acc-2:#0969da; --band:#f6f8fa; --band-ink:#1f2328; --band-acc:#0969da; --band-line:transparent; --now:#0969da; --now-ink:#ffffff;
10 +
  --ok:#1a7f37; --bad:#d1242f; --warn:#9a6700;
11 +
  --add:#dafbe1; --del:#ffebe9; --add-ink:#116329; --del-ink:#82071e;
12 +
  --sy-kw:#cf222e; --sy-str:#0a3069; --sy-num:#0550ae; --sy-cmt:#59636e; --sy-fn:#8250df; --sy-ty:#953800; --sy-var:#1f2328; --sy-const:#0550ae;
13 +
  --gh-btn:#f6f8fa; --gh-btn-hover:#eff2f5; --gh-btn-line:#d1d9e0; --gh-green:#1f883d; --gh-green-hover:#1c8139; --gh-tab:#fd8c73;
14 +
  --gh-header:#f6f8fa; --gh-bm-bg:#ddf4ff; --gh-bm-ink:#0969da; --gh-shadow:0 1px 0 rgba(31,35,40,.04);
15 +
  --gh-font:-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
16 +
  --gh-mono:ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
17 +
  color-scheme: light;
18 +
}
19 +
:root[data-look="github"][data-theme="dark"] {
20 +
  --bg:#0d1117; --panel:#0d1117; --soft:#151b23; --ink:#f0f6fc; --mute:#9198a1; --line:#3d444d; --dim:#656c76;
21 +
  --acc:#4493f8; --acc-2:#4493f8; --band:#151b23; --band-ink:#f0f6fc; --band-acc:#4493f8; --now:#1f6feb; --now-ink:#ffffff;
22 +
  --ok:#3fb950; --bad:#f85149; --warn:#d29922;
23 +
  --add:rgba(46,160,67,.15); --del:rgba(248,81,73,.1); --add-ink:#aff5b4; --del-ink:#ffdcd7;
24 +
  --sy-kw:#ff7b72; --sy-str:#a5d6ff; --sy-num:#79c0ff; --sy-cmt:#9198a1; --sy-fn:#d2a8ff; --sy-ty:#ffa657; --sy-var:#f0f6fc; --sy-const:#79c0ff;
25 +
  --gh-btn:#212830; --gh-btn-hover:#262c36; --gh-btn-line:#3d444d; --gh-green:#238636; --gh-green-hover:#29903b;
26 +
  --gh-header:#010409; --gh-bm-bg:rgba(56,139,253,.1); --gh-bm-ink:#4493f8; --gh-shadow:none;
27 +
  color-scheme: dark;
28 +
}
29 +
30 +
/* Type: the system stack at 14px, no capitals forced on anything. */
31 +
:root[data-look="github"] body { font: 14px/1.5 var(--gh-font); }
32 +
:root[data-look="github"] code, :root[data-look="github"] pre, :root[data-look="github"] kbd, :root[data-look="github"] .mono,
33 +
:root[data-look="github"] table.code td, :root[data-look="github"] .chip { font-family: var(--gh-mono); font-size: 12px; }
34 +
:root[data-look="github"] .px, :root[data-look="github"] .pxs { font-family: var(--gh-font); font-size: inherit; }
35 +
:root[data-look="github"] h2 { font-size: 16px; font-weight: 600; }
36 +
:root[data-look="github"] h3, :root[data-look="github"] th, :root[data-look="github"] dl.facts dt,
37 +
:root[data-look="github"] form.card label, :root[data-look="github"] .field label, :root[data-look="github"] .inbox-nav h3,
38 +
:root[data-look="github"] .tag, :root[data-look="github"] .kind, :root[data-look="github"] .vis, :root[data-look="github"] .runner-status,
39 +
:root[data-look="github"] .chain-state, :root[data-look="github"] aside.side h3 .side-edit {
40 +
  text-transform: none; letter-spacing: normal;
41 +
}
42 +
:root[data-look="github"] h3 { font-size: 14px; font-weight: 600; color: var(--ink); }
43 +
:root[data-look="github"] form.card label, :root[data-look="github"] .field label { font-size: 14px; font-weight: 600; color: var(--ink); }
44 +
:root[data-look="github"] dl.facts dt { font-size: 14px; color: var(--mute); padding-top: 0; }
45 +
:root[data-look="github"] th { font-size: 12px; font-weight: 600; color: var(--mute); }
46 +
:root[data-look="github"] a { color: var(--acc); }
47 +
:root[data-look="github"] kbd { border-radius: 6px; box-shadow: inset 0 -1px 0 var(--line); }
48 +
49 +
/* The header: GitHub's global bar; the site band becomes a quiet second row. */
50 +
:root[data-look="github"] header { background: var(--gh-header); border-bottom: 1px solid var(--line); padding: 12px 24px; gap: 12px; }
51 +
:root[data-look="github"] .brand { gap: 8px; }
52 +
:root[data-look="github"] .brand svg { height: 28px; }
53 +
:root[data-look="github"] .brand .px { font-size: 0; }
54 +
:root[data-look="github"] .brand .px::after { content: "OxygenHub"; font-size: 16px; font-weight: 600; color: var(--ink); }
55 +
:root[data-look="github"] form.find input { border-radius: 6px; background: var(--bg); padding: 5px 12px; font-size: 14px; }
56 +
:root[data-look="github"] form.find input:focus, :root[data-look="github"] form.card input:focus,
57 +
:root[data-look="github"] form.card textarea:focus, :root[data-look="github"] form.card select:focus {
58 +
  outline: 2px solid var(--acc); outline-offset: -1px;
59 +
}
60 +
:root[data-look="github"] header nav .theme-toggle { border-radius: 6px; border-color: var(--gh-btn-line); background: var(--gh-btn); }
61 +
:root[data-look="github"] header nav .bell .count { background: var(--acc); }
62 +
:root[data-look="github"] .band { background: var(--gh-header); border-bottom: 1px solid var(--line); padding: 0 24px; }
63 +
:root[data-look="github"] .band a { color: var(--ink); font-size: 14px; font-weight: 400; text-transform: none; letter-spacing: normal; padding: 8px 12px; border: 0; }
64 +
:root[data-look="github"] .band a:first-child { border: 0; }
65 +
:root[data-look="github"] .band a:hover { background: var(--gh-btn-hover); border-radius: 6px; }
66 +
:root[data-look="github"] .band a.on { background: none; box-shadow: inset 0 -2px 0 var(--gh-tab); font-weight: 600; }
67 +
:root[data-look="github"] .band a.dim { color: var(--mute); opacity: 1; }
68 +
:root[data-look="github"] .band a.admin { color: var(--acc); }
69 +
70 +
/* Repository tabs: underline navigation. */
71 +
:root[data-look="github"] .tabs { background: var(--gh-header); }
72 +
:root[data-look="github"] .tabs-in { padding: 0 24px; gap: 4px; }
73 +
:root[data-look="github"] .tabs .crumb { font-size: 20px; padding: 14px 0 10px; }
74 +
:root[data-look="github"] .tabs a:not(.crumb a) { padding: 8px 10px; font-size: 14px; border-radius: 6px; }
75 +
:root[data-look="github"] .tabs a.on { border-bottom: 0; box-shadow: inset 0 -2px 0 var(--gh-tab); border-radius: 0; font-weight: 600; }
76 +
:root[data-look="github"] .tabs a:hover { background: var(--gh-btn-hover); }
77 +
:root[data-look="github"] main { padding: 24px 24px 32px; }
78 +
79 +
/* Page headings. */
80 +
:root[data-look="github"] .head { border-image: none; border-bottom: 1px solid var(--line); margin: 0 0 16px; padding-bottom: 8px; }
81 +
:root[data-look="github"] .head h1 { font-size: 24px; font-weight: 400; color: var(--ink); }
82 +
:root[data-look="github"] .head h1 small { color: var(--mute); font-size: 14px; }
83 +
84 +
/* Buttons: grey, rounded, sentence case; green for the primary action. */
85 +
:root[data-look="github"] button, :root[data-look="github"] a.go, :root[data-look="github"] button.go, :root[data-look="github"] summary.go {
86 +
  font-family: var(--gh-font); font-size: 14px; font-weight: 500; letter-spacing: normal; text-transform: lowercase;
87 +
  background: var(--gh-btn); color: var(--ink); border: 1px solid var(--gh-btn-line); border-radius: 6px; padding: 5px 16px;
88 +
  box-shadow: var(--gh-shadow); line-height: 20px;
89 +
}
90 +
:root[data-look="github"] button::first-letter, :root[data-look="github"] a.go::first-letter, :root[data-look="github"] summary.go::first-letter { text-transform: uppercase; }
91 +
:root[data-look="github"] button:hover, :root[data-look="github"] a.go:hover, :root[data-look="github"] summary.go:hover { background: var(--gh-btn-hover); color: var(--ink); }
92 +
:root[data-look="github"] button.small, :root[data-look="github"] a.go.small, :root[data-look="github"] form.tiny button { padding: 2px 10px; font-size: 12px; }
93 +
:root[data-look="github"] form.card button[type=submit], :root[data-look="github"] form.card .primary, :root[data-look="github"] button.primary-btn {
94 +
  background: var(--gh-green); color: #ffffff; border-color: rgba(31,35,40,.15);
95 +
}
96 +
:root[data-look="github"] form.card button[type=submit]:hover, :root[data-look="github"] button.primary-btn:hover { background: var(--gh-green-hover); color: #fff; filter: none; }
97 +
:root[data-look="github"] button.danger-btn { color: var(--bad); }
98 +
:root[data-look="github"] button.linkish { background: none; border: 0; padding: 0; box-shadow: none; color: var(--acc); text-transform: none; }
99 +
100 +
/* Boxes: rounded, one border, rows divided inside. */
101 +
:root[data-look="github"] .panel, :root[data-look="github"] form.card, :root[data-look="github"] dl.facts, :root[data-look="github"] .table,
102 +
:root[data-look="github"] .filebox, :root[data-look="github"] .file-diff, :root[data-look="github"] .hist, :root[data-look="github"] ul.feed,
103 +
:root[data-look="github"] article.doc, :root[data-look="github"] .quickstart, :root[data-look="github"] .comment, :root[data-look="github"] .tl-card,
104 +
:root[data-look="github"] .lanes-board, :root[data-look="github"] .file-side, :root[data-look="github"] .strip, :root[data-look="github"] pre.msg,
105 +
:root[data-look="github"] .board-col, :root[data-look="github"] .card-item, :root[data-look="github"] li.hook, :root[data-look="github"] p.chain,
106 +
:root[data-look="github"] .clone-panel, :root[data-look="github"] .sheet, :root[data-look="github"] .empty {
107 +
  border-radius: 6px;
108 +
}
109 +
:root[data-look="github"] .table, :root[data-look="github"] .filebox, :root[data-look="github"] .file-diff, :root[data-look="github"] .hist,
110 +
:root[data-look="github"] ul.feed, :root[data-look="github"] .tl-card { overflow: hidden; }
111 +
:root[data-look="github"] ul.rows { border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
112 +
:root[data-look="github"] ul.rows li { margin: 0; border: 0; border-top: 1px solid var(--line); padding: 12px 16px; }
113 +
:root[data-look="github"] ul.rows li:first-child { border-top: 0; }
114 +
:root[data-look="github"] ul.rows li:hover { background: var(--soft); }
115 +
:root[data-look="github"] ul.rows .name { font-size: 16px; font-weight: 600; }
116 +
:root[data-look="github"] ul.rows li.unread { box-shadow: inset 3px 0 0 var(--acc); }
117 +
:root[data-look="github"] th { background: var(--soft); padding: 8px 16px; }
118 +
:root[data-look="github"] td { padding: 8px 16px; }
119 +
:root[data-look="github"] tr:last-child > td { border-bottom: 0; }
120 +
:root[data-look="github"] tbody tr:hover > td { background: var(--soft); }
121 +
:root[data-look="github"] .filebox > header, :root[data-look="github"] .file-diff > header, :root[data-look="github"] .file-diff > summary,
122 +
:root[data-look="github"] .tl-head { background: var(--soft); }
123 +
:root[data-look="github"] article.doc { padding: 24px 32px; font-size: 16px; line-height: 1.5; }
124 +
:root[data-look="github"] article.doc h1 { font-size: 32px; font-weight: 600; padding-bottom: .3em; border-bottom: 1px solid var(--line); }
125 +
:root[data-look="github"] article.doc h2 { font-size: 24px; font-weight: 600; padding-bottom: .3em; border-bottom: 1px solid var(--line); }
126 +
:root[data-look="github"] article.doc pre { background: var(--soft); border: 0; border-radius: 6px; padding: 16px; }
127 +
:root[data-look="github"] article.doc code { background: color-mix(in srgb, var(--mute) 20%, transparent); border-radius: 6px; padding: .2em .4em; font-size: 85%; }
128 +
:root[data-look="github"] article.doc blockquote { border-left: 4px solid var(--line); }
129 +
:root[data-look="github"] .clone code, :root[data-look="github"] .cmds pre, :root[data-look="github"] .secret { border-radius: 6px; }
130 +
131 +
/* Forms. */
132 +
:root[data-look="github"] form.card input[type=text], :root[data-look="github"] form.card input[type=password], :root[data-look="github"] form.card input[type=email],
133 +
:root[data-look="github"] form.card input[type=search], :root[data-look="github"] form.card input[type=number], :root[data-look="github"] form.card textarea,
134 +
:root[data-look="github"] form.card select, :root[data-look="github"] .field input, :root[data-look="github"] .field select, :root[data-look="github"] .field textarea,
135 +
:root[data-look="github"] .tiny-form input[type=text], :root[data-look="github"] .tiny-form select, :root[data-look="github"] .compare-bar input,
136 +
:root[data-look="github"] details.inline-edit input, :root[data-look="github"] details.inline-edit textarea, :root[data-look="github"] details.linecomment textarea {
137 +
  border-radius: 6px; background: var(--bg); padding: 5px 12px; font-size: 14px;
138 +
}
139 +
140 +
/* Labels, tags and status marks: pills. */
141 +
:root[data-look="github"] .tag, :root[data-look="github"] .label, :root[data-look="github"] .lbl, :root[data-look="github"] .kind,
142 +
:root[data-look="github"] .runner-status, :root[data-look="github"] .vis, :root[data-look="github"] .count-chip, :root[data-look="github"] .chain-link {
143 +
  border-radius: 2em; font-size: 12px; font-weight: 500; padding: 0 8px; line-height: 20px;
144 +
}
145 +
:root[data-look="github"] .lbl-bm { background: var(--gh-bm-bg); color: var(--gh-bm-ink); border-color: transparent; border-radius: 6px; font-family: var(--gh-mono); }
146 +
:root[data-look="github"] .tag.head { background: var(--now); color: var(--now-ink); }
147 +
:root[data-look="github"] .modes a, :root[data-look="github"] .diff-bar .modes a { border-radius: 6px; }
148 +
149 +
/* Avatars are round. */
150 +
:root[data-look="github"] img.avatar { border-radius: 50%; }
151 +
:root[data-look="github"] img.avatar.xl { border-radius: 50%; }
152 +
153 +
/* Settings and side navigation, as GitHub's: a highlighted row, not a rule. */
154 +
:root[data-look="github"] .section-nav a { border-left: 0; border-radius: 6px; color: var(--ink); padding: 6px 8px; }
155 +
:root[data-look="github"] .section-nav a:hover { background: var(--gh-btn-hover); }
156 +
:root[data-look="github"] .section-nav a.on { background: var(--gh-btn-hover); font-weight: 600; box-shadow: inset 3px 0 0 var(--acc); }
157 +
158 +
/* Footer: plain, small, muted. */
159 +
:root[data-look="github"] footer { background: none; border-top: 1px solid var(--line); }
160 +
:root[data-look="github"] footer .brand .px::after { font-size: 14px; color: var(--mute); }
161 +
:root[data-look="github"] .foot { font-size: 12px; color: var(--mute); }
162 +
163 +
/* History: GitHub's commit-list quiet. */
164 +
:root[data-look="github"] .lane { stroke: var(--line); }
165 +
:root[data-look="github"] .node { fill: var(--panel); stroke: var(--mute); }
166 +
:root[data-look="github"] .node.head { fill: var(--acc); stroke: var(--acc); }
167 +
:root[data-look="github"] .chg .title { font-weight: 600; }
modified CHANGELOG.md +4 −0
…
1 unchanged lines
2 2
3 3
OxygenHub runs at https://oxygenhub.io; each deploy's build is on the About page and at `/api/v1/version`.
4 4
5 +
## Unreleased
6 +
7 +
- **A trial GitHub-like look (#74).** `?look=github` on any page turns it on for that browser (a cookie keeps it), and `?look=default` turns it off. It uses Primer colours in light and dark, system fonts, rounded boxes, underline navigation, grey and green buttons, sentence case and pill labels. Nobody else sees it: it is for judging whether that layout reads better.
8 +
5 9
## 0.2.0 (2026-10-01)
6 10
7 11
- **One sign-in for oh and oxy (oxygen#47).** `oh auth login` keeps its token in oxy's credential store (`~/.config/oxy/credentials.toml`, or the keyring through `auth.helper`), and `oh` finds tokens there, so `oxy auth login` signs `oh` in too and the reverse. `~/.config/oh/config.toml` now holds only the default hub. Pinned oxygen brings remote bookmarks by name, and clones check out the repository's default bookmark.
…
15 unchanged lines
modified crates/hub/src/web/statics.rs +1 −0
…
22 unchanged lines
23 23
        mime: "font/woff2",
24 24
        bytes: include_bytes!("../../../../assets/fonts/PressStart2P-400.woff2"),
25 25
    },
26 +
    Asset { path: "github.css", mime: "text/css; charset=utf-8", bytes: include_bytes!("../../../../assets/github.css") },
26 27
    Asset { path: "hub.js", mime: "text/javascript; charset=utf-8", bytes: include_bytes!("../../../../assets/hub.js") },
27 28
    Asset {
28 29
        path: "vendor/editor.js",
…
33 unchanged lines
modified templates/base.html +1 −0
…
5 unchanged lines
6 6
<title>{% block title %}{{ shell.site }}{% endblock %} · {{ shell.site }}</title>
7 7
<link rel="stylesheet" href="/style.css">
8 8
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
9 +
<script>/* A trial look (assets/github.css): ?look=github turns it on for this browser, ?look=default off; a cookie keeps it. */(function(){var q=new URLSearchParams(location.search).get("look");if(q==="github")document.cookie="look=github; path=/; max-age=31536000; SameSite=Lax";else if(q==="default")document.cookie="look=; path=/; max-age=0; SameSite=Lax";if(/(?:^|; )look=github/.test(document.cookie)){document.documentElement.dataset.look="github";document.write('<link rel="stylesheet" href="/static/github.css">');}})();</script>
9 10
<script>/* Theme before first paint: the theme cookie (dark, light or auto; dark when unset), auto following the system. */(function(){var d=document.documentElement,m=document.cookie.match(/(?:^|; )theme=(light|dark|auto)/),p=m?m[1]:"dark",q=window.matchMedia&&matchMedia("(prefers-color-scheme: light)");function a(){d.dataset.theme=p==="auto"?(q&&q.matches?"light":"dark"):p;}d.dataset.themePref=p;a();if(q&&q.addEventListener)q.addEventListener("change",function(){if(d.dataset.themePref==="auto")d.dataset.theme=q.matches?"light":"dark";});})();</script>
10 11
</head>
11 12
<body{% block bodyattrs %}{% endblock %}>
…
50 unchanged lines