<!DOCTYPE html><html lang="en"> <head><meta charset="utf-8"><meta name="language" content="English"><meta name="viewport" content="width=device-width"><title>Aaron Russell - Developer, product builder, serial starter upper</title><meta name="description" content="Technical Product Builder with 20+ years experience helping early-stage companies build and launch products. Full-stack development across web, blockchain, and AI."><!-- Facebook Meta Tags --><meta property="og:type" content="website"><meta property="og:locale" content="en_GB"><meta property="og:url" content="https://aaronrussell.dev/"><meta property="og:title" content="Aaron Russell - Developer, product builder, serial starter upper"><meta property="og:description" content="Technical Product Builder with 20+ years experience helping early-stage companies build and launch products. Full-stack development across web, blockchain, and AI."><meta property="og:image" content="https://aaronrussell.dev/_astro/2025.zWr4gFby_Z26TGbi.png"><!-- Twitter Meta Tags --><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Aaron Russell - Developer, product builder, serial starter upper"><meta name="twitter:description" content="Technical Product Builder with 20+ years experience helping early-stage companies build and launch products. Full-stack development across web, blockchain, and AI."><meta name="twitter:image" content="https://aaronrussell.dev/_astro/2025.zWr4gFby_Z26TGbi.png"><meta name="twitter:creator" content="@aaronrussell"><link rel="canonical" href="https://aaronrussell.dev/"><link rel="icon" href="/favicon.ico" sizes="32x32"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="apple-touch-icon" href="/icon-180.png"><link rel="manifest" href="/site.webmanifest"><link rel="sitemap" href="https://aaronrussell.dev/sitemap.xml" type="application/xml" title="Sitemap"><link rel="alternate" href="https://aaronrussell.dev/feed.xml" type="application/rss+xml" title="RSS Feed"><link rel="alternate" href="https://aaronrussell.dev/feed.json" type="application/feed+json" title="JSON Feed"><meta name="generator" content="Astro v5.16.6"><script type="module" src="/_astro/Layout.astro_astro_type_script_index_0_lang.ZAGPbc9T.js"></script><link rel="stylesheet" href="/_astro/about.DxQj41i3.css"></head> <body class="
	  text-zinc-100 bg-zinc-950 antialiased
		font-mono font-light text-sm sm:text-base underline-offset-[0.225em]"> <div class="min-h-screen flex flex-col"> <header class="flex items-center justify-between gap-(--ar-spacing-2) p-(--ar-spacing-2)"> <div class="flex items-center gap-(--ar-spacing-1)"> <div> <a href="/" rel="home"> <img src="/avatar.webp" alt="Aaron Russell" class="avatar"> </a> </div> <div class="hidden xs:inline text-sm sm:text-base"> <a href="/" rel="home" class="nav-link">Aaron Russell</a> </div> </div> <nav class="flex items-center gap-(--ar-spacing-1)"> <ul class="flex items-center gap-(--ar-spacing-1) text-sm sm:text-base"> <li> <a href="/about" class="nav-link"> About </a> </li><li> <a href="/work" class="nav-link"> Work </a> </li><li> <a href="/posts" class="nav-link"> Posts </a> </li> </ul> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event("astro:load"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="2sKjru" component-url="/_astro/DarkModeToggle.DZDAzOYV.js" component-export="default" renderer-url="/_astro/client.svelte.sNTGbgHX.js" props="{}" ssr client="load" opts="{&quot;name&quot;:&quot;DarkModeToggle&quot;,&quot;value&quot;:true}" await-children><!--[--><button class="w-7 h-7 flex items-center justify-center rounded-full cursor-pointer transition-colors bg-zinc-800 hover:bg-zinc-700" title="Toggle dark mode"><div class="w-4 h-4"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"></path></svg></div></button> <!--[!--><!--]--><!----><!--]--><!--astro:end--></astro-island> </nav> </header> <main class="p-(--ar-spacing-2) pb-16 lg:pb-24 flex-1">  <div class="space-y-16 lg:space-y-24"> <div class="max-w-xl xl:max-w-2xl mx-auto"> <h1 class="text-xl sm:text-2xl xl:text-3xl text-center">Aaron Russell</h1> <hr class="my-8 w-64 h-px mx-auto border-none bg-(image:--bg-aurora-horizontal-fade)"> <p class="text-sm sm:text-base xl:text-lg text-center mb-4">
