krz/hutch

an ios client for sourcehut

clone: git clone https://gitbay.org/krz/hutch.git

f3effdc0691ce2015474529977e6200a25f1b309

verified · cmc

author: Christian Cleberg <hello@cleberg.net> · 2026-03-20T00:35:48Z

update website for v2.1
 website/index.html   | 111 +++++++++++++++++++++-----
 website/privacy.html |  45 ++++++-----
 website/styles.css   | 216 +++++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 311 insertions(+), 61 deletions(-)

diff --git a/website/index.html b/website/index.html
index fb711e2..296f803 100644
--- a/website/index.html
+++ b/website/index.html
@@ -4,7 +4,9 @@
 <head>
   <meta charset="utf-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1" />
-  <title>Hutch — native sourcehut client for iPhone</title>
+  <title>Hutch — native SourceHut client for iOS</title>
+  <meta name="description"
+    content="Hutch is a native iOS client for SourceHut with support for repositories, builds, tickets, mailing lists, projects, and more." />
   <link rel="stylesheet" href="styles.css" />
 </head>
 
@@ -16,51 +18,124 @@
           <img class="app-icon" src="https://img.cleberg.net/apps/hutch/logo/hutch_light.png" alt="Hutch icon" />
           <div>
             <h1>Hutch</h1>
-            <p class="subtitle">A native sourcehut client for iPhone</p>
+            <p class="subtitle">A native SourceHut client for iOS</p>
           </div>
         </a>
 
         <div class="hero-actions">
-          <a href="#" class="store-link">
+          <a href="#" class="store-link" aria-label="Download Hutch on the App Store">
             <img src="storebutton.svg" class="store-img" alt="Download on the App Store" />
           </a>
 
-          <nav class="header-links">
+          <nav class="header-links" aria-label="Hutch links">
             <a href="https://sr.ht/~ccleberg/Hutch/">Source Code</a>
             <span>·</span>
             <a href="mailto:hello@cleberg.net">Email</a>
           </nav>
         </div>
       </div>
+
+      <div class="intro-copy">
+        <p class="lede">SourceHut workflows, built for mobile.</p>
+        <p>Hutch is a fast, native iOS app for working with SourceHut when you are away from your desk. It focuses on
+          the things that matter on mobile: triaging work, reviewing patches, monitoring builds, following discussions,
+          and managing repositories and tickets without a browser.</p>
+      </div>
     </header>
 
     <main>
+      <div class="info-banner">
+        Hutch is currently under review by Apple and not yet available for download.
+        This page will be updated with the App Store link once approved.
+      </div>
       <section class="content-grid">
         <div>
           <h2>Why it exists</h2>
-          <p>Built for people who prefer simple tools, plain text, and fast workflows.</p>
-          <p>Sourcehut is popular because of its simplicity and effectiveness, and I wanted an app that inherited those
-            traits.</p>
+          <p>SourceHut is intentionally simple, efficient, and workflow-focused. Hutch brings that same philosophy to
+            iOS with an interface designed for quick decisions and real work on the go.</p>
+          <p>Instead of treating mobile as a stripped-down viewer, Hutch is meant to be a practical client for reading,
+            responding, creating, and managing work across the SourceHut ecosystem.</p>
         </div>
 
         <div>
           <h2>What it does</h2>
-          <ul>
-            <li>Browse repositories</li>
-            <li>Monitor builds and logs</li>
-            <li>Manage trackers and tickets</li>
-            <li>Git + Mercurial support</li>
-            <li>Profile & key management</li>
+          <ul class="feature-list">
+            <li>Review patch threads and browse mailing lists</li>
+            <li>Manage trackers, tickets, assignees, labels, and comments</li>
+            <li>Browse Git and Mercurial repositories, files, refs, commits, and diffs</li>
+            <li>Submit, monitor, retry, and inspect builds and logs</li>
+            <li>Follow projects linking repositories, trackers, and lists</li>
+            <li>Manage profile settings, SSH keys, PGP keys, and access tokens</li>
           </ul>
         </div>
       </section>
 
       <section class="screenshots">
         <h2>Interface</h2>
