Commit 531f7afbeb

531f7afbebfdba1a038774b6f1ae873a53f3ad4a

parent: 77df444b20

Unsigned

cmc <hello@cleberg.net> · 2026-03-20 00:35 UTC

update website for v2.1

Layout: unified · split

website/index.html +93 −18
@@ -4,7 +4,9 @@
4<head> 4<head>
5 <meta charset="utf-8" /> 5 <meta charset="utf-8" />
6 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1" />
7 <title>Hutch — native sourcehut client for iPhone</title> 7 <title>Hutch — native SourceHut client for iOS</title>
8 <meta name="description"
9 content="Hutch is a native iOS client for SourceHut with support for repositories, builds, tickets, mailing lists, projects, and more." />
8 <link rel="stylesheet" href="styles.css" /> 10 <link rel="stylesheet" href="styles.css" />
9</head> 11</head>
10 12
@@ -16,51 +18,124 @@
16 <img class="app-icon" src="https://img.cleberg.net/apps/hutch/logo/hutch_light.png" alt="Hutch icon" /> 18 <img class="app-icon" src="https://img.cleberg.net/apps/hutch/logo/hutch_light.png" alt="Hutch icon" />
17 <div> 19 <div>
18 <h1>Hutch</h1> 20 <h1>Hutch</h1>
19 <p class="subtitle">A native sourcehut client for iPhone</p> 21 <p class="subtitle">A native SourceHut client for iOS</p>
20 </div> 22 </div>
21 </a> 23 </a>
22 24
23 <div class="hero-actions"> 25 <div class="hero-actions">
24 <a href="#" class="store-link"> 26 <a href="#" class="store-link" aria-label="Download Hutch on the App Store">
25 <img src="storebutton.svg" class="store-img" alt="Download on the App Store" /> 27 <img src="storebutton.svg" class="store-img" alt="Download on the App Store" />
26 </a> 28 </a>
27 29
28 <nav class="header-links"> 30 <nav class="header-links" aria-label="Hutch links">
29 <a href="https://sr.ht/~ccleberg/Hutch/">Source Code</a> 31 <a href="https://sr.ht/~ccleberg/Hutch/">Source Code</a>
30 <span>·</span> 32 <span>·</span>
31 <a href="mailto:hello@cleberg.net">Email</a> 33 <a href="mailto:hello@cleberg.net">Email</a>
32 </nav> 34 </nav>
33 </div> 35 </div>
34 </div> 36 </div>
37
38 <div class="intro-copy">
39 <p class="lede">SourceHut workflows, built for mobile.</p>
40 <p>Hutch is a fast, native iOS app for working with SourceHut when you are away from your desk. It focuses on
41 the things that matter on mobile: triaging work, reviewing patches, monitoring builds, following discussions,
42 and managing repositories and tickets without a browser.</p>
43 </div>
35 </header> 44 </header>
36 45
37 <main> 46 <main>
47 <div class="info-banner">
48 Hutch is currently under review by Apple and not yet available for download.
49 This page will be updated with the App Store link once approved.
50 </div>
38 <section class="content-grid"> 51 <section class="content-grid">
39 <div> 52 <div>
40 <h2>Why it exists</h2> 53 <h2>Why it exists</h2>
41 <p>Built for people who prefer simple tools, plain text, and fast workflows.</p> 54 <p>SourceHut is intentionally simple, efficient, and workflow-focused. Hutch brings that same philosophy to
42 <p>Sourcehut is popular because of its simplicity and effectiveness, and I wanted an app that inherited those 55 iOS with an interface designed for quick decisions and real work on the go.</p>
43 traits.</p> 56 <p>Instead of treating mobile as a stripped-down viewer, Hutch is meant to be a practical client for reading,
57 responding, creating, and managing work across the SourceHut ecosystem.</p>
44 </div> 58 </div>
45 59
46 <div> 60 <div>
47 <h2>What it does</h2> 61 <h2>What it does</h2>
48 <ul> 62 <ul class="feature-list">
49 <li>Browse repositories</li> 63 <li>Review patch threads and browse mailing lists</li>
50 <li>Monitor builds and logs</li> 64 <li>Manage trackers, tickets, assignees, labels, and comments</li>
51 <li>Manage trackers and tickets</li> 65 <li>Browse Git and Mercurial repositories, files, refs, commits, and diffs</li>
52 <li>Git + Mercurial support</li> 66 <li>Submit, monitor, retry, and inspect builds and logs</li>
53 <li>Profile & key management</li> 67 <li>Follow projects linking repositories, trackers, and lists</li>
68 <li>Manage profile settings, SSH keys, PGP keys, and access tokens</li>
54 </ul> 69 </ul>
55 </div> 70 </div>
56 </section> 71 </section>
57 72
58 <section class="screenshots"> 73 <section class="screenshots">
59 <h2>Interface</h2> 74 <h2>Interface</h2>
60 <div class="shot-grid"> 75 <p class="section-intro">From patch review to trackers, builds, repositories, and project organization, Hutch is
61 <img src="https://img.cleberg.net/apps/hutch/screenshots/code.webp"> 76 built to make SourceHut feel at home on iOS.</p>
62 <img src="https://img.cleberg.net/apps/hutch/screenshots/builds.webp"> 77 <div class="shot-scroll" aria-label="Hutch screenshots">
63 <img src="https://img.cleberg.net/apps/hutch/screenshots/todo.webp"> 78 <figure class="shot-card">
79 <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/01_patch.jpg" alt="Patch review screenshot"
80 loading="lazy" />
81 <figcaption>Review patches anywhere</figcaption>
82 </figure>
83 <figure class="shot-card">
84 <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/02_thread.jpg" alt="Threaded inbox screenshot"
85 loading="lazy" />
86 <figcaption>Stay on top of discussions</figcaption>
87 </figure>
88 <figure class="shot-card">
89 <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/03_builds.jpg" alt="Builds screenshot"
90 loading="lazy" />
91 <figcaption>Monitor builds in real time</figcaption>
92 </figure>
93 <figure class="shot-card">
94 <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/04_tickets.jpg" alt="Tickets screenshot"
95 loading="lazy" />
96 <figcaption>Manage issues on the go</figcaption>
97 </figure>
98 <figure class="shot-card">
99 <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/05_repo.jpg" alt="Repository diff screenshot"
100 loading="lazy" />
101 <figcaption>Explore your code</figcaption>
102 </figure>
103 <figure class="shot-card">
104 <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/06_projects.jpg" alt="Projects screenshot"
105 loading="lazy" />
106 <figcaption>Everything in one place</figcaption>
107 </figure>
108 <figure class="shot-card">
109 <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/07_actions.jpg"
110 alt="Build submission screenshot" loading="lazy" />
111 <figcaption>Take action instantly</figcaption>
112 </figure>
113 </div>
114 </section>
115
116 <section class="feature-sections">
117 <div class="feature-panel">
118 <h2>Major features</h2>
119 <ul class="feature-list">
120 <li>Home dashboard with projects, assigned tickets, recent builds, and inbox shortcuts</li>
121 <li>Unread-first inbox with thread detail, patch rendering, and reply via Apple Mail</li>
122 <li>Git and Mercurial repository browsing, settings, ACLs, and creation flows</li>
123 <li>Tracker and ticket workflows including comments, assignees, resolutions, and labels</li>
124 <li>Build submission, build history, log viewing, cancellation, and rebuild flows</li>
125 <li>Project views linking repositories, trackers, and mailing lists into one hub</li>
126 </ul>
127 </div>
128
129 <div class="feature-panel">
130 <h2>Built for SourceHut users</h2>
131 <ul class="feature-list">
132 <li>Native Swift interface with no analytics, ads, or tracking SDKs</li>
133 <li>Deep links for repositories, tickets, and builds via <code>hutch://</code></li>
134 <li>Share actions across repositories, files, commits, tickets, builds, and profiles</li>
135 <li>Pull-to-refresh, loading states, empty states, and error overlays across major screens</li>
136 <li>Keychain-backed authentication with secure SourceHut personal access tokens</li>
137 <li>Profile management including avatars, SSH keys, PGP keys, and token/grant viewing</li>
138 </ul>
64 </div> 139 </div>
65 </section> 140 </section>
66 141
@@ -80,7 +155,7 @@
80 </section> 155 </section>
81 </main> 156 </main>
82 157
83 <footer> 158 <footer class="site-footer">
84 © 2026 <a href="https://cleberg.net">Christian Cleberg</a> 159 © 2026 <a href="https://cleberg.net">Christian Cleberg</a>
85 </footer> 160 </footer>
86 </div> 161 </div>
website/privacy.html +27 −18
@@ -17,12 +17,12 @@
17 alt="Hutch icon" /> 17 alt="Hutch icon" />
18 <div> 18 <div>
19 <h1>Hutch</h1> 19 <h1>Hutch</h1>
20 <p class="subtitle">A native sourcehut client for iPhone</p> 20 <p class="subtitle">A native SourceHut client for iPhone</p>
21 </div> 21 </div>
22 </a> 22 </a>
23 23
24 <div class="hero-actions"> 24 <div class="hero-actions">
25 <a href="#" class="store-link"> 25 <a href="#" class="store-link" aria-label="Download Hutch on the App Store">
26 <img src="storebutton.svg" class="store-img" alt="Download on the App Store" /> 26 <img src="storebutton.svg" class="store-img" alt="Download on the App Store" />
27 </a> 27 </a>
28 28
@@ -40,12 +40,12 @@
40 <h2>Privacy Policy</h2> 40 <h2>Privacy Policy</h2>
41 41
42 <p><strong>Hutch</strong><br> 42 <p><strong>Hutch</strong><br>
43 Last updated: March 17, 2026</p> 43 Last updated: March 20, 2026</p>
44 44
45 <h3>Overview</h3> 45 <h3>Overview</h3>
46 <p> 46 <p>
47 Hutch is a client for SourceHut. This app allows users to browse repositories, 47 Hutch is a native client for SourceHut on iPhone. It lets users work with repositories,
48 tickets, and builds using their own SourceHut account. 48 projects, mailing lists, tickets, and builds using their own SourceHut account.
49 </p> 49 </p>
50 50
51 <h3>Data Collection</h3> 51 <h3>Data Collection</h3>
@@ -53,8 +53,8 @@
53 Hutch does not collect, store, or transmit personal data to the developer. 53 Hutch does not collect, store, or transmit personal data to the developer.
54 </p> 54 </p>
55 <p> 55 <p>
56 All data displayed in the app is retrieved directly from SourceHut using 56 All data shown in the app is retrieved directly from SourceHut using credentials provided by the
57 user-provided authentication credentials. 57 user.
58 </p> 58 </p>
59 59
60 <h3>Authentication</h3> 60 <h3>Authentication</h3>
@@ -62,16 +62,19 @@
62 Hutch uses a SourceHut Personal Access Token (PAT) provided by the user. 62 Hutch uses a SourceHut Personal Access Token (PAT) provided by the user.
63 </p> 63 </p>
64 <p> 64 <p>
65 The token is stored securely on-device and is used only to authenticate requests 65 The token is stored securely on-device using iOS secure storage and is used only to authenticate
66 requests
66 to SourceHut. The developer does not have access to this token. 67 to SourceHut. The developer does not have access to this token.
67 </p> 68 </p>
68 69
69 <h3>Data Usage</h3> 70 <h3>Data Usage</h3>
70 <p>The app communicates with SourceHut servers to:</p> 71 <p>The app communicates with SourceHut servers to:</p>
71 <ul> 72 <ul>
72 <li>fetch repositories, files, and commits</li> 73 <li>fetch repositories, files, commits, and project metadata</li>
73 <li>retrieve and update tickets</li> 74 <li>retrieve and update trackers, tickets, labels, and comments</li>
74 <li>submit and monitor builds</li> 75 <li>read mailing lists, inbox threads, and patch discussions</li>
76 <li>submit, inspect, cancel, and rebuild build jobs</li>
77 <li>manage profile data, avatars, SSH keys, PGP keys, and access tokens</li>
75 </ul> 78 </ul>
76 <p> 79 <p>
77 No data is transmitted to any servers operated by the developer. 80 No data is transmitted to any servers operated by the developer.
@@ -79,7 +82,11 @@
79 82
80 <h3>Third-Party Services</h3> 83 <h3>Third-Party Services</h3>
81 <p> 84 <p>
82 Hutch communicates with SourceHut services (sr.ht) to retrieve user data. 85 Hutch communicates with SourceHut services (sr.ht) to retrieve and update user data.
86 </p>
87 <p>
88 When replying to mailing list threads, Hutch can hand the message off to Apple Mail using the iOS
89 Mail composer.
83 </p> 90 </p>
84 <p> 91 <p>
85 No analytics, advertising, or tracking SDKs are used. 92 No analytics, advertising, or tracking SDKs are used.
@@ -87,15 +94,17 @@
87 94
88 <h3>User-Generated Content</h3> 95 <h3>User-Generated Content</h3>
89 <p> 96 <p>
90 The app displays content from SourceHut, including repositories, tickets, and 97 Hutch displays and edits content from SourceHut, including repositories, tickets, mailing list
91 builds. This content is accessed based on the user’s authentication and 98 threads,
92 permissions. 99 and builds. This content is accessed based on the user’s authentication and permissions.
93 </p> 100 </p>
94 101
95 <h3>Device Permissions</h3> 102 <h3>Device Permissions</h3>
96 <p> 103 <p>
97 Hutch does not request access to sensitive device data such as location, 104 Hutch may request access to Photos when the user chooses to upload a profile avatar.
98 contacts, camera, or microphone. 105 </p>
106 <p>
107 Hutch does not request access to location, contacts, camera, or microphone.
99 </p> 108 </p>
100 109
101 <h3>Changes to This Policy</h3> 110 <h3>Changes to This Policy</h3>
@@ -112,7 +121,7 @@
112 </main> 121 </main>
113 122
114 <footer class="site-footer"> 123 <footer class="site-footer">
115 © 2026 <a href="https://cleberg.net">Christian Cleberg</a> 124 © 2026 <a href="https://cleberg.net">Christian Cleberg</a>
116 </footer> 125 </footer>
117 </div> 126 </div>
118</body> 127</body>
website/styles.css +191 −25
@@ -1,20 +1,36 @@
1:root {
2 --bg: #f3f3f1;
3 --surface: #fff;
4 --border: #ddd;
5 --text: #111;
6 --muted: rgba(0, 0, 0, 0.62);
7 --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
8 --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.06);
9}
10
11* {
12 box-sizing: border-box;
13}
14
1body { 15body {
2 font-family: system-ui; 16 font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
3 background: #f3f3f1; 17 background: var(--bg);
18 color: var(--text);
4 margin: 0; 19 margin: 0;
5} 20}
6 21
7a, 22a,
8a:visited { 23a:visited {
9 color: blue 24 color: blue;
10} 25}
11 26
12img { 27img {
13 max-width: 100% 28 max-width: 100%;
29 display: block;
14} 30}
15 31
16.page { 32.page {
17 max-width: 900px; 33 max-width: 960px;
18 margin: 0 auto; 34 margin: 0 auto;
19 padding: 16px; 35 padding: 16px;
20} 36}
@@ -23,9 +39,10 @@ img {
23.site-header, 39.site-header,
24.content-grid, 40.content-grid,
25.screenshots, 41.screenshots,
26.resources { 42.resources,
27 border: 1px solid #ddd; 43.feature-sections {
28 background: white; 44 border: 1px solid var(--border);
45 background: var(--surface);
29 margin-bottom: 16px; 46 margin-bottom: 16px;
30 padding: 20px; 47 padding: 20px;
31} 48}
@@ -33,9 +50,13 @@ img {
33.brand-row { 50.brand-row {
34 display: flex; 51 display: flex;
35 justify-content: space-between; 52 justify-content: space-between;
53 gap: 20px;
54 align-items: flex-start;
36} 55}
37 56
38.brand, .brand h1, .brand p { 57.brand,
58.brand h1,
59.brand p {
39 color: black; 60 color: black;
40 text-decoration: none; 61 text-decoration: none;
41} 62}
@@ -44,28 +65,30 @@ img {
44 display: flex; 65 display: flex;
45 gap: 16px; 66 gap: 16px;
46 align-items: center; 67 align-items: center;
68 min-width: 0;
47} 69}
48 70
49.brand h1 { 71.brand h1 {
50 margin: 0; 72 margin: 0;
51} 73}
52 74
75.subtitle,
53.brand p { 76.brand p {
54 margin-top: 0; 77 margin-top: 0;
55 opacity: 0.6; 78 opacity: 0.68;
56} 79}
57 80
58.app-icon { 81.app-icon {
59 width: 80px; 82 width: 80px;
60 border-radius: 18px; 83 border-radius: 18px;
61 border: 1px solid rgba(0, 0, 0, 0.08); 84 border: 1px solid rgba(0, 0, 0, 0.08);
62 box-shadow: 85 box-shadow: var(--shadow-sm), 0 4px 12px rgba(0, 0, 0, 0.08);
63 0 1px 2px rgba(0, 0, 0, 0.06), 86 flex: 0 0 auto;
64 0 4px 12px rgba(0, 0, 0, 0.08);
65} 87}
66 88
67.hero-actions { 89.hero-actions {
68 text-align: right; 90 text-align: right;
91 flex: 0 0 auto;
69} 92}
70 93
71.store-img { 94.store-img {
@@ -78,37 +101,108 @@ img {
78} 101}
79 102
80.intro-copy { 103.intro-copy {
81 margin-top: 16px; 104 margin-top: 18px;
82} 105}
83 106
84.lede { 107.lede {
85 padding-top: 1rem; 108 margin: 0 0 10px;
86 font-weight: bold; 109 font-weight: 700;
110 font-size: 1.125rem;
111}
112
113.intro-copy p:last-child {
114 margin-bottom: 0;
87} 115}
88 116
89.content-grid { 117.content-grid,
118.feature-sections {
90 display: grid; 119 display: grid;
91 grid-template-columns: 1fr 1fr; 120 grid-template-columns: 1fr 1fr;
121 gap: 20px;
122}
123
124.content-grid>div,
125.feature-sections>.feature-panel {
126 min-width: 0;
127}
128
129.content-grid h2,
130.screenshots h2,
131.resources h2,
132.feature-panel h2 {
133 margin-top: 0;
92} 134}
93 135
94.content-grid div:first-child { 136.feature-list {
95 padding-right: 0.5rem; 137 margin: 0;
138 padding-left: 1.2rem;
139 line-height: 1.55;
140}
141
142.feature-list li+li {
143 margin-top: 0.45rem;
96} 144}
97 145
98.content-grid div:last-child { 146.section-intro {
99 padding-left: 0.5rem; 147 margin-top: 0;
148 color: var(--muted);
100} 149}
101 150
102.shot-grid { 151.shot-scroll {
103 display: grid; 152 display: grid;
104 grid-template-columns: repeat(3, 1fr); 153 grid-auto-flow: column;
105 gap: 10px; 154 grid-auto-columns: minmax(220px, 280px);
155 gap: 12px;
156 overflow-x: auto;
157 overscroll-behavior-x: contain;
158 padding-bottom: 8px;
159 scroll-snap-type: x proximity;
160 -webkit-overflow-scrolling: touch;
161}
162
163.shot-scroll::-webkit-scrollbar {
164 height: 10px;
165}
166
167.shot-scroll::-webkit-scrollbar-thumb {
168 background: rgba(0, 0, 0, 0.18);
169}
170
171.shot-card {
172 margin: 0;
173 scroll-snap-align: start;
174 border: 1px solid var(--border);
175 overflow: hidden;
176 background: #fafafa;
177 box-shadow: var(--shadow-md);
178}
179
180.shot-card img {
181 width: 100%;
182 height: auto;
183}
184
185.shot-card figcaption {
186 padding: 10px 12px 12px;
187 font-size: 0.95rem;
188 font-weight: 600;
106} 189}
107 190
108.resource-list { 191.resource-list {
109 display: flex; 192 display: flex;
110 flex-direction: column; 193 flex-direction: column;
111 gap: 6px; 194 gap: 6px;
195 margin: 0;
196 padding-left: 1.2rem;
197}
198
199.resource-list ul {
200 margin-top: 6px;
201}
202
203.site-footer,
204footer {
205 padding: 4px 2px 24px;
112} 206}
113 207
114.privacy h2 { 208.privacy h2 {
@@ -125,7 +219,7 @@ img {
125 219
126.privacy p { 220.privacy p {
127 margin: 0 0 14px; 221 margin: 0 0 14px;
128 line-height: 1.45; 222 line-height: 1.5;
129} 223}
130 224
131.privacy ul { 225.privacy ul {
@@ -145,4 +239,76 @@ img {
145 239
146.privacy a:hover { 240.privacy a:hover {
147 text-decoration: underline; 241 text-decoration: underline;
242}
243
244code {
245 font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
246 font-size: 0.95em;
247}
248
249@media (max-width: 760px) {
250 .page {
251 padding: 12px;
252 }
253
254 .brand-row,
255 .content-grid,
256 .feature-sections {
257 grid-template-columns: 1fr;
258 display: grid;
259 }
260
261 .shot-scroll {
262 grid-auto-columns: minmax(240px, 78vw);
263 }
264
265 .brand-row {
266 gap: 16px;
267 }
268
269 .hero-actions {
270 text-align: left;
271 }
272
273 .brand {
274 align-items: flex-start;
275 }
276
277 .store-img {
278 height: 44px;
279 }
280
281 .content-grid,
282 .feature-sections {
283 gap: 12px;
284 }
285
286 .site-header,
287 .content-grid,
288 .screenshots,
289 .resources,
290 .feature-sections,
291 .privacy {
292 padding: 16px;
293 }
294
295 .feature-list,
296 .resource-list {
297 padding-left: 1.1rem;
298 }
299}
300
301.info-banner {
302 margin: 24px auto;
303 padding: 14px 16px;
304 max-width: 960px;
305
306 background: #fff3cd;
307 border: 1px solid #ffeeba;
308
309 color: #856404;
310 font-size: 14px;
311 line-height: 1.5;
312
313 text-align: center;
148}\ No newline at end of file 314}\ No newline at end of file