<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Qoddi Blog]]></title><description><![CDATA[Qoddi Blog : The modern app platform made for business. We post about code, cloud and app deployment]]></description><link>https://blog.qoddi.com/</link><image><url>https://blog.qoddi.com/favicon.png</url><title>Qoddi Blog</title><link>https://blog.qoddi.com/</link></image><generator>Ghost 4.48</generator><lastBuildDate>Tue, 14 Apr 2026 05:12:22 GMT</lastBuildDate><atom:link href="https://blog.qoddi.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Introducing AppJet.ai : a GitHub-native AI that codes full-stack from prompt to deploy]]></title><description><![CDATA[<p>If you ever tried any vibe-coding tool on the market you know they are mostly supercharged NodeJS code editor, full of pre-made components and often unable to really understand your existing code base.</p><p>We created <a href="https://appjet.ai">AppJet</a> for a simple reason: AI is now at a maturity point where it can</p>]]></description><link>https://blog.qoddi.com/introducing-appjet-ai/</link><guid isPermaLink="false">68ab5a9ab667ba000154bc15</guid><category><![CDATA[AI]]></category><category><![CDATA[code]]></category><category><![CDATA[Product]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Wed, 27 Aug 2025 12:50:57 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2025/08/Screenshot-2025-08-24-at-10.14.52-AM.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.qoddi.com/content/images/2025/08/Screenshot-2025-08-24-at-10.14.52-AM.png" alt="Introducing AppJet.ai : a GitHub-native AI that codes full-stack from prompt to deploy"><p>If you ever tried any vibe-coding tool on the market you know they are mostly supercharged NodeJS code editor, full of pre-made components and often unable to really understand your existing code base.</p><p>We created <a href="https://appjet.ai">AppJet</a> for a simple reason: AI is now at a maturity point where it can realistic to use it as a real coding companion. Not just for crafting beautiful landing pages with Vue (AppJet still can do that) but as a real coding expert working alongside you to deliver clean and efficient code, no matter what you want to build or fix.</p><p>We are introducing today <a href="https://appjet.ai">AppJet.ai</a>: a vibe-coding expert integrated with GitHub with extended context searching capabilities, code understanding and deployment capabilities.</p><p>Our roadmap creating <a href="https://appjet.ai">AppJet</a> was simple:</p><ul><li>it has to be full-stack: we are extensively using Rust and Python and we wanted an agent able to work on that, manage databases and understand it,</li><li>directly integrated with GitHub with an efficient code editor: no more commits, the agent works directly on a specific <em><strong>appjet</strong></em> branch,</li><li>directly integrated with Qoddi: Of course we wanted our agent to be able to automatically deploy on our infrastructure,</li><li>Easy to scale: with <a href="https://supabase.co">Supabase</a> integration, your app and your database can scale to millions of users without breaking a sweat... or the bank,</li><li>without any vendor lock-in: Since the beginning of Qoddi we are focused on making our solutions open to multi-cloud and making sure our clients can leave at any time: that&apos;s why they don&apos;t. We keep the same mantra with AppJet: your code is in your GitHub repository, you keep full ownership of it and can migrate to any other hosting solution at any time.</li></ul><p><a href="https://appjet.ai">AppJet</a> ships today with a Free tier including 15 messages with the conversational agent and unlimited deployments. Starter plan includes 150 messages starting a $20 USD per month with unlimited deployments, custom domain names etc..</p><p>Give AppJet a try and tell what you think! We hope you&apos;ll love it as much as we loved making it!</p>]]></content:encoded></item><item><title><![CDATA[Introducing GPU-powered Apps]]></title><description><![CDATA[<p></p><p>We&apos;re thrilled to announce the launch of our new lineup of GPU-powered instances, specifically tailored for researchers, developers, and the public interested in training and using large language models (LLMs) and chatbots. At Qoddi, we&apos;re committed to making AI and LLM research more accessible and affordable,</p>]]></description><link>https://blog.qoddi.com/introducing-qoddis-gpu-line-up/</link><guid isPermaLink="false">6455e110557dcd00015b6daa</guid><category><![CDATA[Product]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Tue, 18 Jul 2023 21:39:32 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2023/05/Inspur-NF5488A5-NVIDIA-HGX-A100-8-GPU-Assembly-8x-A100-2.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.qoddi.com/content/images/2023/05/Inspur-NF5488A5-NVIDIA-HGX-A100-8-GPU-Assembly-8x-A100-2.jpg" alt="Introducing GPU-powered Apps"><p></p><p>We&apos;re thrilled to announce the launch of our new lineup of GPU-powered instances, specifically tailored for researchers, developers, and the public interested in training and using large language models (LLMs) and chatbots. At Qoddi, we&apos;re committed to making AI and LLM research more accessible and affordable, and our new instances are designed to empower you without breaking the bank.</p><h2 id="why-gpu-powered-instances">Why GPU-powered instances?<br></h2><p>Artificial intelligence (AI) and machine learning (ML) technologies have made tremendous advancements in recent years. One of the most exciting areas of research is in natural language processing (NLP), specifically LLMs and chatbots, which have become increasingly sophisticated and capable of understanding and generating human-like text. However, training and deploying these models typically require significant GPU resources, which can be expensive and beyond the reach of many researchers, developers, and enthusiasts.</p><p>To help bridge this gap, our new lineup of GPU-powered instances delivers the computational power required to train, deploy, and utilize state-of-the-art LLMs and chatbots, all at a fraction of the cost of big cloud providers. Our instances come in a variety of sizes and capabilities to suit your specific needs, ensuring you can access the tools and resources you need without overpaying for unnecessary capacity.</p><h2 id="key-benefits-of-qoddis-gpu-powered-instances">Key benefits of Qoddi&apos;s GPU-powered instances<br></h2><ol><li><strong>Affordability</strong>: Our goal is to democratize AI and LLM research by providing cost-effective access to powerful GPU resources. By offering competitive pricing, we are enabling individuals, academic researchers, and small businesses to leverage advanced AI capabilities without the financial burden associated with major cloud providers.</li><li><strong>Scalability</strong>: Our new instances come in various sizes, ensuring you have the right resources to meet your needs. Whether you&apos;re starting with a small-scale project or diving into more extensive research, you can easily scale up or down as required.</li><li><strong>Performance</strong>: Qoddi&apos;s GPU-powered instances are equipped with the latest NVIDIA Tesla A100 GPUs, which deliver outstanding performance in AI and ML workloads. With our high-performance infrastructure, you can rest assured that your projects will run smoothly and efficiently.</li><li><strong>All Qoddi&apos;s features</strong>: GPU-powered instances are created inside the Qoddi&apos;s infrastructure with instant access to all your other apps inside the same project using our local secured network. You can choose to completely isolate your GPU-app from the Internet while keeping the connectivity with other apps (databases, management tools and more). Like any other Qoddi app, your GPU app launch and deploy in seconds and use dedicated builders and CI/CD tools.</li><li><strong>Ease of use</strong>: Qoddi&apos;s platform is user-friendly and provides an intuitive interface for managing and deploying your instances. You can easily launch, monitor, and manage your GPU instances, allowing you to focus on your research and development instead of dealing with complex infrastructure issues.</li></ol><p>Get started today!</p><p>We&apos;re excited to see how our GPU-powered instances will empower researchers and developers to create cutting-edge AI applications, LLMs, and chatbots. To get started, login to your Qoddi account and create your first GPU-powered app! </p><p>Visit our <a href="https://qoddi.com/pricing">pricing page</a> for more informations about Qoddi&apos;s GPU lineup.</p><p>Let&apos;s build the future of AI together!</p>]]></content:encoded></item><item><title><![CDATA[Support for Multi-buildpacks released]]></title><description><![CDATA[<p>There are numerous instances where a single buildpack falls short in app building, for instance when working on a NodeJS app with a PHP backend. </p><p>We are thrilled to announce the global and immediate availability of Multi-Buildpacks for all app sizes, including our Free tier.</p><p>The Multi-Buildpack feature allows you</p>]]></description><link>https://blog.qoddi.com/support-for-multi-buildpacks-released/</link><guid isPermaLink="false">64542977d84cce0001e08834</guid><category><![CDATA[code]]></category><category><![CDATA[Product]]></category><category><![CDATA[buildpacks]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Thu, 04 May 2023 22:02:31 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2023/05/shutterstock_1496806469.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.qoddi.com/content/images/2023/05/shutterstock_1496806469.jpg" alt="Support for Multi-buildpacks released"><p>There are numerous instances where a single buildpack falls short in app building, for instance when working on a NodeJS app with a PHP backend. </p><p>We are thrilled to announce the global and immediate availability of Multi-Buildpacks for all app sizes, including our Free tier.</p><p>The Multi-Buildpack feature allows you to:</p><ul><li>Combine multiple languages within a single final release,</li><li>Specify and enforce the usage of a single buildpack over Qoddi&apos;s autodetection,</li><li>Expedite the development process and deploy more intricate apps by merging web and worker apps into one release.</li></ul><p>Alongside the introduction of multi-buildpacks, we&apos;re expanding support for Add-on buildpacks (such as APT, Static, or the newly introduced FFmpeg buildpacks). These buildpacks are designed to be compatible with the multi-buildpack feature, further enhancing your app&apos;s functionality.</p><p>In today&apos;s fast-paced development landscape, it is crucial for developers to have the right tools and resources at their disposal. Qoddi stands out as the ultimate solution for quickly and efficiently building code, ultimately saving both time and money when deploying apps and app features.</p><p>Here&apos;s why Qoddi is your top choice for app development:</p><ol><li><strong>Streamlined workflow:</strong> Qoddi offers a seamless experience by integrating with your existing development pipeline. This integration enables you to focus on writing code without worrying about managing infrastructure or other deployment complexities.</li><li><strong>Scalable resources:</strong> Qoddi provides scalable resources that can be easily adjusted according to your app&apos;s needs. Whether you&apos;re just starting out or managing a high-traffic application, Qoddi ensures that you have the appropriate resources at your disposal.</li><li><strong>Cost-effective:</strong> By offering a Free tier and a variety of affordable pricing options, Qoddi ensures that developers can access its powerful tools and services without breaking the bank. This cost-effectiveness allows you to invest more in other aspects of your business.</li><li><strong>Continuous innovation:</strong> Qoddi is constantly evolving and improving its features, such as the newly released Multi-Buildpacks, to keep up with the ever-changing development landscape. This commitment to innovation ensures that you always have access to the latest tools and technologies.</li><li><strong>Expert support:</strong> Qoddi&apos;s team of experts is available to assist you with any questions or concerns you may have, ensuring a smooth and trouble-free development experience.</li></ol><p>We believe you&apos;ll appreciate our new Multi-Buildpack feature and welcome your feedback!</p>]]></content:encoded></item><item><title><![CDATA[Project Variables are now available]]></title><description><![CDATA[<p>Environment variables are the best way to store variables like API keys, secrets and databases URLs. Until today you had to create and update Env. Variable manually for each app even if they are inside the same project and share the same credentials.</p><p>Today, we are launching Project-level Variables:</p><figure class="kg-card kg-image-card"><img src="https://blog.qoddi.com/content/images/2023/03/Screenshot-2023-03-10-at-11.54.10-PM.png" class="kg-image" alt loading="lazy" width="922" height="1382" srcset="https://blog.qoddi.com/content/images/size/w600/2023/03/Screenshot-2023-03-10-at-11.54.10-PM.png 600w, https://blog.qoddi.com/content/images/2023/03/Screenshot-2023-03-10-at-11.54.10-PM.png 922w" sizes="(min-width: 720px) 720px"></figure><p>Project-level</p>]]></description><link>https://blog.qoddi.com/shared-variables-are-now-available/</link><guid isPermaLink="false">63e4016c0ff5d700010e38ab</guid><category><![CDATA[Product]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Sun, 12 Mar 2023 22:40:44 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2023/03/environment-variable-secret.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.qoddi.com/content/images/2023/03/environment-variable-secret.jpg" alt="Project Variables are now available"><p>Environment variables are the best way to store variables like API keys, secrets and databases URLs. Until today you had to create and update Env. Variable manually for each app even if they are inside the same project and share the same credentials.</p><p>Today, we are launching Project-level Variables:</p><figure class="kg-card kg-image-card"><img src="https://blog.qoddi.com/content/images/2023/03/Screenshot-2023-03-10-at-11.54.10-PM.png" class="kg-image" alt="Project Variables are now available" loading="lazy" width="922" height="1382" srcset="https://blog.qoddi.com/content/images/size/w600/2023/03/Screenshot-2023-03-10-at-11.54.10-PM.png 600w, https://blog.qoddi.com/content/images/2023/03/Screenshot-2023-03-10-at-11.54.10-PM.png 922w" sizes="(min-width: 720px) 720px"></figure><p>Project-level Variables are environment variables created at the project-level. You can create and consume an unlimited number of environment variable directly from your project main page. Project variables remain persistent after an app (or all apps) is deleted and can be shared to all apps inside the same project.</p><p>Let us know what you think about this new feature and if we can make it even better!</p>]]></content:encoded></item><item><title><![CDATA[Host a complete Mastodon server on Qoddi for $30 per month (and first month free!)]]></title><description><![CDATA[<p>Mastodon recently became a popular decentralized alternative to Twitter and, more importantly, a way to own your part of a global social network.</p><p>Mastodon servers can interact with all other fediverse servers (including other Mastodon server). You don&apos;t have to own your Mastodon server to get started, you</p>]]></description><link>https://blog.qoddi.com/host-a-complete-mastodon-server-on-qoddi/</link><guid isPermaLink="false">639f59aa71babc0001511a57</guid><category><![CDATA[Product]]></category><category><![CDATA[mastodon]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Wed, 21 Dec 2022 21:52:03 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2022/12/5000-1.webp" medium="image"/><content:encoded><![CDATA[<img src="https://blog.qoddi.com/content/images/2022/12/5000-1.webp" alt="Host a complete Mastodon server on Qoddi for $30 per month (and first month free!)"><p>Mastodon recently became a popular decentralized alternative to Twitter and, more importantly, a way to own your part of a global social network.</p><p>Mastodon servers can interact with all other fediverse servers (including other Mastodon server). You don&apos;t have to own your Mastodon server to get started, you can even join the <a href="https://mastodon.qoddi.com">Mastodon of Qoddi</a>. But, if you want to own your data or simply create a new community where you can decide on your own data governance and moderation, launching your own Mastodon server is the way to go.</p><p>Until now, deploying a Mastodon server seemed very complicated, requiring several servers, adjusting the configuration, and knowing about load balancing, SSL certificates, and more. Some one-click deploy solutions exist but are pretty much not scalable, meaning your Mastodon server will never be able to grow outside of the tiny VPS you installed it on at the beginning (you never know, you may have the next Twitter on your hands!).</p><p>Today, we&apos;re proud to launch a simple and automated way to deploy a complete Mastodon stack on Qoddi. The minimum cost for the complete stack is $30 per month (5 instances at $6 per month), and your stack can scale infinitely, thanks to Qoddi&apos;s exclusive technology.</p><h2 id="included-with-your-mastodon-stack">Included with your Mastodon Stack</h2><p>For $30 per month, you will get a complete Mastodon stack ready to be used in production:</p><ul><li>A complete Mastodon stack (5 apps including Postgres and Redis databases),</li><li>Unlimited bandwidth (don&apos;t pay for Internet traffic!),</li><li>Out of Site, Daily Backups (compliant with Mastodon covenant),</li><li>SSL Certificate for your Mastodon domain provided by Let&apos;s Encrypt,</li><li>Complete scalability option to grow your stack up to millions of daily users.</li></ul><h2 id="first-month-free">First month free?</h2><p>For a limited time, you will get $100 free credits (valid one month) when you verify your Qoddi account with a valid credit card: more than enough to run a complete Mastodon stack for free during a whole month!</p><p><a href="https://devcenter.qoddi.com/deploy-a-complete-mastodon-stack-on-qoddi/">Check out our documentation</a> and start your Mastodon account today!</p>]]></content:encoded></item><item><title><![CDATA[Qoddi credits for code-teaching structures]]></title><description><![CDATA[<p>Online resources of code teaching, tutorials, and e-learning program are invaluable resources for the tech community and needs to be recognized as a critical part of the future of tech.</p><p>In addition to that, specific programs or institutions like #WomenWhoCode or #100DaysofCode make a real difference in their communities and,</p>]]></description><link>https://blog.qoddi.com/qoddi-credits-for-code-teaching-structure/</link><guid isPermaLink="false">63365065abe9100001d6eaea</guid><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Fri, 30 Sep 2022 02:32:13 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2022/09/shutterstock_753875071.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.qoddi.com/content/images/2022/09/shutterstock_753875071.jpg" alt="Qoddi credits for code-teaching structures"><p>Online resources of code teaching, tutorials, and e-learning program are invaluable resources for the tech community and needs to be recognized as a critical part of the future of tech.</p><p>In addition to that, specific programs or institutions like #WomenWhoCode or #100DaysofCode make a real difference in their communities and, through code, offers a better future to millions of people worldwide.</p><p>At Qoddi, we know that the infrastructure is a critical part of the learning process, and infrastructure must be accessible to everyone at the same pace as learning new technologies and programming languages.</p><p>Today we are launching a new program, similar to our <a href="https://blog.qoddi.com/flashdrive-student-program/">student program</a>, destined to help people currently learning code via a pre-approved structure or institution to use Qoddi&apos;s infrastructure for free without having to use a credit card to validate their account.</p><p><strong>This new program includes:</strong></p><ul><li>A $200 yearly credit, renewable up to 3 times, to use any of Qoddi&apos;s production services, including datastores, apps, and add-ons,</li><li>No need to have a valid credit card on file to use Qoddi&apos;s services, </li></ul><h2 id="how-to-apply">How to apply</h2><p>To apply for this credit, please contact your code-teaching program or institution. They have a direct enrollment system provided by Qoddi to activate your account using a specific flow.</p><p>If the program or code-teaching structure doesn&apos;t participate in this program yet, please ask them to contact us to get started: it&apos;s completely free and quick.</p>]]></content:encoded></item><item><title><![CDATA[Qoddi for open source projects]]></title><description><![CDATA[<p>At Qoddi, we are strong advocates and sponsors of open-source projects, and with the recent decision from Heroku to stop offering free plans (used by a lot of open-source developers), we felt the importance of having an alternative ready to keep those projects running.</p><p>Qoddi&apos;s infrastructure is compatible</p>]]></description><link>https://blog.qoddi.com/qoddis-offer-for-open-source-projects/</link><guid isPermaLink="false">6309bdc080bd0600011c5d9d</guid><category><![CDATA[open source]]></category><category><![CDATA[Product]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Sat, 27 Aug 2022 06:59:48 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2022/08/Open-Source.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.qoddi.com/content/images/2022/08/Open-Source.jpeg" alt="Qoddi for open source projects"><p>At Qoddi, we are strong advocates and sponsors of open-source projects, and with the recent decision from Heroku to stop offering free plans (used by a lot of open-source developers), we felt the importance of having an alternative ready to keep those projects running.</p><p>Qoddi&apos;s infrastructure is compatible with most of Heroku&apos;s buildpacks and <a href="https://devcenter.qoddi.com/migration-guide-heroku-to-qoddi/">we wrote a guide to migrate a project from Heroku</a>.</p><p>We understand that open source developers need features and options that may not be available in our generous free plan like:</p><ul><li>Custom domain names with SSL,</li><li>Production-ready infrastructure to sustain the growth of the project,</li><li>Ability to deploy Docker containers or apps that require more resources than our free plan.</li></ul><p>If you are the developer of an open source project, you are eligible for a $500 credit, available for 12 months and renewable every year the project remains active.</p><p>$500 for 12 months is enough to deploy a complete infrastructure to promote and manage an open source project with moderate/heavy traffic, including front-end, documentation, and test environments.</p><p>To request the open-source credit:</p><ul><li>Open a dedicated Qoddi account with GitHub login using the same account as your open source project on GitHub,</li><li><a href="https://devcenter.qoddi.com/contact-flashdrive-support/">Send us a message</a> to request the credit,</li><li>The account must be exclusively used to host resources related to your open-source, or the credit will be voided,</li><li>A credit card <strong>is not required</strong> to activate this account.</li></ul><p><strong>To be eligible under this program:</strong></p><ul><li>You must be the creator or the owner of the project,</li><li>It must be completely open-sourced and available on GitHub,</li><li>Have at least 50 stars or 100 forks on its main repository,</li><li>Mention Qoddi as the hosting solution inside the project README</li></ul><p>If you have any questions about this program, feel free to contact us!</p><p> </p>]]></content:encoded></item><item><title><![CDATA[Qoddi's position and assistance in Ukraine]]></title><description><![CDATA[<p>For the last several weeks, we all have been shocked and concerned about the situation in Ukraine and the need for Ukraine-based Internet companies to protect their infrastructure against digital threats.<br>At the same time, we&apos;ve seen an exponential increase in the number of attacks coming from Russia</p>]]></description><link>https://blog.qoddi.com/qoddis-position-and-assistance-in-ukraine/</link><guid isPermaLink="false">62389ef38d21040001e51d70</guid><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Mon, 21 Mar 2022 16:11:41 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2022/03/Flag_of_Ukraine.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.qoddi.com/content/images/2022/03/Flag_of_Ukraine.jpeg" alt="Qoddi&apos;s position and assistance in Ukraine"><p>For the last several weeks, we all have been shocked and concerned about the situation in Ukraine and the need for Ukraine-based Internet companies to protect their infrastructure against digital threats.<br>At the same time, we&apos;ve seen an exponential increase in the number of attacks coming from Russia and Belarus. Our team of engineers and infrastructure specialists works around the clock to make sure Apps and Services hosted on Qoddi stay protected from any type of threats.</p><p>Below we outlined Qoddi&apos;s position on this matter and the steps we took to make sure we help the most we can.</p><h2 id="digital-relief-for-ukraine-based-customers">Digital relief for Ukraine-based customers</h2><p><br>Since March 8th, 2022, Ukraine-based customers have been eligible for a $1500 credit (valid for 1 year) to cover the cost of any pending, past due or current invoice for Ukraine-based customers. We recognize that processing payments in Ukraine can be challenging at this time, and our sales teams can offer additional relief if needed.</p><p>Our team is also available to provide additional customer support, including priority support for Free apps.</p><p>Currently, we are lifting all restrictions on commercial content that can be hosted on free apps (Dev size) if the service hosted provides support, information, or connectivity for the Ukrainian people.</p><h2 id="russia-and-belarus-based-customers">Russia and Belarus based customers</h2><p><br>Starting March 8th, 2022, Qoddi stopped allowing signups for customers based in Russia and Belarus, and we actively monitor current accounts from this country. In the following weeks, while the situation evolves, we will reassess our position on closing current accounts for customers based in Russia and Belarus.</p><p>Qoddi&apos;s terms and conditions are clear on hosting a service that threatens people, encourages violence or terrorism, or poses a threat to other digital assets is not permitted. All accounts that are not compliant with this policy will be immediately banned, with all apps deleted. &#xA0;</p><h2 id="qoddis-presence-in-russia-and-relation-to-russian-government">Qoddi&apos;s presence in Russia and relation to Russian Government</h2><p>Unlike other cloud providers, Qoddi doesn&apos;t have any datacenter, offices, or infrastructure in Russia or Belarus. Since the creation of Qoddi, we have had an internal policy to not do any business with the Russian Government.</p><p>We will continue to update this page in the future as the situation evolves and we work to offering more solutions for people based in Ukraine and needs our help.</p><p></p><p> </p>]]></content:encoded></item><item><title><![CDATA[Qoddi vs Heroku and AWS: what to choose as a Startup]]></title><description><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a></h3><p>You have many options when it comes to choosing a platform to deploy your app. In this article, we will compare AWS, Heroku, and Qoddi.</p><p><strong>Heroku is hosted on</strong></p>]]></description><link>https://blog.qoddi.com/qoddi-vs-heroku-and-aws-what-to-choose-as-a-startup/</link><guid isPermaLink="false">61f6efe3898c0a00013f079e</guid><category><![CDATA[AWS]]></category><category><![CDATA[Getting Started]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Thu, 17 Feb 2022 16:39:21 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2022/01/shutterstock_1489195400.jpg" medium="image"/><content:encoded><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a></h3><img src="https://blog.qoddi.com/content/images/2022/01/shutterstock_1489195400.jpg" alt="Qoddi vs Heroku and AWS: what to choose as a Startup"><p>You have many options when it comes to choosing a platform to deploy your app. In this article, we will compare AWS, Heroku, and Qoddi.</p><p><strong>Heroku is hosted on AWS</strong>, making Heroku, like Qovery for instance, nothing more than a management platform for AWS services. You can do everything you do on Heroku (or Qovery) directly with AWS for a lesser price but Heroku removes all the infrastructure management layer (or DevOps) you still need to have with AWS or any other cloud providers.</p><h2 id="what-is-amazon-web-services-aws">What is Amazon Web Services (AWS)?</h2><p>As a subsidiary of the e-commerce giant Amazon.com, AWS is an IaaS service (Infrastructure as a Service), meaning you are basically renting compute power from them. The main advantage of AWS against its competitor is the multitude of products services derived from that simple abstract: renting compute power.<br>Of course, you can rent VPS on AWS, a virtual instance with just an operating system installed called EC2 but AWS also offers databases (RDS), Block Storage (S3 and Glacier), even AWS Lambda to run code directly without managing infrastructure. </p><p>Using AWS still requires installing and managing infrastructure: servers, load balancers, databases etc... While AWS is a powerful infrastructure provider it&apos;s not a &quot;one-click&quot; process to deploy infrastructure, scale, and maintain it.</p><p>AWS pricing can become a friction point at scale since all services are billed independently. Bandwidth (internet traffic also called egress fees) costs $90 per TB and that alone can bring your monthly invoice to a very high amount of money even for small traffic apps or websites. </p><h2 id="what-is-heroku">What is Heroku?</h2><p>Heroku, part of the Salesforce group, is a PaaS (Platform as a Service) created on top of the AWS infrastructure. Using Heroku, you can deploy apps directly from code, add add-ons and packages like databases or log auditing services, and manage everything from a simple, easy-to-use dashboard. Heroku does all the work in the background and sets up everything your app needs.<br>The main inconvenience of using Heroku is the enormous cost at scale. Since Heroku is created on top of AWS&apos;s infrastructure the cost of AWS is passed to you as a Heroku customer. Heroku also adds a Premium to AWS costs (since it needs to make money for its platform) and a basic production app with Heroku costs $250 per month minimum to run on a limited performance instance.</p><p>Another point of friction using Heroku is the need to use overpriced add-ons even for small apps. All databases are managed and needs to run on Heroku infrastructure and the ability to launch Docker containers on Heroku, while possible is not offered directly from the web platform and requires additional steps and configuration files.</p><h2 id="qoddi-a-complete-infrastructure-solution-for-startups">Qoddi: a complete infrastructure solution for startups</h2><p><a href="https://qoddi.com">Qoddi</a> is a PaaS (like Heroku) but also maintains its own infrastructure like AWS. Since the whole system is custom-created for Qoddi this leverages a lot of savings that can be passed to the customer.</p><p>As a startup you need reliable infrastructure, allowing for fast and simple deployment at moderate costs.</p><p><strong>The main advantage of <a href="https://qoddi.com">Qoddi</a> are:</strong></p><ul><li>Deploy code directly from any repository, all the infrastructure (servers, load balancers, etc...) are created and managed automatically by Qoddi,</li><li> Launch Docker containers, databases (like Postgres or Redis), and developers tools directly from the marketplace at the same costs of other apps,</li><li>Free DEV apps for developers,</li><li>Pipelines with Free preview apps to verify every pull request before sending it to staging and production,</li><li>Tier 1 Infrastructure: Qoddi relies on its own clusters located in North America, Europe, and Singapour with an optimized network to improve delivery times and makes your app reachable everywhere in the world.</li><li>No egress fees: Unlimited traffic is included with all apps,</li><li>All included: Load balancers, backups, bandwidth, build time are included in the price of your app.</li><li><a href="https://blog.qoddi.com/flashdrive-startup-program/">Qoddi Startup Program</a> with generous credits packages for bootstrapped and more advanced startups.</li><li>Included support by email with premium 24/7 support for larger apps.</li></ul><p>The idea behind Qoddi is to offer an alternative to Heroku and AWS for startups and SMBs around the world that need premium app hosting services at an affordable price. &#xA0;</p><p>If you are starting a new company or looking for a reliable alternative to Heroku, feel free to <a href="mailto:sales@qoddi.com">contact our sales team</a> to see how <a href="https://qoddi.com">Qoddi</a> can help you save a lot of time and money by moving your apps to Qoddi.</p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Better Way To Write Async Function in Node/Express/Next - Handle catch(err) Only Once.]]></title><description><![CDATA[<p><strong>Avoid Writing a Lot of Try Catch by Catching The &#x2018;catch()&#x2019; Just Once.</strong></p><h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a><br></h3><p>How annoying it is to write a lot of <em>try-catch</em> for each <em>async</em> function</p>]]></description><link>https://blog.qoddi.com/better-way-to-write-async-function-in-node-express-next-handle-catch-err-only-once/</link><guid isPermaLink="false">620e56e476eb270001bdeae4</guid><category><![CDATA[code]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[ReactJS]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Thu, 17 Feb 2022 14:36:23 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2022/02/shutterstock_1179267760.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.qoddi.com/content/images/2022/02/shutterstock_1179267760.jpg" alt="Better Way To Write Async Function in Node/Express/Next - Handle catch(err) Only Once."><p><strong>Avoid Writing a Lot of Try Catch by Catching The &#x2018;catch()&#x2019; Just Once.</strong></p><h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a><br></h3><p>How annoying it is to write a lot of <em>try-catch</em> for each <em>async</em> function in an <strong>express</strong> app? What if you never need to write a <em>try catch</em> block for all <em>async</em> functions and still be able to handle the errors?<br></p><p><strong>Prerequisites</strong></p><ol><li>You need to know how node, express, middleware, routes and controller functions work together.</li><li>You need to have an understanding of the <strong>err</strong> and <strong>next</strong> handlers of express.</li><li>Understanding basic git and SSH.</li><li>Understanding of NextJS</li></ol><p><strong>Try Catch</strong></p><p>When you write an <em>async</em> function that can throw an error, you need to have the <em>try-catch-finally</em> blocks to handle the errors. Let&#x2019;s say, you write a database query and it fails - the error would come in the <strong>catch.</strong></p><pre><code class="language-node">async function(req, res, next){
Try{
		//something to try
}catch(err){
		//when trying to do something in try fails
}
}
</code></pre><p>If you don&#x2019;t write a <em>try-catch</em> block in an <em>async</em> function, express would not be able to handle the error. You can read more about express error handling <a href="https://expressjs.com/en/guide/error-handling.html">here</a>.</p><h2 id="the-solution"><br>The Solution</h2><p>We are going to write a function called <em>catchAsyncFunction(</em><strong><em>asyncFunction</em></strong><em>)</em> that will take an <em>async</em> function as a parameter. Then it will catch the <em>catch(</em><strong><em>err</em></strong><em>)</em> of the async function. Then pass the error to express using <em>next</em>. Now the error will be available to handle in any middleware after the async function finishes.</p><p>We will be able to write it like this:</p><pre><code class="language-node">catchAsyncFunction(async function(req, res, next){
Try{
		//something to try
}catch(err){
		//when trying to do something in try fails
}
})
</code></pre><p><strong>The catchAsyncFunction</strong></p><p>So, this <em>catchAsyncFunction</em> is gonna be a little function. It is just 3 lines of code you need to have.</p><pre><code class="language-node">function catchAsyncFunction(asyncFunction){
	return (req, res, next) =&gt; {
	asyncFunction(req, res, next).catch(next)
}
}
</code></pre><p><br>Understanding this is a little confusing. But if you check the express error doc, <a href="https://expressjs.com/en/guide/error-handling.html">express error handling</a> - You can pass the catch block of a promise with the <em>next</em> handler.</p><p>If you call an async function and then catch the error, you can pass the error to express middleware using <em>next</em>.</p><p>The <em>catchAsyncFunction</em> takes an <em>asyncFunction</em> as a parameter. Then returns a callback that calls the asyncFunction, catches the error, and passes to the next middleware to use.<br></p><p><strong>Handling the Passed Error</strong></p><p>Now it is easy to handle the error. You can use a middleware at the bottom of all the route middleware. The middleware must have a new handler called <em>err. </em></p><p>When a middleware function takes (err, req, res, next) this four, express thinks of it as an error middleware and passes the error to it. If you don&#x2019;t have an <em>err </em>in any of your functions after the route, it will halt and throw an unhandled raw error.</p><pre><code class="language-node">const express = require(&#x2018;express&#x2019;)
const app = express();