-        <div class="shot-grid">
-          <img src="https://img.cleberg.net/apps/hutch/screenshots/code.webp">
-          <img src="https://img.cleberg.net/apps/hutch/screenshots/builds.webp">
-          <img src="https://img.cleberg.net/apps/hutch/screenshots/todo.webp">
+        <p class="section-intro">From patch review to trackers, builds, repositories, and project organization, Hutch is
+          built to make SourceHut feel at home on iOS.</p>
+        <div class="shot-scroll" aria-label="Hutch screenshots">
+          <figure class="shot-card">
+            <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/01_patch.jpg" alt="Patch review screenshot"
+              loading="lazy" />
+            <figcaption>Review patches anywhere</figcaption>
+          </figure>
+          <figure class="shot-card">
+            <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/02_thread.jpg" alt="Threaded inbox screenshot"
+              loading="lazy" />
+            <figcaption>Stay on top of discussions</figcaption>
+          </figure>
+          <figure class="shot-card">
+            <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/03_builds.jpg" alt="Builds screenshot"
+              loading="lazy" />
+            <figcaption>Monitor builds in real time</figcaption>
+          </figure>
+          <figure class="shot-card">
+            <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/04_tickets.jpg" alt="Tickets screenshot"
+              loading="lazy" />
+            <figcaption>Manage issues on the go</figcaption>
+          </figure>
+          <figure class="shot-card">
+            <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/05_repo.jpg" alt="Repository diff screenshot"
+              loading="lazy" />
+            <figcaption>Explore your code</figcaption>
+          </figure>
+          <figure class="shot-card">
+            <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/06_projects.jpg" alt="Projects screenshot"
+              loading="lazy" />
+            <figcaption>Everything in one place</figcaption>
+          </figure>
+          <figure class="shot-card">
+            <img src="https://img.cleberg.net/apps/hutch/screenshots/iOS/07_actions.jpg"
+              alt="Build submission screenshot" loading="lazy" />
+            <figcaption>Take action instantly</figcaption>
+          </figure>
+        </div>
+      </section>
+
+      <section class="feature-sections">
+        <div class="feature-panel">
+          <h2>Major features</h2>
+          <ul class="feature-list">
+            <li>Home dashboard with projects, assigned tickets, recent builds, and inbox shortcuts</li>
+            <li>Unread-first inbox with thread detail, patch rendering, and reply via Apple Mail</li>
+            <li>Git and Mercurial repository browsing, settings, ACLs, and creation flows</li>
+            <li>Tracker and ticket workflows including comments, assignees, resolutions, and labels</li>
+            <li>Build submission, build history, log viewing, cancellation, and rebuild flows</li>
+            <li>Project views linking repositories, trackers, and mailing lists into one hub</li>
+          </ul>
+        </div>
+
+        <div class="feature-panel">
+          <h2>Built for SourceHut users</h2>
+          <ul class="feature-list">
+            <li>Native Swift interface with no analytics, ads, or tracking SDKs</li>
+            <li>Deep links for repositories, tickets, and builds via <code>hutch://</code></li>
+            <li>Share actions across repositories, files, commits, tickets, builds, and profiles</li>
+            <li>Pull-to-refresh, loading states, empty states, and error overlays across major screens</li>
+            <li>Keychain-backed authentication with secure SourceHut personal access tokens</li>
+            <li>Profile management including avatars, SSH keys, PGP keys, and token/grant viewing</li>
+          </ul>
         </div>
       </section>
 
@@ -80,7 +155,7 @@
       </section>
     </main>
 
-    <footer>
+    <footer class="site-footer">
       © 2026 <a href="https://cleberg.net">Christian Cleberg</a>
     </footer>
   </div>
diff --git a/website/privacy.html b/website/privacy.html
index cc7392e..5d50be4 100644
--- a/website/privacy.html
+++ b/website/privacy.html
@@ -17,12 +17,12 @@
                         alt="Hutch icon" />
                     <div>
                         <h1>Hutch</h1>
-                        <p class="subtitle">A native sourcehut client for iPhone</p>
+                        <p class="subtitle">A native SourceHut client for iPhone</p>
                     </div>
                 </a>
 
                 <div class="hero-actions">
-                    <a href="#" class="store-link">
+                    <a href="#" class="store-link" aria-label="Download Hutch on the App Store">
                         <img src="storebutton.svg" class="store-img" alt="Download on the App Store" />
                     </a>
 
@@ -40,12 +40,12 @@
                 <h2>Privacy Policy</h2>
 
                 <p><strong>Hutch</strong><br>
-                    Last updated: March 17, 2026</p>
+                    Last updated: March 20, 2026</p>
 
                 <h3>Overview</h3>
                 <p>
-                    Hutch is a client for SourceHut. This app allows users to browse repositories,
-                    tickets, and builds using their own SourceHut account.
+                    Hutch is a native client for SourceHut on iPhone. It lets users work with repositories,
+                    projects, mailing lists, tickets, and builds using their own SourceHut account.
                 </p>
 
                 <h3>Data Collection</h3>
@@ -53,8 +53,8 @@
                     Hutch does not collect, store, or transmit personal data to the developer.
                 </p>
                 <p>
-                    All data displayed in the app is retrieved directly from SourceHut using
-                    user-provided authentication credentials.
+                    All data shown in the app is retrieved directly from SourceHut using credentials provided by the
+                    user.
                 </p>
 
                 <h3>Authentication</h3>
