<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>DevToDollars Blog</title>
        <link>https://www.devtodollars.com/blog/</link>
        <description>DevToDollars Blog</description>
        <lastBuildDate>Thu, 19 Feb 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Building Agents using LLMs]]></title>
            <link>https://www.devtodollars.com/blog/guide-to-building-ai-agents/</link>
            <guid>https://www.devtodollars.com/blog/guide-to-building-ai-agents/</guid>
            <pubDate>Thu, 19 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Hey, I'm Amirali, I am builder, who builds products for customers and myself. I'm sharing some of my experience with building ai agents with you guys in this article.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="building-ai-agents-with-llms-banner" src="https://www.devtodollars.com/assets/images/building-with-llms-963aa264fec9565398e1b895cc6e7fee.jpg" width="3830" height="1915" class="img_OK7M"></p>
<p>If you think about it, LLM providers are distributed systems on steroids. Building reliable systems with them, comes with particular challenges. A modern day developer should have proper skills of using LLMs in systems at scale.</p>
<p>Some of the problems one may face when building AI agents using model providers could be:</p>
<ul>
<li class="">Unreliable output of the LLM providers specially with regards to the requested format in the prompt.</li>
<li class="">Running into rate limits boundaries of the provider.</li>
<li class="">Model quality of output dropping or an outage on the provider side.</li>
<li class="">Huge cost of tokens when using llms at scale.</li>
</ul>
<p>My goal in this blog post is to give the builder a mind frame on how to build cool stuff with these systems in a reliable and scalable fashion.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="reliability">Reliability<a href="https://www.devtodollars.com/blog/guide-to-building-ai-agents/#reliability" class="hash-link" aria-label="Direct link to Reliability" title="Direct link to Reliability" translate="no">​</a></h3>
<p>When it comes to reliability, there are a few needs that a developer has to address right off the bat. First and foremost, is LLM providers’ rate limit boundaries. For this purpose, I used technologies such as LLM gateways where one needs to keep track of the token usage by a model and switch providers if the limits are within reach. I’ve used [Portkey] (<a href="https://portkey.ai/" target="_blank" rel="noopener noreferrer" class="">https://portkey.ai/</a>) in the past for this purpose. It’s open source and easy to use, you just need to pass in a config file and you are good to go.</p>
<p>The second important reliability issue, is the format of the output returned by the provider. Imagine your prompt asked for an LLM to return its output in json format, but on the 6th try, a string output is received. Fortunately for us, the providers have a field called response_type where one can pass the type of expected response in the header of the request. The format of this header varies based on specific providers. Please refer the documentation of the provider used for the specific format.</p>
<p>For providers unexpected outage purposes, there two solutions I’ve used in the past. The first solution is using default fallback cases with try catch phrases (i.e default object definitions), so your objects don’t become null suddenly and ur system doesn’t crash.</p>
<p>The second is having another provider as a backup in case one fails in your logic.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="saving-cost">Saving Cost<a href="https://www.devtodollars.com/blog/guide-to-building-ai-agents/#saving-cost" class="hash-link" aria-label="Direct link to Saving Cost" title="Direct link to Saving Cost" translate="no">​</a></h3>
<p>The fastest way to have cost saving, is enabling caching mechanism before the user input reaches the provider. If you have a cache hit, boom, you don’t need to pay the provider. This is particularly good when you are testing with the same data multiple times during development. That way you don’t have to pay for tokens while testing. <a href="https://portkey.ai/" target="_blank" rel="noopener noreferrer" class="">Portkey</a> also provides simple caching system on top of your LLM calls.</p>
<p>You can go nuts here and use a vector database as well. It’s a pretty cool system for building memory for agents and create a converging “history” systems. In the past I’ve used <a href="https://www.pinecone.io/" target="_blank" rel="noopener noreferrer" class="">Pinecone</a> for vector database purposes, however there are many other opensource alternatives that I would like to play around with as well. <a href="https://www.trychroma.com/" target="_blank" rel="noopener noreferrer" class="">Trychroma</a> is a notable one.
If you haven’t worked with vector databases before, they are basically databases that store flat data in vector formats, so you can capture higher dimensional relationships between them. If you are interested read this document for deeper understanding of vector dbs: <a href="https://www.pinecone.io/learn/vector-database/" target="_blank" rel="noopener noreferrer" class="">what is a vector database</a>.</p>
<p>Another cost saving mechanism is fixing the output’s token count with a header variable you pass to the provider. Again each llm provider have their own variable for this and you would have to refer to their documentation. Only risk for token output fixing is getting a truncated output. Be aware of this and handle it with grace if you decide to implement token truncating.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="reaching-for-better-quality">Reaching for Better Quality<a href="https://www.devtodollars.com/blog/guide-to-building-ai-agents/#reaching-for-better-quality" class="hash-link" aria-label="Direct link to Reaching for Better Quality" title="Direct link to Reaching for Better Quality" translate="no">​</a></h3>
<p>We all know how ai can be slopish and at times very spikey. That’s why I write all these blogs by my hand with zero ai involved 😁. Personally I have used multiple layers for this purpose and put a supervisor llm at the end where it determines the quality of the previous layers’ output. You can also use more deterministic systems such as large data sets formed into a vector format and check the llm’s output at different stages against it to verify some sort of quality of response.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="final-thought">Final Thought<a href="https://www.devtodollars.com/blog/guide-to-building-ai-agents/#final-thought" class="hash-link" aria-label="Direct link to Final Thought" title="Direct link to Final Thought" translate="no">​</a></h3>
<p>I hope this article came helpful for developers to build a mind frame around building with these systems. Its really fun to play around with these systems as a developer. If you like to work with me, shoot me an <a href="mailto:amirali@devtodollars.com" target="_blank" rel="noopener noreferrer" class="">email</a>, or join our <a href="https://discord.gg/AU6aQczrR9" target="_blank" rel="noopener noreferrer" class="">Discord Community</a> of builders and build amazing things together. It’s an amazing time to be a builder and hope you all are as excited as I am.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Guide to Building Complex Integrations]]></title>
            <link>https://www.devtodollars.com/blog/guide-to-complex-integrations/</link>
            <guid>https://www.devtodollars.com/blog/guide-to-complex-integrations/</guid>
            <pubDate>Fri, 13 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Hey, I'm Amirali, I am builder, who builds products for customers and myself. I'm sharing some of my experience with building integrations into bigger systems with you guys in this article.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="complex-integration-banner" src="https://www.devtodollars.com/assets/images/integration-ad7b0feb64a75354d0f5f69886f68db1.jpeg" width="1600" height="640" class="img_OK7M"></p>