//your route middleware here

//error catch middleware after all routes
app.use((err, req, res, next)=&gt;{
	console.log(err.stack)
})
</code></pre><p>If no error happens, this middleware will be automatically skipped by express.</p><h2 id="the-implementation">The Implementation</h2><p><strong>Start project</strong><br>Let&#x2019;s start locally with a folder named catchAsyncFunction and run:</p><pre><code class="language-shell">npm init -y
npm i express
npm i -D nodemon
</code></pre><p>To start a node project, install the express framework and install nodemon as devDependency to automate server start on file change. <br></p><p><strong>Paste this code in index.js:</strong></p><pre><code class="language-node">const express = require(&quot;express&quot;);
const app = express();
 
//create catchAsyncFunction
function catchAsyncFunction(asyncFunction) {
   return (req, res, next) =&gt; {
       asyncFunction(req, res, next).catch(next);
   };
}
 
//define your route here
const homeController = catchAsyncFunction(async (req, res, next) =&gt; {
   //const data = await
   //res.json({ msg: &quot;no err&quot; });
 
   throw new Error(&quot;Error happened&quot;);
   //this code will automatically go to error catch middleware
   //no need next() because it passes to the next middleware defined after the route
});
 
//your route middleware here
app.get(&quot;/&quot;, homeController);
 
