<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Damodar Lohani</title>
    <description>The latest articles on Forem by Damodar Lohani (@lohanidamodar).</description>
    <link>https://forem.com/lohanidamodar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F551623%2Fd6834701-4563-4984-8f1d-7c6735acd3b6.jpg</url>
      <title>Forem: Damodar Lohani</title>
      <link>https://forem.com/lohanidamodar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lohanidamodar"/>
    <language>en</language>
    <item>
      <title>Appwrite is now available as a one-click app on the Akamai cloud (Linode) marketplace</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Thu, 13 Jul 2023 06:44:23 +0000</pubDate>
      <link>https://forem.com/appwrite/appwrite-is-now-available-as-a-one-click-app-on-the-akamai-cloud-linode-marketplace-5ajp</link>
      <guid>https://forem.com/appwrite/appwrite-is-now-available-as-a-one-click-app-on-the-akamai-cloud-linode-marketplace-5ajp</guid>
      <description>&lt;p&gt;We have some exciting news. Appwrite, an open-source end-to-end backend server, is now available as a One-Click app on the &lt;a href="https://www.linode.com/marketplace/apps/"&gt;Akamai Marketplace&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rua2d78invh0d6yvx8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rua2d78invh0d6yvx8l.png" alt="Appwrite on Akamai marketplace" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For those who are not yet acquainted, &lt;a href="https://appwrite.io/"&gt;Appwrite&lt;/a&gt; is an open-source back-end-as-a-service that abstracts all the complexity of building a modern application by providing you with a set of REST APIs, GraphQL APIs and Realtime APIs for your core back-end needs. Appwrite takes the heavy lifting for developers and handles user authentication and authorization, databases, file storage, cloud functions, webhooks, and more!&lt;/p&gt;

&lt;p&gt;By making Appwrite available on the Akamai Marketplace, self-hosting a fully-featured backend for your web, mobile, or flutter app is even simpler and faster!&lt;/p&gt;

&lt;p&gt;To help you get started, here is a step-by-step guide on creating and deploying Appwrite from the Akamai Marketplace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-step guide
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Access the Akamai Marketplace&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Log into your Linode account and navigate to the &lt;a href="https://www.linode.com/marketplace/apps/"&gt;marketplace apps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rua2d78invh0d6yvx8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rua2d78invh0d6yvx8l.png" alt="Appwrite on Akamai marketplace" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Select appwrite&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Find the Appwrite One-Click app, and select it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgr30wl76aisu59y4vtku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgr30wl76aisu59y4vtku.png" alt="Appwrite" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Deploy the app&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click on the deploy this app button which should take you to the Akamai cloud create, where Appwrite should already be selected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpgplmdffut41c2u4h4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpgplmdffut41c2u4h4v.png" alt="Create new appwrite instance" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Configure your appwrite instance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Scroll below and update configurations. You'll need to make a few choices regarding the configuration of your Appwrite instance, such as the region where your Linode will be hosted, the Linode plan, and the root password or SSH keys. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn07rymdhv7t801dsjv3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn07rymdhv7t801dsjv3m.png" alt="Configuration" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have provided all the details, click the Create Linode button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvz35xggp3hs82nqdhhoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvz35xggp3hs82nqdhhoc.png" alt="Create" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That should create your Akamai server for Appwrite.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlwll4k5jfjdopsn09yk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlwll4k5jfjdopsn09yk.png" alt="Server created" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the Linode is ready and running, give it a minute or two to complete the Appwrite installation. Finally, you can access your Appwrite console using the server's IP address to create a new account to manage your Appwrite instance. You can also assign domains and update other settings. Learn more about self-hosted Appwrite in our &lt;a href="https://appwrite.io/docs/self-hosting"&gt;self-hosting documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That's it! You'll have your Appwrite instance running on an Akamai server in minutes. Using Appwrite on the Akamai cloud, you can rapidly prototype and deploy applications while maintaining full control over data, user privacy, and UX. Appwrite also supports many popular technologies, including Flutter, iOS, Android, and JavaScript.&lt;/p&gt;

&lt;p&gt;We're excited to see what amazing projects you'll create with the power of Appwrite and Akamai cloud at your fingertips!&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🚀 &lt;a href="https://appwrite.io/docs/getting-started-for-web"&gt;Getting Started Tutorial&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://github.com/appwrite/appwrite"&gt;Appwrite GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📜 &lt;a href="https://appwrite.io/docs"&gt;Appwrite Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://discord.gg/appwrite"&gt;Discord Community&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>news</category>
      <category>appwrite</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Join our #30DaysMasterFlutter Challenge and Learn Flutter &amp; Dart in One Month!</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Mon, 08 May 2023 02:41:54 +0000</pubDate>
      <link>https://forem.com/lohanidamodar/join-our-30daysmasterflutter-challenge-and-master-flutter-dart-in-one-month-16be</link>
      <guid>https://forem.com/lohanidamodar/join-our-30daysmasterflutter-challenge-and-master-flutter-dart-in-one-month-16be</guid>
      <description>&lt;p&gt;Greetings, Aspiring App Developers! 📱&lt;/p&gt;

&lt;p&gt;We're excited to announce that our &lt;a href="https://appwriters.dev/30days/flutter"&gt;#30DaysMasterFlutter &lt;/a&gt;challenge has finally begun, and it's your opportunity to master Flutter &amp;amp; Dart. This project-based course 📚 is completely free and provides you with the foundation to learn one of the most exciting technologies in the app development industry.&lt;/p&gt;

&lt;p&gt;For the next 30 days, we will focus on a significant concept each day and give you the resources to comprehend and implement them. You'll not only learn these concepts but also use them to create real-world projects. 💻🌍 This course is suitable for beginners and experienced programmers alike.&lt;/p&gt;

&lt;p&gt;Don't worry about getting stuck. Our enthusiastic community of learners 👥 is there to support you and answer your queries, share insights, and work collaboratively.&lt;/p&gt;

&lt;p&gt;This journey is about learning, building, and growing together. So let's embark on this adventure and come out as skilled app developers. 🎉&lt;/p&gt;

&lt;p&gt;Remember to use the hashtag &lt;strong&gt;#30DaysMasterFlutter&lt;/strong&gt; on social media to share your progress each day. We can't wait to see your accomplishments! 🏅&lt;/p&gt;

&lt;p&gt;Are you ready to join us? &lt;a href="https://appwriters.dev/30days/flutter"&gt;Let's dive in and start coding!&lt;/a&gt; 🤓&lt;/p&gt;

&lt;p&gt;Happy Learning! 🎓&lt;/p&gt;

&lt;p&gt;Originally posted on &lt;a href="https://appwriters.dev/blog"&gt;appwriters.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
      <category>news</category>
    </item>
    <item>
      <title>Protect Your Applications from Bad Passwords - Introducing Password History</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Thu, 13 Apr 2023 00:31:19 +0000</pubDate>
      <link>https://forem.com/appwrite/protect-your-applications-from-bad-passwords-introducing-password-history-19n5</link>
      <guid>https://forem.com/appwrite/protect-your-applications-from-bad-passwords-introducing-password-history-19n5</guid>
      <description>&lt;p&gt;If you are a developer, security is definitely one of your top concerns. When we built Appwrite, we wanted to help developers build secure applications faster. And we are always looking out for features that make our open-source back-end services more secure.&lt;/p&gt;

&lt;p&gt;However we may write the most secure APIs and applications, but if the end-user chooses a terrible password, all our work would be for nothing. Users selecting a simple, easily guessed password or repeating the same password over and over again, even when changing, are things that make even the most secure applications vulnerable. With Appwrite version 1.3.0, we introduce a password history feature to tackle the problem where users repeatedly use the same password. We also introduce a password dictionary feature to tackle weak passwords, which is talked about in &lt;a href="https://dev.to/appwrite/introducing-password-dictionary-in-appwrite-a-new-layer-of-security-2356"&gt;another article&lt;/a&gt;. In this article, let’s talk about Password History and why it is a valuable tool in your security arsenal.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔐 Password History
&lt;/h2&gt;

&lt;p&gt;Password history is especially important today when online security breaches are becoming more common. By keeping track of their password history, users can ensure they are not repeating their password and also be sure they are safe if there was a data breach previously.&lt;/p&gt;

&lt;p&gt;The newly introduced password history feature is another step in making authentication more secure for end users. With this new feature, you can save users’ last-used passwords and prevent them from reusing them. By default, Password History is disabled and can be enabled through the project’s Auth settings. You can also configure the number of passwords to remember. The maximum number of passwords allowed to save is 20. When you enable this feature, your users cannot reuse passwords they have previously used.&lt;/p&gt;

&lt;p&gt;To configure the password history feature, you can visit Authentication in the dashboard. Under the Security tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3x60l0g8jb23omejlwq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3x60l0g8jb23omejlwq.png" alt="Authentication security" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once there, you can enable password history and set the number of passwords to save. Once you are done, click the Update button to save the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj6l5qlrvrtc9wp8q3gc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj6l5qlrvrtc9wp8q3gc.png" alt="Enable password history feature" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Overall, the Password History features, together with &lt;a href="https://dev.to/appwrite/introducing-password-dictionary-in-appwrite-a-new-layer-of-security-2356"&gt;the password dictionary&lt;/a&gt; feature introduced in Appwrite 1.3, is a valuable tool for improving online security and preventing users from using vulnerable and repeated passwords. By enabling this feature, your users can ensure they are using strong, unique passwords that have not been previously compromised. If you have any queries or want to learn more about Appwrite, you can use the following resources.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔒 &lt;a href="https://appwrite.io/docs/authentication"&gt;Authentication Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://github.com/appwrite"&gt;Appwrite GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📜 &lt;a href="https://appwrite.io/docs"&gt;Appwrite Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://appwrite.io/discord"&gt;Discord Community&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>appwrite</category>
      <category>opensource</category>
      <category>programming</category>
      <category>news</category>
    </item>
    <item>
      <title>I Built Bitly Clone with Redis, Express Svelte and Node ( RESN)</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Sat, 20 Aug 2022 01:13:31 +0000</pubDate>
      <link>https://forem.com/lohanidamodar/i-built-bitly-clone-with-redis-express-svelte-and-node-resn-4c71</link>
      <guid>https://forem.com/lohanidamodar/i-built-bitly-clone-with-redis-express-svelte-and-node-resn-4c71</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;I always wanted to build my own URL shortener that could give metrics like how many times the URL was visited. I had always been busy to try, but redis hackathon felt like perfect opportunity for me to work on this. So I decide to use this opportunity to build myself a URL shortener. I built it using redis as primary database where it uses Redis JSON to store URL details and RedisTimeSeries to store usage metrics.&lt;/p&gt;

&lt;p&gt;The project has two parts a server, provides REST API and is built using ExpressJS. The server is also responsible to interface with Redis. I'm using official Javascript redis package and Redis OM for Node.js to interface with redis database to save and retrieve data.&lt;/p&gt;

&lt;p&gt;And, another is the client, that is build with Sveltekit. It provides web UI where users can create short URLs and view the metrics in beautiful looking charts.&lt;/p&gt;

&lt;p&gt;You can view the live demo of client at &lt;a href="https://urlui.vercel.app"&gt;https://urlui.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;MEAN/MERN Maverics&lt;/p&gt;

&lt;h3&gt;
  
  
  Video
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lssFG92i9hA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Language
&lt;/h3&gt;