<p>When I first started building integrations to a huge system, I thought it would be a piece of cake.
As with building systems in general, I realized they are not necessarily as easy as I thought they would be. There are issues that reveal themselves to you once you are deep into the process.
Issues such as:</p>
<ul>
<li class="">Which system has the latest version of data? What is your tell?</li>
<li class="">How do you synchronize data between the two systems to preserve the latest most correct data.</li>
<li class="">How do you manage the data so every time you synchronize both systems, you don’t have to rewrite all the data.
What are the boundaries of the system you are integrating to? What do they allow you to do and what do they not?</li>
</ul>
<p>As with building systems go, once you work at a problem long enough, the answers reveal themselves to you. So I will be sharing some of my approaches to these problems. My goal is to set a mind frame on how to approach huge integrations from the beginning.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="before-begining-the-integration">Before Begining the Integration<a href="https://www.devtodollars.com/blog/guide-to-complex-integrations/#before-begining-the-integration" class="hash-link" aria-label="Direct link to Before Begining the Integration" title="Direct link to Before Begining the Integration" translate="no">​</a></h3>
<p>When you start integrating into another major provider, I recommend spending some time in their documentation, understanding their apis and database design decisions. I understand AI is great at coding these days, and you can push stuff pretty far with it, but you are still the driver. It will save you time if you drive the machine right. Focus on understanding the boundaries of the external systems as well. What are some of the things that they don’t allow you to do. This is specifically important to understand early on. It holds you back from chasing dead ends and solving impossible problems.</p>
<p>Studying big players APIs is a great place to start when approaching to design a software in a specific vertical. For example, if you want to build an accounting software, I recommend digging deep into <a href="https://www.xero.com/" target="_blank" rel="noopener noreferrer" class="">Xero</a> platform’s api. This will show you abstractions that you might be missing in the beginning, in your DB design. It will also give you a very mature view of a system ahead of time.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="what-an-integration-is-consistent-of">What an integration is consistent of<a href="https://www.devtodollars.com/blog/guide-to-complex-integrations/#what-an-integration-is-consistent-of" class="hash-link" aria-label="Direct link to What an integration is consistent of" title="Direct link to What an integration is consistent of" translate="no">​</a></h3>
<p>An integration is formed from three major things. A sync, a resync and export. Syncing takes the data from the external system to your system. Resync is how your system matches its data with the external system after the initial Sync. Finally, export is how your system sends data from your system to the external system. I recommend implementing in three separate stages (move vertically). Finishing Sync completely, enables you to make all your mistakes and not having to fix it in three different places. I say this because I tried doing sync, resync and export at the same time for each object (moving horizontally). This caused a lot of pain, because if a mistake was made about the third party’s object I had to go back and fix it in three different places.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="part-1-sync">Part 1: Sync<a href="https://www.devtodollars.com/blog/guide-to-complex-integrations/#part-1-sync" class="hash-link" aria-label="Direct link to Part 1: Sync" title="Direct link to Part 1: Sync" translate="no">​</a></h3>
<p>I recommend starting with Sync, it allows you to deeply understand the third parties system and be prepared for next stages of the integration. Store the external objects id in the database, so you can find it later on, this is important.
Recording time when a synchronization happens between two systems is important. At the end of the day, time can be your tell for what is the latest version of the data.
Try to not complicate things, if something has already been exported to the third party, don’t allow the user to edit that field again on your platform, this avoids complications of finding who is the source of truth, and constantly syncing stuff.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="part-2-export">Part 2: Export<a href="https://www.devtodollars.com/blog/guide-to-complex-integrations/#part-2-export" class="hash-link" aria-label="Direct link to Part 2: Export" title="Direct link to Part 2: Export" translate="no">​</a></h3>
<p>Then move to Export. Make sure you have a tell in your database of what object has already been exported to the third party platform. Another important factor about export is making sure you are not writing old data to the third party platform. This is where last sync time comes in handy. Also keep your updated_at field up to date when users change an object on your system, this will save you a lot of headaches later on.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="part-3-resync">Part 3: Resync<a href="https://www.devtodollars.com/blog/guide-to-complex-integrations/#part-3-resync" class="hash-link" aria-label="Direct link to Part 3: Resync" title="Direct link to Part 3: Resync" translate="no">​</a></h3>
<p>Resync is a very important piece. Even tho when you get to resync you are tired from implementing the Sync and Export logic, don’t take it lightly. A method I chose for resync was called modified since. The third party applications usually accept a time variable in their header. It will return objects that have been modified after that specific time. In that way you can make sure the data you have on your application are synced with the latest data on the third party platform. Finally, make sure you cover all the CRUD cases, specially deleted objects on the third party. Sometimes the modified since doesn’t cover deleted objects on the third party causing you to face some weird problems when you are in production.</p>
<p>I recommend wrapping your Resync function in a cron job. The resync cron job that runs for example every day, makes sure your system and the third party system don’t diverge from each other too far.
Its also not a bad idea to run your resync function before each export, just to make sure your data is not out dated between the last resync and export times.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="final-thought">Final Thought<a href="https://www.devtodollars.com/blog/guide-to-complex-integrations/#final-thought" class="hash-link" aria-label="Direct link to Final Thought" title="Direct link to Final Thought" translate="no">​</a></h3>
<p>Integrations are a challenging problem, and are unique to each system. There will be weird stuff that will come up as you build the integration. My aim in this blog post was just to give you an overview and a thinking mind frame when approaching this problem. Maybe you can feed this blog post to your coding agent when you are starting to code a big integration. We are agent friendly, we don’t block coding agents from accessing our website.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The NextJS app I sold for $15K - a full stack breakdown]]></title>
            <link>https://www.devtodollars.com/blog/nextjs-app-sold-for-15k-tech-stack-breakdown/</link>
            <guid>https://www.devtodollars.com/blog/nextjs-app-sold-for-15k-tech-stack-breakdown/</guid>
            <pubDate>Wed, 14 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Below is the tech stack I used to build my NextJS app and sell it for $15k]]></description>
            <content:encoded><![CDATA[<p>Hi everyone!</p>
<p>I've been building an app for a client I can't mention the app yet because she hasn't released it yet, but essentially it's <a href="http://linktr.ee/" target="_blank" rel="noopener noreferrer" class="">linktr.ee</a> for people who host events. It's fairly common app so I figured it'd be cool to share my tech stack and a short blurb on why I chose the tool.</p>
<p>Here's my full tech stack breakdown:</p>
<ul>
<li class=""><strong>Framework (NextJS)</strong> - The opinionated framework makes development a breeze. I'm able to actually focus on the app rather than setting up the code.</li>
<li class=""><strong>State Manager (Plain React / Supabase)</strong> - Honestly with NextJS server routing, I'm able to pass required states from the server and get away with simple plain react states. It's a lot simpler and removes the headache of having another state manager.</li>
<li class=""><strong>Language (Typescript)</strong> - Typescript is TOOO good. Having to not worry about the mysterious types saves sooo much time. One thing to note is that, I use <a href="https://supabase.com/docs/guides/api/rest/generating-types" target="_blank" rel="noopener noreferrer" class="">types directly generated from Supabase</a>. Highly recommend doing this!</li>
<li class=""><strong>Components (ShadCN/UI)</strong> - This one speeds up the front-end work massively. It allows me to only focus on the placement rather than designing the component. One note here, is that I'd recommend copying the placement of similar functioning websites (e.g. copy Apple Notes UI for your note-taking app). They've probably spent hundreds of man hours optimizing for UI so leverage that.</li>
<li class=""><strong>Styling (TailwindCSS)</strong> - This is a no brainer. Tailwind makes adjusting the styling a breeze and allows for me to quickly make changes without having to</li>
<li class=""><strong>Database (Supabase)</strong> - Supabase is a PostgreSQL wrapper that makes it super easy to setup. It is also scales nicely. Highly HIGHLY recommend!</li>
<li class=""><strong>Auth (Supabase Auth)</strong> - The integration between the database and auth is seamless and the client libraries make it a breeze to work with. I recommend checkout out their <a href="https://supabase.com/docs/guides/auth/server-side/nextjs?queryGroups=router&amp;router=app" target="_blank" rel="noopener noreferrer" class="">auth guide</a> to see how to set it up with NextJS.</li>
<li class=""><strong>Server (Supabase Edge Functions)</strong> - Most of the time I don't need server processing because I can directly go through Supabase with it's client library. But when I do (e.g. making calls to OpenAI), I use Supabase Edge Functions. It's bundled with the pricing and the client library makes it easy to call.</li>
<li class=""><strong>Storage (Supabase Storage)</strong> - The client library, Supabase integration, and pricing make it a no brainer for me to use Supabase storage since I'm using it for pretty much everything already.</li>
<li class=""><strong>Hosting (Vercel)</strong> - Hosting on Vercel with Supabase is a breeze. It also has a generous free plan like Supabase</li>
<li class=""><strong>Icons (React Icons)</strong> - React Icons is comprehensive and is easy to work with. If you don't need that many icons I recommend only using <a href="https://lucide.dev/icons/" target="_blank" rel="noopener noreferrer" class="">Lucide Icons</a>, which is already bundled with ShadCN/UI</li>
<li class=""><strong>Analytics (Posthog)</strong> - It's important to have analytics, posthog makes it such a breeze and integrates well with other platforms (e.g. Stripe) to have a full view of your business.</li>
<li class=""><strong>Email (Postmark)</strong> - Postmark has been working well as an email marketing platform but to be honest, I've been looking at a more comprehensive email platform that also makes it easy to setup complicated email campaigns. Might migrate to <a href="https://loops.so/" target="_blank" rel="noopener noreferrer" class="">loops.so</a>.</li>
<li class=""><strong>Payments (Stripe)</strong> - Stripe is an amazing platform and is pretty much the goto payments platform for most SaaS companies. It integrates with pretty much everything and is easy to use.</li>
<li class=""><strong>Payments Sync (Supabase Edge Functions)</strong> - One caveat of using Stripe is that it's often difficult to keep track of payments within your app. What I've done is I setup a sync between Stripe and Supabase through Supabase Edge Functions. You can see my code <a href="https://github.com/devtodollars/mvp-boilerplate/blob/main/supabase/functions/stripe_webhook/index.ts" target="_blank" rel="noopener noreferrer" class="">here</a>.</li>
</ul>
<p>P.S. i've also created a template of above in Github. Feel free to check it out <a href="https://github.com/devtodollars/mvp-boilerplate" target="_blank" rel="noopener noreferrer" class="">here</a></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Get Paid in Flutter with Stripe]]></title>
            <link>https://www.devtodollars.com/blog/how-to-get-paid-in-flutter-with-stripe/</link>
            <guid>https://www.devtodollars.com/blog/how-to-get-paid-in-flutter-with-stripe/</guid>
            <pubDate>Thu, 04 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[This is my guide on the fastest way to get paid with Stripe and Flutter. I'll walk through step-by-step instructions on how I set up stripe integration, how I associate purchases (subscriptions & one-time payments) with users, and how I keep track of all of that within Supabase. Afterwards, I'll talk about the review process and how to tip-toe around the strict AppStore rules.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="flutter-stripe-banner" src="https://www.devtodollars.com/assets/images/flutter-stripe-banner-3a8f1205b6084973ac33c4239bfefd9b.png" width="1200" height="630" class="img_OK7M"></p>
<p>This is my guide on the fastest way to get paid with Stripe and Flutter. I'll walk through step-by-step instructions on how I set up stripe integration, how I associate purchases (subscriptions &amp; one-time payments) with users, and how I keep track of all of that within Supabase. Afterwards, I'll talk about the review process and how to tip-toe around the strict AppStore rules.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="stripe--supabase-integration">Stripe + Supabase Integration<a href="https://www.devtodollars.com/blog/how-to-get-paid-in-flutter-with-stripe/#stripe--supabase-integration" class="hash-link" aria-label="Direct link to Stripe + Supabase Integration" title="Direct link to Stripe + Supabase Integration" translate="no">​</a></h2>
<p>Stripe has a lot of built-in complexity to handle many edge cases. But at the end of the day, what's most important on the Supabase side is to know which user purchased what product or whether or not they are subscribed. My approach to this is to have an <code>active_products</code> column that is synced with Stripe and keeps track of the users' purchased products and products they are currently subscribed to. I also take advantage of Stripe's checkout portal so I don't need to create the payment UI myself.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="user-payment-flow">User Payment Flow<a href="https://www.devtodollars.com/blog/how-to-get-paid-in-flutter-with-stripe/#user-payment-flow" class="hash-link" aria-label="Direct link to User Payment Flow" title="Direct link to User Payment Flow" translate="no">​</a></h3>
<ol>
<li class="">User creates an account (through Supabase)</li>
<li class="">The user goes to the pricing page and selects a payment option</li>
<li class="">The link redirects them to the Flutter app with the price id from Stripe</li>
<li class="">A function is called from the Flutter app which creates a custom checkout portal link</li>
<li class="">The user is redirected to the stripe portal link and makes the purchase</li>
<li class="">A stripe webhook is triggered which updates <code>active_products</code></li>
<li class="">After the purchase, the user is redirected back to the app</li>
<li class="">The app now knows the user's purchases through the stripe table</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="setup">Setup<a href="https://www.devtodollars.com/blog/how-to-get-paid-in-flutter-with-stripe/#setup" class="hash-link" aria-label="Direct link to Setup" title="Direct link to Setup" translate="no">​</a></h3>
<ol>
<li class="">To get things started, you'll need to set up a <a href="https://stripe.com/en-ca" target="_blank" rel="noopener noreferrer" class="">Stripe</a> account and a <a href="https://supabase.com/" target="_blank" rel="noopener noreferrer" class="">Supabase</a> account.</li>
<li class="">Run the <a href="https://github.com/devtodollars/mvp-boilerplate/blob/main/supabase/migrations/20240717231009_init.sql" target="_blank" rel="noopener noreferrer" class="">following SQL commands</a> to create Stripe tables that will sync with stripe</li>
<li class="">Create two Supabase functions, one to <a href="https://github.com/devtodollars/startup-boilerplate/blob/main/supabase/functions/get_stripe_url/index.ts" target="_blank" rel="noopener noreferrer" class="">generate a checkout link</a> and another to <a href="https://github.com/devtodollars/startup-boilerplate/blob/main/supabase/functions/stripe_webhook/index.ts" target="_blank" rel="noopener noreferrer" class="">handle stripe webhooks</a>.</li>
<li class="">After deploying the functions, <a href="https://docs.stripe.com/webhooks#add-a-webhook-endpoint" target="_blank" rel="noopener noreferrer" class="">connect the webhook with Stripe</a> and select all events.</li>
<li class="">Enable, the <a href="https://dashboard.stripe.com/settings/billing/portal" target="_blank" rel="noopener noreferrer" class="">checkout portal</a> in stripe by clicking "Save Changes".</li>
<li class="">Now in your Flutter app, you can call the checkout function to <a href="https://github.com/devtodollars/startup-boilerplate/blob/main/flutter/lib/services/auth_notifier.dart#L105" target="_blank" rel="noopener noreferrer" class="">generate a link</a> so the user can begin their checkout</li>
<li class="">Finally, you can make a <a href="https://github.com/devtodollars/startup-boilerplate/blob/main/flutter/lib/services/auth_notifier.dart#L57" target="_blank" rel="noopener noreferrer" class="">simple query</a> to check whether or not the user is subscribed</li>
</ol>
<p>If you're also interested in setting up analytics, transactional emails, release pipelines, or just want to play around with the demo, I encourage you to check out my <a href="https://github.com/devtodollars/startup-boilerplate" target="_blank" rel="noopener noreferrer" class="">open-source flutter production boilerplate</a>. It has everything you need to build your startup.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="tip-toeing-the-android-and-apple-app-store">Tip Toeing the Android and Apple App Store<a href="https://www.devtodollars.com/blog/how-to-get-paid-in-flutter-with-stripe/#tip-toeing-the-android-and-apple-app-store" class="hash-link" aria-label="Direct link to Tip Toeing the Android and Apple App Store" title="Direct link to Tip Toeing the Android and Apple App Store" translate="no">​</a></h2>
<p>So now you have Stripe set up with the checkout portal and webhooks in place, the payment process should work for web apps. But, the <a href="https://developer.apple.com/app-store/review/guidelines/#in-app-purchase" target="_blank" rel="noopener noreferrer" class="">Apple App Store</a> and <a href="https://support.google.com/googleplay/android-developer/answer/10281818?hl=en#zippy=%2Ccan-i-distribute-my-app-on-other-android-app-stores-or-my-website" target="_blank" rel="noopener noreferrer" class="">Google Play Stores</a> have strict guidelines on what can and cannot be done. There are ways to tiptoe around these guidelines. For example, apps like Netflix, Spotify, and Audible use this approach to circumvent the huge 30% commission Apple has. For us, we do it because it's a hassle to integrate with the respective app stores.</p>
<p>Here's how these companies do it:</p>
<ul>
<li class=""><strong>Netflix</strong>: You are only able to sign in from the app, you are unable to sign up and pay.</li>
<li class=""><strong>Spotify</strong>: When you try to access a premium feature, it directs you to a page that says "You can't upgrade to Premium in the app. We know, it's not ideal."</li>
<li class=""><strong>Audible</strong>: When you click "Buy more Credits" you see a current subscription page with text saying "To manage your account, visit the Audible site or call customer support"</li>
</ul>
<p>Depending on what type of app you have and what business model you are using you can try one of the approaches above. Below are additional tips to help get you approved:</p>
<ul>
<li class="">Do not mention payments within the app and remove all links to the pricing page. I use the <code>kIsWeb</code> flag (or Platform flags) to hide payment stuff in Flutter.</li>
<li class="">Remove your paywalls, and direct the user to a page to tell them to manage their account on the web. Use wording similar to Spotify or Audible.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="additional-options">Additional Options:<a href="https://www.devtodollars.com/blog/how-to-get-paid-in-flutter-with-stripe/#additional-options" class="hash-link" aria-label="Direct link to Additional Options:" title="Direct link to Additional Options:" translate="no">​</a></h2>
<p>Depending on your app sometimes, it doesn't make sense to tip-toe around the app store. Below is a pros and cons table to help you figure out which solution is the best for you. I either recommend using Stripe or RevenueCat, it doesn't make sense to do a self-implementation of this.</p>
<table><thead><tr><th></th><th>Pros</th><th>Cons</th></tr></thead><tbody><tr><td><strong>Stripe</strong></td><td>Lower Fees, All payments done in Stripe, Unified Analytics</td><td>More hoops for the user to jump through in order to pay</td></tr><tr><td><strong>RevenueCat</strong></td><td>Higher Conversion Rates, No need to handle syncing the backend, Unified Analytics</td><td>Web implementation requires Stripe regardless, Higher fees with Revenue Cat, App Store, and Play Store, Longer setup time</td></tr><tr><td><strong>Self Implementation</strong></td><td>Higher Conversion Rates, Circumvent RevenueCat Fees</td><td>Requires you to create webhooks and backend sync for Stripe/App Store/Play Store, No unified analytics out of the box</td></tr></tbody></table>
<p><strong>Note</strong>: You can sign up for Apple's <a href="https://developer.apple.com/app-store/small-business-program/" target="_blank" rel="noopener noreferrer" class="">small business program</a> to only get charged 15% commission fee instead of 30%</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From CTO of YC-Backed Startup back to IndieHacker]]></title>
            <link>https://www.devtodollars.com/blog/from-cto-of-yc-backed-startup-back-to-indiehacker/</link>
            <guid>https://www.devtodollars.com/blog/from-cto-of-yc-backed-startup-back-to-indiehacker/</guid>
            <pubDate>Tue, 02 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Worked as a CTO of a YC-backed company but broke up with my co-founder due to a difference in values. Now I'm helping developers build their startups.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="yc-indiehacker-banner" src="https://www.devtodollars.com/assets/images/yc-indiehacker-banner-332fdeabeb221da39b113fdcf4b9d850.png" width="1200" height="630" class="img_OK7M"></p>
<p>TLDR; Worked as a CTO of a YC-backed company but broke up with my co-founder due to a difference in values. Now I'm helping developers build their startups.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="pre-breakup">Pre-breakup<a href="https://www.devtodollars.com/blog/from-cto-of-yc-backed-startup-back-to-indiehacker/#pre-breakup" class="hash-link" aria-label="Direct link to Pre-breakup" title="Direct link to Pre-breakup" translate="no">​</a></h2>
<p>A couple of months ago, my co-founder and I were working on an AI education startup. We were YC-backed, grew to <a class="" href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/">50,000 users</a>, and earned $10,000 in revenue in under three months. All these metrics seemed to point towards a product with product-market fit, yet we were far from achieving that. We found ourselves behind in a rat race with a handful of competitors. Our runway was nearly depleted as we were spending almost all of our revenue on marketing, and we found ourselves at the intersection of the two most challenging spaces to build a startup: education and consumer. This combination, especially without a targeted niche, made it difficult to stand out in a crowded market.</p>
<p>For these reasons, we decided to explore new opportunities. But, as we were pivoting I realized we had little alignment on direction and ideas. It was clear that we fundamentally wanted different things from startups. His focus was to grow big and it didn't matter what he worked on while I wanted to solve problems meaningful to me. Eventually, I decided that splitting up was the right choice because our differences in values and goals would lead to unhappiness and waste both our time.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="what-i-learned">What I learned:<a href="https://www.devtodollars.com/blog/from-cto-of-yc-backed-startup-back-to-indiehacker/#what-i-learned" class="hash-link" aria-label="Direct link to What I learned:" title="Direct link to What I learned:" translate="no">​</a></h2>
<ul>
<li class="">There's a lot of vanity metrics out there and oftentimes they don't paint the full picture</li>
<li class="">It's way better to focus on a tighter niche</li>
<li class="">Don't join a rat race unless you have a competitive advantage that will bring you to #1</li>
<li class="">Aligning on goals and values are super important in a co-founder relationships</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="what-im-up-to-now">What I'm up to now.<a href="https://www.devtodollars.com/blog/from-cto-of-yc-backed-startup-back-to-indiehacker/#what-im-up-to-now" class="hash-link" aria-label="Direct link to What I'm up to now." title="Direct link to What I'm up to now." translate="no">​</a></h2>
<p>After breaking up with my co-founder, my immediate plan was to create boilerplate code for future startups, share it with folks, and earn a little bit of cash. But what I found was that I found real joy in helping these developers launch their startups. So now I'm on a mission to <em>help developers build startups</em>.</p>
<p>Here are some initiatives I've started in the past month:</p>
<ul>
<li class=""><a href="https://devtodollars.com/blog/resources-for-founders-at-every-stage" target="_blank" rel="noopener noreferrer" class="">Compiled a personal list of startup resources</a></li>
<li class=""><a href="https://github.com/devtodollars/startup-boilerplate" target="_blank" rel="noopener noreferrer" class="">Open-sourced my startup boilerplate code</a></li>
<li class=""><a href="https://discord.gg/Fw4rxWBTGU" target="_blank" rel="noopener noreferrer" class="">Created a discord community of entrepreneurial developers</a></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter Riverpod is Not Complicated - Getting Started with Riverpod]]></title>
            <link>https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/</link>
            <guid>https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/</guid>
            <pubDate>Fri, 29 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[There seems to be a lot of confusion with Riverpod and the way it is used. Admittedly the documentation is lacking. And for someone getting started, there are many decisions to be made.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="riverpod-banner" src="https://www.devtodollars.com/assets/images/riverpod-banner-f8781518de930a538bf2d9955ca68f79.png" width="1200" height="630" class="img_OK7M"></p>
<p>There seems to be a lot of confusion with Riverpod and the way it is used. Admittedly the <a href="https://www.reddit.com/r/FlutterDev/comments/11omsdq/comment/jbu56su/?utm_source=share&amp;utm_medium=web3x&amp;utm_name=web3xcss&amp;utm_term=1&amp;utm_content=share_button" target="_blank" rel="noopener noreferrer" class="">documentation is lacking</a>. And for someone getting started, there are many decisions to be made like:</p>
<ul>
<li class="">Should I use code-generation?</li>
<li class="">How many providers should I create?</li>
<li class="">What should be contained in each provider?</li>
</ul>
<p>Because of this adaptability, it can become very confusing for someone just getting started. I'm creating this blog post to lay some ground rules that I set for myself when using riverpod. If you're getting started with riverpod, following these rules will be a good starting point.</p>
<p>But before reading on these rules, I highly recommend you checkout these guides in this order:</p>
<ol>
<li class=""><a href="https://codewithandrea.com/articles/flutter-state-management-riverpod/" target="_blank" rel="noopener noreferrer" class="">Flutter Riverpod 2.0: The Ultimate Guide</a></li>
<li class=""><a href="https://codewithandrea.com/articles/flutter-riverpod-generator/" target="_blank" rel="noopener noreferrer" class="">How to Auto-Generate your Providers with Flutter Riverpod Generator</a></li>
<li class=""><a href="https://codewithandrea.com/articles/flutter-riverpod-async-notifier/" target="_blank" rel="noopener noreferrer" class="">How to use Notifier and AsyncNotifier with the new Flutter Riverpod Generator</a></li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="basics">Basics<a href="https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/#basics" class="hash-link" aria-label="Direct link to Basics" title="Direct link to Basics" translate="no">​</a></h2>
<p>Because I know some of you are lazy as hell, I'll summarize what I think is important in the below bullet points:</p>
<ul>
<li class="">Riverpod is like a global variable storage and each provider is it's own global variable.</li>
<li class="">Only special widgets <code>ConsumerWidget</code> and <code>ConsumerStatefulWidget</code> have access to these providers.</li>
<li class="">You can access the providers using <code>ref.read</code> and <code>ref.watch</code>
<ul>
<li class=""><code>ref.watch</code> is used in the Widget's <code>build</code> method rebuilds the widget the state changes</li>
<li class=""><code>ref.read</code> is used outside of the Widget's <code>build</code> method</li>
</ul>
</li>
<li class="">There are many different types of providers to choose from and the riverpod generator makes it so you don't need to choose which one to use.</li>
<li class="">There are different modifiers you can apply to the provider when accessing it.<!-- -->
<ul>
<li class="">By default you get the <code>AsyncValue</code> with no modifiers</li>
<li class=""><code>.notifier</code> can be used to access the functions within the provider</li>
<li class=""><code>.future</code> can be used to get the latest value of the state asynchronously</li>
</ul>
</li>
<li class="">An <code>AsyncValue</code> is returned when accessing the provider with no modifiers<!-- -->
<ul>
<li class=""><code>.when</code> is typically used in the Widget <code>build</code> method</li>
<li class=""><code>.value</code> is to get the current value</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="common-pitfalls-of-riverpod">Common Pitfalls of Riverpod<a href="https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/#common-pitfalls-of-riverpod" class="hash-link" aria-label="Direct link to Common Pitfalls of Riverpod" title="Direct link to Common Pitfalls of Riverpod" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="not-using-code-generation">Not Using Code Generation<a href="https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/#not-using-code-generation" class="hash-link" aria-label="Direct link to Not Using Code Generation" title="Direct link to Not Using Code Generation" translate="no">​</a></h3>
<p>I personally hate code generation. It adds an extra generated file and it abstracts logic that might be important to understand.</p>
<p>Because of reasons above, I decided to give riverpod a try without code generation. After a couple of times, of choosing the wrong provider, encountering bugs because of incorrect parameters, I decided that code generation was the way forward.</p>
<p>After I gave it a shot, everything became simple. It saved me hours of hair pulling trying to configure the correct parameters for each provider. Even the riverpod documentation <a href="https://riverpod.dev/docs/concepts/about_code_generation#should-i-use-code-generation" target="_blank" rel="noopener noreferrer" class="">highly recommends code generation</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="grouping-providers-based-on-technology">Grouping Providers based on Technology<a href="https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/#grouping-providers-based-on-technology" class="hash-link" aria-label="Direct link to Grouping Providers based on Technology" title="Direct link to Grouping Providers based on Technology" translate="no">​</a></h3>
<p>When first working with riverpod, I thought the best approach would be to group global variables by the technology. For example, I had a library for my database, I put all my database related functions in the single provider and called it a day. My thinking was that this was just a global variable storage</p>
<p>But by doing this, I lost a lot of the capabilities riverpod provided out of the box. I had to:</p>
<ul>
<li class="">Refresh the UI with <code>ref.watch</code> based on specific criteria</li>
<li class="">I had to manage the states myself which added unnecessary complexity</li>
<li class="">Handle the initialization of states and loading states manually</li>
</ul>
<p>If you want to see how NOT to use riverpod, I encourage you to checkout <a href="https://github.com/fleetingnotes/fleeting-notes-flutter/blob/main/lib/services/providers.dart" target="_blank" rel="noopener noreferrer" class="">how I did it incorrectly with Fleeting Notes</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="not-using-streams">Not Using Streams<a href="https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/#not-using-streams" class="hash-link" aria-label="Direct link to Not Using Streams" title="Direct link to Not Using Streams" translate="no">​</a></h3>
<p>Streams are so so powerful. If you have a database that supports streaming I highly recommend you use streams to <em>streamline</em> your setup. There's no more need to handle updates, inserts, or deletes, they are automatically done so with your backend being the source of truth.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="examples">Examples<a href="https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/#examples" class="hash-link" aria-label="Direct link to Examples" title="Direct link to Examples" translate="no">​</a></h2>
<p>Below are two very common use cases for production applications. One is with authentication and the second is with routing.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="authentication">Authentication<a href="https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/#authentication" class="hash-link" aria-label="Direct link to Authentication" title="Direct link to Authentication" translate="no">​</a></h3>
<p>Below is a simplified version for learning purposes. Checkout the <a href="https://github.com/devtodollars/flutter-production-template/blob/main/flutter/lib/services/auth_notifier.dart" target="_blank" rel="noopener noreferrer" class="">full code here</a>.</p>
<div class="language-dart codeBlockContainer_cssH theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent__0AQ"><pre tabindex="0" class="prism-code language-dart codeBlock_aQGQ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_c50m"><span class="token-line" style="color:#393A34"><span class="token plain">@Riverpod(keepAlive: true)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">class Auth extends _$Auth {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  // We use a stream controller to control when the stream is updated and what object is in the stream.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  final StreamController&lt;AppUser?&gt; authStateController =</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      StreamController.broadcast();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Auth();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  @override</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Stream&lt;AppUser?&gt; build() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    // listen to auth state change</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    final streamSub = client.auth.onAuthStateChange.listen((authState) async {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      refreshUser(authState);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    });</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    // dispose the listeners</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ref.onDispose(() {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      streamSub.cancel();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      authStateController.close();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    });</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    // return the stream</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    return authStateController.stream;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  supa.SupabaseClient get client =&gt; supa.Supabase.instance.client;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  Future&lt;AppUser?&gt; refreshUser(supa.AuthState state) async {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    final session = state.session;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    if (session == null) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	  // set the auth state to null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      authStateController.add(null);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      return null;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    // Make an additional query to get subscription data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    final metadata = await client</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        .from("stripe")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        .select()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        .eq("user_id", session.user.id)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        .maybeSingle();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    // Put together custom user object</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    final user = AppUser(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      session: session,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      authEvent: state.event,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      activeProducts: List&lt;String&gt;.from(metadata?["active_products"] ?? []),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      stripeCustomerId: metadata?["stripe_customer_id"],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    );</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    // update the stream</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    authStateController.add(user);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    return user;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="routing">Routing<a href="https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/#routing" class="hash-link" aria-label="Direct link to Routing" title="Direct link to Routing" translate="no">​</a></h2>
<p>Below is a simplified version for learning purposes. Checkout the <a href="https://github.com/devtodollars/flutter-production-template/blob/main/flutter/lib/services/router_notifier.dart" target="_blank" rel="noopener noreferrer" class="">full code here</a>.</p>
<div class="language-dart codeBlockContainer_cssH theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent__0AQ"><pre tabindex="0" class="prism-code language-dart codeBlock_aQGQ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_c50m"><span class="token-line" style="color:#393A34"><span class="token plain">// This is crucial for making sure that the same navigator is used</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">// when rebuilding the GoRouter and not throwing away the whole widget tree.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">final navigatorKey = GlobalKey&lt;NavigatorState&gt;();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Uri? initUrl = Uri.base; // needed to set intiial url state</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">@riverpod</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">GoRouter router(RouterRef ref) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  // we watch the authState to update the route when auth changes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  final authState = ref.watch(authProvider);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  return GoRouter(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    initialLocation: initUrl?.path, // DO NOT REMOVE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    navigatorKey: navigatorKey,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    redirect: (context, state) async {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      // we redirect the user based on different criteria of auth</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      return authState.when(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        data: (user) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          // build initial path</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          String? path = initUrl?.path;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          final queryString = initUrl?.query.trim() ?? "";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          if (queryString.isNotEmpty &amp;&amp; path != null) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            path += "?$queryString";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          // If user is not authenticated, direct to login screen</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          if (user == null &amp;&amp; path != '/login') {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            return '/login';</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          // If user is authenticated and trying to access login or loading, direct to home</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          if (user != null &amp;&amp; (path == '/login' || path == '/loading')) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            return "/";</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          // After handling initial redirection, clear initUrl to prevent repeated redirections</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          initUrl = null;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          return path;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        error: (_, __) =&gt; "/loading",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        loading: () =&gt; "/loading",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      );</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    routes: &lt;RouteBase&gt;[</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      GoRoute(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        name: 'loading',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        path: '/loading',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        builder: (context, state) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          return const Center(child: CircularProgressIndicator());</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      ),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      GoRoute(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        name: 'login',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        path: '/login',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        builder: (context, state) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          return const AuthScreen();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      ),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      GoRoute(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        name: 'home',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        path: '/',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        builder: (context, state) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          return const HomeScreen(title: "DevToDollars");</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      ),</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  );</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="whats-next">What's Next?<a href="https://www.devtodollars.com/blog/flutter-riverpod-is-not-complicated/#whats-next" class="hash-link" aria-label="Direct link to What's Next?" title="Direct link to What's Next?" translate="no">​</a></h2>
<p>If you liked what you saw, I encourage you to checkout my <a href="https://github.com/devtodollars/flutter-production-template" target="_blank" rel="noopener noreferrer" class="">Flutter production boilerplate</a>. This boilerplate doesn't only get you up and running in under 30 minutes, but also is a good resource if you're building your own app.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Resources for Founders at Every Stage]]></title>
            <link>https://www.devtodollars.com/blog/resources-for-founders-at-every-stage/</link>
            <guid>https://www.devtodollars.com/blog/resources-for-founders-at-every-stage/</guid>
            <pubDate>Sat, 23 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[For the past 2 years I've been building startups and for my most recent startup I was able to reach 50k users in under 6 months. These are the resources that helped me get to where I am today.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="startup-resources-banner" src="https://www.devtodollars.com/assets/images/startup-resources-banner-9ee78efb98a13a4b472d874d89278117.png" width="1200" height="630" class="img_OK7M"></p>
<p>For the past 2 years I've been building startups and for my most recent startup I was able to reach <a class="" href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/">50k users in under 6 months</a>. Throughout my journey, I've been consuming startup content like a fiend. These are the resources that helped me get to where I am today.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="1-before-startup">1. Before Startup<a href="https://www.devtodollars.com/blog/resources-for-founders-at-every-stage/#1-before-startup" class="hash-link" aria-label="Direct link to 1. Before Startup" title="Direct link to 1. Before Startup" translate="no">​</a></h2>
<p>General Startup:</p>
<ul>
<li class=""><a href="https://www.youtube.com/watch?v=BUE-icVYRFU" target="_blank" rel="noopener noreferrer" class="">Should You Start A Startup? (Youtube)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/10127019-the-lean-startup?from_search=true&amp;from_srp=true&amp;qid=vF6n4N2fl2&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">The Lean Startup Method (Book)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/81948.The_E_myth_Revisited" target="_blank" rel="noopener noreferrer" class="">The E-Myth Revisited (Book)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/18050143-zero-to-one?from_search=true&amp;from_srp=true&amp;qid=SvWQkp2kmf&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">Zero to One (Book)</a></li>
</ul>
<p>Talking To Users:</p>
<ul>
<li class=""><a href="https://www.youtube.com/watch?v=MT4Ig2uqjTc" target="_blank" rel="noopener noreferrer" class="">Eric Migicovsky - How to Talk to Users (Youtube)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/52283963-the-mom-test" target="_blank" rel="noopener noreferrer" class="">The Mom Test (Book)</a></li>
</ul>
<p>Startup Ideas:</p>
<ul>
<li class=""><a href="https://www.youtube.com/watch?v=Jcuqq48CNj8" target="_blank" rel="noopener noreferrer" class="">Where Do Great Startup Ideas Come From? (Youtube)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=DOtCl5PU8F0" target="_blank" rel="noopener noreferrer" class="">Kevin Hale - How to Evaluate Startup Ideas (Youtube)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=GMIawSAygO4&amp;list=PLQ-uHSnFig5Nd98Sc9I-kkc0ZWe8peRMC&amp;index=21" target="_blank" rel="noopener noreferrer" class="">Avoid these Tempting Startup Ideas (Youtube)</a></li>
<li class=""><a href="https://youtu.be/Th8JoIan4dg" target="_blank" rel="noopener noreferrer" class="">How to get startup ideas (Youtube)</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="2-initial-enthusiasm">2. Initial Enthusiasm<a href="https://www.devtodollars.com/blog/resources-for-founders-at-every-stage/#2-initial-enthusiasm" class="hash-link" aria-label="Direct link to 2. Initial Enthusiasm" title="Direct link to 2. Initial Enthusiasm" translate="no">​</a></h2>
<p>Building MVP:</p>
<ul>
<li class=""><a href="https://www.youtube.com/watch?v=1hHMwLxN6EM" target="_blank" rel="noopener noreferrer" class="">Michael Seibel - How to Plan an MVP (Youtube)</a></li>
<li class=""><a href="https://youtu.be/QRZ_l7cVzzU" target="_blank" rel="noopener noreferrer" class="">How to Build an MVP (Youtube)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/13078769-running-lean?from_search=true&amp;from_srp=true&amp;qid=Nazr2nTsrl&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">Running Lean (Book)</a></li>
</ul>
<p>Co-founder / Relationships:</p>
<ul>
<li class=""><a href="https://youtu.be/prKi3-rUPHc" target="_blank" rel="noopener noreferrer" class="">How to find the right co-founder (Youtube)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=30a5yFBd7Fo" target="_blank" rel="noopener noreferrer" class="">Kevin Hale - How to Work Together (Youtube)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/71730.Nonviolent_Communication" target="_blank" rel="noopener noreferrer" class="">Non-Violent Communication (Book)</a></li>
<li class=""><a href="https://www.ycombinator.com/cofounder-matching" target="_blank" rel="noopener noreferrer" class="">YC Co-Founder Matching (Platform)</a></li>
</ul>
<p>Getting Customers / Launching:</p>
<ul>
<li class=""><a href="https://youtu.be/hyYCn_kAngI" target="_blank" rel="noopener noreferrer" class="">How to Get Your First Customers (Youtube)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=3xU050kMbHM" target="_blank" rel="noopener noreferrer" class="">Kat Manalac - How to Launch (Again and Again) (Youtube)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/22091581-traction?from_search=true&amp;from_srp=true&amp;qid=z9IEMBqrwK&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">Traction (Book)</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="3-reality-sets-in">3. Reality Sets In<a href="https://www.devtodollars.com/blog/resources-for-founders-at-every-stage/#3-reality-sets-in" class="hash-link" aria-label="Direct link to 3. Reality Sets In" title="Direct link to 3. Reality Sets In" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://www.goodreads.com/book/show/18176747-the-hard-thing-about-hard-things?from_search=true&amp;from_srp=true&amp;qid=kvGh5oeCNF&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">The Hard Thing About Hard Things (Book)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/55338968-the-cold-start-problem?from_search=true&amp;from_srp=true&amp;qid=tSoZrG36g7&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">The Cold Start Problem (Book)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/98233.Founders_at_Work?from_search=true&amp;from_srp=true&amp;qid=xrceojJGuy&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">Founders at Work (Book)</a></li>
<li class=""><a href="https://www.youtube.com/playlist?list=PLQ-uHSnFig5MoTTcgd8EzenEADqGTQPpW" target="_blank" rel="noopener noreferrer" class="">How to Build the Future (Youtube)</a></li>
<li class=""><a href="https://www.meetup.com/find/?suggested=true&amp;source=EVENTS&amp;keywords=founders" target="_blank" rel="noopener noreferrer" class="">Founder Networking Events (Platform)</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="4-experimenting--pivoting">4. Experimenting &amp; Pivoting<a href="https://www.devtodollars.com/blog/resources-for-founders-at-every-stage/#4-experimenting--pivoting" class="hash-link" aria-label="Direct link to 4. Experimenting &amp; Pivoting" title="Direct link to 4. Experimenting &amp; Pivoting" translate="no">​</a></h2>
<p>Time Management / Productivity:</p>
<ul>
<li class=""><a href="https://www.youtube.com/watch?v=XcCmMOWuAF4" target="_blank" rel="noopener noreferrer" class="">Adora Cheung - How to Prioritize Your Time (Youtube)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=nF_YWdz6S0Y" target="_blank" rel="noopener noreferrer" class="">Startup Experts Reveal Their Top Productivity Advice (Youtube)</a></li>
</ul>
<p>Marketing:</p>
<ul>
<li class=""><a href="https://www.goodreads.com/book/show/41943000-the-1-page-marketing-plan" target="_blank" rel="noopener noreferrer" class="">The 1-Page Marketing Plan (Book)</a></li>
<li class=""><a href="https://verbena-possum-b39.notion.site/Twitter-Growth-Playbook-8c57afecb6f741c4a0017f18760638ac" target="_blank" rel="noopener noreferrer" class="">Twitter Growth Playbook (Blog)</a></li>
</ul>
<p>Sales:</p>
<ul>
<li class=""><a href="https://www.youtube.com/watch?v=xZi4kTJG-LE" target="_blank" rel="noopener noreferrer" class="">How to Sell by Tyler Bosmeny (Youtube)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/833015.SPIN_Selling?from_search=true&amp;from_srp=true&amp;qid=yirUTjzAzl&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">Spin Selling (Book)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/42686460-gap-selling?from_search=true&amp;from_srp=true&amp;qid=SlUKYMnHmh&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">Gap Selling (Book)</a></li>
</ul>
<p>Analytics:</p>
<ul>
<li class=""><a href="https://www.youtube.com/watch?v=LLerCc7MOQo" target="_blank" rel="noopener noreferrer" class="">Ilya Volodarsky - Analytics for Startups (Youtube)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=PGqX9fpweyc" target="_blank" rel="noopener noreferrer" class="">Kevin Hale - How to Improve Conversion Rates (Youtube)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/16033602-lean-analytics?from_search=true&amp;from_srp=true&amp;qid=4DJGGgqgo0&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">Lean Analytics (Book)</a></li>
</ul>
<p>Design:</p>
<ul>
<li class=""><a href="https://www.goodreads.com/book/show/43190966-refactoring-ui?from_search=true&amp;from_srp=true&amp;qid=FYoVzawzHs&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">Refactoring UI (Book)</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="5-starts-working">5. Starts Working<a href="https://www.devtodollars.com/blog/resources-for-founders-at-every-stage/#5-starts-working" class="hash-link" aria-label="Direct link to 5. Starts Working" title="Direct link to 5. Starts Working" translate="no">​</a></h2>
<p>Growth:</p>
<ul>
<li class=""><a href="https://www.goodreads.com/book/show/31625067-hacking-growth" target="_blank" rel="noopener noreferrer" class="">Hacking Growth (Book)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=8pNxKX1SUGE" target="_blank" rel="noopener noreferrer" class="">Dalton Caldwell - All About Pivoting (Youtube)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=6lY9CYIY4pQ" target="_blank" rel="noopener noreferrer" class="">Gustaf Alströmer - Growth for Startups (Youtube)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=jwXlo9gy_k4" target="_blank" rel="noopener noreferrer" class="">Kevin Hale - Startup Pricing 101 (Youtube)</a></li>
</ul>
<p>Raising Capital:</p>
<ul>
<li class=""><a href="https://www.youtube.com/watch?v=D81y-kh11oI" target="_blank" rel="noopener noreferrer" class="">Should Your Startup Bootstrap or Raise Venture Capital? (Youtube)</a></li>
<li class=""><a href="https://paulgraham.com/guidetoinvestors.html" target="_blank" rel="noopener noreferrer" class="">The Hacker's Guide to Investors (Blog)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=SMi3JO-hsyY&amp;t=1s" target="_blank" rel="noopener noreferrer" class="">Why Founder's Shouldn't Think Like Investors (Youtube)</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="6-product-market-fit--scaling">6. Product Market Fit &amp; Scaling<a href="https://www.devtodollars.com/blog/resources-for-founders-at-every-stage/#6-product-market-fit--scaling" class="hash-link" aria-label="Direct link to 6. Product Market Fit &amp; Scaling" title="Direct link to 6. Product Market Fit &amp; Scaling" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://www.goodreads.com/book/show/18176747-the-hard-thing-about-hard-things?from_search=true&amp;from_srp=true&amp;qid=37qtpQMDXo&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">The Hard Thing About Hard Things (Book)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/98233.Founders_at_Work?from_search=true&amp;from_srp=true&amp;qid=xrceojJGuy&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">Founders at Work (Book)</a></li>
<li class=""><a href="https://www.goodreads.com/book/show/55338968-the-cold-start-problem?from_search=true&amp;from_srp=true&amp;qid=tSoZrG36g7&amp;rank=1" target="_blank" rel="noopener noreferrer" class="">The Cold Start Problem (Book)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=qnNHW6TYv5I&amp;list=PLQ-uHSnFig5OMuEYI4rnNz08BIHxhxdHG&amp;index=13" target="_blank" rel="noopener noreferrer" class="">Tim Brady - Building Culture (Youtube)</a></li>
<li class=""><a href="https://www.youtube.com/watch?v=7HDO1p3VdYg&amp;list=PLQ-uHSnFig5OMuEYI4rnNz08BIHxhxdHG&amp;index=22" target="_blank" rel="noopener noreferrer" class="">Ali Rowghani - How to Lead (Youtube)</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="other-resources">Other Resources<a href="https://www.devtodollars.com/blog/resources-for-founders-at-every-stage/#other-resources" class="hash-link" aria-label="Direct link to Other Resources" title="Direct link to Other Resources" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://www.youtube.com/playlist?list=PLQ-uHSnFig5Nd98Sc9I-kkc0ZWe8peRMC" target="_blank" rel="noopener noreferrer" class="">Dalton &amp; Michael Show</a></li>
<li class="">YC Startup School: <a href="https://www.youtube.com/playlist?list=PLQ-uHSnFig5MiLRb-l6yiCBGyqfVyVf17" target="_blank" rel="noopener noreferrer" class="">2017</a>, <a href="https://www.youtube.com/playlist?list=PLQ-uHSnFig5NVnJ_cLWM7dLuMQRDeekoX" target="_blank" rel="noopener noreferrer" class="">2018</a>, <a href="https://www.youtube.com/playlist?list=PLQ-uHSnFig5OMuEYI4rnNz08BIHxhxdHG" target="_blank" rel="noopener noreferrer" class="">2019</a>, <a href="https://www.youtube.com/playlist?list=PLQ-uHSnFig5PjfCy7mE77XMGhgky9HV3o" target="_blank" rel="noopener noreferrer" class="">2020</a>, <a href="https://www.youtube.com/playlist?list=PLQ-uHSnFig5M9fW16o2l35jrfdsxGknNB" target="_blank" rel="noopener noreferrer" class="">2023/24</a></li>
<li class=""><a href="https://paulgraham.com/articles.html" target="_blank" rel="noopener noreferrer" class="">Paul Graham Essays</a></li>
<li class=""><a href="https://playbook.samaltman.com/" target="_blank" rel="noopener noreferrer" class="">Startup Playbook by Sam Altman</a></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter vs React - Building a Startup on the Web]]></title>
            <link>https://www.devtodollars.com/blog/flutter-vs-react-building-a-startup-on-the-web/</link>
            <guid>https://www.devtodollars.com/blog/flutter-vs-react-building-a-startup-on-the-web/</guid>
            <pubDate>Sat, 16 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Flutter for web has evolved significantly in the past few years and in this post I wanted to give a comprehensive comparison between using Flutter vs React for developing web apps specifically.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="startup-web-banner" src="https://www.devtodollars.com/assets/images/startup-web-banner-09fde0f4d5104b94ce6012e2d2bc2b68.png" width="1200" height="630" class="img_OK7M"></p>