//catch error here
app.use((err, req, res, next) =&gt; {
   console.log(err.stack);
   res.status(400).json({
       message: err.message,
   });
});
 
//start server
app.listen(5000, () =&gt; {
   console.log(&quot;Server started @5000&quot;);
});
</code></pre><p>Replace package.json script section with this code:</p><pre><code class="language-node">&quot;scripts&quot;: { 
&quot;dev&quot;: &quot;nodemon index.js&quot;,
&quot;start&quot;: &quot;node index.js&quot;
 },
</code></pre><p>Source code:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/qoddiapps/catchAsync"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - qoddiapps/catchAsync</div><div class="kg-bookmark-description">Contribute to qoddiapps/catchAsync development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Better Way To Write Async Function in Node/Express/Next - Handle catch(err) Only Once."><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">qoddiapps</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/20e909357b65b89f72aa170984d32a3aa7a364cd7975777867a47c7e0ad8157f/qoddiapps/catchAsync" alt="Better Way To Write Async Function in Node/Express/Next - Handle catch(err) Only Once."></div></a></figure><p>In the end, we will connect this to a front-end.</p><h2 id="avoiding-try-catch-in-frontendnextjs">Avoiding try catch in frontend - NextJS<br></h2><p>Again annoyingly, for each <em>async</em> function that fetches or sends server data, you have to write <em>try catch</em> blocks in the front-end too. </p><p>On top of that, In <strong>NextJS</strong> we have <em>getServerSideProps</em> or <em>getStaticProps</em> that can&#x2019;t be used in child components. Only to use in root page components. Sometimes, <em>useEffect</em> is the best choice. So, I am going to use <em>useEffect</em> here.</p><p>Sometimes, you have to write a lot of useEffect hooks and have to write <em>fetch(), try </em>and<em> catch</em> multiple times. To avoid this, you can write a function that can handle all <em>fetch() </em>requests from all components.<br></p><h2 id="the-solution-1">The Solution</h2><p>Instead of writing each time the <em>try catch</em> block like this:</p><pre><code class="language-node">useEffect(()=&gt;{
	const bringData = async ()=&gt;{

		try{
			const data = await fetch(URL, 
{
         		method: &apos;GET&apos;,         
credentials: &apos;include&apos;,
headers: {           
Accept: &apos;application/json&apos;,           
&apos;Content-Type&apos;: &apos;application/json&apos;,         
},       
});
}
catch(err){
		//handle error
}
}

