site

personal website, served at mordaunt.dev/site
Log | Files | Refs

index.html (9227B)


      1 <!DOCTYPE html>
      2 <html lang="en">
      3 
      4 <head>
      5   <title>
      6   Sprig Arbor Chat Client · Jack Mordaunt
      7 </title>
      8   <meta charset="utf-8">
      9 <meta name="viewport" content="width=device-width, initial-scale=1.0">
     10 <meta name="color-scheme" content="light dark">
     11 
     12 
     13 
     14 
     15 <meta name="author" content="Jack Mordaunt">
     16 <meta name="description" content="Arbor Chat client in Go.">
     17 <meta name="keywords" content="blog,developer,personal,software,robust,performance,sovereign">
     18 
     19 
     20 
     21   <meta name="twitter:card" content="summary">
     22   <meta name="twitter:title" content="Sprig Arbor Chat Client">
     23   <meta name="twitter:description" content="Arbor Chat client in Go.">
     24 
     25 <meta property="og:url" content="http://jackmordaunt.com/projects/sprig/">
     26   <meta property="og:site_name" content="Jack Mordaunt">
     27   <meta property="og:title" content="Sprig Arbor Chat Client">
     28   <meta property="og:description" content="Arbor Chat client in Go.">
     29   <meta property="og:locale" content="en">
     30   <meta property="og:type" content="article">
     31     <meta property="article:section" content="projects">
     32     <meta property="article:published_time" content="2022-03-17T17:30:23+00:00">
     33     <meta property="article:modified_time" content="2022-03-17T17:30:23+00:00">
     34     <meta property="article:tag" content="Go">
     35     <meta property="article:tag" content="Gio">
     36     <meta property="article:tag" content="Native">
     37     <meta property="article:tag" content="Portfolio">
     38 
     39 
     40 
     41 
     42 <link rel="canonical" href="http://jackmordaunt.com/projects/sprig/">
     43 
     44 
     45 <link rel="preload" href="/fonts/fa-brands-400.woff2" as="font" type="font/woff2" crossorigin>
     46 <link rel="preload" href="/fonts/fa-regular-400.woff2" as="font" type="font/woff2" crossorigin>
     47 <link rel="preload" href="/fonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
     48 
     49 
     50   
     51   
     52   <link rel="stylesheet" href="/css/coder.min.6445a802b9389c9660e1b07b724dcf5718b1065ed2d71b4eeaf981cc7cc5fc46.css" integrity="sha256-ZEWoArk4nJZg4bB7ck3PVxixBl7S1xtO6vmBzHzF/EY=" crossorigin="anonymous" media="screen" />
     53 
     54 
     55 
     56 
     57 
     58 
     59   
     60     
     61     
     62     <link rel="stylesheet" href="/css/coder-dark.min.a00e6364bacbc8266ad1cc81230774a1397198f8cfb7bcba29b7d6fcb54ce57f.css" integrity="sha256-oA5jZLrLyCZq0cyBIwd0oTlxmPjPt7y6KbfW/LVM5X8=" crossorigin="anonymous" media="screen" />
     63   
     64 
     65 
     66 
     67  
     68   
     69     
     70     <link rel="stylesheet" href="/css/custom.min.931a9d02d6f7655cd0cd50317fac1204e00c54ffd0232085acc957b2db5e1283.css" integrity="sha256-kxqdAtb3ZVzQzVAxf6wSBOAMVP/QIyCFrMlXstteEoM=" crossorigin="anonymous" media="screen" />
     71   
     72 
     73 
     74 
     75 
     76 
     77 <link rel="icon" type="image/svg+xml" href="/images/self-tiny-white.svg" sizes="any">
     78 <link rel="icon" type="image/png" href="/images/self-tiny-white.png" sizes="32x32">
     79 <link rel="icon" type="image/png" href="/images/self-tiny-white.png" sizes="16x16">
     80 
     81 <link rel="apple-touch-icon" href="/images/apple-touch-icon.png">
     82 <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
     83 
     84 <link rel="manifest" href="/site.webmanifest">
     85 <link rel="mask-icon" href="/images/safari-pinned-tab.svg" color="#5bbad5">
     86 
     87 
     88 
     89 
     90 
     91 
     92 
     93 <script defer data-domain="jackmordaunt.com" src="https://plausible.io/js/script.js"></script>
     94 
     95 
     96 
     97 
     98 </head>
     99 
    100 
    101 
    102 
    103 
    104 
    105 <body class="preload-transitions colorscheme-auto">
    106   
    107 <div class="float-container">
    108     <a id="dark-mode-toggle" class="colorscheme-toggle">
    109         <i class="fa-solid fa-adjust fa-fw" aria-hidden="true"></i>
    110     </a>
    111 </div>
    112 
    113 
    114   <main class="wrapper">
    115     <nav class="navigation">
    116   <section class="container">
    117     
    118     <a class="navigation-title" href="http://jackmordaunt.com/">
    119       Jack Mordaunt
    120     </a>
    121     
    122     
    123       <input type="checkbox" id="menu-toggle" />
    124       <label class="menu-button float-right" for="menu-toggle">
    125         <i class="fa-solid fa-bars fa-fw" aria-hidden="true"></i>
    126       </label>
    127       <ul class="navigation-list">
    128         
    129           
    130             <li class="navigation-item">
    131               <a class="navigation-link " href="/posts/">Blog</a>
    132             </li>
    133           
    134             <li class="navigation-item">
    135               <a class="navigation-link " href="/about/">About</a>
    136             </li>
    137           
    138             <li class="navigation-item">
    139               <a class="navigation-link " href="/projects/">Projects</a>
    140             </li>
    141           
    142             <li class="navigation-item">
    143               <a class="navigation-link " href="/contact/">Contact</a>
    144             </li>
    145           
    146             <li class="navigation-item">
    147               <a class="navigation-link " href="/pay-with-bitcoin/">Pay</a>
    148             </li>
    149           
    150         
    151         
    152       </ul>
    153     
    154   </section>
    155 </nav>
    156 
    157 
    158     <div class="content">
    159       
    160   <section class="container page">
    161   <article>
    162     <header>
    163     
    164       <h1 class="title">
    165         <a class="title-link" href="http://jackmordaunt.com/projects/sprig/">
    166           Sprig Arbor Chat Client
    167         </a>
    168       </h1>
    169     
    170     </header>
    171 
    172     <style>
    173 .carousel {
    174   display: flex;
    175   overflow: scroll;
    176 }
    177 </style>
    178 <div class="carousel">
    179   <img src="/images/sprig/sprig.webp" alt="Sprig" />
    180 </div>
    181 <h2 id="overview">
    182   Overview
    183   <a class="heading-link" href="#overview">
    184     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    185     <span class="sr-only">Link to heading</span>
    186   </a>
    187 </h2>
    188 <p>Built by <a href="https://git.sr.ht/~whereswaldon"  class="external-link" target="_blank" rel="noopener">~whereswaldon</a>, <a href="https://git.sr.ht/~whereswaldon/sprig"  class="external-link" target="_blank" rel="noopener">Sprig</a> is a client for <a href="https://man.sr.ht/~whereswaldon/arborchat"  class="external-link" target="_blank" rel="noopener">Arbor</a>, an open source federated chat platform.<br>
    189 Sprig is a cross-platform client supporting Windows, macOS, Linux, Android, and iOS.<br>
    190 It&rsquo;s written in <strong>Go</strong>, using the <a href="https://git.sr.ht/~eliasnaur/gio"  class="external-link" target="_blank" rel="noopener"><strong>Gio</strong></a> immediate-mode UI toolkit.</p>
    191 <hr>
    192 <h3 id="my-role">
    193   My Role
    194   <a class="heading-link" href="#my-role">
    195     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    196     <span class="sr-only">Link to heading</span>
    197   </a>
    198 </h3>
    199 <p>When I joined, Sprig stored each chat message as an individual file on disk. This file-per-message model worked reasonably well on Linux, but resulted in <strong>severely degraded performance</strong> on Windows, where reading thousands of tiny files led to <strong>notably slow startup times</strong>.</p>
    200 <p>To address this, I migrated the persistence layer from the filesystem to <a href="https://github.com/boltdb/bolt"  class="external-link" target="_blank" rel="noopener"><strong>BoltDB</strong></a>, an embedded key-value store written in Go. This upgrade significantly improved startup performance across all platforms, with the largest gains on Windows.</p>
    201 <p>In addition to this core performance enhancement, I contributed minor UI improvements and refinements.</p>
    202 <hr>
    203 <h3 id="result">
    204   Result
    205   <a class="heading-link" href="#result">
    206     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    207     <span class="sr-only">Link to heading</span>
    208   </a>
    209 </h3>
    210 <p>The app now launches significantly faster, offers a smoother user experience, and maintains cross-platform compatibility—all without sacrificing the simplicity of a local-first storage model.</p>
    211 <h3 id="platforms">
    212   Platforms
    213   <a class="heading-link" href="#platforms">
    214     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    215     <span class="sr-only">Link to heading</span>
    216   </a>
    217 </h3>
    218 <div style="display: flex; flex-wrap: wrap; gap: 2rem;">
    219   <i class="fa-4x fa-brands fa-windows"></i>
    220   <i class="fa-4x fa-brands fa-apple"></i>
    221   <i class="fa-4x fa-brands fa-linux"></i>
    222   <i class="fa-4x fa-brands fa-android"></i>
    223 </div>
    224 <h3 id="languages">
    225   Languages
    226   <a class="heading-link" href="#languages">
    227     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    228     <span class="sr-only">Link to heading</span>
    229   </a>
    230 </h3>
    231 <div style="display: flex; flex-wrap: wrap; gap: 2rem;">
    232   <img style="max-height: 100px;" src="/images/brands/go.svg"/>
    233 </div>
    234 <h3 id="tech">
    235   Tech
    236   <a class="heading-link" href="#tech">
    237     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    238     <span class="sr-only">Link to heading</span>
    239   </a>
    240 </h3>
    241 <div style="display: flex; flex-wrap: wrap; gap: 2rem;">
    242   <img style="max-height: 100px;" src="/images/brands/gio.svg" class="invert-me"/>
    243   <img style="max-height: 100px;" src="/images/brands/boltdb.webp"/>
    244 </div>
    245 
    246   </article>
    247 </section>
    248 
    249   
    250 
    251     </div>
    252 
    253     <footer class="footer">
    254   <section class="container">
    255     ©
    256     
    257     2025
    258      Jack Mordaunt 
    259     ·
    260     
    261     Powered by <a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a> & <a href="https://github.com/luizdepra/hugo-coder/" target="_blank" rel="noopener">Coder</a>.
    262     
    263   </section>
    264 </footer>
    265 
    266   </main>
    267 
    268   
    269 
    270   
    271   
    272   <script src="/js/coder.min.6ae284be93d2d19dad1f02b0039508d9aab3180a12a06dcc71b0b0ef7825a317.js" integrity="sha256-auKEvpPS0Z2tHwKwA5UI2aqzGAoSoG3McbCw73gloxc="></script>
    273   
    274 
    275   
    276 
    277   
    278 
    279 
    280   
    281 
    282   
    283 
    284   
    285 
    286   
    287 
    288   
    289 
    290   
    291 
    292   
    293 
    294   
    295 
    296   
    297 
    298   
    299 
    300   
    301 
    302   
    303 
    304   
    305 
    306   
    307 
    308   
    309 
    310   
    311 
    312   
    313 </body>
    314 </html>