<p>Flutter for web has evolved significantly in the past few years and in this post I wanted to give a comprehensive comparison between using Flutter vs React for developing web apps specifically. I've used both <a class="" href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/">Flutter and React for startups</a> so I have a good sense of both.</p>
<p>Anyways, the most important thing in startups is iteration speed. The ability to quickly build a product, get customer feedback, and iterate is the thing that sets apart the good startups and the dead startups. Now in my opinion, a good framework (for startups), is one that enables you to iterate as fast as possible. With that knowledge, let's dive into why I think Flutter wins in almost all aspects.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="development-experience">Development Experience<a href="https://www.devtodollars.com/blog/flutter-vs-react-building-a-startup-on-the-web/#development-experience" class="hash-link" aria-label="Direct link to Development Experience" title="Direct link to Development Experience" translate="no">​</a></h2>
<p>Flutter makes the dev life a breeze. Forget the headache of constant null checks, too many variables, and scratching your head over whether an empty array is truly empty. Dart’s tooling is just the cherry on top, making Flutter my go-to for a smooth coding experience.</p>
<p>✅ Flutter |  ❌ Javascript</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="setup-time">Setup Time<a href="https://www.devtodollars.com/blog/flutter-vs-react-building-a-startup-on-the-web/#setup-time" class="hash-link" aria-label="Direct link to Setup Time" title="Direct link to Setup Time" translate="no">​</a></h2>
<p>Flutter is incredibly self-sufficient, providing a wealth of packages right out of the box. This eliminates the need for extensive research on UI libraries or the necessity of third-party libraries for basic functionalities. The ease of access to these tools significantly accelerates the development, allowing for fast iteration cycles.</p>
<p>✅ Flutter |  ❌ Javascript</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="transitioning-to-mobile">Transitioning to Mobile<a href="https://www.devtodollars.com/blog/flutter-vs-react-building-a-startup-on-the-web/#transitioning-to-mobile" class="hash-link" aria-label="Direct link to Transitioning to Mobile" title="Direct link to Transitioning to Mobile" translate="no">​</a></h2>
<p>Although, we are comparing web frameworks, it's also important to note the ability to transition to a native mobile app. Mobile is becoming increasingly prevalent and users are not as tolerant with using web apps on their phone. With React, there is no easy way to transition to mobile and it comes with the logistical nightmare of managing separate codebases for different platforms. This is another easy win for Flutter.</p>
<p>✅ Flutter |  ❌ Javascript</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="seo-and-initial-load-speeds">SEO and Initial Load Speeds<a href="https://www.devtodollars.com/blog/flutter-vs-react-building-a-startup-on-the-web/#seo-and-initial-load-speeds" class="hash-link" aria-label="Direct link to SEO and Initial Load Speeds" title="Direct link to SEO and Initial Load Speeds" translate="no">​</a></h2>
<p>Although not directly related to web apps, I wanted to bring SEO up because this is a contentious topic. React 100% takes this because Flutter is NOT built for static web pages. It has slow initial loading speeds and bad SEO. Now this begs the question: how does this affect my startup iteration speed?</p>
<p>It doesn't.</p>
<p>If you're building a startup, it's much faster to use a no-code landing page builder (e.g. <a class="" href="https://www.devtodollars.com/blog/solopreneur-saas-toolkit-my-tech-stack-as-a-former-cto-of-a-yc-backed-startup/">Framer</a>) to build your landing page. Then the landing page can have a call to action which will lead the user into clicking to the app.</p>
<p>❌ Flutter |  ✅ Javascript</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="hiring">Hiring<a href="https://www.devtodollars.com/blog/flutter-vs-react-building-a-startup-on-the-web/#hiring" class="hash-link" aria-label="Direct link to Hiring" title="Direct link to Hiring" translate="no">​</a></h2>
<p>Some people worry that finding developers who know how to use Flutter might be hard because it's pretty new. This makes sense since not a lot of people have had the chance to learn Flutter yet.</p>
<p>But from what I've seen, it's not a big problem. Flutter is easy to learn and use. I once hired a college intern who only knew how to use React, and guess what? They were able to contribute to our Flutter projects after one week of onboarding.</p>
<p>So, if you're thinking of hiring someone, you don't need to find someone who only knows Flutter. Oftentimes, someone who knows JavaScript (a common programming language) can learn Flutter quickly and do a great job.</p>
<p>❌ Flutter |  ✅ Javascript</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="in-summary">In Summary<a href="https://www.devtodollars.com/blog/flutter-vs-react-building-a-startup-on-the-web/#in-summary" class="hash-link" aria-label="Direct link to In Summary" title="Direct link to In Summary" translate="no">​</a></h2>
<table><thead><tr><th>Feature</th><th>Flutter</th><th>React</th></tr></thead><tbody><tr><td>Development Experience</td><td>✅</td><td>❌</td></tr><tr><td>Setup Time</td><td>✅</td><td>❌</td></tr><tr><td>Transitioning to Mobile</td><td>✅</td><td>❌</td></tr><tr><td>SEO / Initial Load Speed</td><td>❌</td><td>✅</td></tr><tr><td>Hiring</td><td>❌</td><td>✅</td></tr><tr><td>Performance</td><td>❌</td><td>✅</td></tr></tbody></table>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I reached 50k users with Flutter]]></title>
            <link>https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/</link>
            <guid>https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/</guid>
            <pubDate>Sat, 16 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Hey, I'm Matt, once the CTO of a startup backed by YC. Today, I'm here to unravel the steps I took to reach 50,000 users and how you can replicate this success!]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="50k-flutter-banner" src="https://www.devtodollars.com/assets/images/50k-flutter-banner-a334eb50acdd333106c4c08e44a1b31c.png" width="1200" height="630" class="img_OK7M"></p>