bringData();
})
</code></pre><p>you can create a function called <em>apiRequest()</em> that can handle all the <em>try-catch</em> of all components and requests types. Usually, each of your fetch requests will have <strong>api URL</strong>, <strong>data</strong>, <strong>http method type</strong>. So, let&#x2019;s make sure the function can accept them.</p><pre><code class="language-node">const apiRequest = (url, method, formData )=&gt;{
	if(method === &#x2018;GET&#x2019;){
	// handle get request
}else{
// handle other request
}
}
</code></pre><p>Since, except <strong>GET</strong> requests <strong>POST, PATCH, DELETE </strong>can<strong> </strong>have a body property, we have to create an <strong>if else</strong> section to handle these two types of situations. </p><p>It&apos;s just two blocks that will handle all your requests. Let&#x2019;s add an <em>async</em> keyword to it and add <em><strong>try catch</strong></em> once for all.</p><pre><code class="language-node">const apiRequest = async (url, method, formData )=&gt;{
	try{
		if(method === &#x2018;GET&#x2019;){
		// handle get request
		
	
}else{
// handle other request
}
}catch(err){
	return err
}
	
}
</code></pre><p>The <em>try</em> can return data. <em>Catch</em> can return <em>err</em>. <br>Now in this code, you can add your<em> fetch()</em> to handle all requests like this:</p><pre><code class="language-node">const apiRequest = async (url, method, formData )=&gt;{
	try{
		if(method === &#x2018;GET&#x2019;){
		// handle get request
		const response = await fetch(url, 
{
         				method: &apos;GET&apos;,         
credentials: &apos;include&apos;,
headers: {           
Accept: &apos;application/json&apos;,           
&apos;Content-Type&apos;: &apos;application/json&apos;,         
},       
});

const data = await response.json();
return data

	
}else{
// handle other request
		const response = await fetch(url, 
{
         				method: &apos;GET&apos;,         
credentials: &apos;include&apos;,
headers: {           
Accept: &apos;application/json&apos;,           
&apos;Content-Type&apos;: &apos;application/json&apos;,         
},       
body: JSON.stringify(formData)
});

const data = await response.json();
return data
}
}catch(err){
	return err
}
	
}
</code></pre><p>The only difference between<strong> get</strong> and other <strong>http</strong> requests is the use of a <em>body </em>key. We use JSON.stringify(formData) to make a data object to a JSON object. </p><p>Since we are returning data and returning <strong>error</strong> in the <em>catch</em> block, the <em>useEffect</em> hook in the component level can get the data<strong> without throwing an error</strong>. </p><p>So no need to have a <em>catch</em> block there.</p><p>If we send a request to our backend, we will have a code like this:</p><pre><code class="language-node">useEffect(() =&gt; { 
const fetchData = async () =&gt; { 
const data = await apiRequest(&quot;backend url&quot;, &quot;GET&quot;); 
console.log(data); 
}
fetchData(); 
});
</code></pre><h2 id="implement-the-front-end-and-test-it-by-connecting-to-our-previous-backend-on-qoddi"><br>Implement The Front End and Test It By Connecting to Our Previous Backend on Qoddi</h2><p>To create a next app, in your project folder create a new directory called &#x2018;lessAsync&#x2019;. Inside the directory open a terminal and run:</p><pre><code class="language-shell">npx create-next-app ./ -y
</code></pre><p>Now, you will see all the files and folders. <br>Inside <strong>index.js,</strong> remove everything and paste this code:</p><pre><code class="language-node">import Head from &quot;next/head&quot;;
import { useEffect, useState } from &quot;react&quot;;
import { apiRequest } from &quot;../utils/apiRequest&quot;;