@@ -62,16 +62,19 @@
                     Hutch uses a SourceHut Personal Access Token (PAT) provided by the user.
                 </p>
                 <p>
-                    The token is stored securely on-device and is used only to authenticate requests
+                    The token is stored securely on-device using iOS secure storage and is used only to authenticate
+                    requests
                     to SourceHut. The developer does not have access to this token.
                 </p>
 
                 <h3>Data Usage</h3>
                 <p>The app communicates with SourceHut servers to:</p>
                 <ul>
-                    <li>fetch repositories, files, and commits</li>
-                    <li>retrieve and update tickets</li>
-                    <li>submit and monitor builds</li>
+                    <li>fetch repositories, files, commits, and project metadata</li>
+                    <li>retrieve and update trackers, tickets, labels, and comments</li>
+                    <li>read mailing lists, inbox threads, and patch discussions</li>
+                    <li>submit, inspect, cancel, and rebuild build jobs</li>
+                    <li>manage profile data, avatars, SSH keys, PGP keys, and access tokens</li>
                 </ul>
                 <p>
                     No data is transmitted to any servers operated by the developer.
@@ -79,7 +82,11 @@
 
                 <h3>Third-Party Services</h3>
                 <p>
-                    Hutch communicates with SourceHut services (sr.ht) to retrieve user data.
+                    Hutch communicates with SourceHut services (sr.ht) to retrieve and update user data.
+                </p>
+                <p>
+                    When replying to mailing list threads, Hutch can hand the message off to Apple Mail using the iOS
+                    Mail composer.
                 </p>
                 <p>
                     No analytics, advertising, or tracking SDKs are used.
@@ -87,15 +94,17 @@
 
                 <h3>User-Generated Content</h3>
                 <p>
-                    The app displays content from SourceHut, including repositories, tickets, and
-                    builds. This content is accessed based on the user’s authentication and
-                    permissions.
+                    Hutch displays and edits content from SourceHut, including repositories, tickets, mailing list
+                    threads,
+                    and builds. This content is accessed based on the user’s authentication and permissions.
                 </p>
 
                 <h3>Device Permissions</h3>
                 <p>
-                    Hutch does not request access to sensitive device data such as location,
-                    contacts, camera, or microphone.
+                    Hutch may request access to Photos when the user chooses to upload a profile avatar.
+                </p>
+                <p>
+                    Hutch does not request access to location, contacts, camera, or microphone.
                 </p>
 
                 <h3>Changes to This Policy</h3>
@@ -112,7 +121,7 @@
         </main>
 
         <footer class="site-footer">
-      © 2026 <a href="https://cleberg.net">Christian Cleberg</a>
+            © 2026 <a href="https://cleberg.net">Christian Cleberg</a>
         </footer>
     </div>
 </body>
diff --git a/website/styles.css b/website/styles.css
index 0deb034..014e248 100644
--- a/website/styles.css
+++ b/website/styles.css
@@ -1,20 +1,36 @@
+:root {
+  --bg: #f3f3f1;
+  --surface: #fff;
+  --border: #ddd;
+  --text: #111;
+  --muted: rgba(0, 0, 0, 0.62);
+  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
+  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.06);
+}
+
+* {
+  box-sizing: border-box;
+}
+
 body {
-  font-family: system-ui;
-  background: #f3f3f1;
+  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+  background: var(--bg);
+  color: var(--text);
   margin: 0;
 }
 
 a,
 a:visited {
-  color: blue
+  color: blue;
 }
 
 img {
-  max-width: 100%
+  max-width: 100%;
+  display: block;
 }
 
 .page {
-  max-width: 900px;
+  max-width: 960px;
   margin: 0 auto;
   padding: 16px;
 }
