Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Build a landing page and simplify the forge chrome

074ae1605e177e99533af02d8c69ccd1a6a947bb · Keenan Nemetz · 14d ago · parent 62576fa8

Build a landing page and simplify the forge chrome

The instance root is now a landing page rather than the full activity feed:
forge identity, project cards with top language, last commit, issue/change
counts and latest release, a short activity rail, and a first-run empty state.
The full feed moves to /activity with type filters and pagination.

Feeds now cover issues, changes, comments, and releases only; commits and CI
runs already have their own pages. Configuration gains instance_name and
instance_tagline.

Navigation: the crowded global bar becomes Runners, Activity, search, and an
account menu holding Admin, Status, and Log out. Repository pages show the name
and description above the tabs at the home-page header scale, while tab-page
titles stay small. Top-level pages keep the larger header. Drop the workflow
run chip, assigned-issues strip, repository size stat, and footer Status link.

server/web/templates/home.html +86−67

@@ -1,84 +1,103 @@
1 1 {{define "index"}}
2 2 {{template "header" .}}
3 {{if .Query}}
4 <div class="page-head">
5 <div class="page-head-main">
6 <h1>Repositories</h1>
7 <p class="page-sub">Matches for “{{.Query}}”</p>
3 <section class="hero">
4 <div class="hero-main">
5 <h1>{{.Instance.Name}}</h1>
6 <p class="hero-tagline">{{.Instance.Tagline}}</p>
7 {{if .Query}}
8 <p class="hero-vitals">Results for “{{.Query}}” · <a href="/">clear search</a></p>
9 {{else}}
10 <p class="hero-vitals">{{.Vitals.Repos}} {{if eq .Vitals.Repos 1}}repository{{else}}repositories{{end}}{{if .Vitals.ShowRunners}} · {{if .Vitals.Runners}}{{.Vitals.Runners}} runner{{if ne .Vitals.Runners 1}}s{{end}} online{{else}}no runners online{{end}}{{end}}{{if not .Vitals.LastActivity.IsZero}} · last activity {{since .Vitals.LastActivity.Unix}}{{end}}</p>
11 {{end}}
8 12 </div>
9 </div>
10
11 <form class="filters" method="get" action="/" role="search">
12 <input type="search" name="q" value="{{.Query}}" placeholder="Search repositories" aria-label="Search repositories">
13 <button type="submit">{{icon "search"}}Search</button>
14 <a href="/">clear</a>
15 </form>
13 <div class="hero-actions">
14 {{if and .InstanceAdmin .Cards}}<a class="button" href="/admin/repos/new">{{icon "plus"}}New repository</a>{{end}}
15 {{if not .LoggedIn}}
16 <a class="button secondary" href="/login">{{icon "user"}}Sign in</a>
17 {{if .OpenRegistration}}<a class="button secondary" href="/register">Create an account</a>{{end}}
18 {{end}}
19 </div>
20 </section>
16 21
17 {{if .Repos}}
18 <div class="panel">
19 <table>
20 <thead><tr><th>Name</th><th>Description</th><th>Created</th></tr></thead>
21 <tbody>
22 {{range .Repos}}
23 <tr>
24 <td><a href="/r/{{.Name}}">{{.Name}}</a></td>
25 <td class="muted">{{.Description}}</td>
26 <td class="muted nowrap">{{since .Created.Unix}}</td>
27 </tr>
28 {{end}}
29 </tbody>
30 </table>
31 </div>
32 {{else}}
33 <div class="empty-state">
34 <p>No repositories match “{{.Query}}”.</p>
35 <p class="muted">Search looks at repository names and descriptions. Private repositories you cannot read are not included.</p>
36 <a href="/">Clear the search</a>
37 </div>
38 {{end}}
39 {{else}}
40 <div class="home">
22 {{if .Cards}}
23 <div class="home-grid">
41 24 <section class="home-main">
42 <div class="page-head">
43 <div class="page-head-main">
44 <h1>Recent activity</h1>
45 <p class="page-sub">Across every repository you can read.</p>
46 </div>
25 <div class="section-head">
26 <h2>{{if .Query}}Results{{else}}Projects{{end}}</h2>
47 27 </div>
48 {{if .Events}}
49 {{template "activity_events" .}}
50 {{else if .Repos}}
51 <div class="empty-state">
52 <p>No activity yet.</p>
53 <p class="muted">Push a commit, open an issue, or queue a run in one of the repositories.</p>
28 <div class="repo-grid">
29 {{range .Cards}}{{template "repo_card" .}}{{end}}
54 30 </div>
55 {{else}}
56 <div class="empty-state">
57 <p>No repositories yet.</p>
58 <p class="muted">An instance admin can create one.{{if .InstanceAdmin}} <a href="/admin/repos/new">Create a repository</a>.{{end}}</p>
59 </div>
60 {{end}}
61 31 </section>
62 32
63 <aside class="home-side">
64 <h2>Repositories</h2>
65 <form class="side-search" method="get" action="/" role="search">
66 <input type="search" name="q" placeholder="Search repositories" aria-label="Search repositories">
67 </form>
68 {{if .Repos}}
69 <div class="side-list repo-side">
70 {{range .Repos}}
71 <a class="side-row" href="/r/{{.Name}}">
72 <span class="row-title">{{.Name}}</span>
73 {{if .Description}}<span class="muted">{{.Description}}</span>{{end}}
74 </a>
75 {{end}}
33 {{if not .Query}}
34 <aside class="home-rail">
35 <div class="section-head">
36 <h2>Latest</h2>
37 <a class="more" href="/activity">all activity</a>
76 38 </div>
39 {{if .Events}}
40 {{template "activity_events" .}}
77 41 {{else}}
78 <p class="muted">No repositories.</p>
42 <p class="muted">Nothing has happened yet. Push a commit, open an issue, or queue a run.</p>
79 43 {{end}}
80 44 </aside>
45 {{end}}
46 </div>
47 {{else if .Query}}
48 <div class="empty-state">
49 <p>No repositories match “{{.Query}}”.</p>
50 <p class="muted">Search looks at repository names and descriptions. Private repositories you cannot read are not included.</p>
51 <a href="/">Clear the search</a>
52 </div>
53 {{else if .InstanceAdmin}}
54 <div class="empty-state first-run">
55 <span class="empty-icon" aria-hidden="true">{{icon "folder"}}</span>
56 <h2>No repositories yet</h2>
57 <p class="muted">A repository is where code, issues, changes, and runs live. Create the first one to get started.</p>
58 <p class="empty-actions"><a class="button" href="/admin/repos/new">{{icon "plus"}}New repository</a></p>
59 <p class="empty-hint">Or from the instance directory: <code>vole admin repo create demo --owner {{if .User}}{{.User}}{{else}}you{{end}}</code></p>
60 </div>
61 {{else if .LoggedIn}}
62 <div class="empty-state">
63 <p>You do not have access to any repositories yet.</p>
64 <p class="muted">An instance admin can grant your account a role on a repository. Once you have one, it appears here.</p>
65 </div>
66 {{else}}
67 <div class="empty-state">
68 <p>Nothing here is readable without an account.</p>
69 <p class="muted">Sign in with a passkey to see the repositories you have access to. Read-only clones of public repositories need no account.</p>
70 <p><a class="button" href="/login">Sign in</a>{{if .OpenRegistration}} <a class="button secondary" href="/register">Create an account</a>{{end}}</p>
81 71 </div>
82 72 {{end}}
83 73 {{template "footer" .}}
84 74 {{end}}
75
76 {{define "repo_card"}}
77 <article class="repo-card">
78 <div class="repo-card-top">
79 <span class="repo-vis" title="{{if .Private}}Private repository{{else}}Public repository{{end}}">{{if .Private}}{{icon "lock"}}{{else}}{{icon "globe"}}{{end}}</span>
80 <h3><a href="/r/{{.Name}}" title="{{if .Private}}Private repository{{else}}Public repository{{end}}">{{.Name}}</a></h3>
81 {{if .Language}}<span class="repo-lang"><span class="lang-dot {{.LangClass}}" aria-hidden="true"></span>{{.Language}}</span>{{end}}
82 {{if not .Updated.IsZero}}<span class="repo-updated" title="Last activity">{{since .Updated.Unix}}</span>{{end}}
83 </div>
84 {{if .Description}}<p class="repo-desc">{{.Description}}</p>{{end}}
85 <p class="repo-meta">
86 {{if .Commit}}
87 <span class="sha">{{.Branch}}@{{short .Commit.SHA}}</span>
88 <span class="repo-subject">{{.Commit.Subject}}</span>
89 <span>{{.Commit.Author}}</span>
90 <span>{{since .Commit.When}}</span>
91 {{else}}
92 <span class="muted">No commits yet</span>
93 {{end}}
94 </p>
95 {{if or .OpenIssues .OpenChanges .LastTag}}
96 <div class="repo-chips">
97 {{if .OpenIssues}}<a class="chip" href="/r/{{.Name}}/issues">{{icon "circle-dot"}}{{.OpenIssues}} issue{{if ne .OpenIssues 1}}s{{end}}</a>{{end}}
98 {{if .OpenChanges}}<a class="chip" href="/r/{{.Name}}/requests">{{icon "git-pull-request"}}{{.OpenChanges}} change{{if ne .OpenChanges 1}}s{{end}}</a>{{end}}
99 {{if .LastTag}}<a class="chip" href="/r/{{.Name}}/releases/{{.LastTag.Name}}">{{icon "tag"}}{{.LastTag.Name}}</a>{{end}}
100 </div>
101 {{end}}
102 </article>
103 {{end}}