export default function Home() {
    const [errData, errDataSet] = useState(&quot;&quot;);
    useEffect(() =&gt; {
        const fetchData = async () =&gt; {
            const data = await apiRequest(&quot;http://localhost:5000&quot;, &quot;GET&quot;);
            errDataSet(data.message);
        };
        fetchData();
    }, []);
    return (
        &lt;div&gt;
            &lt;Head&gt;
                &lt;title&gt;Less Async&lt;/title&gt;
            &lt;/Head&gt;
            &lt;h1&gt; Test frontend error handling&lt;/h1&gt;
            &lt;h2&gt;{errData}&lt;/h2&gt;
        &lt;/div&gt;
    );
}
</code></pre><p>Outside the pages folder, create a utils folder and create a file called <strong>apiRequest.js</strong> and then paste the code in it:</p><pre><code class="language-node">export const apiRequest = async (url, method, formData) =&gt; {
    try {
        if (method === &quot;GET&quot;) {
            console.log(&quot;ji&quot;);
            // handle get request
            const response = await fetch(url, {
                method: &quot;GET&quot;,
                headers: {
                    Accept: &quot;application/json&quot;,
                    &quot;Content-Type&quot;: &quot;application/json&quot;,
                },
            });

            const data = await response.json();
            return data;
        } else {
            // handle other request
            const response = await fetch(url, {
                method: method,
                headers: {
                    Accept: &quot;application/json&quot;,
                    &quot;Content-Type&quot;: &quot;application/json&quot;,
                },
                body: JSON.stringify(formData),
            });

            const data = await response.json();
            return data;
        }
    } catch (err) {
        return err;
    }
};
</code></pre><h2 id="start-the-app-and-test-it">Start the app and test it</h2><p>Qoddi is a web server deployment service that updates your codebase on git push. Qoddi builds your code and starts the server following your package.json directives. </p><p>On top of that, Qoddi supports nodeJS out of the box. No extra Procfile needed. </p><p>Let&#x2019;s deploy and test it in qoddi.com:</p><ol><li>Configure your package.json for specific node and npm version,</li><li>Add cors and process.env.PORT,</li><li>Set your build script and start script,</li><li>Add your code to a github repository,</li><li>Connect the repo from flashdrive dashboard,</li><li>That&#x2019;s it. The server will be built and started.<br></li></ol><p>You will get a live server link and an internal link to test. But first, we need to update our package.json.</p><p><strong>Update Backend and Frontend package.json</strong></p><p>In <em>package.json</em> we need to specify node and npm version. Open a terminal and check your version with <em><strong>node -v</strong></em> and <em><strong>npm -v</strong></em>. <br>Open both<em> package.json</em> files in your <strong>catchAsync</strong> and <strong>lessAsync </strong>folder and add an <em>&#x2018;engines&#x2019;</em> property:</p><pre><code class="language-node">&#x201C;engines&#x201D;: {
	&#x201C;node&#x201D;: &#x201C;16.13.x&#x201D;,
	&#x201C;npm&#x201D;: &#x201C;8.1.x&#x201D;
}
</code></pre><p>Also, we need to add the cors package to the backend to accept requests from the frontend. Install cors with</p><pre><code class="language-shell">npm i cors
</code></pre><p>In the index.js file, after the line <em>const app = express() </em>add these two lines to add cors:</p><pre><code class="language-node">const app = express();
const cors = require(&#x2018;cors&#x2019;);
app.use(cors)
</code></pre><p><strong>In app.listen method, instead of 5000 as port, let&#x2019;s add a PORT variable:</strong></p><pre><code class="language-node">const PORT = process.env.PORT || 5000
app.listen(PORT, ()=&gt;{
	console.log(`Server started @${PORT}`)
})
</code></pre><p>Similar to Heroku, Qoddi uses a port number from process.env</p><p>Since we already have our start and build script, we just need to update them. In the backend, add a build script with &#x201C;npm install&#x201D; init.</p><pre><code class="language-node">&#x201D;scripts&#x201D;: {
	&#x201C;build&#x201D;: &#x201C;&#x201D;npm install&#x201D;,
	&#x201C;dev&#x201D;: &#x201C;nodemon index.js&#x201D;,
	&#x201D;start&#x201D;: &#x201C;node index.js&#x201D;
}
</code></pre><p>In the frontend, update the start script with:</p><pre><code class="language-node">&#x201C;start&#x201D;: &#x201C;npm install &amp;&amp; next start&#x201D;
</code></pre><p>So, let&#x2019;s create two git repos and push our code to them:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/qoddiapps/catchAsync"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - qoddiapps/catchAsync</div><div class="kg-bookmark-description">Contribute to qoddiapps/catchAsync development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Better Way To Write Async Function in Node/Express/Next - Handle catch(err) Only Once."><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">qoddiapps</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/20e909357b65b89f72aa170984d32a3aa7a364cd7975777867a47c7e0ad8157f/qoddiapps/catchAsync" alt="Better Way To Write Async Function in Node/Express/Next - Handle catch(err) Only Once."></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/qoddiapps/lessAsync"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - qoddiapps/lessAsync</div><div class="kg-bookmark-description">Contribute to qoddiapps/lessAsync development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Better Way To Write Async Function in Node/Express/Next - Handle catch(err) Only Once."><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">qoddiapps</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/6e04c345b0418252f837258387fda692e600c5b4f0216f82d19d7d2a18631a42/qoddiapps/lessAsync" alt="Better Way To Write Async Function in Node/Express/Next - Handle catch(err) Only Once."></div></a></figure><p><strong>Let&#x2019;s deploy</strong></p><p>Create an account on https://qoddi.com and log in to your dashboard. Now click on the new app menu. Let&#x2019;s create the backend first and then create the front-end.</p><p>Dev Apps are Free (up to 3 apps) on Qoddi.com, no credit card is required.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Auto-Scaling is now available for everyone!]]></title><description><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a></h3><p>Worried that your app will not have enough resources as you grow? </p><p>All apps on Qoddi can scale at any time and as part of Qoddi&apos;s new</p>]]></description><link>https://blog.qoddi.com/auto-scaling-is-now-available-for-everyone/</link><guid isPermaLink="false">61f4d71e5d1348000198d036</guid><category><![CDATA[Product]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Tue, 15 Feb 2022 08:11:11 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2022/01/shutterstock_1182466249.jpg" medium="image"/><content:encoded><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a></h3><img src="https://blog.qoddi.com/content/images/2022/01/shutterstock_1182466249.jpg" alt="Auto-Scaling is now available for everyone!"><p>Worried that your app will not have enough resources as you grow? </p><p>All apps on Qoddi can scale at any time and as part of Qoddi&apos;s new interface launch early this week, we made auto-scaling available for everyone after more than 6 months in Beta.</p><p>Auto-Scaling, like Auto-Heal (another feature included with all Qoddi apps), is the guardian angel of your apps and will make sure your app continues to run whatever happens. </p><p>Note: Auto-scaling, like any other scaling feature, is only available to apps created in a production environment.</p><p>Auto-Scaling can be enabled directly from your app settings page and consist on only one simple setting:</p><figure class="kg-card kg-image-card"><img src="https://blog.qoddi.com/content/images/2022/01/Screen-Shot-2022-01-29-at-1.00.09-AM.png" class="kg-image" alt="Auto-Scaling is now available for everyone!" loading="lazy" width="2000" height="495" srcset="https://blog.qoddi.com/content/images/size/w600/2022/01/Screen-Shot-2022-01-29-at-1.00.09-AM.png 600w, https://blog.qoddi.com/content/images/size/w1000/2022/01/Screen-Shot-2022-01-29-at-1.00.09-AM.png 1000w, https://blog.qoddi.com/content/images/size/w1600/2022/01/Screen-Shot-2022-01-29-at-1.00.09-AM.png 1600w, https://blog.qoddi.com/content/images/size/w2400/2022/01/Screen-Shot-2022-01-29-at-1.00.09-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><h2 id="what-happens-then">What happens then?</h2><p>All apps deployed on Qoddi are monitored 24/7 to make sure they work as intended and we send you an email each time your app needs more resources.</p><p>With Auto-Scaling enabled, Qoddi will automatically scale your app by adding more nodes (exact replicas of your app, distributed inside the same Qoddi clusters but on different physical machines). </p><p>To determine if your app needs scaling we monitor CPU, RAM, and Network usage in real-time and add 1 more node every minute your app needs it until the limit is reached or your app doesn&apos;t need more nodes to perform adequately.</p><p>When traffic or usage slows down, we automatically reduce the number of nodes accordingly.</p><p>Auto-Scaling is a free feature (except additional nodes usages of course), available to all production apps starting today! </p><h2 id="scaling-strategy">Scaling strategy</h2><p>When your app is scaled up or down, there is no service interruption and your app keeps running continuously. But it&apos;s important to plan in advance and apply correct settings to your app depending on the workload you expect your app to receives. Even if auto-scaling proved to be extremely reliable and act fast to increase your app capacity you can also use a scaling strategy:</p><ul><li>Select an app size consistent with the planned usage. Using the smallest app size with auto-scaling making the app scale permanently to its limit is not recommended because it will be more costly in the long term: Set an app size consistent with the habitual traffic your app receives and use Auto-Scaling as a fail-safe feature only.</li><li> Check your app monitoring page: you&apos;ll be able to see when your app needs more resources and plan accordingly.</li><li>Datastores cannot scale with Auto-Scaling and set a higher instance size in advance if you expect an increase in traffic on your main app.</li><li>Auto-Scaling is suitable to take care of your app whether it&apos;s a worker (doing background tasks) or a web-facing app.</li><li>Feel free to reach out to our Support Team if you need help creating your scaling strategy or are worried about your app availability in case of a surge of traffic/workload.</li></ul>]]></content:encoded></item><item><title><![CDATA[Create An Instant Search Feature With Meilisearch In A React Frontend]]></title><description><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a></h3><p>Meilisearch is an open-source search engine database alternative to Elastic Search or Algolia. It gives fast autocomplete with under 50ms database query performance.</p><h2 id="how-meilisearch-works">How Meilisearch Works</h2><p>After installing, Meilisearch</p>]]></description><link>https://blog.qoddi.com/create-an-instant-search-feature-with-meilisearch-in-a-react-frontend/</link><guid isPermaLink="false">61ef43198793f20001362cff</guid><category><![CDATA[APIs]]></category><category><![CDATA[Jamstack]]></category><category><![CDATA[nodejs]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Tue, 25 Jan 2022 00:40:02 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2022/01/7c0f260f.webp" medium="image"/><content:encoded><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a></h3><img src="https://blog.qoddi.com/content/images/2022/01/7c0f260f.webp" alt="Create An Instant Search Feature With Meilisearch In A React Frontend"><p>Meilisearch is an open-source search engine database alternative to Elastic Search or Algolia. It gives fast autocomplete with under 50ms database query performance.</p><h2 id="how-meilisearch-works">How Meilisearch Works</h2><p>After installing, Meilisearch provides an API endpoint using the <strong>&#x2018;</strong>[<strong>your-domain</strong>]<strong>/indexes/&#x2019; </strong>link. If we have a database of movies, the endpoint will be <strong>&#x2018;</strong>[<strong>your-domain</strong>]<strong>/indexes/movies&#x2019;</strong>. To have a database of movies we need to create a movies document and insert movie data in it.</p><p>Finally, we can fetch the movie data from a React frontend at a super-fast speed while the user types in a form field searching for movies.</p><h2 id="installing-meilisearch-on-qoddi">Installing Meilisearch On Qoddi</h2><p><strong>Note: MeiliSearch requires a production instance to run correctly, hence it&apos;s not available for free DEV apps.</strong></p><p>Qoddi provides a one-click install of Meilisearch from our marketplace section. Just go to the marketplace and launch the Meilisearch app.</p><p>This will create a new app with Meilisearch API setup. Get the link and API Key,</p><figure class="kg-card kg-image-card"><img src="https://lh3.googleusercontent.com/h3gay2yfoBOo15Kr5EsnrX_AxxB2mTL6D_aVDsr59vmIWY7ZZcNzIp3RF4H7s3sTmpzMiqG3EFdPpZW_3tIpF2oU91ah5738BtBpEguhuvxub0u8IRIPcZHYpQ81p3dRfzIO_UfF" class="kg-image" alt="Create An Instant Search Feature With Meilisearch In A React Frontend" loading="lazy"></figure><h2 id="frontend-project-setup">Frontend Project Setup</h2><p>To fetch the data, we need to set up a frontend with React and NextJS. Start a project with your terminal:</p><pre><code class="language-console">npx create-next-app meilisearch
npm i meilisearch</code></pre><p>We install the Meilisearch npm SDK too.<br></p><h2 id="populating-the-database">Populating The Database</h2><p>Since we don&#x2019;t have a <em><strong>movies</strong></em> document created yet, let&#x2019;s create it. Add this code to <em><strong>addmovies.js</strong></em></p><pre><code class="language-node">const { MeiliSearch } = require(&quot;meilisearch&quot;);
const movies = require(&quot;./movies.json&quot;);
 