<p>Hey, I'm Matt, once the CTO of a startup backed by YC. Today, I'm here to unravel the steps I took to reach 50,000 users and how you can replicate this success!</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="1-identifying-a-problem">1. Identifying a problem<a href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/#1-identifying-a-problem" class="hash-link" aria-label="Direct link to 1. Identifying a problem" title="Direct link to 1. Identifying a problem" translate="no">​</a></h3>
<p>Everything began with a problem that needed solving. In my scenario, this was the tedious task med school students faced creating flashcards from their study material, dedicating precious hours each week to this alone.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="2-understanding-my-customers--competitors">2. Understanding my customers &amp; competitors<a href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/#2-understanding-my-customers--competitors" class="hash-link" aria-label="Direct link to 2. Understanding my customers &amp; competitors" title="Direct link to 2. Understanding my customers &amp; competitors" translate="no">​</a></h3>
<p>Understanding your customers means REALLY getting to know them. I took a trip to California, visiting Stanford and UCLA, to talk directly with over 50 med school students. Coupled with deep dives into online forums and Reddit, I gathered invaluable insights:</p>
<ul>
<li class=""><strong>Who are my users?</strong> They are med students in the U.S., buried under 70+ hours of study each week, all while preparing for the USMLE exam while doing their clinical placements. Improving their study efficiency by even 20% could save them invaluable hours.</li>
<li class=""><strong>What is their current workflow?</strong> Although their study methods vary, they universally rely on question banks as a testing tool. The challenge here lies in ensuring they don’t repeat the same mistakes, which they tackle through various means like manual flashcards, Excel spreadsheets, or using complex software to track their progress.</li>
<li class=""><strong>What does my product offer?</strong> I developed an AI-powered flashcard generator designed to seamlessly integrate into their study routine, allowing for the automatic creation of flashcards from their question bank questions with just a click. This innovation significantly streamlines their study process, eliminating the need for manual flashcard creation.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="3-validating-my-idea">3. Validating my idea<a href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/#3-validating-my-idea" class="hash-link" aria-label="Direct link to 3. Validating my idea" title="Direct link to 3. Validating my idea" translate="no">​</a></h3>
<p>Before diving into product development, validating the idea was crucial. I crafted a Reddit post <a href="https://www.reddit.com/r/step1/comments/19ayx2p/study_uworld_more_efficiently/" target="_blank" rel="noopener noreferrer" class="">here</a> that attracted over 90 upvotes which led to numerous direct messages. This was the first sign of potential success, but the true test is whether or not they would pay for it.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="4-building-my-landing-page">4. Building my landing page<a href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/#4-building-my-landing-page" class="hash-link" aria-label="Direct link to 4. Building my landing page" title="Direct link to 4. Building my landing page" translate="no">​</a></h3>
<p>The decision to opt for a no-code webpage builder over Flutter for the landing page was influenced by three key reasons:</p>
<ol>
<li class=""><strong>Flutter's shortcomings for landing pages</strong>, notably <a href="https://github.com/flutter/flutter/issues/76009" target="_blank" rel="noopener noreferrer" class="">slower load times</a> and <a href="https://github.com/flutter/flutter/issues/46789" target="_blank" rel="noopener noreferrer" class="">subpar SEO capabilities</a>.</li>
<li class=""><strong>Empowering my non-technical co-founder</strong> to make edits, significantly enhancing our agility in making iterations.</li>
<li class=""><strong>The fast speed of deployment</strong> offered by no-code solutions.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="5-web-app-development">5. Web App Development<a href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/#5-web-app-development" class="hash-link" aria-label="Direct link to 5. Web App Development" title="Direct link to 5. Web App Development" translate="no">​</a></h3>
<p>With the landing page set up and the concept validated, I moved on to developing the web application. Opting to <a class="" href="https://www.devtodollars.com/blog/flutter-vs-react-building-a-startup-on-the-web/">focus solely on a web app</a> was driven by two considerations:</p>
<ul>
<li class=""><strong>Speed</strong>: Immediate deployment, avoiding the drawn-out approval processes associated with app stores, and the complications of mobile-specific setups.</li>
<li class=""><strong>Accessibility</strong>: The universal ease of accessing a web link, simplifies user feedback and eliminates the need for app store downloads.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="6-iterating-based-on-customer-feedback">6. Iterating Based on Customer Feedback<a href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/#6-iterating-based-on-customer-feedback" class="hash-link" aria-label="Direct link to 6. Iterating Based on Customer Feedback" title="Direct link to 6. Iterating Based on Customer Feedback" translate="no">​</a></h3>
<p>Following the launch, I reached out to the med students I initially spoke with, seeking their feedback. This step was critical, as their input directly influenced our prioritization of features, including the consideration of mobile support for future development. To date, we haven't added a mobile app, but it remains a goal on our roadmap.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="7-continuing-to-grow">7. Continuing to Grow<a href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/#7-continuing-to-grow" class="hash-link" aria-label="Direct link to 7. Continuing to Grow" title="Direct link to 7. Continuing to Grow" translate="no">​</a></h3>
<p>For us, leveraging TikTok through partnerships with micro-influencers was a game-changer, generating viral content that led to spikes in users.</p>
<p>Throughout this journey, our strategy was to experiment, identify what worked, cut what didn’t, and double down on successful tactics.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="what-now">What Now?<a href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/#what-now" class="hash-link" aria-label="Direct link to What Now?" title="Direct link to What Now?" translate="no">​</a></h3>
<p>Thanks for taking the time to read the post. I'm currently on a mission to help developers build their startups and I hope that my experience is helpful for you! If you want to build a startup with Flutter, checkout my <a href="https://github.com/devtodollars/flutter-production-template" target="_blank" rel="noopener noreferrer" class="">open-source flutter boilerplate</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Flutter is the Best Framework for Startups]]></title>
            <link>https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/</link>
            <guid>https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/</guid>
            <pubDate>Thu, 14 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Flutter stands out as the best tool for achieving quick iterations. In this blog post, I dive deep into why I believe in Flutter's capabilities. I'll share insights from my current startup's workflow using Flutter, discuss some challenges I've encountered along the way, and outline precisely why I consider it a superior choice for any startup looking to move quickly and efficiently.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="flutter-startups-banner" src="https://www.devtodollars.com/assets/images/flutter-startups-banner-902f1130c4de57562840a384b5ae46b6.png" width="1200" height="630" class="img_OK7M"></p>