&lt;p&gt;JS/TS/Node.js&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/lohanidamodar"&gt;
        lohanidamodar
      &lt;/a&gt; / &lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner"&gt;
        redis-hack-urlshortner
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      URL Shortener app built for redis x dev hackathon
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
URL Shortener with Node.JS and Redis&lt;/h1&gt;
&lt;p&gt;A URL shortener application build with ExpressJS, Redis and SvelteKit. Shorten URLs and also get link visit history.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://urlui.vercel.app" rel="nofollow"&gt;Live Demo&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Table of Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#screenshots"&gt;Screenshots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#overview-video"&gt;Overview video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#how-it-works"&gt;How it works&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#how-the-data-is-stored"&gt;How the data is stored:&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#how-the-data-is-accessed"&gt;How the data is accessed:&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#how-to-run-it-locally"&gt;How to run it locally?&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#prerequisites"&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#local-installation"&gt;Local installation&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#running-the-server"&gt;Running the server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#running-the-client"&gt;Running the Client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#environment-variables"&gt;Environment Variables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#deployment"&gt;Deployment&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#vercel"&gt;Vercel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#lets-get-connected"&gt;Let's get connected:&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#more-information-about-redis-stack"&gt;More Information about Redis Stack&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lohanidamodar/redis-hack-urlshortner#getting-started"&gt;Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Screenshots&lt;/h2&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://user-images.githubusercontent.com/6360216/185554653-0db5bb38-f744-4e7c-9fbb-bdc91df8598d.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sVEQXO4L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/6360216/185554653-0db5bb38-f744-4e7c-9fbb-bdc91df8598d.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://user-images.githubusercontent.com/6360216/185554679-860051b6-734b-42f6-b0b4-039613537236.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cxrUHza2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/6360216/185554679-860051b6-734b-42f6-b0b4-039613537236.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://user-images.githubusercontent.com/6360216/185554696-f3ae20d7-d385-4c0b-8784-0d0271ec0464.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iEimv72Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/6360216/185554696-f3ae20d7-d385-4c0b-8784-0d0271ec0464.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Overview video&lt;/h2&gt;
&lt;p&gt;Here's a short video that explains the project and how it uses Redis:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=lssFG92i9hA" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/667e56ab5682b8fdb0b65962e095a3cb107b28c0b35dd1f257c4231d03da096b/68747470733a2f2f692e7974696d672e636f6d2f76692f6c737346473932693968412f6d617872657364656661756c742e6a7067" alt="Embed your YouTube video"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
How it works&lt;/h2&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://user-images.githubusercontent.com/6360216/185571798-01d76032-e03a-4852-bb84-005a243183ca.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IOLFWSaU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/6360216/185571798-01d76032-e03a-4852-bb84-005a243183ca.png" alt="Architecture Diagram"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
How the data is stored:&lt;/h3&gt;
&lt;p&gt;The project uses redis json to store Url records. Each record has following properties&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;originalUrl: string&lt;/li&gt;
&lt;li&gt;shortName: string&lt;/li&gt;
&lt;li&gt;createdAt: date&lt;/li&gt;
&lt;li&gt;updatedAt: date&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To easily work with redis project uses &lt;a href="https://github.com/redis/redis-om-node"&gt;Redis OM for Node.js&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Schema definition&lt;/p&gt;
&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// server/app/om/url.js&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-v"&gt;Entity&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-v"&gt;Schema&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'redis-om'&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s1"&gt;client&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'./client.js'&lt;/span&gt;
&lt;span class="pl-k"&gt;class&lt;/span&gt; &lt;span class="pl-v"&gt;Url&lt;/span&gt; &lt;span class="pl-k"&gt;extends&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lohanidamodar/redis-hack-urlshortner"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FJEUyiYg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9z159kfbwdv06bqp7d2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FJEUyiYg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9z159kfbwdv06bqp7d2o.png" alt="Architecture Diagram" width="880" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2_7-BiVN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4dt2wr5ufuse1zvwmvjk.png" alt="Home Page" width="880" height="560"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Home Page&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9BN7DlL_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sj33yjz63jzqngbfwvwp.png" alt="Create new" width="880" height="560"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Create new Short URL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e4H_K6QV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p4jg8gz7g3yh52j967k6.png" alt="URL History" width="880" height="560"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;History&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KP4eMYGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1i7lzt2ilmv3j7z9m5w1.png" alt="QR Code" width="880" height="560"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;QR Code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LSLfgfb0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmdghh6x81zb6tzm0jdj.png" alt="Metrics" width="880" height="560"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hourly and Daily Metrics using RedisTimeSeries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Check out &lt;a href="https://redis.io/docs/stack/get-started/clients/#high-level-client-libraries"&gt;Redis OM&lt;/a&gt;, client libraries for working with Redis as a multi-model database.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Use &lt;a href="https://redis.info/redisinsight"&gt;RedisInsight&lt;/a&gt; to visualize your data in Redis.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Sign up for a &lt;a href="https://redis.info/try-free-dev-to"&gt;free Redis database&lt;/a&gt;.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>redishackathon</category>
      <category>javascript</category>
      <category>svelte</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Appwrite Loves Open Source: Why I Chose to Support Provider and Riverpod</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Mon, 01 Aug 2022 00:34:22 +0000</pubDate>
      <link>https://forem.com/lohanidamodar/appwrite-loves-open-source-why-i-chose-to-support-provider-and-riverpod-16ag</link>
      <guid>https://forem.com/lohanidamodar/appwrite-loves-open-source-why-i-chose-to-support-provider-and-riverpod-16ag</guid>
      <description>&lt;p&gt;Open-source is at the ❤️ of everything we do at &lt;a href="https://appwrite.io"&gt;Appwrite&lt;/a&gt;, and we want to enable and foster the open-source community that helped us grow to more than 20,000 stars on GitHub.&lt;br&gt;
Open-source projects require a great deal of effort to maintain and grow. We use open-source tools every day to build Appwrite, and we want to help our community. To give back, each Appwrite engineer gets to pick an open-source project for Appwrite to sponsor for one year.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 State Management in Flutter
&lt;/h2&gt;

&lt;p&gt;There are tons of choices when it comes to state management in Flutter. However, for me and my projects, none have been better than the &lt;a href="https://pub.dev/packages/provider"&gt;provider&lt;/a&gt;, and recently the &lt;a href="https://pub.dev/packages/riverpod"&gt;riverpod&lt;/a&gt;, a complete rewrite of provider from the same maintainer. Provider and riverpod both are straightforward to get started with yet pretty powerful to handle large applications and complex use cases. They are easily testable and maintainable. I like provider/riverpod because compared to most of the state management solutions for Flutter, these two have fewer boilerplate codes. The extra bit of code that I have to write for state management with provider/riverpod is minimal—giving me a maintainable code and allowing me to build excellent applications in record time. I am thankful for this package every time I write a Flutter project.&lt;/p&gt;

&lt;p&gt;Apart from riverpod and provider, &lt;a href="https://github.com/rrousselGit"&gt;Remi&lt;/a&gt; maintains other excellent and helpful Flutter packages like &lt;a href="https://github.com/rrousselGit/flutter_hooks"&gt;flutter_hooks&lt;/a&gt; and &lt;a href="https://github.com/rrousselGit/freezed"&gt;freezed&lt;/a&gt; to make the Flutter application robust. I am so excited to choose to sponsor him and his projects which I have been using a lot from day one for my Flutter projects. I thank Appwrite for this great opportunity.&lt;/p&gt;

&lt;h2&gt;
  
  
  ☢️ Open-source Software (OSS) Is Hard
&lt;/h2&gt;

&lt;p&gt;Since Appwrite is open-source, we understand the challenges that OSS projects face. If you fall in love ❤️ with an open-source project (like we have), consider checking out ways to contribute. Most OSS projects happily accept contributions in their own way, whether they be in the form of commits, bug 🐛 reports, advocacy, or even monetary 💰 support. If you love Provider/Riverpod, consider joining us as a sponsor. Or, if you're interested in contributing to Appwrite, check out our &lt;a href="https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md"&gt;contribution guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Learn More about Appwrite
&lt;/h2&gt;

&lt;p&gt;Appwrite is an open-source Backend-as-a-Service (BaaS), packaged as a set of Docker microservices, to give developers of any background the tools necessary to build modern apps quickly and securely.&lt;/p&gt;

&lt;p&gt;Check out Appwrite as the backend for your next &lt;a href="https://appwrite.io/docs/getting-started-for-web"&gt;web&lt;/a&gt;, &lt;a href="https://appwrite.io/docs/getting-started-for-flutter"&gt;Flutter&lt;/a&gt;, or &lt;a href="https://appwrite.io/docs/getting-started-for-server"&gt;server-side&lt;/a&gt; application. Here are some handy links for more information:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md"&gt;Appwrite Contribution Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord"&gt;Appwrite Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite"&gt;Appwrite Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs"&gt;Appwrite Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>appwrite</category>
      <category>opensource</category>
      <category>dart</category>
      <category>flutter</category>
    </item>
    <item>
      <title>Appwrite Phone Authentication with Flutter</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Wed, 29 Jun 2022 00:18:45 +0000</pubDate>
      <link>https://forem.com/appwrite/appwrite-phone-authentication-with-flutter-3jii</link>
      <guid>https://forem.com/appwrite/appwrite-phone-authentication-with-flutter-3jii</guid>
      <description>&lt;p&gt;Phone authentication is one of the most reliable authentication methods for mobile applications. And Appwrite has now introduced phone authentication in our recent release. In this article, we will learn how to implement Appwrite’s phone authentication in our Flutter applications.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;New to Appwrite?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://appwrite.io/" rel="noopener noreferrer"&gt;Appwrite&lt;/a&gt; is an open-source back-end-as-a-service that abstracts all the complexity of building a modern application by providing a set of REST and Realtime APIs for your core back-end needs. Appwrite minimizes the heavy lifting for developers and handles user authentication and authorization, databases, file storage, cloud functions, webhooks, and much more!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Access to an Appwrite project or permission to create one. If you don’t already have an Appwrite server running, follow the official&lt;a href="https://appwrite.io/docs/installation" rel="noopener noreferrer"&gt; installation tutorial&lt;/a&gt; for setup instructions.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://flutter.dev" rel="noopener noreferrer"&gt;Flutter&lt;/a&gt;-configured development machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Twilio Account Setup
&lt;/h2&gt;

&lt;p&gt;We first need to set up a phone service provider for authentication. Twilio is a popular choice – a Twilio account can provide API access keys, allowing Appwrite to send codes to mobile phones. If you don’t have an existing Twilio account, you can visit &lt;a href="https://www.twilio.com/try-twilio" rel="noopener noreferrer"&gt;https://www.twilio.com/try-twilio&lt;/a&gt; and create a free account using your email and password. Via email, you will then receive a verification link, clicking on which will verify your Twilio account. It will also ask you to verify your phone number.&lt;/p&gt;

&lt;p&gt;Enter your phone number and click on the &lt;strong&gt;Verify&lt;/strong&gt; button. You will then receive a code via SMS. Enter the received code in Twilio and click &lt;strong&gt;Submit&lt;/strong&gt; to confirm your number.&lt;/p&gt;

&lt;p&gt;On the next screen, enter your choices. It doesn’t matter which coding language you choose, as we will integrate Twilio with Appwrite, so we don’t have to interface with Twilio directly. Next, click on &lt;strong&gt;Get started with Twilio&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8nyorcdmbh684uo4d5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8nyorcdmbh684uo4d5n.png" alt="Twilio Account"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should then be redirected to the Twilio console. Click the &lt;strong&gt;Getting your Twilio number&lt;/strong&gt; button. The initial trial account can only send texts and calls to your verified numbers, and for testing, that’s perfect. However, for production use, you must upgrade your Twilio account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3ygym94mrh5d08y54j9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3ygym94mrh5d08y54j9.png" alt="Twilio Console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see the Account SID, Auth Token, and Phone number in the console. You will need these in the next session to set up Twillio as an SMS provider Appwrite can use. Your Twilio account should now be ready to integrate with Appwrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Appwrite Setup
&lt;/h2&gt;