client = new MeiliSearch({
   host: &quot;http://&lt;your_meilisearch_qoddi_url&gt;/&quot;,
   headers: {
       Authorization: `Bearer ${MEILI_API_KEY}`,
       &quot;Content-Type&quot;: &quot;application/json&quot;,
   },
});
 
//delete movies and jobs index
// client
//     .index(&quot;movies&quot;)
//     .delete()
//     .then(() =&gt; {
//         console.log(&quot;movies index deleted&quot;);
//     });
 
client.index(&quot;movies&quot;).addDocuments(movies);</code></pre><p>&gt;&gt; <strong>movies.json <a href="https://github.com/qoddiapps/meilisearch-react/blob/main/movies.json">can be found here</a></strong><br><br>Run this file locally with node command to add movies document to the Meilisearch database:</p><pre><code class="language-console">node addmovies.js</code></pre><p>This command will use the <em><strong>addmovies.js</strong></em> script and will add every object in <em><strong>movies.json</strong></em> to our Meilisearch document database.</p><h2 id="search-feature">Search Feature</h2><p>In your <em><strong>index.js</strong></em> of your NextJS project replace the code with:</p><pre><code class="language-node">import { MeiliSearch } from &quot;meilisearch&quot;;
import { useEffect, useState } from &quot;react&quot;;
 
const client = new MeiliSearch({
   host: &quot;http://hvlrjtupcw.us05.qoddiapp.com/&quot;,
   headers: {
       Authorization: `Bearer ${process.env.MEILI_API_KEY}`,
       &quot;Content-Type&quot;: &quot;application/json&quot;,
   },
});
 
const App = () =&gt; {
   const [movies, setMovies] = useState([]);
   const [search, setSearch] = useState(&quot;&quot;);
 
   useEffect(() =&gt; {
       //search movie index based on search value
       client
           .index(&quot;movies&quot;)
           .search(search)
           .then((results) =&gt; {
               setMovies(results.hits);
           });
   }, [search]);
 
   return (
       &lt;div className=&quot;App&quot;&gt;
           &lt;div className=&quot;search&quot;&gt;
               &lt;input
                   type=&quot;text&quot;
                   value={search}
                   onChange={(e) =&gt; setSearch(e.target.value)}
               /&gt;
           &lt;/div&gt;
 
           &lt;div className=&quot;movies&quot;&gt;
               {movies?.map((movie) =&gt; (
                   &lt;div className=&quot;movie&quot; key={movie.id}&gt;
                       &lt;div className=&quot;movie-info&quot;&gt;
                           &lt;p&gt;{movie.id}&lt;/p&gt;
                           &lt;h2&gt;{movie.name}&lt;/h2&gt;
                           &lt;p&gt;{movie.year}&lt;/p&gt;
                       &lt;/div&gt;
                   &lt;/div&gt;
               ))}
           &lt;/div&gt;
       &lt;/div&gt;
   );
};
 
