<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>jeffgat</title>
        <link>https://paragraph.com/@jeffgat</link>
        <description>undefined</description>
        <lastBuildDate>Sat, 05 Sep 2026 17:49:03 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>jeffgat</title>
            <url>https://storage.googleapis.com/papyrus_images/9b72711d8c247a49ec34d81a5e252a175996047963bb4b13dcc4641d5880b0b0.jpg</url>
            <link>https://paragraph.com/@jeffgat</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Technical Frontend Deep Dives for Web3 Developers]]></title>
            <link>https://paragraph.com/@jeffgat/technical-frontend-deep-dives-for-web3-developers</link>
            <guid>JGHaOcMkHRH71bFr4iJL</guid>
            <pubDate>Mon, 23 Jun 2025 00:09:25 GMT</pubDate>
            <description><![CDATA[Stepping out of the kitchen and into code, I didn’t come here to follow recipes. I came to write them. If you’re like me—a frontend dev who cut their teeth on design and found their freedom in crypto—then you know that building for Web3 is a constant tug-of-war between complexity and elegance. In this post, I’m diving into three of the most important frontend techniques that have helped me scale real-world dApps without losing sleep (or my users).1. Using Zustand/Jotai in Production Crypto dA...]]></description>
            <content:encoded><![CDATA[<p>Stepping out of the kitchen and into code, I didn’t come here to follow recipes. I came to write them. If you’re like me—a frontend dev who cut their teeth on design and found their freedom in crypto—then you know that building for Web3 is a constant tug-of-war between complexity and elegance.</p><p>In this post, I’m diving into three of the most important frontend techniques that have helped me scale real-world dApps without losing sleep (or my users).</p><h2 id="h-1-using-zustandjotai-in-production-crypto-dapps" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">1. Using Zustand/Jotai in Production Crypto dApps</h2><p>Global state in Web3 isn’t just UI fluff—it can represent real token balances, on-chain auth, wallet connections, and smart contract interactions.</p><h2 id="h-why-not-redux" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why Not Redux?</h2><p>Redux is a beast. It’s overkill for the lean, reactive needs of most Web3 dApps. Zustand and Jotai, on the other hand, give you atomic state management with way less boilerplate.</p><h2 id="h-zustand-in-practice" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Zustand in Practice:</h2><p><code>import { create } from &apos;zustand&apos;;</code></p><pre data-type="codeBlock" text="const useWalletStore = create((set) =&gt; ({
  address: null,
  setAddress: (addr) =&gt; set({ address: addr }),
  chainId: null,
  setChainId: (id) =&gt; set({ chainId: id }),
}));
"><code><span class="hljs-keyword">const</span> useWalletStore = <span class="hljs-title function_">create</span>(<span class="hljs-function">(<span class="hljs-params">set</span>) =></span> ({
  <span class="hljs-attr">address</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">setAddress</span>: <span class="hljs-function">(<span class="hljs-params">addr</span>) =></span> <span class="hljs-title function_">set</span>({ <span class="hljs-attr">address</span>: addr }),
  <span class="hljs-attr">chainId</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">setChainId</span>: <span class="hljs-function">(<span class="hljs-params">id</span>) =></span> <span class="hljs-title function_">set</span>({ <span class="hljs-attr">chainId</span>: id }),
}));
</code></pre><p>No reducers. No context spaghetti. Just composable, lightweight state.</p><h2 id="h-bonus-persistence-and-middleware" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Bonus: Persistence and Middleware</h2><p>Zustand supports middleware for persisting to localStorage, syncing across tabs, or debugging without extra setup.</p><p>Jotai is even more atomic—ideal for when you want to isolate individual pieces of state (like specific token values or component-scoped loading flags).</p><h2 id="h-2-ssr-and-caching-in-nextjs-for-blockchain-based-frontends" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2. SSR &amp; Caching in Next.js for Blockchain-Based Frontends</h2><p>Let’s be real: most Web3 devs skip SSR. They slap up a bunch of useEffects and call it a day. But if you want SEO, faster Time to First Byte, or robust UX for unauthenticated users, server-side rendering matters.</p><h2 id="h-common-pitfalls" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Common Pitfalls:</h2><ul><li><p>Token balances fetched client-side only? Goodbye to instant feedback.</p></li><li><p>Wallet-dependent UI flickering on page load? UX killer.</p></li></ul><h2 id="h-solution-hybrid-rendering-caching" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Solution: Hybrid Rendering + Caching</h2><p>Here’s what works for me:</p><ul><li><p>getServerSideProps to fetch general data (e.g. token stats, protocol metrics)</p></li><li><p>SWR on the client to hydrate and revalidate wallet-specific data</p></li><li><p>Edge caching using Vercel or custom headers</p></li></ul><pre data-type="codeBlock" text="export async function getServerSideProps() {
  const prices = await fetchTokenPrices();
  return {
    props: { prices },
  };
}
"><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">getServerSideProps</span>(<span class="hljs-params"></span>) {
  <span class="hljs-keyword">const</span> prices = <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetchTokenPrices</span>();
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: { prices },
  };
}
</code></pre><p>Remember: blockchain data doesn’t change every second. Cache it wisely, rehydrate it fast.</p><h2 id="h-3-leveraging-graphql-in-web3-apps-with-live-token-data" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">3. Leveraging GraphQL in Web3 Apps with Live Token Data</h2><p>REST is a relic. GraphQL is how you tame on-chain chaos and offer your UI exactly what it needs.</p><h2 id="h-why-graphql" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why GraphQL?</h2><ul><li><p>Fine-grained queries = less overfetching</p></li><li><p>Combine multiple contracts/subgraphs into one UI layer</p></li><li><p>Cleaner typings when using codegen (e.g. graphql-codegen)</p></li></ul><h2 id="h-tools-i-use" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Tools I Use:</h2><ul><li><p>The Graph Protocol (Subgraph APIs)</p></li><li><p>Apollo Client for caching and reactive updates</p></li><li><p>Satsuma/Subgrounds for querying across multiple chains</p></li></ul><h2 id="h-example" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Example:</h2><pre data-type="codeBlock" text="query GetTokenHolders($id: String!) {
  token(id: $id) {
    id
    symbol
    holders(first: 10) {
      id
      balance
    }
  }
}
"><code>query <span class="hljs-built_in">GetTokenHolders</span>($id: String!) {
  <span class="hljs-built_in">token</span>(id: $id) {
    id
    symbol
    <span class="hljs-built_in">holders</span>(first: <span class="hljs-number">10</span>) {
      id
      balance
    }
  }
}
</code></pre><p>Pair this with useQuery in Apollo and you have real-time token data piped into a responsive, cache-aware UI.</p><h2 id="h-final-thoughts-build-like-its-the-new-internet" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Final Thoughts: Build Like It’s the New Internet</h2><p>Web3 isn’t a trend—it’s a rewrite of how value, identity, and code interact. But if the frontend sucks, no one cares what your protocol does.</p><p>Zustand gives you composability. Next.js gives you speed. GraphQL gives you control. Combine these and you can build experiences that feel like magic—even when your users have no idea they just signed a transaction or bridged assets across chains.</p><p>Design like an artist. Code like an engineer. Think like a rebel. That’s the frontend crypto stack.</p>]]></content:encoded>
            <author>jeffgat@newsletter.paragraph.com (jeffgat)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/2663db86d0c7b4efe8ada9da8ca1b2394d6338f9ef1163937d94feade8da4cf3.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[UI/UX in Web3]]></title>
            <link>https://paragraph.com/@jeffgat/ui-ux-in-web3</link>
            <guid>36uvawn9CQmMcCTEVqH7</guid>
            <pubDate>Fri, 30 May 2025 00:00:55 GMT</pubDate>
            <description><![CDATA[I used to plate duck confit and brûlée creme in the underbelly of Toronto&apos;s kitchens, blasting punk and painting walls with tattoos. Today, I push pixels and code for decentralized applications. If you think the jump from culinary arts to code is wild, try going from Web2 to Web3 UX. As a self-taught designer-turned-frontend developer, I’ve lived through the chaotic beauty of the early web. But nothing prepared me for designing in Web3. It&apos;s not just harder—it&apos;s a fundamentally...]]></description>
            <content:encoded><![CDATA[<p>I used to plate duck confit and brûlée creme in the underbelly of Toronto&apos;s kitchens, blasting punk and painting walls with tattoos. Today, I push pixels and code for decentralized applications. If you think the jump from culinary arts to code is wild, try going from Web2 to Web3 UX.</p><p>As a self-taught designer-turned-frontend developer, I’ve lived through the chaotic beauty of the early web. But nothing prepared me for designing in Web3. It&apos;s not just harder—it&apos;s a fundamentally different beast. Here&apos;s what I&apos;ve learned from the trenches of crypto UI/UX design.</p><hr><h2 id="h-why-designing-for-wallet-ux-is-10x-harder-than-web2" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why Designing for Wallet UX is 10x Harder than Web2</h2><p>In Web2, auth is simple. OAuth, cookies, sessions. You know the drill.</p><p>In Web3? Your user <em>is</em> their wallet. That wallet could be MetaMask, Phantom, Rabby, or a cold storage Ledger buried in a hardware drawer. Each wallet behaves differently. There&apos;s no consistent design standard, no native onboarding flow, and zero margin for error.</p><p>You can’t just say “Connect Wallet” and call it a day. You need to:</p><ul><li><p>Detect installed wallets (and gracefully handle when there are none)</p></li><li><p>Guide users through complex, unfamiliar signing flows</p></li><li><p>Communicate gas fees, network switching, and failed transactions without losing trust</p></li><li><p>Handle multi-chain realities (good luck if you&apos;re bridging assets or supporting L2s)</p></li></ul><p>Every modal matters. Every interaction risks abandonment. This is design in an adversarial environment. UX is not a layer on top—it <em>is</em> the protocol.</p><hr><h2 id="h-breaking-down-the-ux-failures-of-major-dapps-and-how-to-fix-them" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Breaking Down the UX Failures of Major dApps (and How to Fix Them)</h2><p>Let&apos;s not name names, but here are the repeat offenders I see in big-name dApps:</p><h3 id="h-1-wallet-connection-dead-ends" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">1. <strong>Wallet Connection Dead Ends</strong></h3><p>Nothing screams &quot;bounce&quot; like landing on a dApp that greets you with a broken Connect Wallet button. This happens more often than you&apos;d believe. Fix: detect wallet presence, offer fallbacks, and <strong>never</strong> assume MetaMask is the default.</p><h3 id="h-2-gas-fee-ambiguity" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">2. <strong>Gas Fee Ambiguity</strong></h3><p>&quot;Why did that cost $37?&quot; is not a good post-onboarding sentiment. Many apps abstract fees to the point of confusion. Users need transparent previews, cost estimators, and fallback paths.</p><h3 id="h-3-no-state-management-for-on-chain-events" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">3. <strong>No State Management for On-Chain Events</strong></h3><p>Your user clicks &quot;Stake.&quot; The transaction spins. Nothing happens. You lost them. Fix: use robust on-chain listeners, show pending states, and provide confirmations.</p><h3 id="h-4-unclear-transaction-purposes" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4. <strong>Unclear Transaction Purposes</strong></h3><p>Asking a user to sign an arbitrary message without explaining why? That&apos;s not trustless UX. That&apos;s lazy design.</p><h3 id="h-5-mobile-what-mobile" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">5. <strong>Mobile? What Mobile?</strong></h3><p>Too many dApps are built desktop-first. Yet in emerging markets, most users are <em>mobile-only</em>. Progressive enhancements and mobile-first design aren’t optional. They’re survival.</p><hr><h2 id="h-how-to-design-a-seamless-onboarding-flow-for-web3-without-losing-users" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How to Design a Seamless Onboarding Flow for Web3 Without Losing Users</h2><p>The traditional SaaS funnel? It&apos;s dead here. Your user doesn’t want to &quot;sign up.&quot; They want to <em>interact</em>, <em>swap</em>, <em>mint</em>, or <em>stake</em> — now.</p><p>Here’s how to onboard without losing your user:</p><ol><li><p><strong>Progressive Disclosure</strong><br>Don’t show users 8 wallet options at once. Detect their environment and suggest the most likely wallet. Simplify decision trees.</p></li><li><p><strong>Pre-Onboarding Education</strong><br>Brief walkthroughs, ghost tooltips, and inline help text can teach without preaching. Show users what &quot;signing&quot; does before they’re asked to do it.</p></li><li><p><strong>Friction Isn’t Always Bad</strong><br>Sometimes, a tiny delay (e.g. animation during wallet switching) is good. It reduces panic. Create UX that <em>feels</em>confident and guided.</p></li><li><p><strong>Track UX Drop-Off Points</strong><br>Analytics still matter. Where are users leaving? Where are they hesitating? Use this to iterate your flow like you would in Web2.</p></li><li><p><strong>Fail Loud, But Friendly</strong><br>When things go wrong (and they will), don’t hide it. Surface helpful error messages. Encourage retries. Offer backup options.</p></li></ol><hr><h2 id="h-final-thoughts-design-like-a-crypto-punk" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Final Thoughts: Design Like a Crypto Punk</h2><p>Web3 is chaotic, unregulated, full of scams, innovation, and promise. It&apos;s punk rock. It&apos;s permissionless. It forces you to build trust through UX, not marketing.</p><p>To design in Web3 is to rebel against the status quo of Web2 design systems. It means embracing broken standards and still finding ways to guide, educate, and delight users. If you&apos;re a designer or frontend dev making the leap, prepare to unlearn everything.</p><p>Remember: frictionless doesn’t mean trustless. And in Web3, the best UX <em>earns</em> the user’s trust at every interaction.</p><p>We’re not just building products. We’re building new paradigms. And that’s a frontier worth designing for.</p>]]></content:encoded>
            <author>jeffgat@newsletter.paragraph.com (jeffgat)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/17e6908c9f0af1d0aa3154f01b2985688a3853a524169bfab3f9d80bdfc434a9.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>