steid

@jamesgill /

steid/plans/ui.md
9.3 KBCode·Blame·Raw
ab7fea9chore: plans setup1mo
1# UI
2
3## Philosophy
4
5A developer tool people use daily to browse code and manage repos. Optimise for:
6
71. **Speed-first** — minimise clicks, maximise information density
82. **Scannable** — find what you need in under a second
93. **Quiet confidence** — premium without flashy; the UI should disappear
104. **Code-centric** — code is the hero, everything else supports it
11
12| Principle | Meaning |
13|---|---|
14| Readable density | Compact without cramped. Maximise info per viewport. |
15| Clear hierarchy | Strong contrast between labels, content, and muted elements |
16| Functional spacing | 8px on items, 12–16px on sections. No wasted space. |
17| Keyboard-first | Every action reachable without a mouse |
18| Dark-mode primary | Developers live in dark mode. Light mode is supported, secondary. |
19
20**Do:** small type (`text-xs` / `text-sm` for most UI), small buttons, monospace for
21paths, SHAs, and branch names, opacity modifiers for text hierarchy, tight spacing.
22
23**Don't:** large type outside page titles, shadows in dark mode (use borders), bright
24backgrounds, hover animations that move or resize things.
25
26## Where the portfolio framing bites
27
28Steid is portfolio-first, not a Gitea clone. The profile page is the product — repos
29are one kind of thing on it, alongside writing and projects. Any layout inherited from
30a GitHub-shaped forge needs checking against that before it's copied.
31
f0afae5docs: settle the profile page on flat navigation7d
32## The profile page
33
34Settled 2026-08-29, after looking at the built page with real data rather than
35imagining it. Three sections of equal weight — Repositories, Writing, Projects — two of
36them empty boxes, repositories sorted alphabetically so `dotfiles` outranked `steid`.
37A third of the page was content and two thirds advertised incompleteness.
38
39**Flat, app-style navigation. No cards, no boxes.**
40
41```
42James Gill
43@jamesgill
44<bio>
45<links>
46─────────────────────────────────────────────
47Overview Repositories 3 Writing
48─────────────────────────────────────────────
49CURRENTLY BUILDING
50steid Rust
51A self-hostable gitforge where the profile is the product.
52421 tests · updated 2 hours ago
53
54REPOSITORIES All 3 →
55──────────────────────────────────────────
56topcoat-notes 3d
57Notes on building with Topcoat 0.5.
58──────────────────────────────────────────
59dotfiles 2w
60```
61
62- **A tab bar, not stacked sections.** Empty sections stop being visible failures and
63 become destinations that simply have nothing in them yet. It is also what makes
64 Writing shippable without redesigning the page around it.
65- **Tabs are links.** No JavaScript, and each tab is a real URL that can be shared.
66- **One lead item with genuine typographic weight**, then a compact list. This is the
67 editorial layer portfolio-first requires: without it the page has no opinion about
68 what matters, and ordering alone cannot carry that.
69- **Hairlines and hover states, never bordered containers.** The row is the unit.
70- **Recency, not alphabetical.** Alphabetical is a filing rule; a portfolio needs an
71 editorial one.
72- **Sections with nothing in them are hidden from visitors** and shown to the owner as
73 an affordance.
74
30ba450docs: one design language, hierarchy without scale7d
75### One vibe. Hierarchy without scale.
76
77The first version of this design gave the lead item large type and justified it by
78splitting the product into a "portfolio surface" and a "tool surface" with different
79rules. **That was wrong and is not what ships.** Two design languages in one product is
80how a product stops feeling like one thing, and it contradicted this file's own
81philosophy — quiet confidence, the UI disappears, small type throughout.
82
83Nothing exceeds 14px except the page title. The lead item is distinguished by
84**everything except size**:
85
86| Device | Lead | List row |
87|---|---|---|
88| Eyebrow label | yes | no |
89| Weight | 600 | 500 |
90| Description | full width, roomy | compact |
91| Space around it | generous | tight |
92| Separator | hairline below | none |
93
94The cost, stated plainly: the distinction is **subtle**. One weight step is not much,
95and the eyebrow and whitespace carry most of it. That is the right trade for a developer
96tool — but it means the copy in the eyebrow is load-bearing, because it is the clearest
97signal that this item is different.
98
10b155cdocs: the profile eyebrow says "Currently building"7d
99**The eyebrow reads "Currently building"**, chosen over a neutral "Featured". It says
100something rather than labelling something, which is what a portfolio built in public
101wants. The known cost: it is a claim about the present, so pinning a finished project
102makes the page lie. The answer if that becomes a problem is a per-pin label, not a
103blander default.
104
30ba450docs: one design language, hierarchy without scale7d
105The general rule this sets: **hierarchy comes from weight, colour and space. Reach for
106size last, and outside a page title, probably not at all.**
f0afae5docs: settle the profile page on flat navigation7d
107
108### What it needs that does not exist yet
109
110- **`updated_at` on a repository.** The design promises recency and nothing stores it.
111 Asking git costs one fork per repository — a twelve-repo profile would be ~150ms of
112 `execve` before rendering. So it is a column, touched when a push is authorized.
113 Slightly wrong if a push then fails; the alternative is wrong more expensively.
114- **A `/{handle}/repos` index.** The Repositories tab needs a destination; only
115 `/{handle}/repos/{name}` exists.
116- **A way to choose the lead.** A `pinned` flag on the repository, set from the settings
117 page that now exists. No pin, no lead section — automatic "most recent" would put a
118 dotfiles tweak at the top of a portfolio.
119
120### Mocking is harder than it looks here
121
122**Tailwind classes the app does not already use are not in the built stylesheet.**
123`build.rs` scans the real sources, so a mockup written against the served CSS silently
124loses any new utility — `gap-7` and `tracking-widest` collapsed a nav into
125`OverviewRepositories3WritingProjects` before this was understood. Iterate either in the
126app itself or, for throwaway exploration, in plain CSS against the theme's custom
127properties (`--background`, `--foreground`, `--muted-foreground`, `--border`, `--surface`).
128
129Dark mode is a `.dark` class on an ancestor, not `prefers-color-scheme`; a mockup
130without it renders light.
131
ab7fea9chore: plans setup1mo
132## Stack
133
af126c7feat: tailwind theme and the first components25d
134Settled in [0005]decisions/0005-tailwind-and-copied-components.md.
ab7fea9chore: plans setup1mo
135
af126c7feat: tailwind theme and the first components25d
136| Concern | Choice |
137|---|---|
138| Styling | Tailwind via Topcoat's build script — no Node |
139| Theme | `styles.css` at the package root: design tokens, dark-first |
140| Components | `topcoat ui add` for primitives, hand-written for Steid's own |
141| Mono | IBM Plex Mono, for paths, hashes, branches, handles |
ab7fea9chore: plans setup1mo
142
af126c7feat: tailwind theme and the first components25d
143### Tokens
ab7fea9chore: plans setup1mo
144
af126c7feat: tailwind theme and the first components25d
145Defined in `styles.css` on `:root` (light) and `.dark` (dark, the default):
146
147```
148background surface foreground muted-foreground
149primary primary-foreground
150success success-foreground confirmations, git additions
151warning warning-foreground caution, git modifications
152destructive destructive-foreground errors, git deletions
153border ring shadow-xs shadow-sm
154```
155
156`surface`, `success` and `warning` are Steid's additions to Topcoat's `neutral` theme;
157the rest were retuned to the palette below.
158
159**Components reference tokens, never raw colours.** A hardcoded colour will not follow
160a palette change and will not adapt to the colour scheme. This is the convention to
161enforce in review.
162
163### Working on it
ab7fea9chore: plans setup1mo
164
af126c7feat: tailwind theme and the first components25d
165```bash
166topcoat dev # rebuilds CSS and re-bundles on change
167topcoat asset bundle # manual builds only; a stale bundle serves stale CSS
168topcoat ui list # what the registry offers
169topcoat ui add <name> # copies source into src/components/
170```
ab7fea9chore: plans setup1mo
171
64222c3docs: record the icon staging trap and tick the repo-creation check24d
172`components.toml` is the record of what is installed; don't duplicate that list here.
173
174**A registry component can need more than a copy.** `select` draws its chevron with an
175Iconify icon, which needs the `icon-iconify` feature on `topcoat` *and* the icon set
176staged in `build.rs`:
177
178```rust
179topcoat::icon::iconify::BuildConfig::new().icon_set("feather").stage().unwrap();
180```
181
182The build fails with a message naming the missing set, so it is discoverable — but the
183build.rs edit is easy not to expect from a command that only advertises copying a file.
184Icons are embedded at build time; nothing is fetched at runtime.
185
186`topcoat ui add` also rewrites the module list in `src/components.rs` by appending, so
187re-alphabetise it afterwards.
188
ab7fea9chore: plans setup1mo
189## Prior art
190
191Attempt #1 (`steid-backup/AGENTS/UI.md`) has a complete 643-line design system —
192OKLCH light/dark palettes with concrete token values, a type scale, spacing scale, and
193component markup for sidebar, file tree, commit bar, breadcrumbs, badges, empty
194states. It was written for Tailwind + DaisyUI.
195
af126c7feat: tailwind theme and the first components25d
196Its palette has been mined already — the dark-first OKLCH values at hue 260 are what
197`styles.css` was retuned to. Its component markup has not, and comes with two caveats:
198it specifies DaisyUI, which is a separate choice from Tailwind and not bundled by
199Topcoat; and it was written for a GitHub-shaped forge rather than a portfolio-first
200one.
ab7fea9chore: plans setup1mo
201
202It is also, on its own, longer than every other doc in this directory combined — for
203an app that had about nine pages. Take the palette and the principles. Don't
204re-specify components before there are components.