I'm a Technical Product Builder with an eye for great user and developer
        experience. I help early-stage companies build tools and experiences that
        their customers love.
</p> <p class="text-sm sm:text-base xl:text-lg text-center"> <a href="/about" class="link">More »</a> </p> </div> <div class="max-w-4xl xl:max-w-6xl mx-auto space-y-(--ar-spacing-1)"> <div class="max-w-xl xl:max-w-2xl mx-auto"> <h2 class="mb-1 text-base sm:text-lg xl:text-xl">Things I've built</h2> <p class="text-xs sm:text-sm text-zinc-400">Client work, products and open source libraries across web, blockchain and AI.</p> </div> <div class="
        grid grid-cols-2 grid-rows-[12rem_8rem_6rem_6rem] gap-4
        xs:grid-rows-[12rem_10rem_8rem_8rem]
        sm:grid-cols-8 sm:grid-rows-[12rem_12rem_10rem_10rem]
        lg:grid-rows-[14rem_14rem_12rem] lg:gap-8
        "> <div class="col-span-2 sm:col-span-5 sm:row-span-2"> <a href="/work/aldea-computer" class="block size-full"> <img src="/_astro/aldea-brand.Dx6Hyob5_Z1QvpaT.webp" srcset="/_astro/aldea-brand.Dx6Hyob5_Z1QvpaT.webp 1x, /_astro/aldea-brand.Dx6Hyob5_VJJTW.webp 2x" alt="Aldea Computer" loading="lazy" decoding="async" fetchpriority="auto" width="960" height="480" class="image size-full object-cover image-hover"> </a> </div><div class="sm:col-span-3"> <div class="block size-full"> <img src="/_astro/campinmygarden-brand.DBmYMp9R_Z1FPOnU.webp" srcset="/_astro/campinmygarden-brand.DBmYMp9R_Z1FPOnU.webp 1x, /_astro/campinmygarden-brand.DBmYMp9R_ZI8glk.webp 2x" alt="Campinmygarden.com" loading="lazy" decoding="async" fetchpriority="auto" width="448" height="224" class="image size-full object-cover"> </div> </div><div class="sm:col-span-3"> <div class="block size-full"> <img src="/_astro/clubbuzz-brand.rAHa1fPv_E6tb1.webp" srcset="/_astro/clubbuzz-brand.rAHa1fPv_E6tb1.webp 1x, /_astro/clubbuzz-brand.rAHa1fPv_ZxVL8T.webp 2x" alt="ClubBuzz" loading="lazy" decoding="async" fetchpriority="auto" width="448" height="224" class="image size-full object-cover"> </div> </div><div class="sm:col-span-4 lg:col-span-2"> <div class="block size-full"> <img src="/_astro/agentflow-brand.QhcKOVjO_Z1VG8Mm.webp" srcset="/_astro/agentflow-brand.QhcKOVjO_Z1VG8Mm.webp 1x, /_astro/agentflow-brand.QhcKOVjO_9oJMV.webp 2x" alt="AgentFlow" loading="lazy" decoding="async" fetchpriority="auto" width="384" height="192" class="image size-full object-cover"> </div> </div><div class="sm:col-span-4 lg:col-span-2"> <div class="block size-full"> <img src="/_astro/anthropix-brand.BYfHfbbW_Z9MGya.webp" srcset="/_astro/anthropix-brand.BYfHfbbW_Z9MGya.webp 1x, /_astro/anthropix-brand.BYfHfbbW_1Vic28.webp 2x" alt="Anthropix" loading="lazy" decoding="async" fetchpriority="auto" width="384" height="192" class="image size-full object-cover"> </div> </div><div class="sm:col-span-4 lg:col-span-2"> <div class="block size-full"> <img src="/_astro/ollama-brand.DO0xNDjR_1eglMf.webp" srcset="/_astro/ollama-brand.DO0xNDjR_1eglMf.webp 1x, /_astro/ollama-brand.DO0xNDjR_nnSOc.webp 2x" alt="Ollama-ex" loading="lazy" decoding="async" fetchpriority="auto" width="384" height="192" class="image size-full object-cover"> </div> </div><div class="sm:col-span-4 lg:col-span-2"> <div class="block size-full"> <img src="/_astro/eddy-brand.BQuVpl3a_2889l.webp" srcset="/_astro/eddy-brand.BQuVpl3a_2889l.webp 1x, /_astro/eddy-brand.BQuVpl3a_ZpP0ar.webp 2x" alt="Eddy" loading="lazy" decoding="async" fetchpriority="auto" width="384" height="192" class="image size-full object-cover"> </div> </div> </div> <p class="text-center"> <a href="/work" class="text-xs sm:text-sm link">More work »</a> </p> </div> <div class="max-w-xl xl:max-w-2xl mx-auto space-y-(--ar-spacing-1)"> <div> <h2 class="mb-1 text-base sm:text-lg xl:text-xl">From the blog</h2> <p class="text-xs sm:text-sm text-zinc-400">Insights, lessons, thoughts (and some brain farts) from 25+ years of coding.</p> </div> <div class="space-y-8 sm:space-y-10"> <article> <a href="/posts/the-cobblers-children-finally-have-shoes" class="
      grid grid-cols-1 gap-x-4 gap-y-3 group
      xs:grid-cols-2 xs:grid-rows-[auto_1fr]
      sm:grid-cols-[14rem_1fr] sm:gap-x-5"> <div class="row-start-2 xs:row-start-1 xs:row-span-2 h-40"> <img src="/_astro/cobblers-shoes.00XGxqvk_Z1Fk5lt.webp" srcset="/_astro/cobblers-shoes.00XGxqvk_Z1Fk5lt.webp 1x, /_astro/cobblers-shoes.00XGxqvk_Z1sBTH4.webp 2x" alt="The cobbler's children finally have shoes" loading="lazy" decoding="async" fetchpriority="auto" width="359" height="160" class="image size-full object-cover image-group-hover"> </div> <div class="space-y-1"> <div class="flex items-center justify-between gap-8"> <time class="block text-xs sm:text-sm transition-colors text-zinc-400 group-hover:text-zinc-300"> 7 Jan 2026 </time> <div class="flex items-center gap-1"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-orange-500 group-hover:text-orange-300"> <path d="M12 3q1 4 4 6.5t3 5.5a1 1 0 0 1-14 0 5 5 0 0 1 1-3 1 1 0 0 0 5 0c0-2-1.5-3-1.5-5q0-2 2.5-4"></path> </svg> <span class="text-xs text-orange-400 group-hover:text-orange-200">latest</span> </div> </div> <h2 class="
        text-sm sm:text-base leading-snug underline decoration-transparent transition-colors
        group-hover:text-white group-hover:decoration-inherit"> The cobbler&#39;s children finally have shoes </h2> </div> <div class="flex flex-col gap-1"> <div class="flex-auto"> <p class="
          text-sm sm:text-base leading-snug underline decoration-transparent transition-colors
          text-zinc-400 group-hover:text-zinc-300"> After over a decade without a personal website, I&#39;ve finally built myself a proper home on the web. New year, new site, new start.
 </p> </div> </div> </a> </article><article> <a href="/posts/vibe-coding" class="
      grid grid-cols-1 gap-x-4 gap-y-3 group
      xs:grid-cols-2 xs:grid-rows-[auto_1fr]
      sm:grid-cols-[14rem_1fr] sm:gap-x-5"> <div class="row-start-2 xs:row-start-1 xs:row-span-2 h-40"> <img src="/_astro/vibe-coding.CJ6jqZwg_2clL6e.webp" srcset="/_astro/vibe-coding.CJ6jqZwg_2clL6e.webp 1x, /_astro/vibe-coding.CJ6jqZwg_1kcAo9.webp 2x" alt="Vibe coding" loading="lazy" decoding="async" fetchpriority="auto" width="384" height="160" class="image size-full object-cover image-group-hover"> </div> <div class="space-y-1"> <div class="flex items-center justify-between gap-8"> <time class="block text-xs sm:text-sm transition-colors text-zinc-400 group-hover:text-zinc-300"> 12 Feb 2025 </time>  </div> <h2 class="
        text-sm sm:text-base leading-snug underline decoration-transparent transition-colors
        group-hover:text-white group-hover:decoration-inherit"> Vibe coding </h2> </div> <div class="flex flex-col gap-1"> <div class="flex-auto"> <p class="
          text-sm sm:text-base leading-snug underline decoration-transparent transition-colors
          text-zinc-400 group-hover:text-zinc-300"> Thoughts on the shift from traditional &quot;craft&quot; coding to AI-assisted &quot;vibe coding&quot;, and what it means for old and crusty devs like me.
 </p> </div> </div> </a> </article><article> <a href="/posts/announcing-agentflow" class="
      grid grid-cols-1 gap-x-4 gap-y-3 group
      xs:grid-cols-2 xs:grid-rows-[auto_1fr]
      sm:grid-cols-[14rem_1fr] sm:gap-x-5"> <div class="row-start-2 xs:row-start-1 xs:row-span-2 h-40"> <img src="/_astro/agentflow-banner.CQOrsD8e_4N10q.webp" srcset="/_astro/agentflow-banner.CQOrsD8e_4N10q.webp 1x, /_astro/agentflow-banner.CQOrsD8e_Z1susrm.webp 2x" alt="Announcing Agentflow" loading="lazy" decoding="async" fetchpriority="auto" width="384" height="160" class="image size-full object-cover image-group-hover"> </div> <div class="space-y-1"> <div class="flex items-center justify-between gap-8"> <time class="block text-xs sm:text-sm transition-colors text-zinc-400 group-hover:text-zinc-300"> 17 Dec 2024 </time> <div class="flex items-center gap-1"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-yellow-500 group-hover:text-yellow-300"> <path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"></path> </svg> <span class="text-xs text-yellow-200 group-hover:text-yellow-50">featured</span> </div> </div> <h2 class="
        text-sm sm:text-base leading-snug underline decoration-transparent transition-colors
        group-hover:text-white group-hover:decoration-inherit"> Announcing Agentflow </h2> </div> <div class="flex flex-col gap-1"> <div class="flex-auto"> <p class="
          text-sm sm:text-base leading-snug underline decoration-transparent transition-colors
          text-zinc-400 group-hover:text-zinc-300"> A lightweight AI agent framework that uses natural language and Markdown to create powerful workflows.
 </p> </div> </div> </a> </article><article> <a href="/posts/zed-ai-review" class="
      grid grid-cols-1 gap-x-4 gap-y-3 group
      xs:grid-cols-2 xs:grid-rows-[auto_1fr]
      sm:grid-cols-[14rem_1fr] sm:gap-x-5"> <div class="row-start-2 xs:row-start-1 xs:row-span-2 h-40"> <img src="/_astro/zed-ai-review.BJNignXu_2ufzAt.webp" srcset="/_astro/zed-ai-review.BJNignXu_2ufzAt.webp 1x, /_astro/zed-ai-review.BJNignXu_1zYRtJ.webp 2x" alt="Zed AI review: Getting the balance right in AI code editing" loading="lazy" decoding="async" fetchpriority="auto" width="384" height="160" class="image size-full object-cover image-group-hover"> </div> <div class="space-y-1"> <div class="flex items-center justify-between gap-8"> <time class="block text-xs sm:text-sm transition-colors text-zinc-400 group-hover:text-zinc-300"> 20 Sep 2024 </time>  </div> <h2 class="
        text-sm sm:text-base leading-snug underline decoration-transparent transition-colors
        group-hover:text-white group-hover:decoration-inherit"> Zed AI review: Getting the balance right in AI code editing </h2> </div> <div class="flex flex-col gap-1"> <div class="flex-auto"> <p class="
          text-sm sm:text-base leading-snug underline decoration-transparent transition-colors
          text-zinc-400 group-hover:text-zinc-300"> Zed AI takes one solid, modern and fast code editor, and sprinkles on top some thoughtful AI features.
 </p> </div> </div> </a> </article> </div> <p class="text-center"> <a href="/posts" class="text-xs sm:text-sm link">All posts »</a> </p> </div> </div>  </main> <footer class="px-(--ar-spacing-2) pb-(--ar-spacing-3) space-y-16 lg:space-y-24"> <hr class="w-64 h-px mx-auto border-none bg-(image:--bg-aurora-horizontal-fade)"> <div class="flex flex-col items-center gap-(--ar-spacing-1)"> <p class="text-xs sm:text-sm">&copy; 2024-2026 Aaron Russell</p> <ul class="flex items-center gap-2 text-xs sm:text-sm"> <li><a href="https://www.pushcode.com" class="nav-link">Push Code</a></li> <li class="flex gap-2 before:content-['·']"><a href="https://github.com/aaronrussell" class="nav-link">GitHub</a></li><li class="flex gap-2 before:content-['·']"><a href="https://bsky.app/profile/aaronrussell.dev" class="nav-link">Bluesky</a></li><li class="flex gap-2 before:content-['·']"><a href="https://x.com/aaronrussell" class="nav-link">X</a></li> </ul> </div> </footer> </div> </body></html>