<p>Through the years, I've come to realize that in the startup world, speed isn't just an advantage—it's the lifeline. As a former CTO of a YC-backed startup, having launched more than five apps—with the latest one hitting over $10K in revenue in under three months—I've witnessed the undeniable power of rapid iteration. This ability to quickly build, launch, gather feedback, and refine is what really distinguishes the seasoned entrepreneurs from the novices. It's what makes or breaks a startup.</p>
<p>With this in mind, I've found that Flutter stands out as the best tool for achieving quick iterations. In this blog post, I dive deep into why I believe in Flutter's capabilities. I'll share insights from my current startup's workflow using Flutter, discuss some challenges I've encountered along the way, and outline precisely why I consider it a superior choice for any startup looking to move quickly and efficiently.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="my-typical-development-cycle-with-flutter-as-a-startup-founder">My Typical Development cycle with Flutter as a Startup Founder<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#my-typical-development-cycle-with-flutter-as-a-startup-founder" class="hash-link" aria-label="Direct link to My Typical Development cycle with Flutter as a Startup Founder" title="Direct link to My Typical Development cycle with Flutter as a Startup Founder" translate="no">​</a></h2>
<p>From my experience, this workflow has been my go-to. Even for my current startup, I validated the idea with a Reddit post, then created a web app, and marketed and iterated based on customer feedback. I was able to go from idea to product to revenue in just under a week. You can do so too by following this approach. If you're curious about how I structured my code, check out my <a href="https://github.com/devtodollars/flutter-production-template" target="_blank" rel="noopener noreferrer" class="">open-source Flutter boilerplate</a>.</p>
<ol>
<li class=""><strong>Idea Validation</strong>: Before doing the work, I like to test the waters. For example, I check popular posts on reddit to see if there's a genuine interest in my product. This step is critical—no point in building something that nobody wants.</li>
<li class=""><strong>Landing page with <a class="" href="https://www.devtodollars.com/blog/solopreneur-saas-toolkit-my-tech-stack-as-a-former-cto-of-a-yc-backed-startup/">Framer</a></strong>: Next, I create a landing page that conveys what I want to sell. This will be the first touchpoint for potential customers, making it a critical step in validating the product's market fit.</li>
<li class=""><strong>Web App Development with Flutter</strong>: Once I'm sure that this is something people want, I start developing a web app using my <a href="https://github.com/devtodollars/flutter-production-template" target="_blank" rel="noopener noreferrer" class="">open-source Flutter production boilerplate</a>. Here’s why I start with only web in Flutter:<!-- -->
<ul>
<li class=""><strong>Speed</strong>: Deploying a web app is immediate, bypassing the lengthy approval times of app stores.</li>
<li class=""><strong>Accessibility</strong>: A web link is universal, making it easy for users to access and provide feedback without the barriers of downloading from an app store.</li>
</ul>
</li>
<li class=""><strong>Iterate Based on Customer Feedback</strong>: This is where the magic happens. This step is iterative and ongoing, shaping the product to fit the users' needs perfectly.</li>
<li class=""><strong>Expanding to Mobile and Desktop</strong>: Only when there is demand, or I recognize a clear growth path through other platforms, do I consider expanding. Flutter’s cross-platform capability means that transitioning to other platforms is seamless. I treat this as another feature in the pipeline—important, but always prioritized alongside other development needs.</li>
<li class=""><strong>Unified Codebase, Continuous Iteration</strong>: With a single codebase, I continue to evolve the app, making enhancements and adding features based on user feedback and market trends. The beauty of Flutter means every iteration benefits all platforms simultaneously.</li>
</ol>
<p>If you liked what you read above, I also wrote a more in-depth guide on <a class="" href="https://www.devtodollars.com/blog/how-i-reached-50k-users-with-flutter/">how I reached 50k users with Flutter web</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="caveats-with-using-flutter">Caveats with using Flutter<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#caveats-with-using-flutter" class="hash-link" aria-label="Direct link to Caveats with using Flutter" title="Direct link to Caveats with using Flutter" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="dont-use-flutter-as-your-landing-page">Don't Use Flutter as Your Landing Page<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#dont-use-flutter-as-your-landing-page" class="hash-link" aria-label="Direct link to Don't Use Flutter as Your Landing Page" title="Direct link to Don't Use Flutter as Your Landing Page" translate="no">​</a></h3>
<p>Flutter is a tool that enables the creation of apps across multiple platforms — phones, computers, and the web — from a single codebase. While it offers extensive capabilities, it's not without its limitations. Websites developed with Flutter can experience <a href="https://github.com/flutter/flutter/issues/76009" target="_blank" rel="noopener noreferrer" class="">slower initial load times</a> and <a href="https://github.com/flutter/flutter/issues/46789" target="_blank" rel="noopener noreferrer" class="">poor SEO support</a>. This primarily becomes an issue if you're considering Flutter for your landing page, where speed and discoverability are crucial.</p>
<p>Rather than leveraging Flutter for landing pages, a no-code tool like <a href="https://www.framer.com/" target="_blank" rel="noopener noreferrer" class="">Framer</a> can be a more efficient choice. This approach allowed me to quickly create a landing page that had SEO straight out of the box and saved me precious time as my non-technical team members were able to make changes to the website themselves.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="googles-poor-track-record">Google's Poor Track Record<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#googles-poor-track-record" class="hash-link" aria-label="Direct link to Google's Poor Track Record" title="Direct link to Google's Poor Track Record" translate="no">​</a></h3>
<p>Concerns about Google potentially discontinuing Flutter are not unfounded, given its history with other projects (as documented on <a href="https://killedbygoogle.com/" target="_blank" rel="noopener noreferrer" class="">killedbygoogle.com</a>). However, my confidence in Flutter's longevity remains unshaken.</p>
<p>Here's why: Flutter addresses a significant gap in multi-platform development, offering a more streamlined process than its competitors. Additionally, its adoption is on the rise, with major companies like Alibaba, The New York Times, eBay, and Kijiji <a href="https://flutter.dev/showcase" target="_blank" rel="noopener noreferrer" class="">embracing Flutter</a> for their applications.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="hiring-for-flutter">Hiring for Flutter<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#hiring-for-flutter" class="hash-link" aria-label="Direct link to Hiring for Flutter" title="Direct link to Hiring for Flutter" translate="no">​</a></h3>
<p>Some people worry that finding developers who know how to use Flutter might be hard because it's pretty new. This makes sense since not a lot of people have had the chance to learn Flutter yet.</p>
<p>But from what I've seen, it's not really a big problem. Flutter is quite easy to learn and use. I once hired a college intern who only knew how to use React (another way to make apps), and guess what? They were able to start helping out with our Flutter projects after just one week of onboarding. So, if you're thinking of hiring someone, you don't need to find someone who only knows Flutter. A lot of the time, someone who knows JavaScript (a common programming language) can learn Flutter quickly and do a great job. Plus, the language used in Flutter, called Dart, is easy to get if you already know JavaScript or Python. Dart combines the best parts of JavaScript and Python into something new and exciting</p>
<p>So, finding people to work on Flutter projects might seem tough at first because it's new, but it's actually not that bad. Many developers can pick it up quickly and start meaningfully contributing.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="dart-flutter-vs-javascript">Dart (Flutter) vs Javascript<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#dart-flutter-vs-javascript" class="hash-link" aria-label="Direct link to Dart (Flutter) vs Javascript" title="Direct link to Dart (Flutter) vs Javascript" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="superior-development-experience">Superior Development Experience<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#superior-development-experience" class="hash-link" aria-label="Direct link to Superior Development Experience" title="Direct link to Superior Development Experience" translate="no">​</a></h3>
<p>With an understanding of Flutter’s limitations, it’s crucial to explore why I believe Flutter stands out as the premier choice for startups. First and foremost, Flutter offers exceptional language support and a developer experience that far surpasses its JavaScript counterparts.</p>
<p>With Dart, I'm spared the constant null checks, the decision paralysis between using <code>undefined</code> or <code>null</code>, and the confusion over the truthiness of an empty array. JavaScript's ambiguity and redundancy stem from its need to support legacy syntax, whereas Dart (and by extension, Flutter) learns from JavaScript’s missteps, presenting a cleaner, more intuitive language. In my opinion, the A class development experience makes learning and developing on Flutter much faster than it's JS counterpart.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="packages-out-of-the-box">Packages out-of-the-box<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#packages-out-of-the-box" class="hash-link" aria-label="Direct link to Packages out-of-the-box" title="Direct link to Packages out-of-the-box" translate="no">​</a></h3>
<p>Moreover, Flutter is incredibly self-sufficient, providing a wealth of packages right out of the box. This eliminates the need for extensive research on UI libraries or the necessity of third-party libraries for basic functionalities. The ease of access to these tools significantly accelerates the development process, allowing for swift iterations.</p>
<h3 class="anchor anchorTargetStickyNavbar_NoP4" id="single-codebase">Single Codebase<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#single-codebase" class="hash-link" aria-label="Direct link to Single Codebase" title="Direct link to Single Codebase" translate="no">​</a></h3>
<p>Perhaps the most significant advantage, however, is the ability to maintain a single codebase across multiple platforms. This feature is indispensable, especially for solo developers or small teams. The logistical nightmare of managing separate codebases for different platforms is a well-known pain point that Flutter elegantly solves. Plus, with more people using mobile devices these days, choosing to creating a mobile app vs only having a web app can give you a competitive edge.</p>
<h2 class="anchor anchorTargetStickyNavbar_NoP4" id="checkout-my-open-source-flutter-production-boilerplate">Checkout my open-source Flutter Production Boilerplate<a href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/#checkout-my-open-source-flutter-production-boilerplate" class="hash-link" aria-label="Direct link to Checkout my open-source Flutter Production Boilerplate" title="Direct link to Checkout my open-source Flutter Production Boilerplate" translate="no">​</a></h2>
<p>Thanks for taking the time to read this! If you're thinking about using Flutter, I've got something that might help you out. Check out my <a href="https://github.com/devtodollars/flutter-production-template" target="_blank" rel="noopener noreferrer" class="">open-source Flutter production boilerplate</a>. It could save you more than 40 hours of setup time! Or, it might just be a good reference for you. It's packed with all the best tips and tricks I've learned from using Flutter for startups over the last 2 years. I really think it could be super useful for anyone looking to dive into Flutter.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Solopreneur SaaS Toolkit: My Tech Stack as a former CTO of a YC backed startup]]></title>
            <link>https://www.devtodollars.com/blog/solopreneur-saas-toolkit-my-tech-stack-as-a-former-cto-of-a-yc-backed-startup/</link>
            <guid>https://www.devtodollars.com/blog/solopreneur-saas-toolkit-my-tech-stack-as-a-former-cto-of-a-yc-backed-startup/</guid>
            <pubDate>Mon, 11 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Hi! My name is Matt. I'm a former CTO of a YC backed startup and I've built 2 apps in the past that have both generated over $10K USD of revenue.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="tech-stack-banner" src="https://www.devtodollars.com/assets/images/tech-stack-banner-6d004232fb86522134faa5526d4d21dd.png" width="1200" height="630" class="img_OK7M"></p>
