steid

@jamesgill /

steid/plans/ui.md
8.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
75### This deliberately breaks the density rules above
76
77[Philosophy]#philosophy says small type and nothing large outside page titles. That
78still holds — for the **tool** surfaces, where code is the hero and density wins:
79browsing a tree, reading a blob, the log, settings. The **profile** is the portfolio
80surface, and it is the one page whose job is to make an impression rather than to be
81operated. The lead item gets editorial weight there and nowhere else.
82
83If a third kind of surface appears, decide which of the two it is rather than
84splitting the difference.
85
86### What it needs that does not exist yet
87
88- **`updated_at` on a repository.** The design promises recency and nothing stores it.
89 Asking git costs one fork per repository — a twelve-repo profile would be ~150ms of
90 `execve` before rendering. So it is a column, touched when a push is authorized.
91 Slightly wrong if a push then fails; the alternative is wrong more expensively.
92- **A `/{handle}/repos` index.** The Repositories tab needs a destination; only
93 `/{handle}/repos/{name}` exists.
94- **A way to choose the lead.** A `pinned` flag on the repository, set from the settings
95 page that now exists. No pin, no lead section — automatic "most recent" would put a
96 dotfiles tweak at the top of a portfolio.
97
98### Mocking is harder than it looks here
99
100**Tailwind classes the app does not already use are not in the built stylesheet.**
101`build.rs` scans the real sources, so a mockup written against the served CSS silently
102loses any new utility — `gap-7` and `tracking-widest` collapsed a nav into
103`OverviewRepositories3WritingProjects` before this was understood. Iterate either in the
104app itself or, for throwaway exploration, in plain CSS against the theme's custom
105properties (`--background`, `--foreground`, `--muted-foreground`, `--border`, `--surface`).
106
107Dark mode is a `.dark` class on an ancestor, not `prefers-color-scheme`; a mockup
108without it renders light.
109
ab7fea9chore: plans setup1mo
110## Stack
111
af126c7feat: tailwind theme and the first components25d
112Settled in [0005]decisions/0005-tailwind-and-copied-components.md.
ab7fea9chore: plans setup1mo
113
af126c7feat: tailwind theme and the first components25d
114| Concern | Choice |
115|---|---|
116| Styling | Tailwind via Topcoat's build script — no Node |
117| Theme | `styles.css` at the package root: design tokens, dark-first |
118| Components | `topcoat ui add` for primitives, hand-written for Steid's own |
119| Mono | IBM Plex Mono, for paths, hashes, branches, handles |
ab7fea9chore: plans setup1mo
120
af126c7feat: tailwind theme and the first components25d
121### Tokens
ab7fea9chore: plans setup1mo
122
af126c7feat: tailwind theme and the first components25d
123Defined in `styles.css` on `:root` (light) and `.dark` (dark, the default):
124
125```
126background surface foreground muted-foreground
127primary primary-foreground
128success success-foreground confirmations, git additions
129warning warning-foreground caution, git modifications
130destructive destructive-foreground errors, git deletions
131border ring shadow-xs shadow-sm
132```
133
134`surface`, `success` and `warning` are Steid's additions to Topcoat's `neutral` theme;
135the rest were retuned to the palette below.
136
137**Components reference tokens, never raw colours.** A hardcoded colour will not follow
138a palette change and will not adapt to the colour scheme. This is the convention to
139enforce in review.
140
141### Working on it
ab7fea9chore: plans setup1mo
142
af126c7feat: tailwind theme and the first components25d
143```bash
144topcoat dev # rebuilds CSS and re-bundles on change
145topcoat asset bundle # manual builds only; a stale bundle serves stale CSS
146topcoat ui list # what the registry offers
147topcoat ui add <name> # copies source into src/components/
148```
ab7fea9chore: plans setup1mo
149
64222c3docs: record the icon staging trap and tick the repo-creation check24d
150`components.toml` is the record of what is installed; don't duplicate that list here.
151
152**A registry component can need more than a copy.** `select` draws its chevron with an
153Iconify icon, which needs the `icon-iconify` feature on `topcoat` *and* the icon set
154staged in `build.rs`:
155
156```rust
157topcoat::icon::iconify::BuildConfig::new().icon_set("feather").stage().unwrap();
158```
159
160The build fails with a message naming the missing set, so it is discoverable — but the
161build.rs edit is easy not to expect from a command that only advertises copying a file.
162Icons are embedded at build time; nothing is fetched at runtime.
163
164`topcoat ui add` also rewrites the module list in `src/components.rs` by appending, so
165re-alphabetise it afterwards.
166
ab7fea9chore: plans setup1mo
167## Prior art
168
169Attempt #1 (`steid-backup/AGENTS/UI.md`) has a complete 643-line design system —
170OKLCH light/dark palettes with concrete token values, a type scale, spacing scale, and
171component markup for sidebar, file tree, commit bar, breadcrumbs, badges, empty
172states. It was written for Tailwind + DaisyUI.
173
af126c7feat: tailwind theme and the first components25d
174Its palette has been mined already — the dark-first OKLCH values at hue 260 are what
175`styles.css` was retuned to. Its component markup has not, and comes with two caveats:
176it specifies DaisyUI, which is a separate choice from Tailwind and not bundled by
177Topcoat; and it was written for a GitHub-shaped forge rather than a portfolio-first
178one.
ab7fea9chore: plans setup1mo
179
180It is also, on its own, longer than every other doc in this directory combined — for
181an app that had about nine pages. Take the palette and the principles. Don't
182re-specify components before there are components.