export default App;
</code></pre><p><strong>Run <em><strong>npm run dev </strong></em>and test the search functionality by typing in the search box.</strong></p><h2 id="deploy-the-nextjs-app-to-qoddi">Deploy the NextJS app to Qoddi</h2><p>Create a new Qoddi app from code inside the same stack as your MeiliSearch app. After deployment, create an environment variable called <em><strong>MEILI_MASTER_KEY </strong></em>and update your Next config file accordingly:</p><pre><code>env: {
MEILI_MASTER_KEY: process.env.MEILI_MASTER_KEY,
},</code></pre><p>Accessing the NextJS app from your web browser will give you access and search to your MeiliSearch database with lightning-fast responses times.</p><p></p><p><br></p><p><br></p>]]></content:encoded></item><item><title><![CDATA[Discover the new features of NextJS 12 on Qoddi app platform]]></title><description><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a></h3><p>In this tutorial, we will look into the newest NextJS 12 features and use them in a simple project. NextJS 12 comes with a few exciting features. The most</p>]]></description><link>https://blog.qoddi.com/discover-the-new-features-of-nextjs-12/</link><guid isPermaLink="false">61aecb2682adf90001c60f21</guid><category><![CDATA[code]]></category><category><![CDATA[Jamstack]]></category><category><![CDATA[nodejs]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Tue, 07 Dec 2021 03:23:07 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2021/12/next-12-preview.jpeg" medium="image"/><content:encoded><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a></h3><img src="https://blog.qoddi.com/content/images/2021/12/next-12-preview.jpeg" alt="Discover the new features of NextJS 12 on Qoddi app platform"><p>In this tutorial, we will look into the newest NextJS 12 features and use them in a simple project. NextJS 12 comes with a few exciting features. The most intriguing one would be the Rust SWC compiler. Faster compile, faster refresh.</p><h2 id="compiling-jsts-with-rustswc"><br>Compiling JS/TS With Rust - SWC</h2><p>It&#x2019;s pretty awesome how NextJS has changed how websites are built and deployed and still improve everytime to make our life easier. <br>Especially using the new SWC rust compiler that I don&#x2019;t even notice compiling on hot reload. <br><strong>SWC replaces Babel and Terser, a TS/JS compiler and a minify tool.</strong></p><p>Thanks to SWC, <strong><em>build</em></strong> comes from 500ms to 10ms and minifying 250ms -30ms. Also, they made a CSS parsing tool using Rust. So, this is the most exciting feature, using a Rust-based compiler. </p><h2 id="middleware">Middleware</h2><p>Middleware is another new exciting feature that I can&#x2019;t wait to use. Basically create a _middleware.js in any directory inside pages and it will go through each request in that directory. You can manipulate your request traffic with one file. We will be creating middleware later on this tutorial.<br></p><h2 id="reactsuspense-and-reactlazy">React.suspense and React.lazy</h2><p>These two are available since Next 11 as Beta. Now, NextJS12 supports both completely. React suspense is a conditional loading tool: You can load a part of a page or component after the page loads and also you can add a condition that needs to be fulfilled before loading a component. <br><em><strong>React.Suspense</strong></em> re-renders the page with new data. It triggers <em><strong>React.lazy</strong></em> to import the component. For a large page, it really helps to load only what is required for the visitor and then load content based on visitor&apos;s events. Before that we would have to pre-load everything and show them according to the visitor&apos;s behavior. <br>React suspense solves this problem better.</p><p><strong>React lazy</strong> is a new way to import components inside components after the page is already loaded.<br></p><pre><code class="language-Javascript">const TextField = lazy(() =&gt; import(&apos;./formFields/TextField&apos;));</code></pre><p>Another thing, React Suspense can show a loader while the lazy loading is working.</p><h2 id="plan-the-simple-project">Plan the Simple Project</h2><ol><li>We will create our NextJS project.</li><li>Edit the home component</li><li>Create a component that we will load with lazy loading</li><li>Create a loader that will show on screen while loading</li><li>A middleware to test how middleware works.<br><br></li></ol><p><strong>Create a NextJS project with this command and edit the index.js</strong></p><pre><code class="language-shell">npx create-next-app ./</code></pre><p>Paste this code in <strong>index.js :</strong></p><pre><code class="language-Javascript">//import lazy and Suspense from react
import React, { Suspense, lazy } from &quot;react&quot;;
import Head from &quot;next/head&quot;;
import styles from &quot;../styles/Home.module.css&quot;;
//load loader component
import IAmALoader from &quot;../component/IAmALoader&quot;;
//the component to load with lazy load
const ILoadWithLazy = lazy(() =&gt; import(&quot;../component/ILoadWithLazy&quot;));
export default function Home() {
//check if next server loading finishes and if window object initializes
const isServer = typeof window === &quot;undefined&quot;;
return (
&lt;div className={styles.container}&gt;
&lt;Head&gt;
&lt;title&gt;Next 12 features&lt;/title&gt;
&lt;meta
name=&quot;description&quot;
content=&quot;Generated by create next app&quot;
/&gt;
&lt;link rel=&quot;icon&quot; href=&quot;/favicon.ico&quot; /&gt;
&lt;/Head&gt;
&lt;main className={styles.main}&gt;
&lt;h1 className={styles.title}&gt;Let&apos;s load the lazy one&lt;/h1&gt;
{
//start suspense code if window object available
!isServer &amp;&amp; (
&lt;Suspense fallback={&lt;IAmALoader /&gt;}&gt;
&lt;ILoadWithLazy /&gt;
&lt;/Suspense&gt;
)
}
&lt;/main&gt;
&lt;/div&gt;
);
}</code></pre><p>Follow the comments in the above code. We loaded React, lazy, and Suspense from React. Then we loaded the loader component, <strong>&#x2018;IAmLoader&#x2019; </strong>and we used React.lazy and loaded the component <strong>&#x2018;ILoadWithLazy&#x2019;. </strong><br></p><p>Then, inside our component, we checked if NextJS has finished loading the page and window object is available with the <strong>isServer</strong> variable. <br></p><p>Now, inside our return component:</p><pre><code class="language-Javascript">{
//start suspense code if window object available
!isServer &amp;&amp; (
&lt;Suspense fallback={&lt;IAmALoader /&gt;}&gt;
&lt;ILoadWithLazy /&gt;
&lt;/Suspense&gt;
)
}</code></pre><p>We checked if the <strong>window</strong> object is available and we started <strong>Suspense. </strong>Suspense takes a fallback component which runs until the page loading finishes. Inside Suspense, we put our components that need to be rendered with lazy loading.<br></p><p>Let&#x2019;s create a component folder outside of our pages folder and create two files, </p><p><strong>IAmLoader.js</strong>, paste this code in it:</p><pre><code class="language-Javascript">const IAmALoader = () =&gt; {
return &lt;p&gt;Loading&lt;/p&gt;;
};
export default IAmALoader;</code></pre><p><strong>ILoadWithLazy.js</strong>, use this code in it:</p><pre><code class="language-Javascript">const ILoadWithLazy = () =&gt; {
return (
&lt;div className=&quot;loaded-comp&quot;&gt;
&lt;h1&gt;I loaded last because I am lazy.&lt;/h1&gt;
&lt;/div&gt;
);
};
export default ILoadWithLazy;</code></pre><p>We just used <strong>React.lazy</strong> and <strong>React.Suspense</strong>. But in a local environment, it will be too fast to be noticed. We may not see if it&#x2019;s loading lazily on a local server. So, let&#x2019;s quickly start a server on Qoddi app platform and test our code. For more information on how Qoddi deploys NodeJS apps, visit: <a href="https://devcenter.qoddi.com/node-js/">https://devcenter.qoddi.com/node-js/</a> <br></p><h2 id="deploy-to-qoddi">Deploy to Qoddi</h2><p>Qoddi supports Next 12 out of the box.<br>Go to your Qoddi dashboard and create a new app.<br><br>Next, click on the GitHub button, and select your repository<strong> </strong>from the dropdown. Go next and select the branch name. <br><br>And finally, launch your app. Now, while Qoddi builds your app, let&#x2019;s add the middleware features.<br></p><h2 id="next-12-middleware">Next 12 Middleware</h2><p>Add a <strong>_middleware.js</strong> in your pages folder, this will run on each request to the website because it is on the main pages directory. You can also have middlewares in other directories that will run only on pages placed under that same directory. That means middleware in NextJS follows the top-down rule. It runs for each request below the folder, not above.<br></p><pre><code class="language-Javascript">const FirstMiddleware = (req, ev) =&gt; {
const checkNothing = true;
if (!checkNothing) {
return new Response(&quot;Hello World&quot;);
}
return console.log(&quot;hi&quot;);
};
export default FirstMiddleware;</code></pre><p>Now, also push this code to git. Q0ddi will detect the change, and rebuild your app with your new code without you doing anything. <br>This will log to the console on each request. But, if you have <strong>checkNothing </strong>to <strong>false, </strong>it will return <em>Hello World </em>to the browser and won&#x2019;t show any page on any route.</p>]]></content:encoded></item><item><title><![CDATA[Create a Reusable Text Input With React Hook Form]]></title><description><![CDATA[<h3 id="deploy-your-react-and-node-app-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your React and Node app in seconds, with no infrastructure to manage. <a href="https://qoddi.com">Qoddi App Platform is free for developers! Create an account today.</a></h3><p></p><p>Sometimes, managing several input fields gets crazy complex. You may need to recreate the same thing for each form and that&#x2019;s can be really</p>]]></description><link>https://blog.qoddi.com/create-a-reusable-text-input-with-react-hook-form/</link><guid isPermaLink="false">61a2c315d9a71d000117c623</guid><category><![CDATA[code]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[ReactJS]]></category><category><![CDATA[Jamstack]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Sun, 28 Nov 2021 00:06:20 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2021/11/reactjs.png" medium="image"/><content:encoded><![CDATA[<h3 id="deploy-your-react-and-node-app-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your React and Node app in seconds, with no infrastructure to manage. <a href="https://qoddi.com">Qoddi App Platform is free for developers! Create an account today.</a></h3><img src="https://blog.qoddi.com/content/images/2021/11/reactjs.png" alt="Create a Reusable Text Input With React Hook Form"><p></p><p>Sometimes, managing several input fields gets crazy complex. You may need to recreate the same thing for each form and that&#x2019;s can be really time-consuming. </p><p>With a reusable Text Input in React, you can create just one input element in just one component and reuse it everywhere in any form. Let&#x2019;s do this.<br></p><p><strong>Prerequisites</strong></p><ol><li>Understanding of React and how forms work in React</li><li>A free <a href="https://qoddi.com/?t=reactpost">Qoddi.com</a> account to deploy your code<br></li></ol><h2 id="react-form-handle">React form Handle</h2><p>You must have seen this code:</p><pre><code class="language-javascript">//The useState Hook
const [textValue, textValueSet] = useState(&#x2018;&#x2019;)

//onChange Handler
const handleForm = (event)=&gt;{
	textValueSet(event.target.value)
}

return(
	//input field
&lt;input type=&#x201D;text&#x201D; name=&#x201D;textField&#x201D; onChange={handleForm} value={textValue} &gt;
 ) 
</code></pre><p>First, we create a useState hook to store input value. Next, we set the input field value to the useState hook. <br><br>Then, in the input form a onChange handler sets the typed text to useState hook.<br></p><h2 id="react-hook-form">React Hook Form</h2><p>React Hook form is a great library to handle forms. Install it with:</p><pre><code class="language-shell">npm i react-hook-form </code></pre><p>Import react-hook-form at the top of your code:</p><pre><code class="language-javascript">import {useForm} from &#x2018;react-hook-form
</code></pre><p>In your <em>App </em>component, call and destruct <em>useForm</em> like this:</p><pre><code class="language-javascript">const App = ()=&gt;{
	const {register} = useForm()
} 
</code></pre><p>Now, use <strong>register</strong> in your component&#x2019;s <em>return </em>statement:</p><pre><code class="language-javascript">return(
	//input field
&lt;input {...register(&#x2018;textField&#x2019;)}&gt;
 ) 
</code></pre><p>No need to have any more extra data there. Super cool, huh!</p><p>Inside the register call, the argument is the name of the input name. React hook form will build everything with this one single data. </p><p>You can add extra features. Ex - to make a required field, you need to do this:</p><pre><code class="language-javascript">return(
	//input field
&lt;input {...register(&#x2018;textField&#x2019;, {required: true})}&gt;
 ) 
</code></pre><p>Let&#x2019;s add a placeholder, max, and min length:</p><pre><code class="language-javascript">return(
	//input field
&lt;input placeholder=&#x201D;Text Field&#x201D; {...register(&#x2018;textField&#x2019;, {required: true, maxLength: 20, minLength: 2})}&gt;

 ) 
</code></pre><h2 id="error-handling">Error Handling</h2><p>To handle errors, we use the useFormState custom hooks from React Hook Form. formState subscribes to different form states of the plugin. We can subscribe to <em>errors</em> state like this:</p><pre><code class="language-javascript">const {register, formState : {errors} } = useForm()
</code></pre><p>Let&#x2019;s fill our input with error messages:</p><pre><code class="language-javascript">return(
	//input field
&lt;div className=&#x201D;form-field&#x201D;&gt;
&lt;input placeholder=&#x201D;Text Field&#x201D; {...register(&#x2018;textField&#x2019;, {
required: {
value: true,
message: &#x201C;This is required&#x201D;
}, 
maxLength: {
value: 20,
message: &#x201C;Value must be maximum 20&#x201D;
}, 
minLength: {
value: 2,
message: &#x201C;Value must be minimum 2&#x201D;
},
})}&gt;
&lt;p&gt;{
//If error exists in the textField
errors.[textField] &amp;&amp; errors[textField].message
}&lt;/p&gt; 
&lt;/div&gt;


 ) 
</code></pre><p>First, we added value and message property to our validators. Error state checks for the value and message property, if the value doesn&#x2019;t match it shows an error message.</p><p>Then we show the error message under the input field. It will show only if any error exists for the field name.<br></p><h2 id="reusable-input-component">Reusable Input Component</h2><p>To create an error message, let&apos;s create a <strong>TextInput.js</strong> component. <br><br>Each time this component gets used in a form, it may have different maxLength, minLength, message, required property value. </p><p>So, we will let the component receive some props - fieldName (name of the input field), errors from the useForm, placeHolder, isRequired, maximLength and minimLength:</p><pre><code class="language-javascript">const TextInput = ({fieldName, register, errors, placeHolder, isRequired, maximLength, minimLength })=&gt;{
	return(
	//input field
	
&lt;div className=&#x201D;field-name&#x201D;&gt;
&lt;input placeholder= {placeHolder} {...register(fieldName, {
required: {
value: isRequired,
message: &#x201C;This is required&#x201D;
}, 
maxLength: {
value: maximLength,
message: `Value must be maximum ${maximLength}`
}, 
minLength: {
value: minimLength,
message: `Value must be minimum ${minimLength}`
},
})}&gt;

&lt;p&gt;{
//If error exists in the textField
errors[fieldName] &amp;&amp; errors[fieldName].message}&lt;/p&gt;
&lt;div&gt;

 ) 
} 
</code></pre><p>Now, we can import this component and use it in our APP component. Let&#x2019;s implement this.</p><h2 id="implement-design-and-deploy">Implement, Design, and Deploy</h2><p>First, let&#x2019;s create a NextJS React server. Open a folder and open a terminal window. Run:</p><pre><code class="language-shell">npx create-next-app ./ -y  
npm i react-hook-form@latest
code .
</code></pre><p>In your code editor, remove everything from index.js</p><pre><code class="language-javascript">//Import files in App.js
import Head from &quot;next/head&quot;; 
import styles from &quot;../styles/Home.module.css&quot;; 
import { useForm } from &quot;react-hook-form&quot;; 
import TextInput from &quot;../utils/TextInput&quot;; 

//Define App here
export default function App() { 
//destruct useForm of react hook form
const { register, handleSubmit, formState: { errors }, } = useForm(); 

//This runs on submit
const onSubmit = (data) =&gt; { 
console.log(data); 
}; 

//returns the App component
return ( 
	//Form element
&lt;form onSubmit={handleSubmit(onSubmit)}&gt; 

	{//Write TextInput component here and give value to all props
}
&lt;TextInput 
fieldName=&quot;textField&quot; 
register={register} 
errors={errors} 
placeHolder=&quot;Text Field&quot; 
isRequired={true} 
maximLength={20} 
minimLength={2} 
/&gt; 

	//Submit the form
&lt;input type=&quot;submit&quot; value=&quot;Submit to Console&quot; /&gt; 
&lt;/form&gt; 
);
 }
