A CLI-first git forge.

cli forge git self-hosted

https://gitbay.org

Commit 51cfb502fd

51cfb502fd316e5680f786749bf734b874d848ba

parent: b34003973f

Verified · cmc

cmc <hello@cleberg.net> · 2026-08-24T16:44:04Z

web: richer index and owner listings

Repo tables become lists: linked name, description, default branch
with an inline branch icon, private chip. Owner pages present profile
description and website as a lede, org kind as a chip, and membership
as outlined chips with roles. Index login state styled as a toolbar
with a link-style logout button.
internal/web/static/style.css +39
@@ -159,6 +159,45 @@ p.clone code {
159159 .crumbs { color: var(--muted); font-size: var(--fs-2); }
160160 .desc, td.desc { color: var(--muted); }
161161 .error { color: var(--bad); }
162.meta { color: var(--muted); font-size: var(--fs-1); }
163svg.icon { vertical-align: -0.125em; }
164.lede { font-size: var(--fs-3); margin: var(--sp-2) 0; }
165
166/* repo listings (index, owner pages) */
167ul.repolist { list-style: none; margin: var(--sp-2) 0; padding: 0; }
168ul.repolist li { padding: var(--sp-3) 0; border-bottom: 1px solid var(--faint); }
169ul.repolist li.empty { color: var(--muted); }
170ul.repolist p { margin: 0; }
171ul.repolist .reponame { font-size: var(--fs-3); font-weight: 550; }
172ul.repolist .desc { margin-top: 0.1rem; }
173ul.repolist .meta { margin-top: 0.1rem; }
174
175/* member and org chips on owner pages */
176a.memberchip {
177 display: inline-block;
178 border: 1px solid var(--line);
179 border-radius: var(--r-pill);
180 padding: 0.05rem 0.6rem;
181 color: var(--fg);
182 font-size: var(--fs-1);
183 margin: 0 0.15rem 0.15rem 0;
184}
185a.memberchip:hover { text-decoration: none; border-color: var(--accent); color: var(--accent); }
186a.memberchip .role { color: var(--muted); }
187
188/* index toolbar */
189p.toolbar { color: var(--muted); font-size: var(--fs-2); margin-top: var(--sp-4); }
190form.inline { display: inline; }
191button.linklike {
192 background: none;
193 border: none;
194 color: var(--accent);
195 padding: 0;
196 font: inherit;
197 font-size: var(--fs-2);
198 cursor: pointer;
199}
200button.linklike:hover { text-decoration: underline; filter: none; }
162201
163202 /* cards: README, comments */
164203 .readme, .code {
internal/web/templates/index.html +17 −9
@@ -1,15 +1,23 @@
11 {{define "title"}}{{.Site}}{{end}}
22 {{define "content"}}
3{{if .Viewer}}<p class="crumbs">logged in as {{.Viewer}} · <a href="/new">new repository</a> ·
4<form method="post" action="/logout" style="display:inline"><button type="submit">logout</button></form></p>{{end}}
3{{if .Viewer}}<p class="toolbar">logged in as <strong>{{.Viewer}}</strong> · <a href="/new">new repository</a> ·
4<form method="post" action="/logout" class="inline"><button type="submit" class="linklike">logout</button></form></p>{{end}}
55 <h1>repositories</h1>
6<table>
7{{range .Repos}}<tr><td><a href="/{{.OwnerName}}">{{.OwnerName}}</a>/<a href="/{{.OwnerName}}/{{.Name}}">{{.Name}}</a></td><td class="desc">{{.Desc}}</td><td>{{.DefaultBranch}}</td></tr>
8{{else}}<tr><td>no public repositories</td></tr>{{end}}
9</table>
6<ul class="repolist">
7{{range .Repos}}<li>
8 <p class="reponame"><a href="/{{.OwnerName}}">{{.OwnerName}}</a>/<a href="/{{.OwnerName}}/{{.Name}}">{{.Name}}</a></p>
9 {{if .Desc}}<p class="desc">{{.Desc}}</p>{{end}}
10 <p class="meta">{{template "branchicon"}} {{.DefaultBranch}}</p>
11</li>
12{{else}}<li class="empty">no public repositories yet</li>{{end}}
13</ul>
1014 {{if .Mine}}<h2>your private repositories</h2>
11<table>
12{{range .Mine}}<tr><td><a href="/{{.OwnerName}}/{{.Name}}">{{.OwnerName}}/{{.Name}}</a></td><td class="desc">{{.Desc}}</td><td>{{.Visibility}}</td></tr>
15<ul class="repolist">
16{{range .Mine}}<li>
17 <p class="reponame"><a href="/{{.OwnerName}}/{{.Name}}">{{.OwnerName}}/{{.Name}}</a> <span class="chip chip-neutral">{{.Visibility}}</span></p>
18 {{if .Desc}}<p class="desc">{{.Desc}}</p>{{end}}
19 <p class="meta">{{template "branchicon"}} {{.DefaultBranch}}</p>
20</li>
1321 {{end}}
14</table>{{end}}
22</ul>{{end}}
1523 {{end}}
internal/web/templates/layout.html +2
@@ -35,4 +35,6 @@
3535 </div>
3636 {{end}}
3737
38{{define "branchicon"}}<svg class="icon" width="12" height="12" viewBox="0 0 16 16" aria-hidden="true" fill="currentColor"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628a2.25 2.25 0 0 1-1.5-2.122ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM3.5 3.25a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"/></svg>{{end}}
39
3840 {{define "sigbadge"}}<span class="badge badge-{{.State}}" title="{{.Fingerprint}}">{{.State}}{{if .Signer}} · {{.Signer}}{{end}}</span>{{end}}
internal/web/templates/owner.html +13 −14
@@ -1,17 +1,16 @@
11 {{define "title"}}{{.Owner}} · {{.Site}}{{end}}
22 {{define "content"}}
3<h1>{{.Owner}} <span class="badge badge-unsigned">{{.Kind}}</span></h1>
4{{if .Profile.Description}}<p class="desc">{{.Profile.Description}}</p>{{end}}
5{{if .Profile.Website}}<p class="crumbs"><a href="{{.Profile.Website}}" rel="nofollow me">{{.Profile.Website}}</a></p>{{end}}
6{{if .Orgs}}<p class="crumbs">member of: {{range .Orgs}}<a href="/{{.Username}}">{{.Username}}</a> {{end}}</p>{{end}}
7{{if .Members}}<p class="crumbs">members: {{range .Members}}<a href="/{{.Username}}">{{.Username}}</a> ({{.Role}}) {{end}}</p>{{end}}
8<table>
9{{range .Repos}}<tr>
10 <td><a href="/{{.OwnerName}}/{{.Name}}">{{.Name}}</a></td>
11 <td class="desc">{{.Desc}}</td>
12 <td>{{.Visibility}}</td>
13 <td>{{.DefaultBranch}}</td>
14</tr>
15{{else}}<tr><td>no visible repositories</td></tr>{{end}}
16</table>
3<h1>{{.Owner}} <span class="chip chip-neutral">{{.Kind}}</span></h1>
4{{if .Profile.Description}}<p class="desc lede">{{.Profile.Description}}</p>{{end}}
5{{if .Profile.Website}}<p class="meta"><a href="{{.Profile.Website}}" rel="nofollow me">{{.Profile.Website}}</a></p>{{end}}
6{{if .Orgs}}<p class="meta">member of {{range .Orgs}}<a class="memberchip" href="/{{.Username}}">{{.Username}}</a> {{end}}</p>{{end}}
7{{if .Members}}<p class="meta">members {{range .Members}}<a class="memberchip" href="/{{.Username}}">{{.Username}} <span class="role">{{.Role}}</span></a> {{end}}</p>{{end}}
8<ul class="repolist">
9{{range .Repos}}<li>
10 <p class="reponame"><a href="/{{.OwnerName}}/{{.Name}}">{{.Name}}</a>{{if eq .Visibility "private"}} <span class="chip chip-neutral">private</span>{{end}}</p>
11 {{if .Desc}}<p class="desc">{{.Desc}}</p>{{end}}
12 <p class="meta">{{template "branchicon"}} {{.DefaultBranch}}</p>
13</li>
14{{else}}<li class="empty">no visible repositories</li>{{end}}
15</ul>
1716 {{end}}