<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Tech Front: FUT Maidaan]]></title><description><![CDATA[All About FUT Maidaan Tech and Product]]></description><link>https://techfront.substack.com/s/fut-maidaan</link><image><url>https://substackcdn.com/image/fetch/$s_!9gwu!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg</url><title>Tech Front: FUT Maidaan</title><link>https://techfront.substack.com/s/fut-maidaan</link></image><generator>Substack</generator><lastBuildDate>Sat, 02 May 2026 16:03:57 GMT</lastBuildDate><atom:link href="https://techfront.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Prateek Sharma]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[techfront@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[techfront@substack.com]]></itunes:email><itunes:name><![CDATA[Prateek Sharma]]></itunes:name></itunes:owner><itunes:author><![CDATA[Prateek Sharma]]></itunes:author><googleplay:owner><![CDATA[techfront@substack.com]]></googleplay:owner><googleplay:email><![CDATA[techfront@substack.com]]></googleplay:email><googleplay:author><![CDATA[Prateek Sharma]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Tools That Saved Me Weeks of Dev Time]]></title><description><![CDATA[How the right Flutter packages turned months of development into weeks. A practical guide to tool combinations that actually work together.]]></description><link>https://techfront.substack.com/p/tools-that-saved-me-weeks-of-dev</link><guid isPermaLink="false">https://techfront.substack.com/p/tools-that-saved-me-weeks-of-dev</guid><dc:creator><![CDATA[Prateek Sharma]]></dc:creator><pubDate>Fri, 25 Jul 2025 13:03:45 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/6d4b49a3-34a9-4612-8f21-4c67ccbe23e6_1680x1200.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most developers waste months building what could take weeks.</p><p>I used to be one of them. Writing boilerplate APIs, managing dependencies, rebuilding the same UI components.</p><p>The tools were already there but I wasn&#8217;t aware how deadly they are when they are used individually and in combination. And now I use them in every app, like my most recent app - <strong>FUT Maidaan.</strong></p><p>This article is going to share those packages. Feel free to acknowledge if you are using these or haven&#8217;t used them.</p><blockquote><p>If you are figuring out what is <strong>FUT Maidaan</strong> then discover yourself by downloading the app.</p><p><strong><a href="https://bit.ly/40LfRHO">iOS App</a></strong></p><p><strong><a href="https://bit.ly/40dqdA7">Android App</a></strong></p></blockquote><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><em>Support me by subscribing. This will motivate me share more about the <strong>tech you love</strong>.</em></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><div><hr></div><h2><strong>Get_it + Injectable: DI That Actually Works</strong></h2><p>Dependency injection in Flutter starts simple. You pass a repository to a widget. Then that widget needs another service. Soon you're passing five objects through 10 constructors just to reach the widget that needs them.</p><p><strong>Get_it</strong> solves the access problem. </p><p><strong>Injectable</strong> eliminates the boilerplate.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LepW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LepW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg 424w, https://substackcdn.com/image/fetch/$s_!LepW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg 848w, https://substackcdn.com/image/fetch/$s_!LepW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!LepW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LepW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg" width="1044" height="494" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:494,&quot;width&quot;:1044,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:193801,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LepW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg 424w, https://substackcdn.com/image/fetch/$s_!LepW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg 848w, https://substackcdn.com/image/fetch/$s_!LepW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!LepW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa93a65d3-34ae-43a7-add7-f1d4e6b409b0_1044x494.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>That <strong>lazySingleton</strong> annotation does heavy lifting. Injectable scans your code, finds these annotations and generates all the dependency registration code. No manual setup. No forgotten dependency registrations.</p><p>The real magic happens with the mono-repo structure. Each package declares its own dependencies and these dependencies are executed on app launch. <strong>Only non-lazy ones are gonna be instantiated.</strong> </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VCXe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VCXe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg 424w, https://substackcdn.com/image/fetch/$s_!VCXe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg 848w, https://substackcdn.com/image/fetch/$s_!VCXe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!VCXe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VCXe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg" width="561" height="242.3477011494253" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:451,&quot;width&quot;:1044,&quot;resizeWidth&quot;:561,&quot;bytes&quot;:136662,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VCXe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg 424w, https://substackcdn.com/image/fetch/$s_!VCXe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg 848w, https://substackcdn.com/image/fetch/$s_!VCXe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!VCXe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4d9372f-8983-4cdc-9325-b6361def28e7_1044x451.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Injectable knows to inject <code>ApiClient</code> and <code>SupabaseClient</code> automatically. When you need the repository anywhere in your app, just ask for it. No prop drilling. No global variables. Just clean dependency injection that scales with your app.</p><p>The combination reduces your mistakes and makes you focus on writing business logic and not the wiring code. <strong>Every hour saved on dependency management is an hour spent on features users actually care about.</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/p/tools-that-saved-me-weeks-of-dev?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/p/tools-that-saved-me-weeks-of-dev?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>Melos: Mono-repo Without the Pain</strong></h2><p>Flutter's package management wasn't built for large apps. Create ten packages with interdependencies and watch your productivity die. Change one shared model? Update five pubspec files. Run pub get five times. Wait for five builds.</p><p>Melos changes the game entirely.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Wfp2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Wfp2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Wfp2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Wfp2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Wfp2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Wfp2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg" width="499" height="138.1331417624521" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:289,&quot;width&quot;:1044,&quot;resizeWidth&quot;:499,&quot;bytes&quot;:66805,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Wfp2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Wfp2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Wfp2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Wfp2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d85edf3-2f83-491a-9b2e-2ec700449464_1044x289.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>3 commands replace 30. But the real power is in the structure it enables.</p><p>I organized <strong>FUT Maidaan</strong> into clear boundaries:</p><ul><li><p><strong>Quality layer</strong> - Shared lint rules and test utilities</p></li><li><p><strong>Utility layer</strong> - Cross-cutting concerns like navigation and DI</p></li><li><p><strong>Core layer</strong> - Business logic, API clients, design system</p></li><li><p><strong>Feature layer</strong> - Actual screens users interact with</p></li></ul><div><hr></div><p>I have written a complete article just on the Mono-Repo, which addresses package distribution and their co-working relationship in detail. I think this is a must read, if you want to really create a scalable Flutter app.</p><div class="embedded-post-wrap" data-attrs="{&quot;id&quot;:167981238,&quot;url&quot;:&quot;https://techfront.substack.com/p/inside-mono-repo-flutter-architecture&quot;,&quot;publication_id&quot;:3875859,&quot;publication_name&quot;:&quot;Tech Front&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9gwu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;title&quot;:&quot;Inside Mono-Repo Flutter Architecture - FUT Maidaan&quot;,&quot;truncated_body_text&quot;:&quot;Most Flutter developers build their apps like a single giant house where everything lives under one roof. The kitchen connects directly to the bedroom, the bathroom shares pipes with the living room and when you need to fix the plumbing, you have to tear down half the structure. This approach worked fine when I was building small apps but when I started&#8230;&quot;,&quot;date&quot;:&quot;2025-07-11T17:02:45.917Z&quot;,&quot;like_count&quot;:1,&quot;comment_count&quot;:0,&quot;bylines&quot;:[{&quot;id&quot;:312563172,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;handle&quot;:&quot;prateeksharmatech&quot;,&quot;previous_name&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;bio&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;profile_set_up_at&quot;:&quot;2025-01-24T15:02:08.907Z&quot;,&quot;reader_installed_at&quot;:&quot;2025-02-06T18:15:09.012Z&quot;,&quot;publicationUsers&quot;:[{&quot;id&quot;:3951995,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875859,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:true,&quot;publication&quot;:{&quot;id&quot;:3875859,&quot;name&quot;:&quot;Tech Front&quot;,&quot;subdomain&quot;:&quot;techfront&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Exploring the craft of software development with deep dives into mobile frameworks, architecture, and the journey of a thoughtful engineer.&quot;,&quot;logo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T16:05:28.303Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;newspaper&quot;,&quot;is_personal_mode&quot;:false}},{&quot;id&quot;:3951271,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875153,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:false,&quot;publication&quot;:{&quot;id&quot;:3875153,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;subdomain&quot;:&quot;prateeksharmatech&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;logo_url&quot;:null,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T15:12:22.665Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;profile&quot;,&quot;is_personal_mode&quot;:true}}],&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;utm_campaign&quot;:null,&quot;belowTheFold&quot;:true,&quot;type&quot;:&quot;newsletter&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPostToDOM"><a class="embedded-post" native="true" href="https://techfront.substack.com/p/inside-mono-repo-flutter-architecture?utm_source=substack&amp;utm_campaign=post_embed&amp;utm_medium=web"><div class="embedded-post-header"><img class="embedded-post-publication-logo" src="https://substackcdn.com/image/fetch/$s_!9gwu!,w_56,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg" loading="lazy"><span class="embedded-post-publication-name">Tech Front</span></div><div class="embedded-post-title-wrapper"><div class="embedded-post-title">Inside Mono-Repo Flutter Architecture - FUT Maidaan</div></div><div class="embedded-post-body">Most Flutter developers build their apps like a single giant house where everything lives under one roof. The kitchen connects directly to the bedroom, the bathroom shares pipes with the living room and when you need to fix the plumbing, you have to tear down half the structure. This approach worked fine when I was building small apps but when I started&#8230;</div><div class="embedded-post-cta-wrapper"><span class="embedded-post-cta">Read more</span></div><div class="embedded-post-meta">10 months ago &#183; 1 like &#183; Prateek Sharma</div></a></div><div><hr></div><h4>Running build_runner in all packages with just 1 command</h4><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OXpm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OXpm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg 424w, https://substackcdn.com/image/fetch/$s_!OXpm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg 848w, https://substackcdn.com/image/fetch/$s_!OXpm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!OXpm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OXpm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg" width="1044" height="326" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:326,&quot;width&quot;:1044,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:116718,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OXpm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg 424w, https://substackcdn.com/image/fetch/$s_!OXpm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg 848w, https://substackcdn.com/image/fetch/$s_!OXpm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!OXpm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16b0f8f0-4ba4-4685-8655-c81409b4a8af_1044x326.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>That script runs code generation only in packages that need it. Change a model in the domain package? Only domain regenerates. The player feature package stays untouched. What used to take five minutes now takes thirty seconds.</p><p>Package management becomes invisible. You think about features and architecture, not about keeping dependencies in sync.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2><strong>Dio + Cache Interceptor: Smart API Calls</strong></h2><p>Mobile users have limited data. Servers have limited capacity. Yet most apps hammer both with redundant requests.</p><p>Player stats don't change every second. So why fetch them every time?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WVcD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WVcD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WVcD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WVcD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WVcD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WVcD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg" width="553" height="242.59961685823754" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:458,&quot;width&quot;:1044,&quot;resizeWidth&quot;:553,&quot;bytes&quot;:184326,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WVcD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WVcD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WVcD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WVcD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c9de5f-aff7-4f1d-9e8b-95eca4775608_1044x458.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This configuration creates intelligent caching. Fresh data serves from cache instantly. Stale data triggers a background refresh. Network errors fall back to cached data. Users see instant responses while data updates silently.</p><p>Combined with Retrofit for type safety:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-vy0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-vy0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-vy0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-vy0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-vy0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-vy0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg" width="697" height="217.6455938697318" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:326,&quot;width&quot;:1044,&quot;resizeWidth&quot;:697,&quot;bytes&quot;:127010,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-vy0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-vy0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-vy0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-vy0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49df4f21-094a-4d34-852d-b547414332ad_1044x326.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>No more parsing JSON manually. No more runtime type errors. The compiler catches mistakes before users do. Each endpoint becomes a simple method call with full IDE support.</p><p>The cache even handles offline scenarios. Users can browse previously viewed players without internet. The app feels fast because it is fast. <strong>Cache-first architecture with automatic invalidation</strong> <strong>-</strong> <strong>the best of both worlds</strong>.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/p/tools-that-saved-me-weeks-of-dev/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/p/tools-that-saved-me-weeks-of-dev/comments"><span>Leave a comment</span></a></p><div><hr></div><h2><strong>Supabase: Skip the Backend Entirely</strong></h2><p>Traditional app development means building two systems. Your Flutter app and an entire backend with authentication, APIs, database management and many more.</p><p>For now I am just using Supabase database and Edge functions. This app will have authentication later which will then include RLS on tables and more user driven data.</p><p>If you want to know how easy it has been to filter players by any type of query in Flutter, check this article.</p><div class="embedded-post-wrap" data-attrs="{&quot;id&quot;:168206348,&quot;url&quot;:&quot;https://techfront.substack.com/p/building-supabase-filters-that-actually&quot;,&quot;publication_id&quot;:3875859,&quot;publication_name&quot;:&quot;Tech Front&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9gwu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;title&quot;:&quot;Building Supabase Filters That Actually Work&quot;,&quot;truncated_body_text&quot;:&quot;Supabase promises database queries that \&quot;just work.\&quot;&quot;,&quot;date&quot;:&quot;2025-07-19T02:00:36.917Z&quot;,&quot;like_count&quot;:1,&quot;comment_count&quot;:0,&quot;bylines&quot;:[{&quot;id&quot;:312563172,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;handle&quot;:&quot;prateeksharmatech&quot;,&quot;previous_name&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;bio&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;profile_set_up_at&quot;:&quot;2025-01-24T15:02:08.907Z&quot;,&quot;reader_installed_at&quot;:&quot;2025-02-06T18:15:09.012Z&quot;,&quot;publicationUsers&quot;:[{&quot;id&quot;:3951995,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875859,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:true,&quot;publication&quot;:{&quot;id&quot;:3875859,&quot;name&quot;:&quot;Tech Front&quot;,&quot;subdomain&quot;:&quot;techfront&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Exploring the craft of software development with deep dives into mobile frameworks, architecture, and the journey of a thoughtful engineer.&quot;,&quot;logo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T16:05:28.303Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;newspaper&quot;,&quot;is_personal_mode&quot;:false}},{&quot;id&quot;:3951271,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875153,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:false,&quot;publication&quot;:{&quot;id&quot;:3875153,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;subdomain&quot;:&quot;prateeksharmatech&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;logo_url&quot;:null,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T15:12:22.665Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;profile&quot;,&quot;is_personal_mode&quot;:true}}],&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;utm_campaign&quot;:null,&quot;belowTheFold&quot;:true,&quot;type&quot;:&quot;newsletter&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPostToDOM"><a class="embedded-post" native="true" href="https://techfront.substack.com/p/building-supabase-filters-that-actually?utm_source=substack&amp;utm_campaign=post_embed&amp;utm_medium=web"><div class="embedded-post-header"><img class="embedded-post-publication-logo" src="https://substackcdn.com/image/fetch/$s_!9gwu!,w_56,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg" loading="lazy"><span class="embedded-post-publication-name">Tech Front</span></div><div class="embedded-post-title-wrapper"><div class="embedded-post-title">Building Supabase Filters That Actually Work</div></div><div class="embedded-post-body">Supabase promises database queries that "just work&#8230;</div><div class="embedded-post-cta-wrapper"><span class="embedded-post-cta">Read more</span></div><div class="embedded-post-meta">9 months ago &#183; 1 like &#183; Prateek Sharma</div></a></div><p>The GUI makes development visual. See your data structure. Test queries interactively. Debug permission issues instantly. When building complex filters with nested OR conditions, visual query building beats writing SQL in the dark.</p><p>File storage? Built in. Row-level security? Configure in the dashboard. Indexes? Easy to setup. Cron Runs? Easy to maintain and monitor. Every backend feature you'd spend weeks building already exists and works.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2><strong>Mappable + Bloc: State That Scales</strong></h2><p>State management is where Flutter apps become unmaintainable. Manual JSON parsing. Forgotten copyWith parameters. Equality checks that miss fields.</p><p>Dart Mappable automates the mundane:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8NxE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8NxE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg 424w, https://substackcdn.com/image/fetch/$s_!8NxE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg 848w, https://substackcdn.com/image/fetch/$s_!8NxE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!8NxE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8NxE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg" width="540" height="398.2758620689655" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:770,&quot;width&quot;:1044,&quot;resizeWidth&quot;:540,&quot;bytes&quot;:221387,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8NxE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg 424w, https://substackcdn.com/image/fetch/$s_!8NxE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg 848w, https://substackcdn.com/image/fetch/$s_!8NxE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!8NxE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23cf3f51-efda-4567-a234-76169cf15a72_1044x770.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>One annotation generates:</p><ul><li><p><code>fromJson</code> and <code>toJson</code> for API communication</p></li><li><p><code>copyWith</code> for immutable updates</p></li><li><p><code>==</code> and <code>hashCode</code> for proper equality</p></li><li><p><code>toString</code> for debugging</p></li></ul><p>No manual maintenance. Add a field, regenerate, everything updates. Remove a field, the compiler catches every usage.</p><p>This pairs perfectly with Bloc's event-driven architecture:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hPGd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hPGd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg 424w, https://substackcdn.com/image/fetch/$s_!hPGd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg 848w, https://substackcdn.com/image/fetch/$s_!hPGd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!hPGd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hPGd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg" width="1044" height="684" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:684,&quot;width&quot;:1044,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:241349,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hPGd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg 424w, https://substackcdn.com/image/fetch/$s_!hPGd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg 848w, https://substackcdn.com/image/fetch/$s_!hPGd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!hPGd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18c05748-9904-475b-a4e9-b464bcaca6ed_1044x684.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Every state change is traceable. Every update is immutable. The compiler ensures you handle all states. Testing becomes trivial events in, states out, no surprises.</p><p>The combination enforces good patterns. You can't accidentally mutate state. You can't forget to handle loading states. The architecture guides you toward maintainable code.</p><h2><strong>Build Runner: The Compound Effect</strong></h2><p>Code generation sounds boring until you realize its impact. Every model needs serialization. Every service needs registration. Every API needs implementation.</p><p>Build Runner automates it all:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!h9WW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!h9WW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg 424w, https://substackcdn.com/image/fetch/$s_!h9WW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg 848w, https://substackcdn.com/image/fetch/$s_!h9WW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!h9WW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!h9WW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg" width="584" height="234.94252873563218" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:420,&quot;width&quot;:1044,&quot;resizeWidth&quot;:584,&quot;bytes&quot;:114389,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!h9WW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg 424w, https://substackcdn.com/image/fetch/$s_!h9WW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg 848w, https://substackcdn.com/image/fetch/$s_!h9WW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!h9WW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1657d00e-1472-4b0e-b404-6f44486244e6_1044x420.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>But the magic is in what it generates. Take this API definition:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PgkN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PgkN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg 424w, https://substackcdn.com/image/fetch/$s_!PgkN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg 848w, https://substackcdn.com/image/fetch/$s_!PgkN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!PgkN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PgkN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg" width="602" height="242.183908045977" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:420,&quot;width&quot;:1044,&quot;resizeWidth&quot;:602,&quot;bytes&quot;:131893,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168939816?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PgkN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg 424w, https://substackcdn.com/image/fetch/$s_!PgkN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg 848w, https://substackcdn.com/image/fetch/$s_!PgkN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!PgkN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6a5f8143-ac1f-409c-802c-57717d8c0d5a_1044x420.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Build Runner creates the entire implementation. HTTP calls, error handling, JSON parsing - everything generated. You write the interface, the tool writes the implementation.</p><p>With mono-repo structure, generation becomes incremental:</p><ul><li><p>Touch a model in domain? Only domain regenerates</p></li><li><p>Add an API in api_client? Only api_client rebuilds</p></li><li><p>Create a new bloc in a feature? Only that feature updates</p></li></ul><p>Five-minute builds become thirty-second updates.</p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2><strong>Firebase Test Labs: Testing on Real Devices</strong></h2><p>Emulators lie. Your high-end development phone lies. Only real devices tell the truth.</p><p>My first release proved this. Perfect on my iPhone and Samsung S20. Crashed on low-end Samsung devices. Firebase Test Labs caught what I missed.</p><p>This tests on flagship phones, mid-range devices and ancient hardware. Different Android versions. Different memory constraints. Different CPU speeds.</p><p>The results are enlightening. That smooth animation? Janky on old phones. That clever algorithm? Times out on slow processors. Test Labs is must before you submit app to google play, otherwise after multiple rejections your app will be suspended and you will have to change package id and name of the app, which I had to do. That&#8217;s why you see <strong>FUT Maidaan</strong> on iOS and <strong>FUTMaidaan</strong> on Google play.</p><p>Combined with BDD tests for clarity:</p><pre><code>Feature: Player Data Loading

  Scenario: Player data loads successfully
    Given I am on the player list page
    When the page loads
    Then I see text {'Lionel Messi'}
    And I see text {'93'}
    And I see text {'RW'}
    And I don't see text {'Loading...'}

  Scenario: Player data fails to load
    Given I am on the player list page
    And the network is unavailable
    When the page loads
    Then I see text {'Failed to load players'}
    And I don't see text {'Lionel Messi'}
    And I see widget {RetryButton}

  Scenario: Loading state is displayed
    Given I am on the player list page
    And the API response is delayed
    When the page loads
    Then I see text {'Loading...'}
    And I see widget {CircularProgressIndicator}
    And I don't see text {'Lionel Messi'}</code></pre><p>Anyone can read these tests. Product managers. Designers. New developers. Clear tests catch bugs before users do.</p><p>Most importantly when you upgrade to newer Flutter version and update dependencies, you might have fixed all compilation issues but runtime issues will only be caught in tests without running and checking whole app.</p><div><hr></div><h2><strong>The Compound Architecture</strong></h2><p>These tools create something greater than their parts. Each combination solves specific pain points:</p><p><strong>Get_it + Injectable</strong> removes dependency management friction. Write business logic, not wiring code.</p><p><strong>Dio + Cache + Retrofit</strong> creates type-safe, offline-capable APIs. Users get instant responses and servers get fewer requests.</p><p><strong>Mappable + Bloc</strong> enforces immutable, testable state management. Bugs become compiler errors.</p><p><strong>Melos + Build Runner</strong> enables true incremental builds. Change one file, rebuild one package.</p><p>The architecture emerges naturally. Clean boundaries between packages. Clear data flow through layers. Testable components at every level.</p><p>This isn't over-engineering. It's acknowledging that apps grow, requirements change and good architecture pays dividends. <strong>Every shortcut in month one becomes technical debt in month six.</strong></p><h2><strong>Start With Your Pain Points</strong></h2><p>You don't need every tool immediately. Start where it hurts most.</p><p>Drowning in prop drilling? Add <strong>Get_it + Injectable</strong>. </p><p>Fighting with API boilerplate? Try <strong>Dio + Retrofit</strong>. </p><p>Managing multiple features? <strong>Introduce Melos</strong>.</p><p>But commit to structure early. A mono-repo might seem excessive for five screens. By screen fifty, you'll thank yourself. Clean architecture might feel rigid initially. When adding features becomes trivial, you'll understand why.</p><p>These tools saved me weeks. But beyond time, they brought predictability. Predictable builds. Predictable state. Predictable deployment. In software development, predictability is the foundation of speed.</p><p>Ship faster by building better foundations. These tools show you how.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><strong>Enjoyed this article? </strong>Want more such content on Flutter, Compose, and modern UI development, <strong>subscribe to TechFront SubStack</strong>, where I share insights, tutorials, and best practices to level up your development skills. <strong>Don&#8217;t miss out on exclusive articles</strong> and resources tailored for passionate developers like you! reading Tech Front! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Building Supabase Filters That Actually Work]]></title><description><![CDATA[From Naive Chains to Production-Ready Patterns: A Deep Dive into Complex Query Building for PostgreSQL.]]></description><link>https://techfront.substack.com/p/building-supabase-filters-that-actually</link><guid isPermaLink="false">https://techfront.substack.com/p/building-supabase-filters-that-actually</guid><dc:creator><![CDATA[Prateek Sharma]]></dc:creator><pubDate>Sat, 19 Jul 2025 02:00:36 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9f51087f-012b-4fb8-bd3f-5251959a5ce9_1680x1200.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Supabase promises database queries that "just work."</p><p>But every developer knows the truth: filters break, performance crawls and what looked simple in the docs becomes a debugging nightmare at 2 AM.</p><p>I've spent months untangling Supabase filter chains in FUT Maidaan, discovering patterns that transform fragile queries into bulletproof data pipelines.</p><p>Here's the exact system I use to build filters that handle millions of rows without breaking a sweat.</p><blockquote><p>If you are figuring out what is FUT Maidaan then discover yourself by downloading the app.</p><p><strong><a href="https://bit.ly/40LfRHO">iOS App</a></strong> </p><p><strong><a href="https://bit.ly/40dqdA7">Android App</a></strong></p></blockquote><h2>The Monster We're Dealing With</h2><p>Before we dive in, let me show you the complexity we're tackling. This is a real filter function from FUT Maidaan - a football player database with thousands of cards:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JiI3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JiI3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg 424w, https://substackcdn.com/image/fetch/$s_!JiI3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg 848w, https://substackcdn.com/image/fetch/$s_!JiI3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!JiI3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JiI3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg" width="600" height="515.625" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:880,&quot;width&quot;:1024,&quot;resizeWidth&quot;:600,&quot;bytes&quot;:323485,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!JiI3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg 424w, https://substackcdn.com/image/fetch/$s_!JiI3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg 848w, https://substackcdn.com/image/fetch/$s_!JiI3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!JiI3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff82ce6fe-de30-468a-8aa6-308adc1df525_1024x880.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>That's <strong>twelve different filter types</strong>. Users can search for <strong>"left-footed Brazilian strikers from Premier League with 85+ rating who have the Finesse Shot playstyle."</strong> And they expect instant results.</p><p>If you're thinking "just chain some <code>.where()</code> calls," you're in for a world of pain. Let me show you why and more importantly, how to build this correctly.</p><h2>The Domain: Understanding Football Card Filtering</h2><p>In FUT Maidaan, players have multiple attributes that users want to filter by. A player card isn't just a name and rating - it's a complex entity with leagues, nations, positions, special abilities (roles and playstyles) and various ratings. Users might want to find specific combinations like <strong>"German midfielders from Bayern Munich with the Deep-Lying Playmaker role."</strong></p><p>This creates unique challenges. A player can have multiple roles and playstyles. Positions aren't just simple strings - they're hierarchical (a striker can play as center forward, right wing, or left wing). And users expect to combine all these filters seamlessly.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!O_in!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!O_in!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg 424w, https://substackcdn.com/image/fetch/$s_!O_in!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg 848w, https://substackcdn.com/image/fetch/$s_!O_in!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!O_in!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!O_in!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg" width="1456" height="907" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:907,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:649141,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!O_in!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg 424w, https://substackcdn.com/image/fetch/$s_!O_in!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg 848w, https://substackcdn.com/image/fetch/$s_!O_in!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!O_in!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c8408a-cf5f-41ff-850d-c4b6a03bda6d_2428x1513.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>The Naive Approach (And Why It Fails)</h2><p>When I first started, I tried the obvious approach:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!onru!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!onru!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg 424w, https://substackcdn.com/image/fetch/$s_!onru!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg 848w, https://substackcdn.com/image/fetch/$s_!onru!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!onru!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!onru!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg" width="578" height="581.951171875" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1031,&quot;width&quot;:1024,&quot;resizeWidth&quot;:578,&quot;bytes&quot;:292414,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!onru!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg 424w, https://substackcdn.com/image/fetch/$s_!onru!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg 848w, https://substackcdn.com/image/fetch/$s_!onru!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!onru!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a51770a-1cbb-4e8b-97e2-aaf041490d83_1024x1031.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This approach has several problems. First, chaining <code>.or()</code> conditions creates increasingly complex SQL that Postgres struggles to optimize. Second, each method call might create a new query instance, leading to unexpected behavior. Third, there's no clear pattern for handling different filter types - some need OR logic, others need AND and some need special operators like <code>contains</code> for arrays.</p><h2>The PostgrestFilterBuilder Pattern</h2><p>The key insight is treating your query as a mutable builder object. Here's how the correct approach starts:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p3jt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p3jt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg 424w, https://substackcdn.com/image/fetch/$s_!p3jt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg 848w, https://substackcdn.com/image/fetch/$s_!p3jt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!p3jt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p3jt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg" width="720" height="414.140625" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:589,&quot;width&quot;:1024,&quot;resizeWidth&quot;:720,&quot;bytes&quot;:201647,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!p3jt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg 424w, https://substackcdn.com/image/fetch/$s_!p3jt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg 848w, https://substackcdn.com/image/fetch/$s_!p3jt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!p3jt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b0b4c4f-60fb-42db-838d-16e278787785_1024x589.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Notice how we're reassigning <code>postgresFilterBuilder</code> each time? This ensures we're always working with the latest query state. <strong>It's like building with LEGO blocks</strong> - each filter adds another piece to your structure.</p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Handling Multiple Values: The inFilter Magic</h2><p>Here's where things get interesting. When users select multiple leagues or clubs, you need to find players in ANY of those selections. The naive approach uses OR chains but there's a better way:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1w65!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1w65!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png 424w, https://substackcdn.com/image/fetch/$s_!1w65!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png 848w, https://substackcdn.com/image/fetch/$s_!1w65!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png 1272w, https://substackcdn.com/image/fetch/$s_!1w65!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1w65!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png" width="658" height="431.8125" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:672,&quot;width&quot;:1024,&quot;resizeWidth&quot;:658,&quot;bytes&quot;:125774,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1w65!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png 424w, https://substackcdn.com/image/fetch/$s_!1w65!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png 848w, https://substackcdn.com/image/fetch/$s_!1w65!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png 1272w, https://substackcdn.com/image/fetch/$s_!1w65!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fe5b38-7e35-4a78-8202-9b810f6bae9a_1024x672.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The <code>inFilter</code> method translates to SQL's <code>IN</code> operator, which Postgres optimizes much better than multiple OR conditions. It's cleaner, faster and less error-prone.</p><h2>The Array Contains Pattern for Complex Filters</h2><p>Now here's where it gets really interesting. In FUT Maidaan, players can have multiple roles and playstyles. These are stored as arrays of ids in the database. How do you filter for players who have ANY of the selected roles?</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fdMU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fdMU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fdMU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fdMU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fdMU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fdMU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg" width="616" height="210.546875" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:350,&quot;width&quot;:1024,&quot;resizeWidth&quot;:616,&quot;bytes&quot;:95309,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fdMU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fdMU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fdMU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fdMU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff55ae705-1ec9-4fb7-8d35-4ef2d3973fa7_1024x350.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The <code>contains</code> method checks if the database array contains ANY of the provided values. This is perfect for our use case where a player might have multiple roles and we want to find players with at least one of the selected roles.</p><h2>The Overlap Operator for Advanced Array Filtering</h2><p>But what about playstyles? Here's where I discovered something powerful - <strong>the overlap operator</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aCYu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aCYu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg 424w, https://substackcdn.com/image/fetch/$s_!aCYu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg 848w, https://substackcdn.com/image/fetch/$s_!aCYu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!aCYu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aCYu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg" width="1024" height="249" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:249,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:136057,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!aCYu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg 424w, https://substackcdn.com/image/fetch/$s_!aCYu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg 848w, https://substackcdn.com/image/fetch/$s_!aCYu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!aCYu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c699e5a-3b42-46d4-9a91-66b0934f7e89_1024x249.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The <strong>.ov.</strong> operator checks if arrays overlap. This query finds players who have ANY of the selected playstyles in EITHER their regular or "plus" playstyle arrays. It's like asking "Does this player have Finesse Shot OR Long Shot in their regular abilities OR their upgraded abilities?"</p><p>This is player_details table from supabase, for your reference to understand that how playstyles and roles are stored for a player. Each row is one player.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!teaC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!teaC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png 424w, https://substackcdn.com/image/fetch/$s_!teaC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png 848w, https://substackcdn.com/image/fetch/$s_!teaC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png 1272w, https://substackcdn.com/image/fetch/$s_!teaC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!teaC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png" width="1456" height="203" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:203,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:37239,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!teaC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png 424w, https://substackcdn.com/image/fetch/$s_!teaC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png 848w, https://substackcdn.com/image/fetch/$s_!teaC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png 1272w, https://substackcdn.com/image/fetch/$s_!teaC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29f6d8e6-dbcb-4774-acd2-0ee869701d75_1768x246.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p></p><div class="directMessage button" data-attrs="{&quot;userId&quot;:312563172,&quot;userName&quot;:&quot;Prateek Sharma&quot;,&quot;canDm&quot;:null,&quot;dmUpgradeOptions&quot;:null,&quot;isEditorNode&quot;:true}" data-component-name="DirectMessageToDOM"></div><div><hr></div><h2>Range Filters: The Edge Cases Matter</h2><p>Rating filters seem simple but edge cases will bite you:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MHPi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MHPi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg 424w, https://substackcdn.com/image/fetch/$s_!MHPi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg 848w, https://substackcdn.com/image/fetch/$s_!MHPi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!MHPi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MHPi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg" width="1024" height="747" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:747,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:232081,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MHPi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg 424w, https://substackcdn.com/image/fetch/$s_!MHPi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg 848w, https://substackcdn.com/image/fetch/$s_!MHPi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!MHPi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4eb5c6b2-393d-4417-bcc2-f3e4654ada65_1024x747.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Why these edge cases?</strong> Users might slide both handles to the same value (wanting exactly 87-rated players). Or they might not touch the slider at all (1-99 range), in which case adding filters just slows things down.</p><ol><li><p>When users haven&#8217;t touched range slider or when the start is 1 and end is 99, there is no need to apply filter as all players&#8217; rating is in this range.</p></li><li><p>When start and end is equal, this means they want exactly same overall rating player, so here <code>eq</code> is correct filter.</p></li><li><p>When start and end is not same, we can use <code>gte</code> start and <code>lte</code> end on overall rating.</p></li></ol><p>I would like you to watch this custom rating slider. I will be writing about it in future, so here is the glimpse. It can work as a range or a single value.</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;a3708103-a43e-4239-bf7d-f38236ccbe78&quot;,&quot;duration&quot;:null}"></div><div><hr></div><h2>Video Tutorials</h2><p>I have created a complete playlist of most important Supabase Filters. If you wish, you can watch them. All videos are &lt; 5 minutes.</p><div id="youtube2-bqIhqD-dZ94" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;bqIhqD-dZ94&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/bqIhqD-dZ94?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.youtube.com/techieblossom?sub_confirmation=1&quot;,&quot;text&quot;:&quot;Subscribe Techie Blossom&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.youtube.com/techieblossom?sub_confirmation=1"><span>Subscribe Techie Blossom</span></a></p><div><hr></div><h2>The Critical Order of Operations</h2><p>After applying all filters, the ordering strategy is crucial:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!E6Dz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!E6Dz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg 424w, https://substackcdn.com/image/fetch/$s_!E6Dz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg 848w, https://substackcdn.com/image/fetch/$s_!E6Dz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!E6Dz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!E6Dz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg" width="1024" height="240" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:240,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:118849,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!E6Dz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg 424w, https://substackcdn.com/image/fetch/$s_!E6Dz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg 848w, https://substackcdn.com/image/fetch/$s_!E6Dz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!E6Dz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F434fb04d-0104-4205-be92-40383b2e40de_1024x240.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Why three order clauses? This creates deterministic sorting. Without it, players with the same rating appear in random order across pages, causing duplicates in pagination. The secondary and tertiary sorts ensure consistent ordering even when primary values match.</p><h2>Pagination: The Silent Performance Killer</h2><p>Notice the pagination calculation at the start:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ih_P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ih_P!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ih_P!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ih_P!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ih_P!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ih_P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg" width="1024" height="215" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:215,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:52032,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ih_P!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ih_P!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ih_P!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ih_P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15423d56-8803-41f9-8001-2547f40cc4c3_1024x215.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The <code>range()</code> method expects inclusive bounds. Getting this wrong means missing the last item on each page. But more importantly, this approach uses offset-based pagination, which has a hidden cost - Postgres still processes all skipped rows. For page 100 with 30 items per page, it processes 3,000 rows to return 30.</p><p>This is OK for few pages but as pages increase, cursor based pagination would make more sense. I will be updating this article where I will be comparing the performance of offset based and cursor based.</p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/p/building-supabase-filters-that-actually/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/p/building-supabase-filters-that-actually/comments"><span>Leave a comment</span></a></p><div><hr></div><h2>The Complete Pattern in Action</h2><p>Let's trace through a real user scenario. A user wants to find:</p><ul><li><p>Brazilian players (nation filter)</p></li><li><p>From Premier League or La Liga (league filter)</p></li><li><p>Who are strikers (position filter)</p></li><li><p>With 85+ overall rating (range filter)</p></li><li><p>Having the "Advanced Forward++" role (role filter)</p></li></ul><p>Here's how our code handles it:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ujDL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ujDL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ujDL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ujDL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ujDL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ujDL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg" width="1024" height="830" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:830,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:371892,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/168206348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ujDL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ujDL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ujDL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ujDL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3ceb074-dff4-4d67-98c1-de00087f859c_1024x830.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ol><li><p>Transform complex objects to simple IDs</p></li><li><p>Build the query incrementally</p></li><li><p>Apply each filter with the appropriate method</p></li><li><p>Apply sorting and pagination</p></li></ol><p>Each filter method is chosen specifically for its use case. Single values use eq, multiple values use inFilter, array fields use contains and ranges use gte/lte.</p><h2>Performance Insights from Production</h2><p>After implementing this pattern, here's what I observed in production:</p><p>Complex queries with 8+ active filters return in under 200ms. The key factors:</p><ul><li><p>Using <code>inFilter</code> instead of OR chains reduced query time by 60%. More importantly they work as expected</p></li><li><p>Proper compound indexes on commonly filtered columns (league, nation, position)</p></li><li><p>The three-level ordering strategy eliminated pagination duplicates</p></li><li><p>Caching the column list (<code>_columnsToFetchForList</code>) instead of using wildcard</p></li></ul><h2>The Lessons Learned</h2><p>Building complex Supabase filters taught me several principles:</p><p><strong>Start with PostgrestFilterBuilder</strong> - It gives you a mutable query object you can build incrementally. This is cleaner than trying to chain everything in one go.</p><p><strong>Choose the right operator for each filter type</strong> - Use <strong>inFilter</strong> for multiple IDs, <strong>contains</strong> for array membership, <code>ilike</code> for text search and standard comparison operators for ranges.</p><p><strong>Handle edge cases explicitly</strong> - Empty arrays, null values and full ranges all need special handling. Don't assume your filters will always have sensible values.</p><p><strong>Order matters for pagination</strong> - Multiple order clauses ensure deterministic results across pages. Without this, users see duplicate or missing results.</p><p><strong>Wrap in proper error handling</strong> - Database queries fail. Network requests timeout. Plan for it from the start with Result types or similar patterns.</p><p>Next time you're building complex filters in Supabase, remember: it's not about chaining methods, it's about building a query systematically. Start with PostgrestFilterBuilder, choose the right operators, handle edge cases and always plan for failure. Your future self at 2 AM will thank you.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><strong>Enjoyed this article? </strong>Want more such content on Flutter, Compose, and modern UI development, <strong>subscribe to TechFront SubStack</strong>, where I share insights, tutorials, and best practices to level up your development skills. <strong>Don&#8217;t miss out on exclusive articles</strong> and resources tailored for passionate developers like you! reading Tech Front! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>If you haven&#8217;t read about how all this started, I would recommend to understand the key insights that I shared in the previous two posts about my learnings and journey to make it to production on both mobile platforms - Android and iOS with Flutter.</p><div class="embedded-post-wrap" data-attrs="{&quot;id&quot;:167981238,&quot;url&quot;:&quot;https://techfront.substack.com/p/inside-mono-repo-flutter-architecture&quot;,&quot;publication_id&quot;:3875859,&quot;publication_name&quot;:&quot;Tech Front&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9gwu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;title&quot;:&quot;Inside Mono-Repo Flutter Architecture - FUT Maidaan&quot;,&quot;truncated_body_text&quot;:&quot;Most Flutter developers build their apps like a single giant house where everything lives under one roof. The kitchen connects directly to the bedroom, the bathroom shares pipes with the living room and when you need to fix the plumbing, you have to tear down half the structure. This approach worked fine when I was building small apps but when I started&#8230;&quot;,&quot;date&quot;:&quot;2025-07-11T17:02:45.917Z&quot;,&quot;like_count&quot;:1,&quot;comment_count&quot;:0,&quot;bylines&quot;:[{&quot;id&quot;:312563172,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;handle&quot;:&quot;prateeksharmatech&quot;,&quot;previous_name&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;bio&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;profile_set_up_at&quot;:&quot;2025-01-24T15:02:08.907Z&quot;,&quot;reader_installed_at&quot;:&quot;2025-02-06T18:15:09.012Z&quot;,&quot;publicationUsers&quot;:[{&quot;id&quot;:3951995,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875859,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:true,&quot;publication&quot;:{&quot;id&quot;:3875859,&quot;name&quot;:&quot;Tech Front&quot;,&quot;subdomain&quot;:&quot;techfront&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Exploring the craft of software development with deep dives into mobile frameworks, architecture, and the journey of a thoughtful engineer.&quot;,&quot;logo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T16:05:28.303Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;newspaper&quot;,&quot;is_personal_mode&quot;:false}},{&quot;id&quot;:3951271,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875153,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:false,&quot;publication&quot;:{&quot;id&quot;:3875153,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;subdomain&quot;:&quot;prateeksharmatech&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;logo_url&quot;:null,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T15:12:22.665Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;profile&quot;,&quot;is_personal_mode&quot;:true}}],&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;utm_campaign&quot;:null,&quot;belowTheFold&quot;:true,&quot;type&quot;:&quot;newsletter&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPostToDOM"><a class="embedded-post" native="true" href="https://techfront.substack.com/p/inside-mono-repo-flutter-architecture?utm_source=substack&amp;utm_campaign=post_embed&amp;utm_medium=web"><div class="embedded-post-header"><img class="embedded-post-publication-logo" src="https://substackcdn.com/image/fetch/$s_!9gwu!,w_56,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg" loading="lazy"><span class="embedded-post-publication-name">Tech Front</span></div><div class="embedded-post-title-wrapper"><div class="embedded-post-title">Inside Mono-Repo Flutter Architecture - FUT Maidaan</div></div><div class="embedded-post-body">Most Flutter developers build their apps like a single giant house where everything lives under one roof. The kitchen connects directly to the bedroom, the bathroom shares pipes with the living room and when you need to fix the plumbing, you have to tear down half the structure. This approach worked fine when I was building small apps but when I started&#8230;</div><div class="embedded-post-cta-wrapper"><span class="embedded-post-cta">Read more</span></div><div class="embedded-post-meta">10 months ago &#183; 1 like &#183; Prateek Sharma</div></a></div><div class="embedded-post-wrap" data-attrs="{&quot;id&quot;:167185492,&quot;url&quot;:&quot;https://techfront.substack.com/p/building-my-side-project-for-8-years&quot;,&quot;publication_id&quot;:3875859,&quot;publication_name&quot;:&quot;Tech Front&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9gwu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;title&quot;:&quot;Building My Side Project for 8 Years: The FUT Maidaan Story&quot;,&quot;truncated_body_text&quot;:&quot;Most developers work on side projects for a few months before moving on to the next idea.&quot;,&quot;date&quot;:&quot;2025-07-07T16:24:16.415Z&quot;,&quot;like_count&quot;:0,&quot;comment_count&quot;:0,&quot;bylines&quot;:[{&quot;id&quot;:312563172,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;handle&quot;:&quot;prateeksharmatech&quot;,&quot;previous_name&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;bio&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;profile_set_up_at&quot;:&quot;2025-01-24T15:02:08.907Z&quot;,&quot;reader_installed_at&quot;:&quot;2025-02-06T18:15:09.012Z&quot;,&quot;publicationUsers&quot;:[{&quot;id&quot;:3951995,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875859,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:true,&quot;publication&quot;:{&quot;id&quot;:3875859,&quot;name&quot;:&quot;Tech Front&quot;,&quot;subdomain&quot;:&quot;techfront&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Exploring the craft of software development with deep dives into mobile frameworks, architecture, and the journey of a thoughtful engineer.&quot;,&quot;logo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T16:05:28.303Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;newspaper&quot;,&quot;is_personal_mode&quot;:false}},{&quot;id&quot;:3951271,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875153,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:false,&quot;publication&quot;:{&quot;id&quot;:3875153,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;subdomain&quot;:&quot;prateeksharmatech&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;logo_url&quot;:null,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T15:12:22.665Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;profile&quot;,&quot;is_personal_mode&quot;:true}}],&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;utm_campaign&quot;:null,&quot;belowTheFold&quot;:true,&quot;type&quot;:&quot;newsletter&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPostToDOM"><a class="embedded-post" native="true" href="https://techfront.substack.com/p/building-my-side-project-for-8-years?utm_source=substack&amp;utm_campaign=post_embed&amp;utm_medium=web"><div class="embedded-post-header"><img class="embedded-post-publication-logo" src="https://substackcdn.com/image/fetch/$s_!9gwu!,w_56,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg" loading="lazy"><span class="embedded-post-publication-name">Tech Front</span></div><div class="embedded-post-title-wrapper"><div class="embedded-post-title">Building My Side Project for 8 Years: The FUT Maidaan Story</div></div><div class="embedded-post-body">Most developers work on side projects for a few months before moving on to the next idea&#8230;</div><div class="embedded-post-cta-wrapper"><span class="embedded-post-cta">Read more</span></div><div class="embedded-post-meta">10 months ago &#183; Prateek Sharma</div></a></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Inside Mono-Repo Flutter Architecture - FUT Maidaan]]></title><description><![CDATA[How I turned 3-minute Flutter builds into 15-second wins with modular packages]]></description><link>https://techfront.substack.com/p/inside-mono-repo-flutter-architecture</link><guid isPermaLink="false">https://techfront.substack.com/p/inside-mono-repo-flutter-architecture</guid><dc:creator><![CDATA[Prateek Sharma]]></dc:creator><pubDate>Fri, 11 Jul 2025 17:02:45 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f0707428-5167-4cee-b1a1-10797273b612_1680x1200.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most Flutter developers build their apps like a <strong>single giant house</strong> where everything lives under one roof. The kitchen connects directly to the bedroom, the bathroom shares pipes with the living room and when you need to fix the plumbing, you have to tear down half the structure. This approach worked fine when I was building small apps but when I started working on <strong>FUT Maidaan</strong>, a complex football player <strong>database app with over 18,000 players</strong>, I realized I needed something completely different. Here&#8217;s how I transformed a potentially chaotic codebase into a collection of <strong>independent, reusable building blocks</strong> that made development faster, testing simpler and maintenance effortless.</p><blockquote><p>If you are figuring out what is FUT Maidaan then discover yourself downloading the app.</p><p><strong><a href="https://bit.ly/40LfRHO">iOS App</a></strong> </p><p><strong><a href="https://bit.ly/40dqdA7">Android App</a></strong></p></blockquote><p></p><div><hr></div><h2>The Problem with Monolithic Flutter Apps</h2><p>When you create a standard Flutter app, everything exists in a single package. Your API calls, UI components, business logic and feature screens all mingle together in the same <em>lib</em> folder. This creates several problems that become more apparent as your app grows.</p><p><strong>Code generation becomes painfully slow.</strong> When you run <em>build_runner</em> on a large monolithic app, it has to process thousands of files even when you&#8217;ve only changed a small widget. This means longer coffee breaks and broken development flow.</p><p><strong>Testing becomes a nightmare</strong> because everything depends on everything else. Want to test your player details screen? You&#8217;ll need to mock the entire app context, navigation system and API layer just to verify that a rating displays correctly.</p><p><strong>Sharing code between projects becomes impossible.</strong> That beautiful design system you built? Or complex design-agnostic widgets that you built It&#8217;s so tightly coupled to your current app that extracting it for your next project would require major surgery.</p><blockquote><p><em>Note: In FUT Maidaan app, initial build_runner executions were taking 2-3 minutes for simple model changes. This development friction was slowing down feature implementation significantly.</em></p></blockquote><p></p><div><hr></div><h2>The Mono-Repo Solution</h2><p>A mono-repo architecture solves these problems by breaking your app into <strong>small, focused packages</strong> that live in the same repository but operate independently. Think of it like building with <em><strong>Lego blocks</strong></em> instead of carving everything from a single piece of marble.</p><p>In FUT Maidaan app, I organized packages into <strong>four distinct categories</strong> that each serve a specific purpose. This organization isn&#8217;t arbitrary. It follows the dependency flow and ensures that <strong>lower-level packages never depend on higher-level</strong> ones.</p><h3>Quality Packages: The Foundation</h3><p>Quality packages form the foundation of the entire system:</p><ul><li><p><strong>quality_analysis</strong> - Holds only the linter rules and every package depends on it, ensuring all packages follow the same lint rules</p></li><li><p><strong>quality_bdd_test</strong> - Provides <strong>Gherkin-style test cases</strong> and testing framework that feature and domain packages depend on</p></li></ul><h3>Utility Packages: App-Agnostic Services</h3><p>Utility packages provide functionality that could work in any Flutter app:</p><ul><li><p><strong>utility_navigation</strong> - Abstracts <em>go_router</em> or <em>auto_route</em> packages for consistent navigation across features</p></li><li><p><strong>utility_di</strong> - Configures dependency injection using <em>get_it</em> and <em>injectable</em> for almost all packages, creating a clean dependency graph</p></li></ul><h3>Core Packages: Shared Business Concerns</h3><p>Core packages handle the fundamental business logic that multiple features need:</p><ul><li><p><strong>core_api_client</strong> - Foundation for API connection via <em>dio</em> with custom interceptors, consistent error handling and token management</p></li><li><p><strong>core_design_system</strong> - Atomic design principles for modular and consistent app UI following reusable component patterns</p></li><li><p><strong>core_domain</strong> - Common data layer, domain layer and presentation layer consumed by multiple features, containing shared models, APIs and repositories. This package follows clean architecture.</p></li></ul><h3>Feature Packages: Self-Contained User Flows</h3><p>Feature packages implement specific user journeys using clean architecture:</p><ul><li><p><strong>feature_player</strong> - Follows clean architecture (data, domain, presentation) for onboarding, player lists and player details screens</p></li><li><p><strong>feature_filter</strong> - Manages search and filtering functionality with complex query building UI</p></li><li><p><strong>Additional features</strong> - Easy to spin up new features following the same patterns</p></li></ul><p>And, here&#8217;s how the <strong>main</strong> <strong>pubspec.yaml</strong> looks like:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HdM6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HdM6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HdM6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HdM6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HdM6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HdM6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg" width="1024" height="1220" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1220,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:373248,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167981238?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!HdM6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HdM6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HdM6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HdM6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60912560-009e-489c-a8d9-d91422c5efe3_1024x1220.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>How Dependencies Flow Through the System</h2><p>The beauty of this architecture lies in how packages depend on each other. <strong>Dependencies always flow downward</strong>, creating a directed acyclic graph that prevents circular dependencies and makes the system predictable.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kCSQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kCSQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kCSQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kCSQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kCSQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kCSQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg" width="1456" height="1702" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1702,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:681559,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167981238?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kCSQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kCSQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kCSQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kCSQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec8180b9-d16e-49ab-a750-fab330770cd8_2728x3188.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Don&#8217;t worry by looking at these many arrows. They are for your clarity. Let me walk you through how this dependency flow works in practice:</p><p><strong>Feature packages</strong> sit at the top and can depend on any lower-level package. When the player feature needs to make an API call, it uses repositories from the <em>domain</em> package. When it needs to display a component, it imports from the <em>design_system</em> package. When it needs navigation, it calls the <em>navigation</em> package.</p><p><strong>Core packages</strong> depend only on utility and quality packages. The domain package uses dependency injection from the utility layer and follows lint rules from the quality layer but it <em>never</em> imports anything from feature packages.</p><p><strong>Utility packages</strong> depend only on quality packages. They provide foundational services but don&#8217;t know anything about your business logic or UI.</p><p><strong>Quality packages</strong> depend on nothing except external libraries. They establish the rules and testing framework that everything else follows. If you later wish to have common test files in <em>bdd_test </em>package, as it won&#8217;t violate the rule of features depending on quality.</p><p>This dependency structure creates several powerful benefits:</p><ul><li><p>When you modify a low-level package, you immediately know which packages might be affected</p></li><li><p>When you want to add a new feature, you can be confident it won&#8217;t break existing functionality if you follow the dependency rules</p></li><li><p>Circular dependencies become impossible by design and even if you face such a challenge, you know the architecture is disturbed and you are moving in opposite direction of modular app.</p></li><li><p>Code reuse becomes natural rather than forced</p></li></ul><p></p><div><hr></div><h2>The Magic of Granular Code Generation</h2><p>One of the most immediate benefits I noticed was the <strong>dramatic improvement in code generation speed</strong>. When I modify a single component in the <strong>design_system or </strong>add api in <strong>domain</strong> package, I run <strong>build_runner </strong>for only that package and it processes files in that package only. This typically takes <strong>10-15 seconds</strong> instead of the <strong>2-3 minutes</strong> required for a monolithic app.</p><p>This speed improvement compounds throughout development:</p><ul><li><p>You make changes more frequently because the feedback loop is faster</p></li><li><p>You experiment more freely because you&#8217;re not waiting for long build processes</p></li><li><p>You catch errors sooner because you can regenerate code after each small change</p></li></ul><p>The improved speed comes from <strong>isolating the blast radius of changes</strong>. When you modify a model in the <em>player</em> feature package, only that package needs to regenerate its code. The filter package, domain package and design_system package remain untouched.</p><blockquote><p><strong>Real-world impact:</strong> What used to be a 3-minute wait for code generation after changing a single data model became a 15-second operation. Over a full development day, this saved hours of waiting time. You can always run build_runner in <em>watch</em> mode to never wait.</p></blockquote><h2></h2><div class="directMessage button" data-attrs="{&quot;userId&quot;:312563172,&quot;userName&quot;:&quot;Prateek Sharma&quot;,&quot;canDm&quot;:null,&quot;dmUpgradeOptions&quot;:null,&quot;isEditorNode&quot;:true}" data-component-name="DirectMessageToDOM"></div><div><hr></div><h2>Clean Architecture Within Each Package</h2><p>Each package in my mono-repo follows <strong>clean architecture principles</strong> but the implementation varies based on the package&#8217;s purpose. Feature packages implement the full <em>data-domain-presentation</em> layering, while utility packages focus on a single responsibility.</p><h3>Feature Package Architecture</h3><p>In feature packages like <strong>player</strong> and <strong>filter</strong>, the architecture follows these layers:</p><p><strong>Presentation Layer</strong> contains BLoC state management classes that handle user interactions. These BLoCs communicate exclusively with use cases from the domain layer, never directly with repositories or data sources.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_P-H!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_P-H!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_P-H!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_P-H!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_P-H!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_P-H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg" width="1024" height="795" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:795,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:281851,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167981238?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_P-H!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_P-H!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_P-H!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_P-H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8d43582-a91d-4de4-b64f-217973dc0a06_1024x795.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Domain Layer</strong> contains use cases, entities and repository interfaces. Use cases encapsulate business logic and coordinate between different repositories. For example, the <code>GetPlayerDetails</code> use case might calls both the <code>PlayerRepository</code> and <code>PriceRepository</code> to build a complete player profile.</p><p><strong>Data Layer</strong> implements repository interfaces and manages data sources. Repositories coordinate between local storage using Drift and remote APIs through Supabase. They handle caching, error handling and data transformation transparently.</p><h3>Shared Domain Architecture</h3><p>The <strong>domain</strong> package follows a similar structure but contains only <strong>shared concerns</strong>. Its entities represent core business concepts like <code>Player</code>, <code>Team</code> and <code>League</code> that multiple features need. Its repositories handle data that doesn&#8217;t belong to a specific feature. For any feature specific API calls or business logic, the feature packages will have their own data-domain layers.</p><h2></h2><div><hr></div><h2>State Management That Scales</h2><p>I chose <strong>flutter_bloc</strong> as the sole state management solution because it enforces clear boundaries between different parts of the system. Each BLoC handles a specific user flow and communicates through well-defined events and states.</p><p>The state management follows a strict communication pattern:</p><ol><li><p><strong>UI triggers events</strong> &#8594; BLoCs receive user interactions</p></li><li><p><strong>BLoCs call use cases</strong> &#8594; Business logic coordination happens here</p></li><li><p><strong>Use cases call repositories</strong> &#8594; Data fetching and manipulation</p></li><li><p><strong>Repositories return data</strong> &#8594; Results flow back up the chain</p></li></ol><p>To reduce the verbosity that BLoC is known for, I use the <em>mappable</em> package instead of <em>freezed</em>. Mappable generates immutable classes with less boilerplate and supports inheritance for data classes, which proves useful for complex state hierarchies. <em><strong>As I remember, new freezed version also does it, but I am preferring 1 generated file over 2.</strong></em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!va4e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!va4e!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg 424w, https://substackcdn.com/image/fetch/$s_!va4e!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg 848w, https://substackcdn.com/image/fetch/$s_!va4e!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!va4e!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!va4e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg" width="1024" height="829" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:829,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:224456,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167981238?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!va4e!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg 424w, https://substackcdn.com/image/fetch/$s_!va4e!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg 848w, https://substackcdn.com/image/fetch/$s_!va4e!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!va4e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1564fff1-215a-4ebc-893d-fe640029a9f7_1024x829.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The state management architecture <strong>scales beautifully</strong> as the app grows. Adding a new feature means creating new BLoCs and respective pages that follow the same patterns. These BLoCs can safely depend on existing use cases and repositories without risking conflicts.</p><h2></h2><div><hr></div><h2>API Architecture That Adapts</h2><p>The <strong>api_client</strong> package demonstrates how mono-repo architecture handles <strong>cross-cutting concerns elegantly</strong>. All network communication flows through this single package but features remain decoupled from specific API implementations.</p><p>I use <strong>Retrofit with Dio</strong> to generate type-safe API clients. The <strong>api_client</strong> package provides a configured <em>Dio</em> instance with two custom interceptors that handle common concerns automatically:</p><ul><li><p><code>ApiKeyInterceptor</code> - Attaches authentication tokens to every request, eliminating repetitive boilerplate in feature code</p></li><li><p><code>ApiErrorInterceptor</code> - Transforms network errors into domain-specific exceptions that the presentation layer can handle appropriately</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ppbh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ppbh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ppbh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ppbh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ppbh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ppbh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg" width="1024" height="655" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:655,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:195632,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167981238?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ppbh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ppbh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ppbh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ppbh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56e49706-9810-477a-a83e-aa7143598387_1024x655.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This centralized approach proved <strong>invaluable when I had to switch data sources</strong>. The original API I was using stopped updating player data for several months, which would have been catastrophic for a football app during the most important part of the season.</p><p>Because my API logic was isolated in the <strong>api_client</strong> and <strong>domain</strong> packages, <strong>switching from the external API to Supabase took only two days</strong>. I modified the repository implementations in the domain package and updated the API client configuration. No feature code needed to change because the use cases and BLoCs continued working with the same interfaces.</p><blockquote><p><strong>Crisis Management:</strong> When your primary data source fails, having isolated API logic means the difference between a two-day fix and a complete rewrite. This architectural decision saved my app during a critical period. Before making shift to Supabase, I was calling API for fetching players and almost everything but last season that API vanished. When I switched to supabase, all I had to do was make supabase calls from repository layer instead of calling API.</p></blockquote><h2></h2><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/p/inside-mono-repo-flutter-architecture/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/p/inside-mono-repo-flutter-architecture/comments"><span>Leave a comment</span></a></p><div><hr></div><h2>Dependency Injection That Just Works</h2><p>Managing dependencies across multiple packages could become a nightmare without proper tooling. I use <strong>get_it with injectable</strong> to create a dependency graph that configures itself automatically.</p><p>Each package defines its own dependencies using injectable annotations:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TYw8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TYw8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TYw8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TYw8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TYw8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TYw8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg" width="1456" height="557" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:557,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:574144,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167981238?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TYw8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TYw8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TYw8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TYw8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96500ac0-3627-4afe-a1f7-0a60fb8e14e8_2320x888.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When the app starts, all package dependency modules are registered with <em>get_it</em> in the correct order. This ensures that when a BLoC needs a use case and that use case needs a repository, everything is available without manual wiring.</p><p>The dependency injection setup follows the <strong>same hierarchical structure</strong> as the packages themselves:</p><ol><li><p>Quality packages register first</p></li><li><p>Utility packages register second</p></li><li><p>Core packages register third</p></li><li><p>Feature packages register last</p></li></ol><p>This order ensures that dependencies are always available when they&#8217;re needed. Injectable generates all the registration code, so adding a new dependency is as simple as adding an annotation.</p><h2></h2><div><hr></div><h2>Testing That Makes Sense</h2><p>The package structure makes testing <strong>significantly more straightforward</strong> because each package has clear boundaries and minimal dependencies. You can test a use case by mocking only its direct dependencies, not the entire application context.</p><p>I use <strong>BDD-style tests</strong> with the <em>bdd_widget_test</em> package to create readable test scenarios:</p><pre><code>Feature: Player Data Loading

  Scenario: Player data loads successfully
    Given I am on the player list page
    When the page loads
    Then I see text {'Lionel Messi'}
    And I see text {'93'}
    And I see text {'RW'}
    And I don't see text {'Loading...'}

  Scenario: Player data fails to load
    Given I am on the player list page
    And the network is unavailable
    When the page loads
    Then I see text {'Failed to load players'}
    And I don't see text {'Lionel Messi'}
    And I see widget {RetryButton}

  Scenario: Loading state is displayed
    Given I am on the player list page
    And the API response is delayed
    When the page loads
    Then I see text {'Loading...'}
    And I see widget {CircularProgressIndicator}
    And I don't see text {'Lionel Messi'}</code></pre><p>These tests read like natural language specifications and can be understood by non-technical stakeholders. Appropriate <strong>_test.dart files are created on generation</strong>. More on this in future posts. The isolated nature of packages means you can <strong>run tests for individual packages</strong> without setting up the entire application.</p><p>When you need to test integration between packages, the dependency injection system makes it easy to replace real services with test doubles. You can test the complete user flow while still maintaining control over external dependencies.</p><p></p><div><hr></div><h2>The Development Experience</h2><p>Working with this architecture feels <strong>fundamentally different</strong> from traditional Flutter development. Adding a new feature becomes a process of <em>composing existing building blocks</em> rather than weaving new functionality into an existing codebase.</p><p>When I decided to add <strong>player price tracking</strong> to FUT Maidaan, the process was remarkably clean:</p><ol><li><p>Created a new API client in the <em>domain</em> package for price data</p></li><li><p>Added price-related use cases that coordinated with existing player data</p></li><li><p>Updated the player feature to display the new price information</p></li><li><p>The filter feature, design system and navigation packages remained completely untouched</p></li></ol><p>I developed this solo, so this doesn&#8217;t apply to me. But for larger teams the modular structure also makes <strong>code review more focused</strong>. When someone reviews a pull request that adds filter functionality, they only need to understand the filter package and its immediate dependencies. They don&#8217;t need to comprehend the entire application to verify that the changes are correct.</p><div class="pullquote"><p><strong>Building solo and working on multiple projects simultaneously demands that your app architecture is modular , scalable and has clear separation of concerns, otherwise most of your time goes in recollecting how the app is developed. No matter app is small or big, if your app is scalable then you don&#8217;t procrastinate adding new feature to app for months.</strong></p></div><p>Development speed improvements compound throughout the day:</p><ul><li><p><strong>Code generation runs faster</strong> - Only affected packages rebuild</p></li><li><p><strong>Tests run faster</strong> - You can test individual packages in isolation</p></li><li><p><strong>Builds complete faster</strong> - Each package processes only what it needs</p></li></ul><p>This speed improvement accumulates throughout the day, making development more enjoyable and productive.</p><h2></h2><div><hr></div><h2>Sharing Code Between Projects</h2><p>This is an ambitious thought - One of the <strong>long-term benefits</strong> of mono-repo architecture is code reusability. The <em>design_system</em> package I built for FUT Maidaan contains many components that would work perfectly in other sports apps or any app that needs clean data visualization.</p><p>The utility packages are <strong>completely app-agnostic</strong>:</p><ul><li><p>The navigation abstraction could work with any routing solution</p></li><li><p>Dependency injection configuration applies to any Flutter project</p></li><li><p>Analysis rules establish consistent code quality standards</p></li></ul><p>Even some core packages like <em>api_client</em> could be adapted for other projects with minimal changes. The HTTP interceptors, error handling and caching logic solve common problems that most apps face.</p><p>This reusability means that <strong>future projects can start with a solid foundation</strong> instead of building everything from scratch. You&#8217;re not just building an app; you&#8217;re building a toolkit for all your future apps.</p><h2></h2><div><hr></div><h2>Building Your Own Mono-Repo</h2><p>If you&#8217;re convinced that mono-repo architecture could benefit your Flutter project, <strong>start small and grow incrementally</strong>. Begin by extracting your most reusable components into separate packages within your existing project structure.</p><h3>Step-by-Step Migration Strategy</h3><p><strong>Create a </strong><em>design_system</em><strong> package first</strong> because it has minimal dependencies and immediate benefits. Keep it free from domain knowledge; think how material widgets are created. Move your reusable widgets, themes and style constants into this package and update your feature code to import from it.</p><p><strong>Next, extract utility concerns</strong> like navigation and dependency injection. These packages will be used by multiple features and help establish the dependency flow patterns that make mono-repo architecture effective.</p><p><strong>Gradually extract feature functionality</strong> into dedicated packages, ensuring that each package follows clean architecture principles and maintains clear boundaries with other packages.</p><p><strong>Set up proper tooling</strong> using <em>melos</em> for mono-repo management, which allows you to run commands across all packages with 1 command and manage dependencies effectively.</p><p>The <strong>investment in setting up this architecture pays dividends quickly</strong>. You&#8217;ll notice faster development cycles, easier testing and more maintainable code within the first few weeks of adoption.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><strong>Enjoyed this article? </strong>Want more such content on Flutter, Compose, and modern UI development, <strong>subscribe to TechFront SubStack</strong>, where I share insights, tutorials, and best practices to level up your development skills. <strong>Don&#8217;t miss out on exclusive articles</strong> and resources tailored for passionate developers like you! reading Tech Front! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p>The mono-repo approach <strong>transformed how I think about Flutter development</strong>. Instead of building apps as monolithic structures, I now build them as collections of focused, reusable components that happen to work together to create a cohesive user experience. This shift in perspective makes complex projects manageable and sets the foundation for building better apps faster.</p><p><em>I have used this structure in over 4-5 apps now and it has never felt that I over-engineered for no reason or I made a mistake.</em></p><p>When you&#8217;re ready to scale beyond simple Flutter apps, mono-repo architecture provides the structure and discipline needed to manage complexity without sacrificing development speed. The initial investment in proper architecture pays off exponentially as your project grows and evolves.</p><div class="pullquote"><p>This architecture deep-dive is just the beginning. Building FUT Maidan from idea to App Store taught me dozens of lessons about what actually works in production. More insights from the trenches coming soon.</p></div><p>If you haven&#8217;t read about how all this started, I would recommend to understand the key insights that I shared in this post about my learnings and journey to make it to production on both mobile platforms - Android and iOS with Flutter.</p><div class="embedded-post-wrap" data-attrs="{&quot;id&quot;:167185492,&quot;url&quot;:&quot;https://techfront.substack.com/p/building-my-side-project-for-8-years&quot;,&quot;publication_id&quot;:3875859,&quot;publication_name&quot;:&quot;Tech Front&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9gwu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;title&quot;:&quot;Building My Side Project for 8 Years: The FUT Maidaan Story&quot;,&quot;truncated_body_text&quot;:&quot;Most developers work on side projects for a few months before moving on to the next idea.&quot;,&quot;date&quot;:&quot;2025-07-07T16:24:16.415Z&quot;,&quot;like_count&quot;:0,&quot;comment_count&quot;:0,&quot;bylines&quot;:[{&quot;id&quot;:312563172,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;handle&quot;:&quot;prateeksharmatech&quot;,&quot;previous_name&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;bio&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;profile_set_up_at&quot;:&quot;2025-01-24T15:02:08.907Z&quot;,&quot;reader_installed_at&quot;:&quot;2025-02-06T18:15:09.012Z&quot;,&quot;publicationUsers&quot;:[{&quot;id&quot;:3951995,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875859,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:true,&quot;publication&quot;:{&quot;id&quot;:3875859,&quot;name&quot;:&quot;Tech Front&quot;,&quot;subdomain&quot;:&quot;techfront&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Exploring the craft of software development with deep dives into mobile frameworks, architecture, and the journey of a thoughtful engineer.&quot;,&quot;logo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg&quot;,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T16:05:28.303Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;newspaper&quot;,&quot;is_personal_mode&quot;:false}},{&quot;id&quot;:3951271,&quot;user_id&quot;:312563172,&quot;publication_id&quot;:3875153,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:false,&quot;publication&quot;:{&quot;id&quot;:3875153,&quot;name&quot;:&quot;Prateek Sharma&quot;,&quot;subdomain&quot;:&quot;prateeksharmatech&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;Passionate developer with 12+ years of experience, sharing insights on software development, mobile frameworks, and architecture. Creator of Techie Blossom (35K+ subscribers). Join a journey of self-learning and building impactful systems.&quot;,&quot;logo_url&quot;:null,&quot;author_id&quot;:312563172,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-01-24T15:12:22.665Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Prateek Sharma&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;profile&quot;,&quot;is_personal_mode&quot;:true}}],&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;utm_campaign&quot;:null,&quot;belowTheFold&quot;:true,&quot;type&quot;:&quot;newsletter&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPostToDOM"><a class="embedded-post" native="true" href="https://techfront.substack.com/p/building-my-side-project-for-8-years?utm_source=substack&amp;utm_campaign=post_embed&amp;utm_medium=web"><div class="embedded-post-header"><img class="embedded-post-publication-logo" src="https://substackcdn.com/image/fetch/$s_!9gwu!,w_56,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg" loading="lazy"><span class="embedded-post-publication-name">Tech Front</span></div><div class="embedded-post-title-wrapper"><div class="embedded-post-title">Building My Side Project for 8 Years: The FUT Maidaan Story</div></div><div class="embedded-post-body">Most developers work on side projects for a few months before moving on to the next idea&#8230;</div><div class="embedded-post-cta-wrapper"><span class="embedded-post-cta">Read more</span></div><div class="embedded-post-meta">10 months ago &#183; Prateek Sharma</div></a></div>]]></content:encoded></item><item><title><![CDATA[Building My Side Project for 8 Years: The FUT Maidaan Story]]></title><description><![CDATA[Seven years of scrolling cluttered FUT apps taught me one thing: nobody was going to clean up the mess for me. So I built FUT Maidaan&#8212;and shipped it to both app stores as a solo developer.]]></description><link>https://techfront.substack.com/p/building-my-side-project-for-8-years</link><guid isPermaLink="false">https://techfront.substack.com/p/building-my-side-project-for-8-years</guid><dc:creator><![CDATA[Prateek Sharma]]></dc:creator><pubDate>Mon, 07 Jul 2025 16:24:16 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9d1d3d56-b9ff-45a2-ba62-abcfe7631dff_1680x1200.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most developers work on side projects for a few months before moving on to the next idea.</p><p>I spent 8 years building the same side project (FUT Maidaan) while working my regular job.</p><p>Here&#8217;s why I stuck with one idea for so long and what it taught me about <strong>persistence</strong>, user experience, and building something from scratch.</p><h2><strong>The Problem That Wouldn&#8217;t Leave Me Alone</strong></h2><p>The story starts in 2016 when I was deep into FIFA Ultimate Team. Like millions of other players, I relied on third-party apps to check player stats, prices, and build my dream squad.</p><p>But every app I used frustrated me in the same ways.</p><p>The player cards were cluttered messes. Apps would show three different card styles - minimal, regular, and large - depending on screen space. But none of them displayed the information I actually needed clearly.</p><p>I wanted to see league, club, nation, position, name and rating at a glance. Instead, I got cramped layouts where critical details were barely visible.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HHOv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HHOv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png 424w, https://substackcdn.com/image/fetch/$s_!HHOv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png 848w, https://substackcdn.com/image/fetch/$s_!HHOv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png 1272w, https://substackcdn.com/image/fetch/$s_!HHOv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HHOv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png" width="1456" height="1406" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1406,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3007989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167185492?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!HHOv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png 424w, https://substackcdn.com/image/fetch/$s_!HHOv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png 848w, https://substackcdn.com/image/fetch/$s_!HHOv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png 1272w, https://substackcdn.com/image/fetch/$s_!HHOv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9254f55d-2521-41f9-86f6-8936f501dfca_2368x2286.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>BTW, Look at the ads. Just bloated through out the app.</p><p>The filters were even worse. These apps threw every possible filter at you, most of which no one ever used. Want to select a club after choosing a league? You&#8217;d have to navigate through the entire league selection again. Well, they are much improved in newer app but still user has to type in to the club name. Not a fast or intuitive way.</p><p>For example, I selected Premier League and I see all clubs to select from. Either I type in or scroll a long list of clubs.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!N-6q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!N-6q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png 424w, https://substackcdn.com/image/fetch/$s_!N-6q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png 848w, https://substackcdn.com/image/fetch/$s_!N-6q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png 1272w, https://substackcdn.com/image/fetch/$s_!N-6q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!N-6q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png" width="309" height="627.888" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2286,&quot;width&quot;:1125,&quot;resizeWidth&quot;:309,&quot;bytes&quot;:435546,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167185492?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!N-6q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png 424w, https://substackcdn.com/image/fetch/$s_!N-6q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png 848w, https://substackcdn.com/image/fetch/$s_!N-6q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png 1272w, https://substackcdn.com/image/fetch/$s_!N-6q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f658eb-d53b-46e0-a3e4-e902273fea43_1125x2286.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>The interface felt like it was designed by someone who had never actually played the game.</p><p>But the biggest problem wasn&#8217;t what these apps showed - it was what they didn&#8217;t show. No one was tracking market trends the way financial apps track stock indices. Players would rise and fall in value, but there was no way to understand the broader market movements across different positions.</p><p>I knew I could build something better. But knowing and doing are separated by years of work, false starts, and steady persistence.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/p/building-my-side-project-for-8-years?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/p/building-my-side-project-for-8-years?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p></p><h2><strong>The Seven-Year Struggle</strong></h2><p>The first roadblock hit immediately. <strong>Player data wasn&#8217;t freely available.</strong></p><p>EA Sports had APIs until FIFA 22, but they were limited and didn&#8217;t include prices - that is the most crucial information for any FUT player. I built prototype after prototype using <strong>Android native and Flutter</strong>, each one getting scrapped when I couldn&#8217;t access the data I needed.</p><p>For years, this cycle continued. I&#8217;d get excited about a new approach, a new workaround, spend weeks building, then abandon the project when I couldn&#8217;t access the data I needed.</p><p>I accumulated many unfinished projects, each teaching me something new but none reaching completion.</p><p>The breakthrough came in 2023-24 when I finally found an API that provided both player data and pricing. It had rate limits and wasn&#8217;t perfect but it was enough to get started again.</p><p>Seven years after starting, I could finally build the app I&#8217;d been imagining.</p><h2><strong>Rethinking Everything From Scratch</strong></h2><p>But having the data was just the beginning. Now I had to solve the design problems that had bothered me for so long.</p><p>I threw out the traditional FUT card approach entirely. Instead of cramming information into card layouts, I created clean list tiles that displayed all essential information clearly.</p><p>The <strong>card colors became subtle rating box backgrounds and borders</strong>, giving visual distinction without sacrificing readability.</p><p>For the player detail pages, I eliminated the redundant information that plagued other apps. Why show the same stats twice?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rXjJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rXjJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png 424w, https://substackcdn.com/image/fetch/$s_!rXjJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png 848w, https://substackcdn.com/image/fetch/$s_!rXjJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png 1272w, https://substackcdn.com/image/fetch/$s_!rXjJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rXjJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png" width="1456" height="983" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c6b7a467-72db-43a2-8444-14239c475531_3415x2306.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:983,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2684958,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167185492?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rXjJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png 424w, https://substackcdn.com/image/fetch/$s_!rXjJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png 848w, https://substackcdn.com/image/fetch/$s_!rXjJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png 1272w, https://substackcdn.com/image/fetch/$s_!rXjJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b7a467-72db-43a2-8444-14239c475531_3415x2306.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I designed each page like a product page, using the card&#8217;s color scheme as an intelligent theme throughout the interface. Players could understand what type of card they were viewing without seeing the actual card cluttering the screen.</p><p>The filter system got a complete rethink. I removed every filter I&#8217;d never used in seven years of playing FIFA. The remaining filters became contextual - select a league, and you&#8217;d only see clubs from that league.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fDCX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fDCX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fDCX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fDCX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fDCX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fDCX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg" width="1456" height="1027" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1027,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1305607,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167185492?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fDCX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fDCX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fDCX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fDCX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aeaf0fb-6f39-4fff-9bf7-7bf5fe3640ec_3455x2436.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>No more navigating through irrelevant options.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/p/building-my-side-project-for-8-years/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://techfront.substack.com/p/building-my-side-project-for-8-years/comments"><span>Leave a comment</span></a></p><h2><strong>The Innovation That Solved a Real Gap</strong></h2><p>The feature I am most satisfied with was the index system.</p><p><strong>Taking inspiration from stock market indices</strong>, I created separate indexes for forwards, midfielders, defenders, and goalkeepers. These indexes tracked market trends in each position, giving players insights no other app provided.</p><p>For the first time, you could see how the entire midfielder market was performing, not just individual players.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-5X2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-5X2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-5X2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-5X2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-5X2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-5X2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg" width="1456" height="1440" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1440,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1218767,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167185492?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-5X2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-5X2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-5X2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-5X2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6f52685-f855-45c6-b3f2-f2f67d49424a_2313x2288.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>Building Solo: Every Hat, Every Decision</strong></h2><p>The technical architecture had to support 18,000+ players with complex filtering and real-time price updates. I chose Flutter for cross-platform development and Supabase for its unlimited read/write capabilities.</p><p>The mono-repo structure kept everything organized and maintainable.</p><p>My wife <a href="https://www.linkedin.com/in/preetimodi/">Preeti</a>, who has a background in development and product management, collaborated with me on the design work. I drew the initial sketches and wireframes, but she developed the main color palette and created the logo entirely.</p><p>The logo was completely her vision - she took my rough concept of incorporating football elements and crafted the elegant <strong>F and M design</strong> where the F forms a player with a football. Her color choices ensured the app worked beautifully in both light and dark themes.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Agfl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Agfl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png 424w, https://substackcdn.com/image/fetch/$s_!Agfl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png 848w, https://substackcdn.com/image/fetch/$s_!Agfl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png 1272w, https://substackcdn.com/image/fetch/$s_!Agfl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Agfl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png" width="292" height="140.51127819548873" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dbf706c8-cd1e-494c-a909-053456174e53_1064x512.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:512,&quot;width&quot;:1064,&quot;resizeWidth&quot;:292,&quot;bytes&quot;:42440,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://techfront.substack.com/i/167185492?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Agfl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png 424w, https://substackcdn.com/image/fetch/$s_!Agfl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png 848w, https://substackcdn.com/image/fetch/$s_!Agfl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png 1272w, https://substackcdn.com/image/fetch/$s_!Agfl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbf706c8-cd1e-494c-a909-053456174e53_1064x512.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Building solo meant wearing every hat. I was the business analyst defining requirements, the product manager prioritizing features, the developer architecting the system, the designer crafting the interface, and the release engineer publishing to app stores.</p><blockquote><p><strong><a href="https://bit.ly/40LfRHO">iOS App</a></strong> </p><p><strong><a href="https://bit.ly/40dqdA7">Android App</a></strong></p></blockquote><h2><strong>The Real Education</strong></h2><p>The development process taught me more about persistence than any corporate project had before. When you&#8217;re building something completely on your own, every decision carries weight.</p><p>There&#8217;s no product manager to blame for poor requirements, no designer to blame for confusing interfaces. The responsibility is entirely yours.</p><p><strong>Firebase Test Labs</strong> caught performance issues on low-end devices. <strong>Apple&#8217;s review process flagged copyright concerns</strong> on the second release, forcing me to navigate complex intellectual property questions as a solo developer.</p><p>Google Play Store required <strong>multiple submissions</strong> to meet their quality standards.</p><p>Each obstacle required careful problem-solving because I was responsible for finding the solutions. This wasn&#8217;t a client project with external deadlines and budgets. This was <strong>seven years of evenings, weekends</strong>, and consistent belief that I could build something better.</p><div class="install-substack-app-embed install-substack-app-embed-web" data-component-name="InstallSubstackAppToDOM"><img class="install-substack-app-embed-img" src="https://substackcdn.com/image/fetch/$s_!9gwu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc48b3f17-3416-44cc-922d-432e45196616_1772x1772.jpeg"><div class="install-substack-app-embed-text"><div class="install-substack-app-header">Get more from Prateek Sharma in the Substack app</div><div class="install-substack-app-text">Available for iOS and Android</div></div><a href="https://substack.com/app/app-store-redirect?utm_campaign=app-marketing&amp;utm_content=author-post-insert&amp;utm_source=techfront" target="_blank" class="install-substack-app-embed-link"><button class="install-substack-app-embed-btn button primary">Get the app</button></a></div><h2><strong>Launch and Beyond</strong></h2><p>The app launched with player listings, detailed player pages, search functionality and my innovative filter system. The index feature worked exactly as I&#8217;d envisioned, updating daily through scheduled Supabase edge functions.</p><p>The clean interface finally solved the cluttered mess that had frustrated me for years.</p><p>But launching was just the beginning. The roadmap includes player comparisons, <strong>AI-powered search, pack opening simulations, squad building</strong>, and even gameplay between users.</p><p>Each feature represents months of additional work, but the foundation is solid enough to support ambitious expansion.</p><h2><strong>What Seven Years Taught Me</strong></h2><p>Working evenings and weekends for seven years while maintaining a full-time job required consistent dedication. I&#8217;d hit points where I didn&#8217;t want to touch the code but motivation always returned.</p><p>The idea stayed with me throughout.</p><p>This experience taught me something valuable about building products. Most developers create smaller apps or quick projects. But there&#8217;s something deeply rewarding about building something substantial entirely yourself.</p><p>Every line of code, every design decision, every feature prioritization reflects your vision without compromise.</p><p>The app hasn&#8217;t made me rich or famous yet. User acquisition is its own challenge, requiring skills I&#8217;m still developing. But that misses the point.</p><p><strong>The real value was in the building itself.</strong></p><p>Seven years of thinking about user experience made me a better designer. Architecting a complex Flutter application from scratch made me a better developer. Managing every aspect of product development made me understand how software truly gets built.</p><p>Building FUT Maidaan taught me that persistence often matters more than talent, that understanding user needs beats adding features, and that building something entirely your own provides a unique kind of satisfaction.</p><p>The app exists because I wasn&#8217;t willing to accept that cluttered, poorly designed software was good enough. Seven years later, that decision led to both <strong>a better product and valuable learning experiences</strong>.</p><div class="pullquote"><p>Taking the longer path often teaches you the most important lessons.</p></div><p><strong>Building something this complex solo required architectural decisions that would either make or break the entire project.</strong> The mono-repo structure I chose became the foundation that allowed me to iterate quickly, maintain clean separation of concerns, and scale from a simple prototype to a production app handling 18,000+ players.</p><p><strong>How do you architect a Flutter app so it can grow from MVP to a feature-rich platform without collapsing under its own complexity?</strong> The answer lies in understanding how to structure packages, manage dependencies, and create boundaries that prevent your codebase from becoming an unmaintainable mess.</p><p><strong>In Next Post, I&#8217;ll walk you through the exact mono-repo architecture that powered FUT Maidaan.</strong> You&#8217;ll see how I organized features, core utilities, and design systems into separate packages. More importantly, you&#8217;ll understand the thinking behind each decision and how this structure enabled me to add major features without rewriting existing code.</p><p><strong>Whether you&#8217;re building your first serious Flutter project or refactoring an existing app that&#8217;s become difficult to maintain, this architecture pattern will change how you think about organizing your code.</strong></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techfront.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><strong>Enjoyed this article? </strong>Want more such content on Flutter, Compose, and modern UI development, <strong>subscribe to TechFront SubStack</strong>, where I share insights, tutorials, and best practices to level up your development skills. <strong>Don&#8217;t miss out on exclusive articles</strong> and resources tailored for passionate developers like you! reading Tech Front! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>