&lt;p&gt;Follow the &lt;a href="https://appwrite.io/docs/installation" rel="noopener noreferrer"&gt;official guide&lt;/a&gt; to set up and run Appwrite. For Appwrite to know about Appwrite, we need to open the &lt;code&gt;.env&lt;/code&gt; file from the appwrite directory where you installed Appwrite, and update the following environment variables.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

_APP_PHONE_PROVIDER=phone://&amp;lt;ACCOUNT SID&amp;gt;:&amp;lt;AUTH TOKEN&amp;gt;@twilio
_APP_PHONE_FROM=&amp;lt;TWILIO_PHONE_NUMBER&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the environment variables are updated, run the following command from the command line in the installation directory that contains the &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;docker-compose.yml&lt;/code&gt; files.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker-compose up -d


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will restart the containers, providing new values for the environment variables, so Appwrite can connect to Twilio. We are now ready to implement phone authentication in our application. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install and Configure Appwrite’s Flutter SDK&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cloning the project we created for this tutorial lets us skip the setup and UI part, and focus on the main topic. Clone &lt;a href="https://github.com/lohanidamodar/appwrite_phone_auth.git" rel="noopener noreferrer"&gt;https://github.com/lohanidamodar/appwrite_phone_auth.git&lt;/a&gt;. Once cloned, open it in your favorite IDE.&lt;/p&gt;

&lt;p&gt;We will start by adding Appwrite’s SDK as a dependency. Open &lt;code&gt;pubspec.yaml&lt;/code&gt; file and add Appwrite’s SDK under dependencies.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;appwrite&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^6.0.0&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If the IDE doesn’t get dependencies automatically, run the following command from the terminal.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

flutter pub get


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, open &lt;code&gt;lib/providers/app_state.dart&lt;/code&gt; file. This is where we will configure our Appwrite SDK. First, import the appwrite package.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:appwrite/appwrite.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:appwrite/models.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Response type definitions&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the AuthState class, add new properties.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;ChangeNotifier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt;  &lt;span class="n"&gt;_account&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then in the constructor, let’s configure the client and instantiate the account.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

  &lt;span class="n"&gt;AuthState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'YOUR_ENDPOINT'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;YOUR_PROJECT_ID&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the SDK is installed and configured, the final step is adding the platform to our Appwrite project. Open the Appwrite console and choose the project you created for this application. You can find the &lt;strong&gt;Add Platform&lt;/strong&gt; button on the project home page. Click on the &lt;strong&gt;Add Platform&lt;/strong&gt;button and select &lt;strong&gt;New Flutter App&lt;/strong&gt;. In the dialog box that appears, choose the appropriate Flutter platform, assign it a recognizable name, and add the application ID or package name based on the platform. You must complete this step for each Flutter platform you build in your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjb5w83fzq4ved7bo7rld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjb5w83fzq4ved7bo7rld.png" alt="Add Flutter Platform"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Flutter developers can find more detail instructions on using Appwrite in our official&lt;a href="https://appwrite.io/docs/getting-started-for-flutter" rel="noopener noreferrer"&gt; Getting Started for Flutter&lt;/a&gt; guide.&lt;/p&gt;

&lt;p&gt;Now that our SDK is installed and configured, we are ready to implement phone authentication in our application. &lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Session with a Phone
&lt;/h2&gt;

&lt;p&gt;Two steps are needed to create a valid session for users with phone numbers. First, to initiate the session creation process, we will use the setup provider for sending a verification code to the provided phone number. Next, the verification code will confirm and create a valid session for the user. So let’s implement those two methods in our &lt;code&gt;AuthState&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;To initiate the session, we call &lt;code&gt;createPhoneSession&lt;/code&gt; from the account service and pass the &lt;code&gt;userId&lt;/code&gt; and phone numbers. Passing &lt;code&gt;'unique()'&lt;/code&gt; as &lt;code&gt;userId&lt;/code&gt; allows Appwrite to generate a unique Id.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
          &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createPhoneSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;userId:&lt;/span&gt; &lt;span class="s"&gt;'unique()'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;number:&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;AppwriteException&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;isLoggedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;notifyListeners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Calling &lt;code&gt;createPhoneSession&lt;/code&gt; returns a token object with &lt;code&gt;userId&lt;/code&gt;. We save the &lt;code&gt;userId&lt;/code&gt; because we need it to confirm authentication and create a valid session. To do that, we need to call &lt;code&gt;updatePhoneSession&lt;/code&gt; from the account service. Let’s follow the &lt;code&gt;confirmSession&lt;/code&gt; method.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;confirmSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'userId not known, call `createSession` first to get userId'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;notifyListeners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;updatePhoneSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;userId:&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;secret:&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;getAccount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;AppwriteException&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;isLoggedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now let’s call these methods in the appropriate UI. Open &lt;code&gt;lib/login.dart&lt;/code&gt; and find the Login button. In the onPressed action of the button, add the following code after the check.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ref&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AuthState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_phoneController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Navigator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pushNamed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'/verify'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Open &lt;code&gt;lib/verify_phone.dart&lt;/code&gt; and find the Verify button. In the onPressed action of the button, add the following code after the check.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;loggedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ref&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AuthState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;confirmSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loggedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Navigator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pushReplacementNamed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ScaffoldMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;showSnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;content:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AuthState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here we are calling Appwrite with the code received in the SMS. There’s one last thing we need to do -- we need to make a call to get an account. Open &lt;code&gt;lib/providers/app_state.dart&lt;/code&gt; and add the following function.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getAccount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;isLoggedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;notifyListeners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;AppwriteException&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;isLoggedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;notifyListeners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Call this function in the constructor of the &lt;code&gt;AuthState&lt;/code&gt;, so when the application starts, it checks if we already have a valid session. You can now run the application and see the phone authentication in action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That’s how easy it is to set up phone authentication with Appwrite. You can choose between different providers --&lt;a href="https://twilio.com/" rel="noopener noreferrer"&gt;Twilio&lt;/a&gt;, &lt;a href="https://www.telesign.com/" rel="noopener noreferrer"&gt;Telesign&lt;/a&gt;, and &lt;a href="https://www.textmagic.com/" rel="noopener noreferrer"&gt;TextMagic&lt;/a&gt; at the moment. You are also welcome to contribute by adding more providers. To learn more about Appwrite and to integrate it with Flutter, here are a few more resources that might help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs/getting-started-for-flutter" rel="noopener noreferrer"&gt;Getting Started for Flutter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs" rel="noopener noreferrer"&gt;Appwrite Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord" rel="noopener noreferrer"&gt;Appwrite Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite/appwrite" rel="noopener noreferrer"&gt;Appwrite Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>appwrite</category>
      <category>flutter</category>
      <category>dart</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Stripe Payment with Flutter and Appwrite</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Wed, 22 Jun 2022 01:49:22 +0000</pubDate>
      <link>https://forem.com/appwrite/stripe-payment-with-flutter-and-appwrite-2c68</link>
      <guid>https://forem.com/appwrite/stripe-payment-with-flutter-and-appwrite-2c68</guid>
      <description>&lt;p&gt;Stripe is one of the most popular payment providers to accept payments online. In this tutorial, we will integrate Stripe in our Appwrite Store mobile application built with Flutter and receive payments using Stripe. We will be writing the Appwrite cloud function using Dart to process the payments using Stripe.&lt;/p&gt;

&lt;p&gt;If you don't know what &lt;a href="https://appwrite.io" rel="noopener noreferrer"&gt;Appwrite&lt;/a&gt; is, Appwrite is a self-hosted backend-as-a-service platform that provides developers with all the core APIs required to build any application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To continue with this tutorial and take full advantage of it, you need the following things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flutter setup and running - &lt;a href="https://docs.flutter.dev/get-started/install" rel="noopener noreferrer"&gt;https://docs.flutter.dev/get-started/install&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Access to Appwrite project or permission to create one - &lt;a href="https://appwrite.io/docs/installation" rel="noopener noreferrer"&gt;https://appwrite.io/docs/installation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stripe account, you can create one for free - &lt;a href="https://dashboard.stripe.com/register" rel="noopener noreferrer"&gt;https://dashboard.stripe.com/register&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💰 Setup Stripe
&lt;/h2&gt;

&lt;p&gt;Let's start by properly setting up our Stripe account to ensure we have all secrets we need in the future. We will be using test mode for this example, but the same steps could be followed in production mode.&lt;br&gt;
You start by visiting the Stripe website and signing up. Once in the dashboard, you can switch to the Developers page and enter the API keys tab. In there, copy the publishable key as well as a secret key. Click the Reveal key button to copy the secret key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j06f7ljzygt4j5v26wf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j06f7ljzygt4j5v26wf.png" alt="Stripe Setup" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please make sure you turn on the test mode, so we use test keys and not the real keys for testing purposes.&lt;/p&gt;
&lt;h2&gt;
  
  
  🔧 Setup Appwrite
&lt;/h2&gt;

&lt;p&gt;Before we move on, we need to set up an Appwrite project. After following installation instructions and signing up, you can create a project with a custom project ID &lt;code&gt;flutter-stripe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5x9wtmzphdlnc7he034x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5x9wtmzphdlnc7he034x.png" alt="Create Appwrite Project" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the project is created, hop into the Settings page and copy the endpoint, we will need this next to set up our Appwrite CLI.&lt;/p&gt;
&lt;h2&gt;
  
  
  🧑‍💻 CLI Installation
&lt;/h2&gt;

&lt;p&gt;Let's now install the Appwrite CLI, which we will use in the next section to set up the database required for our application.&lt;/p&gt;

&lt;p&gt;Install the CLI using one of the methods from our &lt;a href="https://appwrite.io/docs/command-line#installation" rel="noopener noreferrer"&gt;CLI installation guide&lt;/a&gt;. Once the CLI is installed, you need to log in to authorize CLI and gain access to your Appwrite instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize the client&lt;/span&gt;
appwrite client &lt;span class="nt"&gt;--endpoint&lt;/span&gt; https://&amp;lt;API endpoint&amp;gt;/v1 

&lt;span class="c"&gt;# Login, this command is interactive; login with your console email&lt;/span&gt;
&lt;span class="c"&gt;# and password&lt;/span&gt;
appwrite login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint is the URL you get from the project settings page.&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 Source Code
&lt;/h2&gt;

&lt;p&gt;The source code required for this tutorial is available in the &lt;a href="https://github.com/lohanidamodar/flappwrite-stripe" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. Clone the repository using git or download the zip directly from GitHub and extract. The project comes with an &lt;code&gt;appwrite.json&lt;/code&gt; file. Next, let‘s set up collections. The collection is already defined in the &lt;code&gt;appwrite.json&lt;/code&gt;, and you need to deploy it. Navigate to the folder containing &lt;code&gt;appwrite.json&lt;/code&gt; from your terminal and run the following command to deploy the collection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;appwrite deploy collection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create a new collection in your project, and you can check it via the Appwrite console if you’d like. Next, let's add some products to our products collection.&lt;br&gt;
Let's set up some base products using Appwrite CLI. Still, in the same folder from your terminal, use the following command to add new products.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;appwrite database createDocument &lt;span class="nt"&gt;--collectionId&lt;/span&gt; &lt;span class="s1"&gt;'products'&lt;/span&gt; &lt;span class="nt"&gt;--documentId&lt;/span&gt; &lt;span class="s1"&gt;'unique()'&lt;/span&gt; &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{"name":"Appwrite Backpack","price":20.0, "imageUrl": "https://cdn.shopify.com/s/files/1/0532/9397/3658/products/all-over-print-backpack-white-front-60abc9d286d19_1100x.jpg"}'&lt;/span&gt; &lt;span class="nt"&gt;--read&lt;/span&gt; &lt;span class="s1"&gt;'role:all'&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the same command to add a few more products with a different name, price, and image of your choice, so that we have something to buy in our shop application. Now we have our Appwrite instance ready and some products in our collection for us to buy. Next, let's set up our mobile application built with Flutter that allows us to log in and buy stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠 Flutter Project Set up
&lt;/h2&gt;