@@ -23,9 +39,10 @@ img {
 .site-header,
 .content-grid,
 .screenshots,
-.resources {
-  border: 1px solid #ddd;
-  background: white;
+.resources,
+.feature-sections {
+  border: 1px solid var(--border);
+  background: var(--surface);
   margin-bottom: 16px;
   padding: 20px;
 }
@@ -33,9 +50,13 @@ img {
 .brand-row {
   display: flex;
   justify-content: space-between;
+  gap: 20px;
+  align-items: flex-start;
 }
 
-.brand, .brand h1, .brand p {
+.brand,
+.brand h1,
+.brand p {
   color: black;
   text-decoration: none;
 }
@@ -44,28 +65,30 @@ img {
   display: flex;
   gap: 16px;
   align-items: center;
+  min-width: 0;
 }
 
 .brand h1 {
   margin: 0;
 }
 
+.subtitle,
 .brand p {
   margin-top: 0;
-  opacity: 0.6;
+  opacity: 0.68;
 }
 
 .app-icon {
   width: 80px;
   border-radius: 18px;
   border: 1px solid rgba(0, 0, 0, 0.08);
-  box-shadow:
-    0 1px 2px rgba(0, 0, 0, 0.06),
-    0 4px 12px rgba(0, 0, 0, 0.08);
+  box-shadow: var(--shadow-sm), 0 4px 12px rgba(0, 0, 0, 0.08);
+  flex: 0 0 auto;
 }
 
 .hero-actions {
   text-align: right;
+  flex: 0 0 auto;
 }
 
 .store-img {
@@ -78,37 +101,108 @@ img {
 }
 
 .intro-copy {
-  margin-top: 16px;
+  margin-top: 18px;
 }
 
 .lede {
-  padding-top: 1rem;
-  font-weight: bold;
+  margin: 0 0 10px;
+  font-weight: 700;
+  font-size: 1.125rem;
+}
+
+.intro-copy p:last-child {
+  margin-bottom: 0;
 }
 
-.content-grid {
+.content-grid,
+.feature-sections {
   display: grid;
   grid-template-columns: 1fr 1fr;
+  gap: 20px;
+}
+
+.content-grid>div,
+.feature-sections>.feature-panel {
+  min-width: 0;
+}
+
+.content-grid h2,
+.screenshots h2,
+.resources h2,
+.feature-panel h2 {
+  margin-top: 0;
 }
 
-.content-grid div:first-child {
-  padding-right: 0.5rem;
+.feature-list {
+  margin: 0;
+  padding-left: 1.2rem;
+  line-height: 1.55;
+}
+
+.feature-list li+li {
+  margin-top: 0.45rem;
 }
 
-.content-grid div:last-child {
-  padding-left: 0.5rem;
+.section-intro {
+  margin-top: 0;
+  color: var(--muted);
 }
 
-.shot-grid {
+.shot-scroll {
   display: grid;
-  grid-template-columns: repeat(3, 1fr);
-  gap: 10px;
+  grid-auto-flow: column;
+  grid-auto-columns: minmax(220px, 280px);
+  gap: 12px;
+  overflow-x: auto;
+  overscroll-behavior-x: contain;
+  padding-bottom: 8px;
+  scroll-snap-type: x proximity;
+  -webkit-overflow-scrolling: touch;
+}
+
+.shot-scroll::-webkit-scrollbar {
+  height: 10px;
+}
+
+.shot-scroll::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.18);
+}
+
+.shot-card {
+  margin: 0;
+  scroll-snap-align: start;
+  border: 1px solid var(--border);
+  overflow: hidden;
+  background: #fafafa;
+  box-shadow: var(--shadow-md);
+}
+
+.shot-card img {
+  width: 100%;
+  height: auto;
+}
+
+.shot-card figcaption {
+  padding: 10px 12px 12px;
+  font-size: 0.95rem;
+  font-weight: 600;
 }
 
 .resource-list {
   display: flex;
   flex-direction: column;
   gap: 6px;
+  margin: 0;
+  padding-left: 1.2rem;
+}
+
+.resource-list ul {
+  margin-top: 6px;
+}
+
+.site-footer,
+footer {
+  padding: 4px 2px 24px;
 }
 
 .privacy h2 {
@@ -125,7 +219,7 @@ img {
 
 .privacy p {
   margin: 0 0 14px;
-  line-height: 1.45;
+  line-height: 1.5;
 }
 
 .privacy ul {
@@ -145,4 +239,76 @@ img {
 
 .privacy a:hover {
   text-decoration: underline;
+}
+
+code {
+  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
+  font-size: 0.95em;
+}
+
+@media (max-width: 760px) {
+  .page {
+    padding: 12px;
+  }
+
+  .brand-row,
+  .content-grid,
+  .feature-sections {
+    grid-template-columns: 1fr;
+    display: grid;
+  }
+
+  .shot-scroll {
+    grid-auto-columns: minmax(240px, 78vw);
+  }
+
+  .brand-row {
+    gap: 16px;
+  }
+
+  .hero-actions {
+    text-align: left;
+  }
+
+  .brand {
+    align-items: flex-start;
+  }
+
+  .store-img {
+    height: 44px;
+  }
+
+  .content-grid,
+  .feature-sections {
+    gap: 12px;
+  }
+
+  .site-header,
+  .content-grid,
+  .screenshots,
+  .resources,
+  .feature-sections,
+  .privacy {
+    padding: 16px;
+  }
+
+  .feature-list,
+  .resource-list {
+    padding-left: 1.1rem;
+  }
+}
+
+.info-banner {
+  margin: 24px auto;
+  padding: 14px 16px;
+  max-width: 960px;
+
+  background: #fff3cd;
+  border: 1px solid #ffeeba;
+
+  color: #856404;
+  font-size: 14px;
+  line-height: 1.5;
+
+  text-align: center;
 }
\ No newline at end of file