</code></pre><p>Create a utils folder in your root project directory and create a <strong>TextInput.js</strong> in it. Paste this code in this file:</p><pre><code class="language-javascript">const TextInput = (
{ fieldName, register, errors, placeHolder, isRequired, maximLength, minimLength }
) =&gt; { 

return ( 

//Input field
&lt;div className=&quot;form-field&quot;&gt; 
&lt;input 
placeholder={placeHolder} {...register(fieldName, { 
required: { 
value: isRequired, 
message: &quot;This is required&quot;, 
}, 
maxLength: { 
value: maximLength, 
message: `Value must be maximum ${maximLength}`, 
}, 
minLength: { 
value: minimLength, 
message: `Value must be minimum ${minimLength}`, 
}, 
}
)} 
/&gt; 

&lt;p&gt; { 

//Shows if error exist
errors[fieldName] &amp;&amp; errors[fieldName].message 

} &lt;/p&gt; 
&lt;/div&gt; ); 
}; 

export default TextInput;
</code></pre><p><strong>Now, build the code and check the input field and its error handling.</strong></p><figure class="kg-card kg-image-card"><img src="https://blog.qoddi.com/content/images/2021/11/Screen-Shot-2021-11-27-at-7.04.06-PM.png" class="kg-image" alt="Create a Reusable Text Input With React Hook Form" loading="lazy" width="2000" height="289" srcset="https://blog.qoddi.com/content/images/size/w600/2021/11/Screen-Shot-2021-11-27-at-7.04.06-PM.png 600w, https://blog.qoddi.com/content/images/size/w1000/2021/11/Screen-Shot-2021-11-27-at-7.04.06-PM.png 1000w, https://blog.qoddi.com/content/images/size/w1600/2021/11/Screen-Shot-2021-11-27-at-7.04.06-PM.png 1600w, https://blog.qoddi.com/content/images/size/w2400/2021/11/Screen-Shot-2021-11-27-at-7.04.06-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>We quickly created a reusable Text Input we can use anywhere we want inside our React.JS app.</p><p>The easiest way to deploy your code on a live platform is with <a href="https://qoddi.com">Qoddi.com</a>: Qoddi is free for developers and can scale indefinitely for production apps!</p>]]></content:encoded></item><item><title><![CDATA[Connect to Postgres from Rust with Actix and Diesel]]></title><description><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a><br></h3><p>Qoddi apps can communicate with each other inside the same stack using Qoddi&apos;s internal network capabilities: an ultra-fast internal network between apps installed inside the same cluster.</p>]]></description><link>https://blog.qoddi.com/connect-to-postgres-from-rust-actix-with-diesel/</link><guid isPermaLink="false">61931def61282600011db941</guid><category><![CDATA[code]]></category><category><![CDATA[Rust]]></category><category><![CDATA[Databases]]></category><dc:creator><![CDATA[Qoddi]]></dc:creator><pubDate>Tue, 16 Nov 2021 03:29:08 GMT</pubDate><media:content url="https://blog.qoddi.com/content/images/2021/11/rust_2-1.png" medium="image"/><content:encoded><![CDATA[<h3 id="deploy-your-code-in-seconds-with-no-infrastructure-to-manage-qoddi-app-platform-is-free-for-developers-create-an-account-today">Deploy your code in seconds, with no infrastructure to manage. <a href="https://qoddi.com/">Qoddi App Platform is free for developers! Create an account today.</a><br></h3><img src="https://blog.qoddi.com/content/images/2021/11/rust_2-1.png" alt="Connect to Postgres from Rust with Actix and Diesel"><p>Qoddi apps can communicate with each other inside the same stack using Qoddi&apos;s internal network capabilities: an ultra-fast internal network between apps installed inside the same cluster. In this tutorial, we will learn how to connect a Rust app to a Postgres database using Actix with Diesel</p><p>This post describes the creation of a Qoddi app along with a Postgres SQL, you can use an external database (like an AWS RDS database or a database located on another Qoddi cluster) using its web address.</p><p>This tutorial uses ENV variables to set and uses the database, you can connect to an external database by setting the DATABASE_URL ENV variable :</p><pre><code>DATABASE_URL=postgres://[user]:[password]@[internal_name or URL]/database</code></pre><p>Actix is a great RUST framework used to increase the capabilities of apps built on Rust.<br> <br>Creating a REST API using RUST is simple. In this tutorial, we will use Diesel, an ORM, and Query builder, that simplifies the uses of databases inside a Rust project.</p><h2 id="prepare-your-app-locally">Prepare your app locally</h2><p>You need to have Rust installed locally. <a href="https://www.rust-lang.org/tools/install">Check this tutorial</a> to install <strong>rustup</strong> to do that easily. <br>It will also install <em>cargo</em>, a package manager to manage rust projects. Simply run:</p><pre><code class="language-shell">cargo new rust-actix-diesel-connect
</code></pre><p><strong>This will create a new project called rust-actix-diesel-connect. Let&#x2019;s update our <em>Cargo.toml,</em> add some dependencies:</strong></p><pre><code class="language-ssh">[package]
name = &quot;rust-actix-diesel-connect&quot;
version = &quot;0.1.0&quot;
edition = &quot;2018&quot;
 
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
[dependencies]
actix-web = &quot;3&quot;
diesel = { version = &quot;1.4.8&quot;, features = [&quot;postgres&quot;, &quot;r2d2&quot;,] }
dotenv = &quot;0.15.0&quot;
r2d2 = &quot;0.8.9&quot;
</code></pre><p>We are using Diesel ORM with postgres with the r2d2 feature enabled.<br><br>R2d2 has a ConnectionManager that can create a connection to a postgres database along with a database pool.</p><p>Now let&apos;s update <strong><em>src/main.rs </em></strong>with this code:</p><pre><code class="language-ssh">use actix_web::{ web, App, HttpServer, HttpResponse, Responder};
use dotenv::dotenv;
use std::env;
 
mod postgres;
 
async fn home() -&gt; impl Responder {
   HttpResponse::Ok().body(&quot;PostgreSQL connected&quot;)
}
 
#[actix_web::main]
async fn main() -&gt; std::io::Result&lt;()&gt; {
   dotenv().ok();
   env::set_var(&quot;RUST_LOG&quot;, &quot;actix_web=debug&quot;);
   let host = env::var(&quot;HOST&quot;).expect(&quot;Host not set&quot;);
   let port = env::var(&quot;PORT&quot;).expect(&quot;Port not set&quot;);
 
   let pool = postgres::get_pool();
   HttpServer::new(move || {
       App::new()
       .data(pool.clone())
           .route(&quot;/&quot;, web::get().to(home))
          
   })
   .bind(format!(&quot;{}:{}&quot;, host, port))?
   .run()
   .await
}
</code></pre><p>Here we are using Actix, dotenv, and standard env library. We are also importing a module called Postgres and we will write our Postgres configuration there.</p><p>In the main function, we created a pool from the Postgres config and inserted that in our actix server data method.</p><p>Now, let&#x2019;s create a <strong>postgres.rs</strong> file and write our postgres connection:</p><pre><code class="language-script">use diesel::pg::PgConnection;
use diesel::r2d2::ConnectionManager;
use dotenv::dotenv;
use r2d2::Pool;
use std::env;
 
// The Postgres-specific connection pool managing all database connections.
pub type PostgresPool = Pool&lt;ConnectionManager&lt;PgConnection&gt;&gt;;
 
pub fn get_pool() -&gt; PostgresPool {
   // it from the environment within this function
   dotenv().ok();
   let url = env::var(&quot;DATABASE_URL&quot;).expect(&quot;no DB URL&quot;);
   let migr = ConnectionManager::&lt;PgConnection&gt;::new(url);
   r2d2::Pool::builder()
       .build(migr)
       .expect(&quot;could not build connection pool&quot;)
}
</code></pre><p>From r2d2 we import ConnectionManager and Pool and create a PostgresPool with it. Our get_pool function simply uses our environment variable DATABASE_URL and creates a new connection to our database.</p><p>Install diesel_cli locally with this command:</p><pre><code class="language-script">cargo install diesel_cli --no-default-features --features postgres</code></pre><h2 id="add-a-procfile-to-your-project">Add a Procfile to your project</h2><p>Procfile is used to let the Qoddi orchestrator how to start and manage your app. &#xA0;<a href="https://devcenter.qoddi.com/rust/ ">Check this tutorial</a> for a more detailed Rust deployment.</p><p>For this app we simply need to add a Procfile to our root app folder with this command:</p><pre><code class="language-shell">web: /workspace/bin/rust-actix-diesel-connect</code></pre><p>Once it&apos;s done, push your code to GitHub or any Git software.</p><h2 id="qoddi-app-with-postgres">Qoddi App with Postgres</h2><p>Create a new Qoddi app and select Postgres as a datastore:</p><figure class="kg-card kg-image-card"><img src="https://blog.qoddi.com/content/images/2021/11/Screen-Shot-2021-11-15-at-10.20.09-PM.png" class="kg-image" alt="Connect to Postgres from Rust with Actix and Diesel" loading="lazy" width="2000" height="1094" srcset="https://blog.qoddi.com/content/images/size/w600/2021/11/Screen-Shot-2021-11-15-at-10.20.09-PM.png 600w, https://blog.qoddi.com/content/images/size/w1000/2021/11/Screen-Shot-2021-11-15-at-10.20.09-PM.png 1000w, https://blog.qoddi.com/content/images/size/w1600/2021/11/Screen-Shot-2021-11-15-at-10.20.09-PM.png 1600w, https://blog.qoddi.com/content/images/size/w2400/2021/11/Screen-Shot-2021-11-15-at-10.20.09-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>Connect your repository to Qoddi using the automatic or manual method. <a href="https://devcenter.qoddi.com/git-set-up-at-app-creation/">Check this tutorial for more information</a>. </p><p>Once your app is built, the connection to the app is made automatically by the builder:</p><p><br>You can edit the <strong>DATABASE_URL</strong> env variable to connect to another database (external or internal to the same stack).</p><p>Code related to this tutorial <a href="https://github.com/qoddiapps/rust_actix_diesel_connect">can be found here</a>.</p><p><br></p><p><br></p>]]></content:encoded></item></channel></rss>