&lt;p&gt;In the project you downloaded from GitHub, you can find another folder named &lt;code&gt;flutter_stripe&lt;/code&gt; that contains our Flutter shopping application. Let's set it up and run. First, let's set up the configurations. Open the project in your favorite Flutter IDE. Copy &lt;code&gt;flutter_stripe/lib/utils/config.example.dart&lt;/code&gt; as &lt;code&gt;flutter_stripe/lib/utils/config.dart&lt;/code&gt; and inside it, replace &lt;code&gt;[ENDPOINT]&lt;/code&gt; and &lt;code&gt;[PROJECT_ID]&lt;/code&gt; with your endpoint and project ID that you got from Appwrite project settings page. Replace &lt;code&gt;[STRIPE_PUBLISHABLE_KEY]&lt;/code&gt; with the Stripe's publishable key that you got from the Stripe dashboard starting with &lt;code&gt;sk_test_&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now run the project in your emulator or your device, and you should see the following screen. We have already implemented registration, login, products display, and shopping cart so we can focus on the stripe integration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzjx5a9dbk6fx60ttm3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzjx5a9dbk6fx60ttm3h.png" alt="App screenshots" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can create a new account from the registration page and log in to see the products page. There you can add products to your cart and view your cart. Tapping on the &lt;strong&gt;Checkout&lt;/strong&gt; button in the cart will navigate you to an empty page. Let's implement a checkout page to allow payment with Stripe. First, add the &lt;code&gt;[flutter_stripe](https://pub.dev/packages/flutter_stripe)&lt;/code&gt; package as a dependency in &lt;code&gt;pubspec.yaml&lt;/code&gt; and run &lt;code&gt;flutter pub get&lt;/code&gt; to download the dependencies.&lt;/p&gt;

&lt;p&gt;Next, let’s initialize the stripe SDK. Open &lt;code&gt;flappwrite_stripe/lib/main.dart&lt;/code&gt; and add the following imports.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter_stripe/flutter_stripe.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the main function, initialize the Stripe SDK&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;WidgetsFlutterBinding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ensureInitialized&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;Stripe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;publishableKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;publishableKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Stripe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;merchantIdentifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'merchent.flappwrite.test'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Stripe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;urlScheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'appwrite-callback-&lt;/span&gt;&lt;span class="si"&gt;${config.projectId}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Stripe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;applySettings&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(....);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that Stripe is initialized let's set up the checkout page. Open &lt;code&gt;flappwrite_stripe/lib/screens/checkout.dart&lt;/code&gt; and add &lt;code&gt;CardField&lt;/code&gt; and an &lt;code&gt;ElevatedButton&lt;/code&gt; to confirm the payment as the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:convert'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flappwrite_stripe/providers/cart.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter_riverpod/flutter_riverpod.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter_stripe/flutter_stripe.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:appwrite_auth_kit/appwrite_auth_kit.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CheckoutScreen&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;ConsumerWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;CheckoutScreen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;_cardEditController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CardEditController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WidgetRef&lt;/span&gt; &lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Checkout'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;16.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;[&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authNotifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
              &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authNotifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authNotifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;textTheme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bodyLarge&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;copyWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nl"&gt;fontWeight:&lt;/span&gt; &lt;span class="n"&gt;FontWeight&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SizedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;CardField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;controller:&lt;/span&gt; &lt;span class="n"&gt;_cardEditController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;ListTile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Total Amount"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nl"&gt;trailing:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="err"&gt;\$&lt;/span&gt;&lt;span class="si"&gt;${ref.watch(cartTotalProvider).toStringAsFixed(2)}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;TextStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;fontWeight:&lt;/span&gt; &lt;span class="n"&gt;FontWeight&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;ElevatedButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;onPressed:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;__confirmPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Confirm"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the confirm button is pressed, we need to charge the user for the total amount of products in their shopping cart. So let's begin.&lt;/p&gt;

&lt;p&gt;Let’s define a new method in the widget &lt;code&gt;_confirmPressed&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;_confirmPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WidgetRef&lt;/span&gt; &lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Woops we can't do this yet &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first step here is to get a payment intent by sending Stripe's amount, currency, and customer details, which can only be done from the server-side using Stripe's secret key. So before we proceed further with payment in App, we will write an Appwrite cloud function that will accept the amount to create a payment intent and return the client secret.&lt;/p&gt;

&lt;h2&gt;
  
  
  ☁ Create Payment Cloud Function
&lt;/h2&gt;

&lt;p&gt;We will be using the Appwrite CLI to initialize our function. from the project folder  (the folder that contains &lt;code&gt;appwrite.json&lt;/code&gt;), spin up a terminal and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;appwrite init &lt;span class="k"&gt;function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's an interactive command that will ask you for a name and runtime. Give it the name &lt;code&gt;createPaymentIntent&lt;/code&gt; and choose &lt;code&gt;Dart 2.16&lt;/code&gt; as the runtime. If &lt;code&gt;Dart 2.16&lt;/code&gt; is not available in the list, it's probably not enabled in your Appwrite server. You can do that by updating the &lt;code&gt;_APP_FUNCTIONS_RUNTIMES&lt;/code&gt; in the &lt;code&gt;.env&lt;/code&gt; file in your Appwrite installation folder. Look at the &lt;a href="[https://appwrite.io/docs/installation/environment](https://appwrite.io/docs/environment-variables)-variables#functions"&gt;environment docs&lt;/a&gt; to learn more about Appwrite’s environment variables.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;pubspec.yaml&lt;/code&gt; and add &lt;code&gt;dart_appwrite&lt;/code&gt; and &lt;code&gt;stripedart&lt;/code&gt; under dependencies. Next, we validate the environment variables required by the function to work properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appwrite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appwrite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'STRIPE_SECRET_KEY'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'STRIPE_PUBLISHABLE_KEY'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Stripe payment keys are missing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_ENDPOINT'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Appwrite endpoint is missing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the environment variables are validated, we can initialize the Appwrite SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_FUNCTION_JWT'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="n"&gt;client&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_ENDPOINT'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_FUNCTION_PROJECT_ID'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setJWT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's get the details of the user executing the function from Appwrite. Let's write a function that gets the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's update our start function to get the user details and check if stripe customer id already exists for the user in their preferences.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_ENDPOINT'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_FUNCTION_PROJECT_ID'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setJWT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;prefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prefs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'stripeCustomerId'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, if the &lt;code&gt;customerId&lt;/code&gt; doesn't exist, we will create a new account; we will set up Stripe SDK and create a customer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'STRIPE_SECRET_KEY'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// create account for customer if it doesn't already exist&lt;/span&gt;
  &lt;span class="kd"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;stripe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;customers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;params:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;prefs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'stripeCustomerId'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;updatePrefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;prefs:&lt;/span&gt; &lt;span class="n"&gt;prefs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we also save customer ID in the user's preference for next-time access.&lt;/p&gt;

&lt;p&gt;Now that we have the customer ID, we can create a payment intent from the amount and the currency provided during function execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;     &lt;span class="c1"&gt;// data provided to the function during execution&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonDecode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_FUNCTION_DATA'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;paymentIntent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;stripe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;paymentIntents&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;params:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"amount"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'amount'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s"&gt;"currency"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'currency'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s"&gt;"customer"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s"&gt;"paymentIntent"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paymentIntent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"client_secret"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paymentIntent&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'client_secret'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our function is now ready, and the complete function looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:convert'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:dart_appwrite/dart_appwrite.dart'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;appwrite&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:dart_appwrite/models.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:stripedart/stripedart.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appwrite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;appwrite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'STRIPE_SECRET_KEY'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'STRIPE_PUBLISHABLE_KEY'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Stripe payment keys are missing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_ENDPOINT'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Appwrite endpoint is missing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// final userId = request.env['APPWRITE_FUNCTION_USER_ID'];&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_FUNCTION_JWT'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="n"&gt;client&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_ENDPOINT'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_FUNCTION_PROJECT_ID'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setJWT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;prefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prefs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'stripeCustomerId'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'STRIPE_SECRET_KEY'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// create account for customer if it doesn't already exist&lt;/span&gt;
  &lt;span class="kd"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;stripe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;customers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;params:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;prefs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'stripeCustomerId'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;updatePrefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;prefs:&lt;/span&gt; &lt;span class="n"&gt;prefs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonDecode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'APPWRITE_FUNCTION_DATA'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;paymentIntent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;stripe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;paymentIntents&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;params:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"amount"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'amount'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s"&gt;"currency"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'currency'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s"&gt;"customer"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s"&gt;"paymentIntent"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paymentIntent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"client_secret"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paymentIntent&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'client_secret'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's deploy the function using the Appwrite CLI. Still, in the project folder containing &lt;code&gt;appwrite.json&lt;/code&gt;, use the following command to deploy the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;appwrite&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interactive command allows you to choose the functions to deploy. We can use space to select that function and press return to deploy as we have only one. If you now go to your Appwrite console and tap on the Functions from the sidebar, you should see your function in the list. Tap on the Settings button for the function and in the overview, make sure your function is built and ready for execution. If the build has failed, check the logs for the build to figure out what happened.&lt;/p&gt;

&lt;p&gt;Finally, we need to set up the function's environment variable. Open your function's settings page and scroll below to find the &lt;strong&gt;Variables&lt;/strong&gt; section. Please tap on the add variable button, add three variables as &lt;code&gt;STRIPE_SECRET_KEY&lt;/code&gt;, &lt;code&gt;STRIPE_PUBLISHABLE_KEY&lt;/code&gt;, and the &lt;code&gt;APPWRITE_ENDPOINT&lt;/code&gt; and give them proper values obtained from Stripe and your Appwrite's endpoint, respectively.&lt;/p&gt;

&lt;p&gt;Now let's get back to our Flutter app to set up the rest of the payment flow. Open &lt;code&gt;flappwrite_stripe/lib/screens/checkout.dart&lt;/code&gt; and add new method in the widget &lt;code&gt;_fetchClientSecret&lt;/code&gt; with the following details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;    &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_fetchClientSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;functions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Functions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authNotifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createExecution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;functionId:&lt;/span&gt; &lt;span class="s"&gt;'[FUNCTION_ID]'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;data:&lt;/span&gt; &lt;span class="n"&gt;jsonEncode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="s"&gt;'currency'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'usd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;'amount'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="nl"&gt;xasync:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonDecode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'client_secret'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can get the &lt;code&gt;FUNCTION_ID&lt;/code&gt; from your &lt;code&gt;appwrite.json&lt;/code&gt; or the function's settings page in the Appwrite console. Finally, we will complete the &lt;code&gt;_confirmPressed&lt;/code&gt; function like the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;_cardEditController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ScaffoldMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;showSnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;content:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Card details not entered completely"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;clientSecret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;fetchClientSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cartTotalProvider&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clientSecret&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ScaffoldMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;showSnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;content:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to fetch client secret"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// you should get proper billing details from the user&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;billingDetails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BillingDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;email:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authNotifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;phone:&lt;/span&gt; &lt;span class="s"&gt;'+48888000888'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;address:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;city:&lt;/span&gt; &lt;span class="s"&gt;'Kathmandu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;country:&lt;/span&gt; &lt;span class="s"&gt;'NP'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;line1:&lt;/span&gt; &lt;span class="s"&gt;'Chabahil, Kathmandu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;line2:&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;state:&lt;/span&gt; &lt;span class="s"&gt;'Bagmati'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;postalCode:&lt;/span&gt; &lt;span class="s"&gt;'55890'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;paymentIntent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Stripe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;confirmPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;PaymentMethodParams&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;billingDetails:&lt;/span&gt; &lt;span class="n"&gt;billingDetails&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;setupFutureUsage:&lt;/span&gt; &lt;span class="n"&gt;PaymentIntentsFutureUsage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;OffSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentIntent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;PaymentIntentsStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Succeeded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cartProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;emptyCart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;ScaffoldMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;showSnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;content:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Success!: The payment was confirmed successfully!"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Navigator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;StripeException&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ScaffoldMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;showSnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SnackBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;content:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;localizedMessage&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our Application is now ready. Run the application, add some products to the shopping cart, and tap checkout. On the checkout page, add a test card details &lt;code&gt;4242 4242 4242 4242&lt;/code&gt;, and any valid validity date from the future, and any three-digit number is CCV. Finally, when you tap submit, you should be able to confirm the payment and see that you have received payment in the Stripe dashboard. That’s it; you can now build an application that can accept payment from your users.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope you enjoyed this tutorial. You can find the complete code of this project in the &lt;a href="https://github.com/lohanidamodar/flappwrite-stripe/tree/final" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. To learn more about Appwrite, you can visit our documentation or join us on our discord.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs" rel="noopener noreferrer"&gt;Appwrite Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord" rel="noopener noreferrer"&gt;Appwrite Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite" rel="noopener noreferrer"&gt;Appwrite Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>flutter</category>
      <category>appwrite</category>
      <category>stripe</category>
      <category>programming</category>
    </item>
    <item>
      <title>Appwrite Zoom OAuth Integration</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Tue, 21 Jun 2022 00:45:13 +0000</pubDate>
      <link>https://forem.com/appwrite/appwrite-zoom-oauth-integration-3gao</link>
      <guid>https://forem.com/appwrite/appwrite-zoom-oauth-integration-3gao</guid>
      <description>&lt;p&gt;We just released Appwrite 0.14, and among other excellent features, we also added Zoom OAuth2 support. This new feature will allow you to build applications with Zoom integrations quickly. In this article, we will learn to set up Zoom authentication in our applications using Appwrite. By the end of this tutorial, you will know that setting up Zoom OAuth using Appwrite is so easy that we can do it in a few minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  New to Appwrite
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://appwrite.io/"&gt;Appwrite&lt;/a&gt; is an open-source back-end-as-a-service that abstracts all the complexity of building a modern application by providing a set of REST and Realtime APIs for your core back-end needs. Appwrite takes the heavy lifting for developers and handles user authentication and authorization, databases, file storage, cloud functions, webhooks, and much more!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along with this tutorial, you’ll need access to an Appwrite project or permissions to create one. If you don’t already have an Appwrite server running, follow the official&lt;a href="https://appwrite.io/docs/installation"&gt; installation tutorial&lt;/a&gt; to set one up.&lt;/p&gt;

&lt;p&gt;You will also need a Zoom account, and if you don’t have one, you can easily create one for free by visiting&lt;a href="https://zoom.us"&gt; https://zoom.us&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Zoom OAuth App
&lt;/h2&gt;

&lt;p&gt;Once we have our Appwrite server up and running, we need to create a Zoom OAuth App from the &lt;a href="https://marketplace.zoom.us"&gt; Zoom App Marketplace&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To create the Zoom OAuth app, log in to your Zoom account in the marketplace and head over to&lt;a href="https://marketplace.zoom.us/develop/create"&gt; https://marketplace.zoom.us/develop/create&lt;/a&gt; and click the &lt;strong&gt;Create&lt;/strong&gt; button on the OAuth app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fciys7wsvtimmmmwshegv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fciys7wsvtimmmmwshegv.png" alt="Zoom OAuth" width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Provide a suitable &lt;strong&gt;name&lt;/strong&gt; for your App and choose the &lt;strong&gt;App Type&lt;/strong&gt; to be &lt;strong&gt;User-managed app&lt;/strong&gt;, and click on the &lt;strong&gt;Create&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2an2y9sw0lc03fc0ka3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2an2y9sw0lc03fc0ka3v.png" alt="Zoom OAuth 2" width="636" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be redirected to your new app’s page, where you can find the &lt;strong&gt;Client ID&lt;/strong&gt; and &lt;strong&gt;Client Secret&lt;/strong&gt;. Copy the production &lt;strong&gt;Client ID&lt;/strong&gt; and &lt;strong&gt;Client Secret&lt;/strong&gt; as we’ll need them in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable Zoom in Appwrite
&lt;/h2&gt;

&lt;p&gt;Next, switch to your Appwrite Dashboard and head over to &lt;strong&gt;Users →Settings.&lt;/strong&gt; This is where we will set up the Zoom OAuth provider. Scroll to the end of the list and enable the Zoom OAuth provider. You’ll be asked to enter the &lt;strong&gt;App ID&lt;/strong&gt; and &lt;strong&gt;App Secret&lt;/strong&gt; from the previous step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F985tz20hz3lb3j20zjx2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F985tz20hz3lb3j20zjx2.png" alt="Zoom OAuth Appwrite" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, copy the redirect URL from Appwrite’s Zoom OAuth Setting dialog and paste it to your Zoom App’s &lt;strong&gt;Redirect URL&lt;/strong&gt; field for both development and production environments, as well as in the &lt;strong&gt;Add allow lists field&lt;/strong&gt;. If your web application is running in a separate domain, you need to add that to the &lt;strong&gt;Add allow lists&lt;/strong&gt; as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvp4oc0p9xeu0l7jplmt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvp4oc0p9xeu0l7jplmt.png" alt="Zoom OAuth Redirect URL" width="800" height="1029"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Sign In With Zoom in Your Project
&lt;/h2&gt;

&lt;p&gt;Once you have set up Zoom OAuth credentials in the Appwrite console, you are ready to implement Zoom Sign In in your project. Let's see how we can do it on various platforms.&lt;/p&gt;

&lt;p&gt;You can use our client SDKs for various platforms to authenticate your users with OAuth2 providers. Before you can authenticate, you need to add our SDK as dependency and configure it with an endpoint and project ID. To learn to configure our SDKs you can follow the getting started guide for each platform. The appropriate links are provided in each section below. Once you have the SDK configured, you can instantiate and call the account service to create a session from the OAuth2 provider. Below are the examples for different platforms to initialize clients and perform OAuth2 login.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web
&lt;/h3&gt;

&lt;p&gt;First you need to add a web platform in your project from the Appwrite console. Adding a web platform allows appwrite to validate the request it receives and also prevents cross origin errors in your browser. In the project settings page, click on &lt;strong&gt;Add Platform&lt;/strong&gt; button and select &lt;strong&gt;New Web App&lt;/strong&gt;. In the dialog box that appears, give a recognizable name to your platform and add the host name of your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn3vkse0vsjahed2i3xw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn3vkse0vsjahed2i3xw.png" alt="Add Web Platform" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the&lt;a href="https://appwrite.io/docs/getting-started-for-web"&gt; Getting Started for Web&lt;/a&gt; guide for detailed instruction on how to use Appwrite with your web application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;appwrite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Appwrite&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;appwrite&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'YOUR_END_POINT'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'YOUR_PROJECT_ID'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;appwrite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createOAuth2Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"zoom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"[YOUR_END_POINT]/auth/oauth2/success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"[YOUR_END_POINT]/auth/oauth2/failure"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Flutter
&lt;/h3&gt;

&lt;p&gt;For Flutter, in Android, to properly handle redirecting your users back to your mobile application after completion of OAuth flow, you need to set the following in your AndroidManifest.xml file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;manifest&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
  &lt;span class="nt"&gt;&amp;lt;application&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ...
    &lt;span class="c"&gt;&amp;lt;!-- Add this inside the `&amp;lt;application&amp;gt;` tag, along side the existing `&amp;lt;activity&amp;gt;` tags --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;activity&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"com.linusu.flutter_web_auth.CallbackActivity"&lt;/span&gt; &lt;span class="na"&gt;android:exported=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;intent-filter&lt;/span&gt; &lt;span class="na"&gt;android:label=&lt;/span&gt;&lt;span class="s"&gt;"flutter_web_auth"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.action.VIEW"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.DEFAULT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.BROWSABLE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;data&lt;/span&gt; &lt;span class="na"&gt;android:scheme=&lt;/span&gt;&lt;span class="s"&gt;"appwrite-callback-[PROJECT_ID]"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/intent-filter&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/activity&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/manifest&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also need to add the Flutter platform in your project from the Appwrite console. Adding Flutter platforms allows appwrite to validate the request it receives and also prevents requests from unknown applications. In the project settings page, click on &lt;strong&gt;Add Platform&lt;/strong&gt; button and select &lt;strong&gt;New Flutter App&lt;/strong&gt;. In the dialog box that appears, select the appropriate Flutter platform, give a recognizable name to your platform and add the application ID or package name based on the platform. You need to follow this step for each Flutter platform you will build your application for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi8ddt0skqw6h3ng3dn09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi8ddt0skqw6h3ng3dn09.png" alt="Add Flutter Platform" width="800" height="525"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;For more detailed instructions on getting started with Appwrite for Flutter developers follow our official&lt;a href="https://appwrite.io/docs/getting-started-for-flutter"&gt; Getting Started for Flutter&lt;/a&gt; guide. Finally, you can call account.createOAuth2Session from your application as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:appwrite/appwrite.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;client&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'YOUR_END_POINT'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'YOUR_PROJECT_ID'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createOAuth2Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;provider:&lt;/span&gt; &lt;span class="s"&gt;"zoom"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Android
&lt;/h3&gt;

&lt;p&gt;For Android, to properly handle redirecting your users back to your mobile application after completion of OAuth flow, you need to set the following in your AndroidManifest.xml file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;manifest&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
  &lt;span class="nt"&gt;&amp;lt;application&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ...
    &lt;span class="c"&gt;&amp;lt;!-- Add this inside the `&amp;lt;application&amp;gt;` tag, along side the existing `&amp;lt;activity&amp;gt;` tags --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;activity&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"io.appwrite.views.CallbackActivity"&lt;/span&gt; &lt;span class="na"&gt;android:exported=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;intent-filter&lt;/span&gt; &lt;span class="na"&gt;android:label=&lt;/span&gt;&lt;span class="s"&gt;"android_web_auth"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.action.VIEW"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.DEFAULT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.BROWSABLE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;data&lt;/span&gt; &lt;span class="na"&gt;android:scheme=&lt;/span&gt;&lt;span class="s"&gt;"appwrite-callback-[PROJECT_ID]"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/intent-filter&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/activity&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/manifest&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also need to add the Android platform in your project from the Appwrite console. Adding Android platforms allows appwrite to validate the request it receives and also prevents requests from unknown applications. In the project settings page, click on &lt;strong&gt;Add Platform&lt;/strong&gt; button and select &lt;strong&gt;New Android App&lt;/strong&gt;. In the dialog box that appears give your platform a recognizable name and add the package name of your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc03xaaoh6wukmz00kxfl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc03xaaoh6wukmz00kxfl.png" alt="Add Android Platform" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more detailed instructions on getting started with Appwrite for Android developers follow our official&lt;a href="https://appwrite.io/docs/getting-started-for-android"&gt; Getting Started for Android&lt;/a&gt; guide. Finally, you can call account.createOAuth2Session from your application as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;androidx.appcompat.app.AppCompatActivity&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.os.Bundle&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.GlobalScope&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.launch&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.appwrite.Client&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.appwrite.services.Account&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity_main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;applicationContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://[HOSTNAME_OR_IP]/v1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your API Endpoint&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"5df5acd0d48c2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your project ID&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;account&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nc"&gt;GlobalScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createOAuth2Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;activity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@MainActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"zoom"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apple
&lt;/h3&gt;

&lt;p&gt;To capture the Appwrite OAuth callback URL, the following URL scheme needs to add to your Info.plist&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleURLTypes&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleTypeRole&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Editor&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleURLName&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;io.appwrite&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleURLSchemes&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;appwrite-callback-[PROJECT_ID]&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also need to add Apple platform in your project from Appwrite console. Adding Apple platforms allows appwrite to validate the request it receives and also prevents requests from unknown applications. In the project settings page, click on &lt;strong&gt;Add Platform&lt;/strong&gt; button and select &lt;strong&gt;New Apple App&lt;/strong&gt;. In the dialog box that appears select appropriate Apple platform tab and give your platform a recognizable name and add the package name of your application. For each supported Apple platform you need to follow this process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdmdoe86mk5zekrliulg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdmdoe86mk5zekrliulg7.png" alt="Add Apple Platform" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more detailed instructions on getting started with Appwrite for iOS developers follow our official&lt;a href="https://appwrite.io/docs/getting-started-for-apple"&gt; Getting Started for Apple&lt;/a&gt; guide. Finally, you can call account.createOAuth2Session from your application as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Appwrite&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[YOUR_ENDPOINT]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[YOUR_PROJECT_ID]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createOAuth2Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"zoom"&lt;/span&gt;
&lt;span class="p"&gt;){&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;err&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"logged in"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Well, that’s all that is to set up Zoom OAuth-based authentication with Appwrite. It is straightforward using Appwrite to set up Zoom OAuth-based authentication in your application. Following resources can be handy if you want to explore Appwrite further.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs"&gt;Appwrite Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord"&gt;Appwrite Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite/appwrite"&gt;Appwrite Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>flutter</category>
      <category>appwrite</category>
      <category>zoom</category>
      <category>oauth</category>
    </item>
    <item>
      <title>Implementing OAuth on Flutter with Appwrite</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Fri, 17 Jun 2022 04:18:17 +0000</pubDate>
      <link>https://forem.com/appwrite/appwrite-flutter-implementing-oauth-login-aem</link>
      <guid>https://forem.com/appwrite/appwrite-flutter-implementing-oauth-login-aem</guid>
      <description>&lt;p&gt;Today, we will learn to set up social authentication in our Flutter applications using Appwrite. By the end of this tutorial, you will know that setting up social authentication in the Flutter app using Appwrite is so easy that it can be done in a few minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To take full advantage of this tutorial, you need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access to the Appwrite project or permission to create one. If you don’t already have an Appwrite server running, follow the official installation tutorial to set up one.&lt;/li&gt;
&lt;li&gt;Flutter configured development machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;

&lt;p&gt;To begin, clone the &lt;a href="https://github.com/lohanidamodar/flappwrite_oauth"&gt;repository&lt;/a&gt; I’ve prepared for this tutorial where I have already set up a basic UI so that we can focus on implementing social login with Appwrite. We will start by adding and configuring the Appwrite SDK.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felic05pbvaqoah8lmh7u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felic05pbvaqoah8lmh7u.png" alt="Demo App" width="800" height="863"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Appwrite’s SDK
&lt;/h2&gt;

&lt;p&gt;First, open &lt;code&gt;pubspec.yaml&lt;/code&gt; and add &lt;code&gt;appwrite: 4.0.2&lt;/code&gt; as a dependency, and run &lt;code&gt;flutter pub get&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;appwrite&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;4.0.2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next open &lt;code&gt;main_screen.dart&lt;/code&gt; and import the package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:appwrite/appwrite.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;_MainScreenState&lt;/code&gt; , let’s configure the client.&lt;/p&gt;

&lt;p&gt;First, create a client property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_MainScreenState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MainScreen&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in &lt;code&gt;initState&lt;/code&gt; function, we configure the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'https://demo.appwrite.io/v1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// your endpoint&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'flappwrite_oauth'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Yout project id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure Discord OAuth
&lt;/h2&gt;

&lt;p&gt;Either use an existing Appwrite project or create a new one. Go to &lt;strong&gt;Users →Settings.&lt;/strong&gt; This is where we will set up the OAuth providers. Let’s first set up Discord. Click to turn on the Discord’s switch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7oke8qgsp5t4lum06bj1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7oke8qgsp5t4lum06bj1.png" alt="Discord OAuth on Appwrite" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to fill in the app ID and secret in the dialog that appears. We can get that from the Discord developer portal following the &lt;a href="https://discord.com/developers/docs/topics/oauth2"&gt;official guide&lt;/a&gt;. Copy the callback URL provided in the dialog and paste it into Discords setup for the redirect URL. Click Update once the app ID and secrets are filled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fik9hyasb2399q6d48n8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fik9hyasb2399q6d48n8w.png" alt="Discord OAuth Setup" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Google Sign In
&lt;/h2&gt;

&lt;p&gt;In the Appwrite console, visit the Users→Settings page. There, find Google from the list and turn the switch on. To complete this, you will need an App ID and App Secret, which you can easily set up from Google API Console. Check out &lt;a href="https://support.google.com/googleapi/answer/6158849"&gt;their official documentation&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxf9hqsv3ac2de980rgo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxf9hqsv3ac2de980rgo.png" alt="Google OAuth on Appwrite" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you get and fill in the Google &lt;strong&gt;App ID&lt;/strong&gt; and the &lt;strong&gt;App Secret&lt;/strong&gt;, you need to provide the callback URL shown in the dialog to the Google OAuth2's Authorized redirect URIs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsz58qwt5vuzcnknx41ml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsz58qwt5vuzcnknx41ml.png" alt="Google OAuth Setup" width="800" height="933"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Authorized JavaScript origins are required only for a web app. If you are also using Flutter web, you should add the URL as the Authorized JavaScript origins&lt;/p&gt;

&lt;p&gt;Now that we have configured Google and Discord OAuth in the Appwrite console, we will implement this social auth in our Flutter application in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implement OAuth login on Appwrite
&lt;/h2&gt;

&lt;p&gt;Before we can make any request to the Appwrite server from our applications, we need to add the platform we are building for &lt;a href="http://Appwrite.In"&gt;Appwrite.&lt;/a&gt; On the project dashboard, click &lt;strong&gt;Add Platform&lt;/strong&gt; → &lt;strong&gt;New Flutter App&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwws3gwhznhdep8uz2s0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwws3gwhznhdep8uz2s0.png" alt="Add Platform" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the dialog that appears, add the relevant platforms. I’ll be adding Android. If you want to add more than one platform, follow the same process for each platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxb78p4w9nacfhynsmxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxb78p4w9nacfhynsmxd.png" alt="Add Flutter Android Platform" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, in Android, to handle redirection successfully after the authentication is completed, we need to add the following to the &lt;code&gt;AndroidManifest.xml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;manifest&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
  &lt;span class="nt"&gt;&amp;lt;application&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ...
    &lt;span class="c"&gt;&amp;lt;!-- Add this inside the `&amp;lt;application&amp;gt;` tag, along side the existing `&amp;lt;activity&amp;gt;` tags --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;activity&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"com.linusu.flutter_web_auth.CallbackActivity"&lt;/span&gt; &lt;span class="na"&gt;android:exported=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;intent-filter&lt;/span&gt; &lt;span class="na"&gt;android:label=&lt;/span&gt;&lt;span class="s"&gt;"flutter_web_auth"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.action.VIEW"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.DEFAULT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.BROWSABLE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;data&lt;/span&gt; &lt;span class="na"&gt;android:scheme=&lt;/span&gt;&lt;span class="s"&gt;"appwrite-callback-[PROJECT_ID]"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/intent-filter&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/activity&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/manifest&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For iOS, version 12+ and macOS version 10.15+ are required for OAuth to work.&lt;/p&gt;

&lt;p&gt;Finally, we can now log in with Google and Discord in our Application. It is straightforward. We instantiate &lt;code&gt;Account&lt;/code&gt; with an instance of &lt;code&gt;Client&lt;/code&gt; and call &lt;code&gt;createOAuth2Session&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createOAuth2Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;provider:&lt;/span&gt; &lt;span class="s"&gt;'google'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;main_screen.dart&lt;/code&gt; find &lt;code&gt;_MainScreenState&lt;/code&gt;, and there find the &lt;code&gt;handleLogin&lt;/code&gt; function. This is called when we press Google login or Discord login buttons. We pass the respective provider, &lt;code&gt;google&lt;/code&gt;, or &lt;code&gt;discord&lt;/code&gt; as the param. Update the &lt;code&gt;handleLogin&lt;/code&gt; function as the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;handleLogin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createOAuth2Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;provider:&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;checkedLoggedIn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing to note, we only need to pass the provider and not the success and failure URL. Success and failure URLs are required only if we implement our own web application that handles completing the login process from the authorization code obtained from OAuth providers. However, this is handled by the Appwrite server internally, so we don’t need to provide the success and failure URLs.&lt;/p&gt;

&lt;p&gt;Another thing to note, the log-in and sign-up process for OAuth-based authentication are the same, and the createOAuth2Session automatically creates a User if it doesn’t already exist in Appwrite. Also, if a user account already exists with the same email address, the OAuth session is linked to the same user account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Well, that’s all that is required to set up OAuth-based authentication with Appwrite. The final code can be found in the &lt;a href="https://github.com/lohanidamodar/flappwrite_oauth/tree/final"&gt;final branch of the repository&lt;/a&gt;. The challenging parts are setting up the specific provider and getting the client ID and secret from them. The rest is straightforward using Appwrite. Following resources can be handy if you want to explore Appwrite further.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs/getting-started-for-flutter"&gt;Getting Started for Flutter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs"&gt;Appwrite Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord"&gt;Appwrite Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite/appwrite"&gt;Appwrite Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>appwrite</category>
      <category>flutter</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What's New in Appwrite's Storage</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Wed, 09 Mar 2022 19:45:41 +0000</pubDate>
      <link>https://forem.com/appwrite/whats-new-in-appwrites-storage-30pf</link>
      <guid>https://forem.com/appwrite/whats-new-in-appwrites-storage-30pf</guid>
      <description>&lt;p&gt;Appwrite comes with a robust storage service to help you manage files required for your application. Appwrite’s storage service provides API for uploading and managing files, manipulating images, getting image previews, and more. It has built-in security, access control using users, teams, and roles, built-in encryption, and antivirus scanning. Also, the image preview manipulation endpoint comes with caching to keep it efficient. With the release of Appwrite 0.13, we are adding more power to Appwrite’s already powerful storage service. We have introduced buckets to group files with additional configurations. We have improved efficient handling of large files and have introduced support for external storage services to use as Appwrites storage location. Let’s look at each of these new features independently&lt;/p&gt;

&lt;p&gt;Appwrite is an open source backend-as-a-service that abstracts all the complexity involved in building a modern application by providing you with a set of REST APIs for your core backend needs. Appwrite handles user authentication and authorization, databases, file storage, cloud functions, webhooks, and much more! If anything is missing, you can extend Appwrite using your favorite backend language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Buckets
&lt;/h2&gt;

&lt;p&gt;With version 0.13 of Appwrite, we have introduced buckets. Buckets are simply a collection of files. If you have previously worked with Appwrite’s database service, buckets are similar to collections in database service. Buckets allow you to have additional control over your files. You can group files based on domain, type, or any other logic that suits your application using buckets. Buckets make file organization better. Not only that, buckets allow you additional control by specifying what type and size of files can go into it, whether or not to encrypt the files in the bucket and whether or not to scan files going into the bucket with antivirus. To learn more about buckets, visit our storage docs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftk8z1ufp5rdjzscqc9rm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftk8z1ufp5rdjzscqc9rm.png" alt="Image description" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  External Storage Support
&lt;/h2&gt;

&lt;p&gt;Files are important and even important is to have them in a reliable storage. Appwrite 0.13.0 introduces support for AWS S3 and DigitalOcean spaces as a storage solution for Appwrite. So, if you want to, you can set any files uploaded to Appwrite storage to directly be uploaded to AWS S3 bucket or DigitalOcean spaces. In the upcoming days we will introduce support for more storage solutions so that you will not be limited to these two services. To learn more about setting up Appwrite to use S3 or DigitalOcean spaces, check out the storage environment variables docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Large File
&lt;/h2&gt;

&lt;p&gt;There are many applications where we would want to use and store huge files. Appwrite 0.12, and the previous versions did not handle large files efficiently. From version 0.13, Appwrite handles the uploading and downloading of large files efficiently. You can now upload gigabytes of files easily using the chunked upload process. Appwrite uploads large files by breaking them into smaller chunks so that the server can handle them efficiently and the API is more robust and stable. Check out our blog post to learn more about implementing large file support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Storage is an essential service for applications, and Appwrite, a back-end service, provides a practical storage service that you can use to manage your application files. And with the 0.13 version of Appwrite, the storage service adds more powerful features that will help you organize your files, play with large files for complex applications, and more. We hope these new features of Appwrite will open up a whole new domain of possibilities for developers out there. We can’t wait to see what you will build with it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Efficiently Handling Large Files Upload and Download</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Tue, 08 Mar 2022 16:41:54 +0000</pubDate>
      <link>https://forem.com/appwrite/efficiently-handling-large-files-upload-and-download-5eg1</link>
      <guid>https://forem.com/appwrite/efficiently-handling-large-files-upload-and-download-5eg1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Uploading files to remote servers is an essential operation for many applications. While developing a tool like Appwrite, it is crucial to efficiently handle the uploading of files to use it in their application without being concerned about the efficiency and reliability. Managing files upload comes with a challenge when dealing primarily with huge files. We need to think about efficient resource usage in both the client and server and a reliable upload process. This article will discuss our learning from adding support for huge file upload in Appwrite’s 0.13 release. So let’s get started.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://appwrite.io"&gt;Appwrite&lt;/a&gt; is an open source backend-as-a-service that abstracts all the complexity involved in building a modern application by providing you with a set of REST APIs for your core backend needs. Appwrite handles user authentication and authorization, databases, file storage, cloud functions, webhooks, and much more! If anything is missing, you can extend Appwrite using your favorite backend language.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;First, when discussing file uploads using the HTTP protocol, let us understand the basic upload process from client and server perspectives. To upload a file to the client, first, we load the file into memory and make a request over HTTP to the server. The server then receives the file and saves it in a temporary location. Then we can decide to move the file to the appropriate location. The problem with this process is that the server freezes until the file is completely uploaded. And If we want to handle huge files, say gigabytes of files, we would need as many resources, memory, and CPU to handle those files. Also, the server would take much time to respond to requests. If the upload fails in between, the client will have to re-initiate the upload process from the beginning, which wastes time and resources. Also, imagine a server where hundreds of users are trying to upload gigabytes of files simultaneously. The server would need considerable resources to handle those requests. Many requests will have to wait long before the server can respond to them if the server resources are limited, which is not recommended. So this method is suitable for reasonably small file size uploads. Now that we know the challenges of uploading files, we will discuss what options are available to upload files in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling File Uploads
&lt;/h2&gt;

&lt;p&gt;Researching the ways to handle file uploads to web servers, we mainly found two ways. On is the basic upload process we discussed in the previous section. If we use this approach, it is recommended to set a maximum upload size limit to around 20-30 MB to keep things simple and effective. But for us, that was not an option, as a developer tool limiting our users and would be unsuitable for various applications.&lt;/p&gt;

&lt;p&gt;The next method that we found was the chunked upload process. Which was efficient, less resource-intensive, and in case of failure, would support resumable upload. Which meant we could use this for smaller as well as huge files. And that is what we decided to implement in Appwrite 0.13 to power our developers. In the next section, we will look into how this method works and its efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chunking and Content Range
&lt;/h2&gt;

&lt;p&gt;Until a specific file size, it is okay to use the simple file upload approach. However, when the file size grows, it is recommended to use chunked upload. So how do we upload files using chunks? In this method, we don’t send the whole file in a single request; we instead send a chunk (a part of the file) and make multiple requests with each part. The benefit is that the server doesn’t have to receive the whole file at once but rather receives small chunks. This makes both the upload process and server responsive. Also, we can only upload those chunks that failed; we don’t have to upload the whole file again. This makes uploading large files efficiently, even over unstable connections. Also, this opens up another possibility to upload multiple chunks in parallel, making the upload process much faster if the network bandwidth allows. While sending each chunk, we set the associated content-range header. The server uses the content-range header to determine the total chunks uploaded and part of the file the chunk belongs to. The content-range header is defined in the HTTP specification. The syntax is defined as the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Content-Range: &amp;lt;unit&amp;gt; &amp;lt;range-start&amp;gt;-&amp;lt;range-end&amp;gt;/&amp;lt;size&amp;gt;
Content-Range: &amp;lt;unit&amp;gt; &amp;lt;range-start&amp;gt;-&amp;lt;range-end&amp;gt;/*
Content-Range: &amp;lt;unit&amp;gt; */&amp;lt;size&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to set the unit, generally in bytes, and then the range-start is the start offset of this chunk and range-end is the end offset of this chunk, and finally, the size is the total size of the file. The value of range-start, range-end, and size must be in the unit provided. These headers in each chunk will tell the server exactly how to combine the chunks to get the original file. Now that we know how the chunked upload process works let’s see how we can make the upload process resumable in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resumable Upload
&lt;/h2&gt;

&lt;p&gt;With the implementation of chunked upload, it is relatively easy to implement resumable uploads. To make it happen, we can track each successful chunk uploaded and each that has failed during upload. Whenever the upload process stops in between, we will record all the successfully uploaded chunks. Next time, we can start the upload process only for the remaining chunks. This makes it very easy to upload large files over an unstable connection as we can upload small chunks and only upload failed and remaining chunks with as many retries as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Handling file uploads reliably and efficiently can be challenging. We saw in this article that we have two ways of uploading files: one, we upload the whole file in a single request, and another where we upload a file in smaller chunks. We should use the first approach for smaller file sizes, maybe up to 20-30MB, and for any file larger than that, it's best to implement a chunked upload to make the upload process reliable and efficient. We hope this article will be helpful to anyone trying to build an upload service. However, if you are using Appwrite, you will not have to think about all these things. Appwrite handles everything internally to provide reliable and efficient storage service to upload and manage files.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Working with database indexes ( the right way )</title>
      <dc:creator>Damodar Lohani</dc:creator>
      <pubDate>Wed, 12 Jan 2022 12:39:59 +0000</pubDate>
      <link>https://forem.com/appwrite/working-with-database-indexes-the-right-way--4agp</link>
      <guid>https://forem.com/appwrite/working-with-database-indexes-the-right-way--4agp</guid>
      <description>&lt;h2&gt;
  
  
  👀 Overview
&lt;/h2&gt;

&lt;p&gt;The database is an integral part of any modern application. We use a database to provide pre-filled information to our users or sync information supplied by users across their devices or their shared community and a failure can cause massive damage to our application and its users. That means, all modern applications must have well structured, scalable, and maintained database to provide optimum service to our users. A database index is an essential feature of any database system, which helps make the database more performant to access data according to the needs of our application. Using database indexes effectively can make your queries much faster, hence making your application much more performant. Who doesn't love extra seconds of responsiveness in their application?&lt;/p&gt;

&lt;h2&gt;
  
  
  🎬 Introduction to Database Indexes
&lt;/h2&gt;

&lt;p&gt;Indexes are a data structure technique used to quickly locate and access data in the database. It improves the performance of the database by minimizing the number of disk reads required to find the data.&lt;/p&gt;

&lt;p&gt;An index is a small table with only two columns, a key, and a reference. The key is the candidate key of the table that we want to index, and the reference column contains pointers to hold the disk block address where the value for that specific key is stored. An index takes a search key as the input and returns a collection of matching records. Imagine you have to find data in a persons table with the person's name, and suppose you don't have an index. Then the database will have to look at each record to figure out whether or not it is the matching record. Going through every record in a table is called a full table scan, and it takes a long time, based on the number of records in the table. However, if you have indexed the table's name column when you search for a particular name, the database will first query the index and get the pointer to the data, then get the matching data. This way database will have to go through only the index instead of scanning the whole table. An index table might be shorter than the data table itself and is sorted to be able to search efficiently.&lt;/p&gt;

&lt;p&gt;If it seems too complex to understand, let's take an example from something simpler. Let's assume that we have a box that contains small pieces of paper with English words written on them, one for every word in the English language, and on the back side has the definition of the word. How would we find the definition of 'simplicity'? The slowest way would be to read each piece of paper, one by one, until we find the definition. Though, we could find it much faster if we had all the words sorted ahead of time.&lt;/p&gt;

&lt;p&gt;In other words, we need a dictionary.&lt;/p&gt;

&lt;p&gt;Finding definitions of words is much faster with a dictionary in hand since the words are listed in alphabetical order. How would we use a dictionary to speed up our search? We would open to a page, look at the first word, and check if we need to flip ahead or back in the book. We repeat this until we find the right page, and eventually, the definition of 'simplicity'. So how would we instruct a computer to do this sort of search? We'll need ask everyone's favorite Computer Science subject for the answer: data structures and algorithms, but only in a simplified way 😉&lt;/p&gt;

&lt;p&gt;Our dictionary search is faster because we can quickly eliminate the need to check large chunks of pages - if we flip to the middle-most page in the dictionary and check the first word on the page, we eliminate the need to check &lt;em&gt;half&lt;/em&gt; of the pages of the entire dictionary. The data structure representation of this concept is the &lt;strong&gt;binary search tree&lt;/strong&gt;, or B-tree. This data structure optimizes our search from scaling linearly (&lt;code&gt;O(n)&lt;/code&gt;) to scaling logarithmically (&lt;code&gt;O(log(n))&lt;/code&gt;), which results in massive performance gains for big data sets.&lt;/p&gt;

&lt;p&gt;The downside to indexing is that indexes require additional space on the disk. Also, these indexes are kept in sorted order to access the corresponding data quickly, and one can perform a binary search on the index itself. It's important to keep the index balanced along with the constantly updating data. This means that with every write operation (insert, update and delete), the index will also have to be updated, decreasing the write performance.&lt;/p&gt;

&lt;p&gt;Creating an index requires additional disk space and also decreases the write performance. So too many indexes can cause issues arising from file systems size limits, degraded write performances, and more. We should be careful and plan what fields we want to index. A poorly indexed database is as bad or worse than a database that is not indexed.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧑‍💻 Types of Database Indexes
&lt;/h2&gt;

&lt;p&gt;Indexing in Database is defined based on the attributes it's indexing. There are four main types of indexing methods that are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Primary Indexes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A database table must have some way to uniquely identify each record, so it can read and write data from the correct block of storage. A primary index serves this purpose: by requiring a unique ID for each record, the database can prepare a pre-sorted list (a B-tree, usually) of IDs that point to their locations on disk, vastly improving the speed to find individual records.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unique Indexes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Primary indexes require a unique identifier that it maps to the record's disk location (for good reason), but we can use B-trees to enforce any attribute to be unique.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Secondary Indexes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Databases can use B-trees to prepare similar pre-sorted lists for any attribute of data that's commonly queried. If we commonly check our &lt;code&gt;Inventory&lt;/code&gt; for low-stock items (&lt;code&gt;count &amp;lt; 5&lt;/code&gt;), we can increase query performance by creating a secondary index for the &lt;code&gt;count&lt;/code&gt; field. We can do the same across multiple attributes (&lt;code&gt;count &amp;lt; 5 &amp;amp;&amp;amp; price &amp;gt; 100&lt;/code&gt;), but the &lt;a href="https://stackoverflow.com/questions/2292662/how-important-is-the-order-of-columns-in-indexes"&gt;order and sorted direction increasingly matters&lt;/a&gt; as you add more attributes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fulltext Indexes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we want to search for specific text, databases support &lt;code&gt;fulltext&lt;/code&gt; indexes to create data structures to support this. The implementation of fulltext indexes can vary between different database systems, but the principle allows us to check our &lt;code&gt;Inventory&lt;/code&gt; for items with &lt;code&gt;name LIKE apple&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's common that &lt;code&gt;where&lt;/code&gt; clause use indexes. However, B-tree indexes can also help the &lt;code&gt;order by&lt;/code&gt;, &lt;code&gt;group by&lt;/code&gt;, &lt;code&gt;select&lt;/code&gt; and other clauses.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔖 Introducing Indexes in the Appwrite Database
&lt;/h2&gt;

&lt;p&gt;Appwrite is an open-source back-end server for all your apps, be it Flutter, Web, Android, or iOS. It helps developers innovate by taking care of modern application development's complex and repetitive parts. Appwrite provides authentication, database, storage, cloud functions, realtime APIs, webhooks, and more. With version 0.12 of Appwrite, we are pleased to announce the newest refactored database service with support for powerful queries and indexes.&lt;/p&gt;

&lt;p&gt;Appwrite 0.12 comes with a refactored database service. We bring a database service that is much on par with the DBMS service we implement internally with this version. We get features like indexes, advanced queries, and more to our database. The basic attributes of our database are on par with the underlying database. On top of that, we have added advanced attributes like URL, email, and more that allows you to design complex data structure for your application with proper validation without much work.&lt;/p&gt;

&lt;p&gt;Another significant feature introduced with the database in this version are indexes. We already saw above how important indexes are for performance, so we bring you the power to manage your indexes with the Appwrite database to make your queries even more performant. We also made a design decision with Appwrite's new database. With this version, we only allow querying on the fields that have indexes. If you have previously used databases like MariaDB or MySQL, they will enable you to perform queries even when you have not created any index which can lead to full table scans. This is a huge performance hit and can cause database bottlenecks. That is why with Appwrite, we prevent such queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  🗂 Indexes Supported by Appwrite
&lt;/h2&gt;

&lt;p&gt;Appwrite as of writing of this article supports &lt;strong&gt;unique&lt;/strong&gt;, &lt;strong&gt;key&lt;/strong&gt; and &lt;strong&gt;fulltext&lt;/strong&gt; indexes. Let's look at each of these indexes, what they are and when to create these.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unique Index&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A unique index must use unique values. However, values can be null. Appwrite uses MariaDB's unique index internally, so you get all the benefits of MariaDB's unique index. Each key in the unique index identifies only one record. However, each record in the table may not be represented because of the possibility of the null value. That means you can create a unique key index for unique attributes. For example, suppose you have a user profile collection where you store users' email. In that case, you can create a unique index for email attribute both to prevent duplication and easily find records using email. You can also create a unique index for a combination of attributes. For example, if you support multiple user profiles with different names, you can create a unique index for a combination of email and name attribute.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Key Index&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key index doesn't have to be unique. You might want to add an index to attributes that you want to filter and order your records during accessing. Appwrite uses MariaDB's plain indexes internally, so you get all the benefits of MariaDB's key index. For example, if you are ordering the list of users in the decreasing order of their joining date, you can create a key index for &lt;code&gt;dateJoined&lt;/code&gt; in descending order. This will improve performance, as we already discussed above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fulltext Index&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fulltext indexes allow searching a portion of text in an attribute. Appwrite uses MariaDB's Fulltext index internally, so you get all the benefits of a full-text index from MariaDB. For example, in your users table, if you have a short biography attribute where users store their short bio, and your application allows searching for users based on words mentioned in their bio, then it's a good idea to create a full-text index for the biography attribute. If you want to pre-populate large data sets in your collection, it's best to first populate the collection with data and then create the required indexes.&lt;/p&gt;

&lt;p&gt;Now that we know what indexes are supported by Appwrite let's look at how we can manage indexes in Appwrite. There are two ways you can achieve this, first is using Appwrite's console, and the second is using Appwrite's server-side APIs and SDKs. We will look at both ways. Before moving on to managing indexes, if you have not already installed Appwrite, visit our &lt;a href="https://appwrite.io/docs/installation"&gt;installation docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🕵️‍♂️ Managing Indexes in the Appwrite Database
&lt;/h2&gt;

&lt;p&gt;We have already learned the importance of the indexes above. And same implies to Appwrite's database service as well. Having proper indexes affects a lot in performance. You can use this &lt;a href="https://dev.to/appwrite/appwrite-012-database-improvements-3kmh"&gt;benchmarking&lt;/a&gt; to reference how performance is impacted by having and not having indexes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create Collection and Attributes&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before we can create an index, we first need to create a collection and few attributes. So we will create a &lt;code&gt;courses&lt;/code&gt; collection that will have the following attributes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+--------------+--------+------+----------+-------+---------+
| Attribute Id | Type   | Size | Required | Array | Default |
+--------------+--------+------+----------+-------+---------+
| title        | string | 255  | true     | false | null    |
+--------------+--------+------+----------+-------+---------+
| slug         | string | 255  | true     | false | null    |
+--------------+--------+------+----------+-------+---------+
| description  | string | 1000 | false    | false | null    |
+--------------+--------+------+----------+-------+---------+
| authors      | string | 60   | false    | true  | null    |
+--------------+--------+------+----------+-------+---------+
| category     | string | 60   | false    | false | null    |
+--------------+--------+------+----------+-------+---------+
| credit       | float  | -    | true     | false | null    |
+--------------+--------+------+----------+-------+---------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a new collection, log in to the Appwrite console, create a project, or access an existing one. Then access the database by clicking on the &lt;strong&gt;Database&lt;/strong&gt; from left side menu. Once there, you can click on the &lt;strong&gt;Add Collection&lt;/strong&gt; button. You will see a dialog to choose a custom id if you wish to by clicking on the edit icon next to the auto-generated field. Now enter the collection id as &lt;code&gt;courses&lt;/code&gt; and name as &lt;code&gt;Courses&lt;/code&gt;. Finally, click on the &lt;strong&gt;Create&lt;/strong&gt; button, and you should be directed to a new page with collection details. Access the &lt;strong&gt;Attributes&lt;/strong&gt; tab, and to create attributes, carry out the following steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2vx1agj8nvdkr66g0bu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2vx1agj8nvdkr66g0bu.png" alt="Create Collection" width="800" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the &lt;strong&gt;Add Attribute&lt;/strong&gt; button and select &lt;strong&gt;New String Attribute&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0ds9cvy6qd63zl5de59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0ds9cvy6qd63zl5de59.png" alt="Add Attribute" width="800" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the dialog box you receive, set &lt;code&gt;title&lt;/code&gt; as the attribute id.&lt;/li&gt;
&lt;li&gt;Size, make it 255&lt;/li&gt;
&lt;li&gt;Make it required and&lt;/li&gt;
&lt;li&gt;Click on the &lt;strong&gt;Create&lt;/strong&gt; button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1owomcksqjn6r7d16hf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1owomcksqjn6r7d16hf.png" alt="Add Attribute Details" width="800" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This should add the title attribute. Repeat steps 1 to 6 for each attribute choosing the right option to create attributes defined above.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create Indexes&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that we have a collection and attributes, we can plan our index. First, we would like to perform a text search on the title, so we should create a full-text index for the title. Then we want the slug to be unique, so we should create a unique index for the slug attribute. Finally, we might want to filter by author, category, and credit, so we create the key index for each attribute. Now that we have a plan for indexing, let's create those indexes. First, access the &lt;strong&gt;indexes&lt;/strong&gt; tab. Once there, follow the given steps to add an index.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the &lt;strong&gt;Add Index&lt;/strong&gt; button to access the dialog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwxd25a6l5ew20smo1lu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwxd25a6l5ew20smo1lu.png" alt="Add index button" width="800" height="691"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, type &lt;code&gt;title_fulltext&lt;/code&gt; in the Index Key field&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Fulltext&lt;/code&gt; as the type and &lt;/li&gt;
&lt;li&gt;Under attributes, just select &lt;code&gt;title&lt;/code&gt; and leave the ordering as &lt;code&gt;ASC&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiv604pztnlmk78lfl6dr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiv604pztnlmk78lfl6dr.png" alt="Index details" width="800" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This should add a &lt;code&gt;Fulltext&lt;/code&gt; index for the &lt;code&gt;title&lt;/code&gt; attribute. The newly added index should be listed in the indexes tab. Now repeat steps 1 to 4 for every index we planned above, choosing the appropriate options to create all the required indexes.&lt;/p&gt;

&lt;p&gt;You can also use Appwrite's server-side SDKs to create these indexes. If you have never used server SDK, please go through the &lt;a href="https://appwrite.io/docs/getting-started-for-server"&gt;getting started with server docs&lt;/a&gt;. You can use the SDK of your choice and use &lt;code&gt;createIndex&lt;/code&gt; function as described in &lt;a href="https://appwrite.io/docs/server/database?sdk=nodejs-default#databaseCreateIndex"&gt;docs&lt;/a&gt; from Appwrite's database service to add a new index. There are also methods to create collection, create attributes, indexes and update, delete them. This way, you can write and save a script that can add collection, create attributes and create indexes that you can run on any Appwrite instance to set up your collections.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deleting Indexes&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to delete or remove an index that you are no longer using in your applications, you can do it easily from the indexes tab. While there, you can see the list of available indexes in a table with a delete button for each row. Click the delete button on the row of the index you want to delete, and in the confirmation dialog that appears, click ok. If you accidentally delete an index, you can easily recreate it. However, it might take much time if the database already has tons of data. You can also use &lt;a href="https://appwrite.io/docs/server/database?sdk=nodejs-default#databaseCreateIndex"&gt;deleteIndex&lt;/a&gt; function from the database service using the server-side SDKs.&lt;/p&gt;

&lt;p&gt;Now that we know how to manage indexes with Appwrite database, let's look at how to choose indexes correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧭 Choosing Indexes
&lt;/h2&gt;

&lt;p&gt;You should carefully plan what indexes to add based on the queries you make from your applications. Any extra indexes will waste resources as well as hamper performance. The index may not make much difference in a small collection, but as soon as your collection grows, indexes will start to speed queries dramatically. If you want to perform a search query, you should create a full-text index. With Appwrite, we also notify you when you try to query an un-indexed field, so you know what to index. If you created an index but have not used it, remove those to increase create and update queries performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  👋 Conclusion
&lt;/h2&gt;

&lt;p&gt;Database indexes are a critical aspect of database design for your application, and with Appwrite, we make it easy to manage your indexes. Properly planned indexes will improve performance by a lot and prevent database failure. We hope this article was a helpful guide to database indexing while designing a data structure for your next application and will help you build robust and performant apps. If you have any queries ( pun intended! )  or confusion, please reach us on our &lt;a href="https://appwrite.io/discord"&gt;Discord server&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Resources
&lt;/h2&gt;

&lt;p&gt;To learn more about Appwrite and its services, including the Database service we discussed in this article, you can use the following resources.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/discord"&gt;Discord Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs/database"&gt;Database Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/appwrite/appwrite-012-database-improvements-3kmh"&gt;Appwrite Database Benchmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[Getting Started with Server Side SDKs](&lt;a href="https://appwrite.io/docs/getting-started-for-server"&gt;https://appwrite.io/docs/getting-started-for-server&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>database</category>
      <category>discuss</category>
      <category>programming</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