<p>Hi! My name is Matt. I'm a former CTO of a YC backed startup and I've built 2 apps in the past that have both generated over $10K USD of revenue.</p>
<p>Before moving onto my third startup, I wanted to take a step back, reflect on what I've done and create a good base for future startups. Which is why I've decided to write down my tech stack and create some boilerplate code for my future startups. I hope sharing this can help you build your startup!</p>
<p><a href="https://github.com/devtodollars/flutter-supabase-production-template" target="_blank" rel="noopener noreferrer" class="">Github Boilerplate Code</a></p>
<p><strong>Development</strong></p>
<ul>
<li class="">Frontend (<a class="" href="https://www.devtodollars.com/blog/why-flutter-is-the-best-framework-for-startups/">Flutter</a>)<!-- -->
<ul>
<li class="">State Management (<a href="https://pub.dev/packages/riverpod" target="_blank" rel="noopener noreferrer" class="">riverpod</a>)</li>
<li class="">Routing (<a href="https://pub.dev/packages/go_router" target="_blank" rel="noopener noreferrer" class="">go_router</a>)</li>
</ul>
</li>
<li class="">Backend (<a href="https://supabase.com/" target="_blank" rel="noopener noreferrer" class="">Supabase</a>)<!-- -->
<ul>
<li class="">Backend Functions (<a href="https://supabase.com/docs/guides/functions" target="_blank" rel="noopener noreferrer" class="">Deno</a>)</li>
<li class="">Database (<a href="https://supabase.com/docs/guides/database/overview" target="_blank" rel="noopener noreferrer" class="">PostgreSQL</a>)</li>
</ul>
</li>
<li class="">Payments (<a href="https://stripe.com/" target="_blank" rel="noopener noreferrer" class="">Stripe</a>)</li>
<li class="">Generative AI (<a href="https://openai.com/" target="_blank" rel="noopener noreferrer" class="">OpenAI</a>)</li>
<li class="">Documentation (<a href="https://www.gitbook.com/" target="_blank" rel="noopener noreferrer" class="">Gitbook</a>)</li>
</ul>
<p><strong>DevOps</strong></p>
<ul>
<li class="">CICD (<a href="https://github.com/features/actions" target="_blank" rel="noopener noreferrer" class="">Github Actions</a>)</li>
<li class="">Project Planning (<a href="https://docs.github.com/en/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects" target="_blank" rel="noopener noreferrer" class="">Github Projects</a>)</li>
<li class="">Code Management (<a href="https://github.com/" target="_blank" rel="noopener noreferrer" class="">Github</a>)</li>
</ul>
<p><strong>Design &amp; UX</strong></p>
<ul>
<li class="">Landing Page (<a href="https://framer.com/projects/" target="_blank" rel="noopener noreferrer" class="">Framer</a>)</li>
<li class="">Design (<a href="https://www.canva.com/" target="_blank" rel="noopener noreferrer" class="">Canva</a>)</li>
</ul>
<p><strong>Analytics &amp; Monitoring</strong></p>
<ul>
<li class="">Analytics (<a href="https://posthog.com/" target="_blank" rel="noopener noreferrer" class="">Posthog</a>)</li>
<li class="">Error Monitoring (<a href="https://sentry.io/welcome/" target="_blank" rel="noopener noreferrer" class="">Sentry</a>)</li>
</ul>
<p><strong>Communications &amp; Marketing</strong></p>
<ul>
<li class="">Email API / SMTP (<a href="https://postmarkapp.com/" target="_blank" rel="noopener noreferrer" class="">Postmark</a>)</li>
<li class="">Help Desk (<a href="https://www.intercom.com/" target="_blank" rel="noopener noreferrer" class="">Intercom</a>)</li>
<li class="">Community Management (<a href="https://discord.com/" target="_blank" rel="noopener noreferrer" class="">Discord</a>)</li>
</ul>
<p><strong>Productivity &amp; Collaboration</strong></p>
<ul>
<li class="">Quick Notes (<a href="https://apps.apple.com/ca/app/notes/id1110145109" target="_blank" rel="noopener noreferrer" class="">Apple Notes</a>)</li>
<li class="">Notes &amp; Documentation (<a href="https://obsidian.md/" target="_blank" rel="noopener noreferrer" class="">ObsidianMD</a>)</li>
<li class="">Personal Task Management (<a href="https://www.usemotion.com/" target="_blank" rel="noopener noreferrer" class="">Motion</a>)</li>
<li class="">Meetings (<a href="https://meet.google.com/" target="_blank" rel="noopener noreferrer" class="">Google Meets</a>)</li>
<li class="">Emails (<a href="https://superhuman.com/" target="_blank" rel="noopener noreferrer" class="">Superhuman</a>)</li>
</ul>
<p><strong>Infrastructure &amp; Hosting</strong></p>
<ul>
<li class="">Web App Host (<a href="https://www.netlify.com/" target="_blank" rel="noopener noreferrer" class="">Netlify</a>)</li>
<li class="">Domain Management (<a href="https://www.cloudflare.com/" target="_blank" rel="noopener noreferrer" class="">Cloudflare</a>)</li>
</ul>
<p><strong>Tools &amp; Utilities</strong></p>
<ul>
<li class="">IDE (<a href="https://iterm2.com/" target="_blank" rel="noopener noreferrer" class="">iTerm2</a> / <a href="https://astronvim.com/" target="_blank" rel="noopener noreferrer" class="">AstroNvim</a>)</li>
<li class="">Password Manager (<a href="https://1password.com/" target="_blank" rel="noopener noreferrer" class="">1Password</a>)</li>
<li class="">Digital Workspace (<a href="https://workspace.google.com/intl/en_ca/" target="_blank" rel="noopener noreferrer" class="">Google Workspace</a>)</li>
<li class="">Video Editing (<a href="https://www.descript.com/" target="_blank" rel="noopener noreferrer" class="">Descript</a>)</li>
<li class="">Quick Video Recording (<a href="https://www.screen.studio/" target="_blank" rel="noopener noreferrer" class="">Screen Studio</a>)</li>
</ul>
<p><strong>Personal Setup</strong></p>
<ul>
<li class="">Computer (M1 Macbook Pro 14")</li>
<li class="">Browser (<a href="https://arc.net/" target="_blank" rel="noopener noreferrer" class="">Arc</a>)</li>
</ul>]]></content:encoded>
        </item>
    </channel>
</rss>