<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Avinash Prasad's Blog]]></title><description><![CDATA[Learning in Public. (github/avionmission)]]></description><link>https://blog.avionmission.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1735457292725/7ed675ed-4a88-48eb-b4c7-b8d941e0894e.png</url><title>Avinash Prasad&apos;s Blog</title><link>https://blog.avionmission.com</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 16:47:42 GMT</lastBuildDate><atom:link href="https://blog.avionmission.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Build an AI UI Generator with Gemini API, Next.js (Tutorial)]]></title><description><![CDATA[https://www.youtube.com/watch?v=IFQI3t89eO8&t=282s
 
In this tutorial, we will build an AI UI Generator using Next.js and the Gemini API. It is similar to v.0 by Vercel which allows you to generate UI with a simple prompt and use it in your web apps....]]></description><link>https://blog.avionmission.com/build-an-ai-ui-generator-with-gemini-api-nextjs-tutorial</link><guid isPermaLink="true">https://blog.avionmission.com/build-an-ai-ui-generator-with-gemini-api-nextjs-tutorial</guid><category><![CDATA[gemini]]></category><category><![CDATA[GPT 4]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[generative-ui]]></category><category><![CDATA[texttocodegenerator]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Avinash Prasad]]></dc:creator><pubDate>Sun, 07 Jul 2024 08:22:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735308228113/6454debc-2ad3-4e22-897b-d47e852f657b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=IFQI3t89eO8&amp;t=282s">https://www.youtube.com/watch?v=IFQI3t89eO8&amp;t=282s</a></div>
<p> </p>
<p>In this tutorial, we will build an AI UI Generator using Next.js and the Gemini API. It is similar to <a target="_blank" href="https://v0.dev/">v.0 by Vercel</a> which allows you to generate UI with a simple prompt and use it in your web apps.</p>
<p>This type of dynamic code generation can be the beginning of a new paradigm in software development where User Interfaces are generated by AI according to user's needs. This concept is being termed as "Generative UI".</p>
<p>Here's an example of how our application will work:</p>
<p><img src="https://github.com/avionmission/ui-generator/raw/master/public/uigeneratordemo.png" alt class="image--center mx-auto" /></p>
<p>Let's begin by creating a new Next.js project.</p>
<h3 id="heading-step-1-create-a-new-nextjs-project">Step 1: Create a new Next.js project</h3>
<pre><code class="lang-bash">npx create-next-app@13.4 ui-generator
</code></pre>
<p>You will be prompted to select settings for the new project, make sure to follow these choices:</p>
<ul>
<li><p>For TypeScript, select <strong>No</strong> because this tutorial uses JavaScript.</p>
</li>
<li><p>Feel free to choose any option for enabling ESLint.</p>
</li>
<li><p>Choose <strong>Yes</strong> for Tailwind CSS.</p>
</li>
<li><p>Exclude the <em>src/</em> directory by selecting <strong>No</strong>, which is the default option.</p>
</li>
<li><p>Enable App Router by selecting <strong>Yes</strong>, which is the recommended option.</p>
</li>
<li><p>Lastly, select <strong>No</strong> for <code>import alias</code> configuration.</p>
</li>
</ul>
<p>Change the working directory to your new Next.js project, <em>ui-generator</em> and run the application to make sure everything is fine:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ui-generator
npx run dev
</code></pre>
<h3 id="heading-step-2-building-the-frontend">Step 2: Building the Frontend</h3>
<p>In the new app router in Next.js, <code>app/page.js</code> hosts the code for the home page. Remove everything inside it apart from the outer <code>div</code>s, and now we have an empty canvas to create anything we want.</p>
<p>Create a simple interface for this application which includes an input box to enter a prompt, a <code>div</code> placeholder for the code to be generated, and button to copy code:</p>
<pre><code class="lang-javascript"><span class="hljs-string">'use client'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex min-h-screen flex-col items-center p-12"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"max-w-5xl w-full flex-col items-center justify-center text-sm lg:flex"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-3xl mb-4 font-bold text-gray-600'</span>&gt;</span>UI Generator<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative flex items-center w-full h-12 rounded-lg focus-within:shadow-md bg-transparent overflow-hidden"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"peer h-full w-full outline-none bg-gray-100 text-sm text-gray-700 pl-4 pr-12"</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter a prompt..."</span>
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleGenerate}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"absolute right-0 flex items-center justify-center h-full w-12 bg-blue-500 hover:bg-blue-600 text-white cursor-pointer"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-2xl'</span>&gt;</span>➔<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'flex'</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'bg-blue-500 text-white px-5 py-3 mt-7 hover:bg-blue-600 m-2'</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleCopy}</span>&gt;</span>Copy Code<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'bg-transparent border-2 border-gray-300 rounded mt-7 p-2 flex justify-center'</span>&gt;</span>
          {/* Generated code */}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  )
}
</code></pre>
<h3 id="heading-step-3-obtain-the-gemini-api-key">Step 3: Obtain the Gemini API Key</h3>
<p>Before we start working on our back-end of the application, we need to obtain the Gemini API key to be able to leverage Google's generative AI tools.</p>
<p>Go to <a target="_blank" href="https://ai.google.dev/aistudio">https://ai.google.dev/aistudio</a> to get the Gemini API key for free.</p>
<p>Create a <code>.env</code> file in the root of your project and store your API key:</p>
<pre><code class="lang-json">GEMINI_API_KEY=[YOUR API KEY]
</code></pre>
<h3 id="heading-step-4-create-server-side-function-to-handle-post-requests">Step 4: Create server-side function to handle POST Requests</h3>
<p>Install the Google AI JavaScript SDK enables you to use Google's generative AI models. Make sure you are in your project's root directory and run the following command in your terminal:</p>
<pre><code class="lang-bash">npm install @google/generative-ai
</code></pre>
<p>In Next.js app router, you can define custom route handlers in <code>route.js</code> file inside the app director. For example the file <code>app/api/generate/route.js</code> maps to <code>/api/generate</code> route.</p>
<p>Let's create a function to handle POST requests in <code>/api/generate/route.js</code> :</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { GoogleGenerativeAI } <span class="hljs-keyword">from</span> <span class="hljs-string">'@google/generative-ai'</span>;
<span class="hljs-keyword">import</span> { NextResponse } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/server'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">POST</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">const</span> genAI = <span class="hljs-keyword">new</span> GoogleGenerativeAI(process.env.GEMINI_API_KEY)

    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> model = genAI.getGenerativeModel({ <span class="hljs-attr">model</span>: <span class="hljs-string">"gemini-pro"</span> });

        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> req.json()
        <span class="hljs-keyword">const</span> prompt = data.body + <span class="hljs-string">". Write jsx code and use tailwindcss for modern UI. Don't make any imports. Only output code."</span>;

        <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> model.generateContent(prompt);
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> result.response;
        <span class="hljs-keyword">const</span> code = <span class="hljs-keyword">await</span> response.text()

        <span class="hljs-keyword">return</span> NextResponse.json({<span class="hljs-attr">code</span>: code})
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(error)     
    }
}
</code></pre>
<p>Here, we create an instance of <code>GoogleGenerativeAI</code> from the API key we stored in the <code>.env</code> file, define a model that uses <code>gemini-pro</code> model.</p>
<p>We retrieve the JSON data from the request body and store it in a variable <code>data</code>. But we don't directly pass it as a prompt to the Gemini API. Instead, we add some "prompt injection", i.e. additional instruction for the AI model so that we can have control over the output we get.</p>
<p>Then we pass the prompt to Gemini using the <code>generateContent()</code> method. Finally we pass the generated output as a JSON response object.</p>
<h3 id="heading-step-5-create-a-client-side-function-to-handle-post-request">Step 5: Create a client side function to handle POST request</h3>
<p>First, we will define two state variables in our home page <code>page.js</code> :</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [prompt, setPrompt] = useState(<span class="hljs-string">''</span>);
<span class="hljs-keyword">const</span> [code, setCode] = useState(<span class="hljs-string">''</span>);
</code></pre>
<p>Set an <code>onChange</code> listener to bind the state variable <code>prompt</code> to the input text:</p>
<pre><code class="lang-javascript">&lt;input
  className=<span class="hljs-string">"peer h-full w-full outline-none bg-gray-100 text-sm text-gray-700 pl-4 pr-12"</span>
  type=<span class="hljs-string">"text"</span>
  value={prompt}
  onChange={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> setPrompt(e.target.value)}
  placeholder=<span class="hljs-string">"Enter a prompt..."</span>
/&gt;
</code></pre>
<p>Create a function called <code>handleGenerate()</code> above the return function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleGenerate = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/api/generate'</span>, {
        <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
        <span class="hljs-attr">headers</span>: {
          <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
        },
        <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">body</span>: prompt })
      });

      <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
      <span class="hljs-keyword">if</span> (response.ok) {
        setCode(data.code);

      } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">console</span>.error(data.error);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error);
    }
  };
</code></pre>
<p>This function initiates an HTTP POST request to the endpoint <code>/api/generate</code> using the <code>fetch</code> function. It sends the prompt as a request object.</p>
<p>Set an <code>onClick</code> listener in your send button to execute the <code>handleGenerate</code> function:</p>
<pre><code class="lang-javascript">&lt;div onClick={handleGenerate} className=<span class="hljs-string">"absolute right-0 flex items-center justify-center h-full w-12 bg-blue-500 hover:bg-blue-600 text-white cursor-pointer"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-2xl'</span>&gt;</span>➔<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>We need to display the code which is stored in the <code>code</code> state variable somewhere:</p>
<pre><code class="lang-javascript">&lt;div className=<span class="hljs-string">'bg-transparent rounded mt-7 p-2 flex justify-center'</span>&gt;
    {code}
&lt;/div&gt;
</code></pre>
<p>Now test the application by running <code>npm run dev</code> and test the application by entering a prompt such as "create a pricing section for my website".</p>
<h3 id="heading-step-6-rendering-generated-jsx-code">Step 6: Rendering Generated JSX Code</h3>
<p>Now the final piece of the puzzle is rendering the generated code into user interface instead of just displaying the code. For that, we will use a library called <code>html-react-parser</code> .</p>
<p>Open a new terminal, change directory to the root of your project and run:</p>
<pre><code class="lang-bash">npm install html-react-parser
</code></pre>
<p>To use <code>html-react-parser</code> , in your <code>page.js</code> make the following import:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> parser <span class="hljs-keyword">from</span> <span class="hljs-string">'html-react-parser'</span>;
</code></pre>
<p>Now use the <code>parse</code> method to convert String into JSX code:</p>
<pre><code class="lang-javascript">&lt;div className=<span class="hljs-string">'bg-transparent rounded mt-7 p-2 flex justify-center'</span>&gt;
    {parse(code)}
&lt;/div&gt;
</code></pre>
<h3 id="heading-step-7-function-to-copy-code">Step 7: Function to Copy code</h3>
<p>You can write a function to copy code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleCopy = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> navigator.clipboard.writeText(code);
      alert(<span class="hljs-string">"Code copied to clipboard"</span>)
    } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to copy: '</span>, err)
    }
  }
</code></pre>
<p>It uses the <code>navigator.clipboard.writeText</code> method to write the text stored in the variable <code>code</code> to the system clipboard.</p>
<h3 id="heading-wrapping-up">Wrapping Up</h3>
<p>You can get the full code for this project at the github repo: <a target="_blank" href="https://github.com/avionmission/ui-generator">https://github.com/avionmission/ui-generator</a></p>
]]></content:encoded></item><item><title><![CDATA[The Practical Guide to Kubernetes ☸️ for Beginners (DevOps Essentials #2)]]></title><description><![CDATA[Welcome to the second chapter of the series DevOps Essentials, where we will take a practical hands-on approach to learning Kubernetes. I will also explain the architecture of Kubernetes and important concepts like Pods, Clusters, Nodes, and useful t...]]></description><link>https://blog.avionmission.com/practical-guide-to-kubernetes</link><guid isPermaLink="true">https://blog.avionmission.com/practical-guide-to-kubernetes</guid><category><![CDATA[Devops]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[cloud native]]></category><dc:creator><![CDATA[Avinash Prasad]]></dc:creator><pubDate>Mon, 22 May 2023 08:01:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684740530107/c50be229-e57b-4c46-a4e5-68ffcc5a57bb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the second chapter of the series <strong><em>DevOps Essentials</em></strong>, where we will take a practical hands-on approach to learning Kubernetes. I will also explain the architecture of Kubernetes and important concepts like Pods, Clusters, Nodes, and useful tools like Minikube and Killercoda.</p>
<p>This series is specifically designed to help developers who are new to DevOps gain a solid understanding of all the essential Cloud Native tools and paradigms. Make sure to <a target="_blank" href="https://avionmission.hashnode.dev/newsletter"><strong>subscribe to our newsletter</strong></a> so you don't miss an episode. Let's Begin!</p>
<h2 id="heading-why-is-kubernetes">Why is Kubernetes?</h2>
<p>Instead of starting with formal definitions of Kubernetes and "container orchestration", let's start with WHY you should care so that you understand the relevance of Kubernetes instead of rote-learning it as a concept. And it ties back to Docker.</p>
<p><a target="_blank" href="https://avionmission.hashnode.dev/beginners-guide-to-docker-devops-essentials-1">In the last chapter</a> we talked about Containerisation, docker, how to build a docker image, run your containerized application, and push it to Dockerhub.</p>
<p>It's important to recognize that managing containerized applications in production environments can present certain challenges.</p>
<p>One such challenge is the manual management of containers. Docker allows you to run containers individually, but <strong>as your application expands to multiple containers or multiple instances of the same container, coordinating and scaling them becomes increasingly cumbersome</strong>. This is where the need for a container orchestration platform like Kubernetes arises.</p>
<p>One of the key problems that Kubernetes solves is container scheduling and scaling. <strong>It <em>intelligently</em> schedules containers, ensuring efficient resource utilization and optimizing performance.</strong> Additionally, Kubernetes <strong>enables horizontal scaling by automatically adding or removing container instances based on workload demands, ensuring your application can handle varying levels of traffic.</strong></p>
<p>Now you understand the relevance and importance of Kubernetes and <em>container orchestration</em>.</p>
<p>Before we talk about Kubernetes architecture and how it actually works, let's get you a taste of <em>using</em> Kubernetes. We will skip the boring installation part by using an online cloud-based Kubernetes playground!!</p>
<h2 id="heading-lets-start-using-kubernetes">Let's start using Kubernetes!</h2>
<p><a target="_blank" href="https://killercoda.com/playgrounds">Killercoda</a> is a platform that provides a Kubernetes playground on the cloud. It allows users to spin up Kubernetes clusters and experiment with Kubernetes features and functionalities without the need for local installations or infrastructure setup.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684561098101/e581cfbe-4f0c-4862-9d38-e25553852f79.png" alt class="image--center mx-auto" /></p>
<p>After logging on to <a target="_blank" href="https://killercoda.com/playgrounds">https://killercoda.com/playgrounds</a>, select the Kubernetes 1.27 environment. Click 'Start' and you'll get a 60-minute session and a terminal to experiment with K8s.</p>
<p>By the way, Kubernetes is also called K8s (because there are 8 letters between K and s :P).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684590801231/21124d41-28ec-42d9-820a-bedc654f0327.png" alt class="image--center mx-auto" /></p>
<p>Let's deploy your first container using Kubernetes, enter the following command in the terminal:</p>
<pre><code class="lang-bash">kubectl run nginx --image=nginx
</code></pre>
<p>Congrats 🎉 You created your first deployment (aka pod) and ran it on a "cluster". Let me explain what just happened:</p>
<ul>
<li><p><code>kubectl</code> is the cli tool used to interact with Kubernetes "clusters". A cluster is a group of nodes (physical or virtual machines) that work together to run a containerized application.</p>
</li>
<li><p><code>run</code> is a command in Kubectl used to create and run a deployment or a single instance of a containerized application called "Pod".</p>
</li>
<li><p>In Kubernetes everything runs as a "Pod" and every pod has its own IP. It's important to note that <strong>Pods in Kubernetes can have multiple containers, and these containers share the same network namespace and IP address.</strong> Each container within the Pod is assigned a unique port, allowing them to receive traffic individually.</p>
</li>
<li><p><code>nginx</code> is the name we gave to this deployment/pod, but you can choose any name.</p>
</li>
<li><p><code>--image=nginx</code> specifies the container image to use for the deployment. In this example, we are using the Nginx Docker image, which is pulled from the docker hub.</p>
</li>
</ul>
<p>If you want to see the list of all the pods running, use <code>kubectl get pods</code> :</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684593169215/528ef24a-7707-4eba-a374-59c66a4139c4.png" alt class="image--center mx-auto" /></p>
<p>But it shows very limited information about the pods. To see additional information such as node name, IP address, etc. use the <code>--o wide</code> flag. This can be useful for troubleshooting or understanding the pod distribution across nodes. Just run the command <code>kubectl get pods -o wide</code> :</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684593637625/7bf1147c-be82-4d29-81c9-6797f52254c0.png" alt class="image--center mx-auto" /></p>
<p>Let's try something more interesting than just running a pod with a container and seeing the list of pods.</p>
<p>So we have a pod named nginx running, which uses the <code>nginx</code> webserver container. How do you access this container?</p>
<p>Run this command: <code>kubectl exec -it nginx -- sh</code></p>
<ul>
<li><p><code>exec</code>: This subcommand is used to execute a command in a container.</p>
</li>
<li><p><code>-it</code>: These flags stand for "interactive". It enable an interactive session with the container.</p>
</li>
<li><p><code>-- sh</code>: It specifies the command to be executed in the container, which in this case is <code>sh</code> (the shell).</p>
</li>
</ul>
<p>By entering this command, you can access the shell environment of the "nginx" container. So now you can perform various operations within the container, such as running commands, inspecting the container's file system, and more.</p>
<p>Try running <code>curl http://localhost</code> while inside the interactive shell of the nginx container:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684654811764/93c8cb21-c34c-4e5f-9cbb-9b4516c89573.png" alt class="image--center mx-auto" /></p>
<p>If the Nginx container is functioning correctly, you should see the HTML content of the "Welcome to nginx" page in the output of the <code>curl</code> command.</p>
<p>You can use the command <code>exit</code> to come out of interactive shell and back to the <code>controlplane</code> . But wait....what is a <code>controlplane</code> ???</p>
<p>Perfect. Now that you have some hands-on experience with using Kubernetes. We should get into how it actually works, how do pods function and what does the Architecture of Kubernetes look like? Let's go. 🚀</p>
<h2 id="heading-kubernetes-architecture-explained">Kubernetes Architecture Explained</h2>
<p>To understand the architecture of Kubernetes you need to understand how a "<strong>cluster</strong>" works. The cluster is the fundamental infrastructure required to run Kubernetes.</p>
<h3 id="heading-clusters">Clusters</h3>
<p>A Kubernetes <strong>cluster</strong> consists of multiple nodes. Nodes are virtual or physical machines. These nodes work together to manage and run containerized applications.</p>
<p>Without a cluster, there is no Kubernetes infrastructure to manage containers and orchestrate application deployments. The cluster provides the necessary resources, networking, and coordination mechanisms for running and scaling containerized applications.</p>
<p>When we used Killercoda in the above walkthrough to experiment with Kubernetes functions, Killercoda provided us with a pre-configured cluster that was ready to use.</p>
<p>For local development and testing on your own machine, I'll show you how to use a tool called <code>Minikube</code> to set up a single-node Kubernetes cluster on your local machine.</p>
<p>A Kubernetes cluster has a very particular structure analogous to the Kubernetes Architecture. Let's break it down.</p>
<h3 id="heading-the-structure-of-a-cluster">The Structure of a Cluster</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684740419255/a66021fc-5011-4da8-80f2-da73acb56aa8.png" alt class="image--center mx-auto" /></p>
<p>When you set up a Kubernetes cluster two kinds of nodes (physical/virtual machines) are established: Control plane nodes and Worker nodes. In the above example, there is one Control plane node and 2 Worker nodes. Let's understand what they do and what each of their components do:</p>
<ol>
<li><p><strong>Control Plane Node</strong></p>
<p> The Control Plane Node <strong>hosts the components that are responsible for managing and controlling the cluster's overall state.</strong></p>
<p> They are not created or replicated automatically when new pods are created. Instead, <strong>they remain stable to provide a consistent management and control layer for the cluster.</strong></p>
<p> Let's understand the relevance of each component (refer to the above diagram):</p>
<ol>
<li><p>API Server: It serves as the central control point for the Kubernetes cluster. It exposes the Kubernetes API, receives and processes requests from clients, and interacts with the <strong>etcd</strong> database.</p>
</li>
<li><p>etcd: It is a distributed key-value store that <strong>stores the cluster's configuration data and the state of the cluster</strong>. It <strong>provides a consistent and reliable data store for the control plane nodes</strong>.</p>
</li>
<li><p>Scheduler: It is <strong>responsible for assigning newly created pods to nodes based on resource requirements, node availability, and scheduling policies.</strong></p>
</li>
<li><p>Controller Manager: It <strong>runs various controllers that monitor the cluster's state and perform actions to maintain the desired state</strong>. Examples include the Node Controller, ReplicaSet Controller, and Service Controller.</p>
</li>
<li><p>CCM (Cloud Controller Manager): It is <strong>an optional component that integrates Kubernetes with cloud provider-specific features and functionalities.</strong> It manages cloud resources like load balancers, storage volumes, and network configurations.</p>
</li>
</ol>
</li>
<li><p><strong>Worker Nodes</strong></p>
<p> <strong>Worker nodes are</strong> the compute nodes in the Kubernetes cluster <strong>where application workloads run</strong>. They are <strong>responsible for executing containers and handling the actual computation.</strong></p>
<p> Worker nodes, on the other hand, can be added or removed from the cluster dynamically based on scaling requirements or hardware changes. <strong>When a new worker node is added, it joins the cluster and becomes available to run pods.</strong></p>
<p> The <strong>control plane components</strong>, including the API server and Scheduler, <strong>are responsible for scheduling pods to the available worker nodes.</strong></p>
<p> In our example we have one Controle plane node and two Worker nodes. Be every worker node has the same components:</p>
<ol>
<li><p>Kubelet: It is an agent running on each worker node that <strong>communicates with the control plane and manages the containers running on the node.</strong> It takes care of container lifecycle management, executing commands, and reporting the node's status to the control plane.</p>
</li>
<li><p>Kube-proxy: It is <strong>responsible for network proxying and load balancing within the cluster.</strong> It handles the networking tasks required for communication between services, routing traffic, and managing network policies.</p>
</li>
<li><p>pod 1, pod 2,..pod n: These represent the pods running on the worker node. <strong>A Pod,</strong> as mentioned earlier, <strong>is the smallest unit of deployment in Kubernetes, each pod can run multiple containers.</strong></p>
</li>
<li><p>Container-d: <strong>It is the container runtime</strong> used to manage container operations, such as container creation, execution, and termination.</p>
</li>
</ol>
</li>
</ol>
<p>Now you understand the entire architecture of a Kubernetes Cluster. The Control plane node components collectively manage and control the cluster, while worker nodes are responsible for handling container management and execution.</p>
<p>If you run the command <code>kubectl get nodes</code> in your Killercoda Kubernetes playground terminal. You can see there are two nodes running, one control-plane node and one worker node:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684737038381/05c10783-9458-4141-a0fa-7e1051526b33.png" alt class="image--center mx-auto" /></p>
<p>We have used Killercoda Playground to experiment with Kubernetes. But you can't rely on online playgrounds such as Killercoda to use Kubernetes because it only gives you 60 minute session time, after which all your work is lost.</p>
<p>Hence, you need to setup Kubernetes locally on your computer if you want experiment with and learn Kubernetes.</p>
<h2 id="heading-minikube">Minikube</h2>
<p>For local development and testing, you can use a tools called Minikube. <strong>It allows you to set up a single-node Kubernetes cluster on your local machine.</strong> It provides a lightweight and convenient way to set up and experiment with Kubernetes without needing a full-scale production environment.</p>
<p>A <strong>"single-node cluster"</strong> means that the control plane node and the worker node are not separate, and all Kubernetes components, such as the API server, Scheduler, Controller Manager, etcd, kubelet, and kube-proxy, run on the same node.</p>
<p>In a single-node cluster, you can deploy and manage containers using Kubernetes concepts and APIs, just as you would in a multi-node cluster.</p>
<p>Minikube is an excellent option for learning Kubernetes. It provides a convenient and self-contained environment for understanding and experimenting with Kubernetes concepts, features, and workflows.</p>
<p>You can setup minikube on your local machine, based on your system using <a target="_blank" href="https://minikube.sigs.k8s.io/docs/start/">this guide</a> from the minikube documentation. But before installing minkube, make sure you install <code>kubectl</code> using this guide.</p>
<p>Minikube provides a simplified way to set up a Kubernetes environment for development and learning purposes, and <code>kubectl</code> allows you to interact with the cluster and manage Kubernetes resources.</p>
<h3 id="heading-working-with-minikube">Working with Minikube</h3>
<p>Once both <code>kubectl</code> and Minikube are installed, you can start using Minikube to create and manage your local Kubernetes cluster.</p>
<p>Run the command <code>minikube start</code> to create a local single-node Kubernetes cluster (make sure the Docker engine is running in your Docker Desktop app if you are a Windows or Mac user).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684736706710/ec474044-e5e6-438d-96f0-0ecc0f6186e8.png" alt class="image--center mx-auto" /></p>
<p>(Yes I'm using Windows in a DevOps tutorial, HARAAAAM, I know)</p>
<p>You can run the command <code>kubectl get nodes</code>, you can see that a node named <code>minikube</code> is running and it is assigned the role <code>control-plane</code> but in fact, it can also act as a worker node.</p>
<p>Now go ahead and ahead and deploy a Pod which uses the nginx container using <code>kubectl</code>, but WAIT!! we are not going to use the command <code>kubectl run nginx --image=nginx</code> which we used previously.</p>
<p>While the <code>kubectl run</code> command with the <code>--image</code> flag is convenient for quickly launching a Pod, using a <strong>Pod YAML file</strong> offers more control, flexibility, and understanding of the underlying Kubernetes configuration. <strong>It is particularly useful when working with more complex Pod configurations or when managing pods as part of larger deployments.</strong></p>
<p>Here's how you can create a new Kubernetes Pod using a Pod YAML file:</p>
<ol>
<li><p>Go to your project directory.</p>
</li>
<li><p>Create a file called <code>pod.yaml</code> , it can have any name.</p>
</li>
<li><p>Add this YAML code in <code>pod.yaml</code> :</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Pod</span>
 <span class="hljs-attr">metadata:</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-pod</span>
     <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span>
         <span class="hljs-attr">tier:</span> <span class="hljs-string">dev</span>
 <span class="hljs-attr">spec:</span>
     <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-container</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">nginx</span>
</code></pre>
</li>
<li><p>This YAML file defines a Pod named "nginx-pod" with a single container named "nginx-container" based on the "nginx" image which it will pull from Dockerhub (if it doesn't find it locally).</p>
</li>
<li><p>Finally create the Pod using the <code>kubectl create</code> command which is used to create a Kubernetes resource defined in a YAML file:</p>
<pre><code class="lang-bash"> kubectl create -f pod.yaml
</code></pre>
</li>
<li><p>You can check if the pod is running by using the command <code>kubectl get pods</code></p>
</li>
</ol>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this chapter, we learned the fundamentals of Kubernetes. With the Killercoda online playground, we deployed our first container using Kubernetes and the <code>kubectl</code> command-line tool. We also understood the architecture of Kubernetes, consisting of control plane nodes and worker nodes.</p>
<p>You have setup Minikube, a tool for creating a local Kubernetes cluster. With this knowledge, you are ready to dive deeper into Kubernetes and DevOps. In a future chapter, we also dive into the Advanced concepts of Kubernets.</p>
<p><strong>Remember, this is just the beginning of our DevOps journey! We will be covering a range of topics in this DevOps Essentials series. Never miss an episode, by subscribing to the newsletter.</strong> 👇</p>
]]></content:encoded></item><item><title><![CDATA[How to use Python code in your React App (React + Flask Tutorial)]]></title><description><![CDATA[Are you a Python developer transitioning into web development and missing the vast array of powerful Python libraries? If so, fear not, for there is a solution! By using a Flask backend for your React application, you can seamlessly execute Python co...]]></description><link>https://blog.avionmission.com/how-to-use-python-code-in-your-react-app-react-flask-tutorial</link><guid isPermaLink="true">https://blog.avionmission.com/how-to-use-python-code-in-your-react-app-react-flask-tutorial</guid><category><![CDATA[Python]]></category><category><![CDATA[React]]></category><category><![CDATA[Machine Learning]]></category><dc:creator><![CDATA[Avinash Prasad]]></dc:creator><pubDate>Mon, 08 May 2023 06:17:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1683525503809/b30a8ce4-8bbd-482f-bb3e-46665f13b1e2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Are you a Python developer transitioning into web development and missing the vast array of powerful Python libraries? If so, fear not, for there is a solution!</strong> By using a Flask backend for your React application, you can seamlessly execute Python code on the server side and harness its functionality within your web app.</p>
<p><strong>In this tutorial, I will guide you through setting up a Flask backend and demonstrate how you can effortlessly leverage the results of executed Python code within your React application.</strong> Say goodbye to limitations and unlock the full potential of Python in your web development endeavors!</p>
<h2 id="heading-flask-vs-django">Flask vs Django</h2>
<p>Both are popular web frameworks for Python but have different approaches and use cases. Flask is a lightweight web framework for Python, designed to make web development quick and straightforward. <strong>Whether you're a beginner or an experienced developer, Flask provides an intuitive way to create powerful web applications, RESTful APIs, and even microservices</strong>.</p>
<p>When I was <a target="_blank" href="https://github.com/avionmission/smartfeedai/tree/42e8289e53c68207f09388dc72f8fbda760c689a">building my own project</a>, I started by using Django, but I found it overwhelming considering my simple use case. Flask's simplicity is what I love about it, you can get started quickly and easily, especially for smaller projects or prototypes.</p>
<p>It provides a solid foundation for web development without imposing too many constraints or assumptions. With Flask, you have more freedom to choose and integrate only the components and libraries you need, making it easier to maintain and understand your codebase.</p>
<p>Let's dive into code, and actually show you how simple it is to set up a Flask backend for your react app!</p>
<h2 id="heading-creating-a-flask-react-app-step-by-step">Creating a Flask + React App (step by step)</h2>
<h3 id="heading-step-1-setup-your-react-frontend"><strong>Step 1:</strong> Setup your React frontend</h3>
<ul>
<li><p>You can use Gatsby or Nextjs for your project. But to keep things simple for this example we will use the good old <code>create react app</code> :</p>
<pre><code class="lang-bash">  npx create-react-app react-flask-app
  <span class="hljs-built_in">cd</span> react-flask-app
</code></pre>
</li>
</ul>
<h3 id="heading-step-2-create-a-virtual-environment"><strong>Step 2:</strong> Create a virtual environment</h3>
<ul>
<li><p>We will place our backend API directory inside the same directory for this example so create a new folder <code>api</code> inside the project folder.</p>
</li>
<li><p><strong>Then we need to create a virtual environment. Why?</strong> Because creating a virtual environment before setting up a Flask API provides a controlled and isolated environment for your project, where you can install project-specific dependencies and manage the project's environment separately from the system-wide Python installation. <strong>It is a good practice that promotes maintainability, stability, and collaboration in your Flask API development workflow.</strong></p>
</li>
<li><pre><code class="lang-bash">    <span class="hljs-built_in">cd</span> api
    python3 -m venv venv
</code></pre>
</li>
<li><p>This command creates a virtual environment named "venv" using Python 3.</p>
</li>
</ul>
<h3 id="heading-step-3-activate-the-virtual-environment-and-install-flask-other-libraries-you-need">Step 3: Activate the virtual environment and install Flask, other libraries you need</h3>
<ul>
<li><pre><code class="lang-bash">    . venv/bin/activate 
    pip install flask python-dotenv scikit-learn
</code></pre>
</li>
<li><p><code>. venv/bin/activate</code> command activates the virtual environment created earlier. The dot (.) at the beginning is a shorthand way to execute the script in the current shell session. The "venv/bin/activate" is the path to the activation script of the virtual environment. Activating the virtual environment sets up the environment variables and modifies the system's PATH to prioritize the Python interpreter and packages within the virtual environment.</p>
</li>
<li><p><code>pip install flask python-dotenv scikit-learn</code> command uses the package manager "pip" to install two Python packages: <code>flask</code> and <code>python-dotenv</code>. The <code>python-dotenv</code> is a package used for managing environment variables from a <code>.env</code> file.</p>
</li>
<li><p>We also installed scikit-learn, let's try and use it in our application.</p>
</li>
</ul>
<h3 id="heading-step-4-creating-a-machine-learning-endpoint-using-python-and-flask">Step 4: Creating a Machine Learning endpoint using Python and Flask</h3>
<ul>
<li><p>In the API directory create <code>api.py</code> and add this code:</p>
<pre><code class="lang-bash">  from sklearn import datasets
  from sklearn.model_selection import train_test_split
  from sklearn.neighbors import KNeighborsClassifier

  app = Flask(__name__)

  @app.route(<span class="hljs-string">'/api/ml'</span>)
  def predict():
      <span class="hljs-comment"># Load the iris dataset</span>
      iris = datasets.load_iris()
      X = iris.data  <span class="hljs-comment"># Features</span>
      y = iris.target  <span class="hljs-comment"># Target variable</span>

      <span class="hljs-comment"># Split the data into training and testing sets</span>
      X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

      <span class="hljs-comment"># Create a K-Nearest Neighbors classifier</span>
      knn = KNeighborsClassifier(n_neighbors=3)

      <span class="hljs-comment"># Train the classifier</span>
      knn.fit(X_train, y_train)

      <span class="hljs-comment"># Make predictions on the test set</span>
      y_pred = knn.predict(X_test)

      <span class="hljs-comment"># Print the accuracy of the model</span>
      accuracy = knn.score(X_test, y_test)

      <span class="hljs-built_in">return</span>{<span class="hljs-string">'accuracy'</span>: accuracy}
</code></pre>
<ul>
<li><p>This code sets up a Flask API with <code>/api/ml</code> route which performs a machine learning prediction using scikit-learn.</p>
</li>
<li><p>Inside the <code>/api/ml</code> route, we have a simple ML program, the code loads the Iris dataset, splits it into training and testing sets, and trains a K-Nearest Neighbors classifier. It then makes predictions on the test set and calculates the accuracy of the model. Finally, it returns the accuracy as a JSON response.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-step-5-using-the-python-code-in-our-react-frontend">Step 5: Using the Python code in our react frontend</h3>
<ul>
<li><p>To run the Flask backend, use this command (while the virtual environment is active):</p>
<pre><code class="lang-bash">  flask run
</code></pre>
</li>
<li><p>Now in a separate terminal run the react frontend with:</p>
<pre><code class="lang-bash">  npm start
</code></pre>
</li>
<li><p>Let's see how we can get the accuracy of the ML model, that our flask backend returns in our react code:</p>
<pre><code class="lang-javascript">    <span class="hljs-keyword">const</span> [accuracy, setAccuracy] = useState(<span class="hljs-number">0</span>);

    useEffect(<span class="hljs-function">() =&gt;</span> {
      fetch(<span class="hljs-string">"/api/ml"</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json()).then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> { setAccuracy(data.accuracy) });
    }, [])
</code></pre>
</li>
<li><p>This code snippet sets up a state variable <code>accuracy</code> with an initial value of 0 using <strong>useState hook</strong>. It uses the <strong>useEffect hook</strong> to make an API request to <code>/api/ml</code> when the component mounts.</p>
</li>
<li><p>The response from the Flask API is parsed as JSON, and the accuracy value is extracted and stored in the <code>accuracy</code> state variable using the setAccuracy function. This triggers the update of the accuracy value. You can use this accuracy value in your react app, perhaps inside a &lt;p&gt; tag to display it.</p>
</li>
<li><p>That's it now you can write any kind of Python code, execute it in the backend, retrieve the code and use it in your React frontend!</p>
</li>
</ul>
<h3 id="heading-important">Important</h3>
<ul>
<li><p>In the <code>package.json</code> file in your project folder, add this:</p>
<pre><code class="lang-javascript">  <span class="hljs-string">"proxy"</span>: <span class="hljs-string">"http://127.0.0.1:5000"</span>
</code></pre>
</li>
<li><p><strong>Why do we need to add this?</strong> Due to security restrictions known as the Same-Origin Policy, the React app running on one port (e.g., 3000) may not be able to directly make API requests to a different port (e.g., 5000) where your Flask API is running. <strong>By specifying</strong> <code>"proxy": "</code><a target="_blank" href="http://127.0.0.1:5000"><code>http://127.0.0.1:5000</code></a><code>"</code> <strong>in the</strong> <code>package.json</code> <strong>file, you are telling the development server to proxy API requests that cannot be handled by the React app to the specified URL.</strong></p>
</li>
<li><p>Add <code>venv</code> in to your <code>.gitignore</code> file. Ignoring the <code>venv</code> folder helps maintain project reproducibility. By allowing each developer to create their own virtual environment, you ensure that everyone is working with the same set of dependencies.</p>
</li>
<li><p>It is also a good practice because <strong>excluding the</strong> <code>venv</code> <strong>folder from version control helps protect sensitive information that might be stored within the environment, such as API keys</strong>, access tokens, or database credentials.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In your Flask backend, you can write any kind of Python code and create routes and endpoints to handle specific functionalities. <strong>By defining these routes and endpoints, you can execute the corresponding Python code and retrieve the results as JSON data.</strong></p>
<p><strong>To integrate this data into your React app, you can use the fetch API or similar methods to make requests to these endpoints and receive the JSON data in your React app.</strong> This allows you to utilize the data retrieved from the Flask backend within your React app for further processing or display.</p>
<p><a target="_blank" href="https://twitter.com/avionmission">Follow me on Twitter</a> for more tips &amp; tricks, and app development content updates.</p>
<hr />
<p>👨‍💻 If you are looking to hire someone to help you with your React + Flask app, look no further ;) <a target="_blank" href="https://twitter.com/avionmission">DM me on Twitter</a> or check out <a target="_blank" href="https://avionmission.com">https://avionmission.com</a></p>
]]></content:encoded></item><item><title><![CDATA[Beginners Guide to Docker 🐋 (DevOps Essentials #1)]]></title><description><![CDATA[Welcome to the first chapter of the series DevOps Essentials, where we will be exploring the fundamentals of Docker.
This series is specifically designed to help students and developers who are new to DevOps gain a solid understanding of all the esse...]]></description><link>https://blog.avionmission.com/beginners-guide-to-docker-devops-essentials-1</link><guid isPermaLink="true">https://blog.avionmission.com/beginners-guide-to-docker-devops-essentials-1</guid><category><![CDATA[Devops]]></category><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Avinash Prasad]]></dc:creator><pubDate>Fri, 05 May 2023 16:50:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1683302954536/bf1041c1-f94f-4fd9-a903-97826479e179.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the first chapter of the series <strong><em>DevOps Essentials</em></strong>, where we will be exploring the fundamentals of Docker.</p>
<p>This series is specifically designed to help students and developers who are new to DevOps gain a solid understanding of all the essential Cloud Native tools.</p>
<p><strong>Throughout this series, I plan to cover everything you need to learn to master DevOps, from the basics of Docker &amp; Kubernetes to more advanced topics like CI/CD, Service Mesh, Infrastructure Monitoring, and more.</strong> Make sure to <a target="_blank" href="https://avionmission.hashnode.dev/newsletter">subscribe to our newsletter</a> so you don't miss an episode. Let's Begin!</p>
<h2 id="heading-the-story-of-docker">The Story of Docker</h2>
<p>Instead of starting with a definition of Docker, let's start with understanding what problems led to developers creating Docker. <strong>What problem did it solve?</strong></p>
<p>In the early days of software development, building and running applications on different computers was a major challenge. <strong>Developers would often encounter issues with compatibility and system dependencies, which would take hours, if not days, to resolve.</strong> Moreover, setting up the servers and computers that hosted the applications was a tedious and time-consuming process.</p>
<p>Before the advent of Docker and containerization, when developers worked together, they often struggled and had frustration related to dependency and environment conflicts.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683294730974/cf250528-d238-42a4-b3fb-cd0552b046a0.png" alt class="image--center mx-auto" /></p>
<p><strong>However, the advent of containerization technology has revolutionized the way we build and run applications. Docker, in particular, has become the go-to tool for developers and IT professionals who want to simplify and streamline the application deployment process.</strong></p>
<p>So, what is Docker, and how does it work? In simple terms, <strong>Docker is a tool that allows developers to run their applications in an isolated environment known as a "container." A container is essentially a lightweight, portable package that contains everything needed to run an application, including the code, runtime, system tools, libraries, and dependencies.</strong></p>
<p>With Docker, developers can create a container that can run on any computer, regardless of the underlying operating system or hardware. This solves the problem of the infamous phrase "but it's working on my computer," which developers often encounter when collaborating on projects. Docker ensures that everyone is working in the same environment, regardless of their local setup.</p>
<h3 id="heading-difference-between-container-and-image">Difference between Container and Image</h3>
<p>You might notice me using the words "container" and "image" interchangeably but the two are different. Beginners often get confused between the two so it's important to understand the difference.</p>
<p><strong>An image is essentially a read-only template that contains the instructions for creating a Docker container. It is a snapshot of a Docker container that includes the application code, libraries, dependencies, and any other files or configurations required to run the application.</strong></p>
<p>On the other hand, a container is a runnable instance of an image that can be launched and stopped. When you start a container, Docker creates a writable layer on top of the image that allows you to make changes to the container without affecting the image itself. This writable layer is also deleted when the container is stopped or removed.</p>
<p><strong>In summary, an image is a static snapshot of an application and its dependencies, while a container is a dynamic, running instance of that image.</strong></p>
<h2 id="heading-the-docker-architecture">The Docker Architecture</h2>
<p>Now that you understand what problem Docker solves and what it basically does, we'll get into the specifics. Let's talk about the different components and terms related to the Docker Architecture:</p>
<p><img src="https://docs.docker.com/assets/images/architecture.svg" alt="Docker Architecture diagram" /></p>
<ol>
<li><p><strong>Runtime</strong>: The runtime is the environment where the application runs, including the operating system, libraries, and dependencies.</p>
</li>
<li><p><strong>Docker Engine (daemon):</strong> The Docker engine handles tasks such as creating, starting, stopping, and removing containers, as well as managing the storage and networking required for the containers.</p>
</li>
<li><p><strong>Orchestration:</strong> Orchestration refers to the process of managing multiple Docker containers as a group, which can be achieved using tools like Kubernetes and Docker Swarm.</p>
</li>
<li><p><strong>Docker client:</strong> The Docker client is the primary way that users interact with Docker. It accepts commands from users and communicates with the Docker daemon to execute those commands.</p>
</li>
<li><p><strong>Docker host:</strong> The Docker host is the physical or virtual machine where the Docker daemon runs. It is responsible for running containers and managing their resources.</p>
</li>
<li><p><strong>Docker registry:</strong> A Docker registry is a central repository where Docker images are stored and distributed. <strong>The most commonly used registry is Docker Hub, which is a public registry that anyone can use to store and share their Docker images.</strong> However, organizations can also set up their own private registry for added security.</p>
</li>
</ol>
<h2 id="heading-installing-docker">Installing Docker</h2>
<p>To use Docker on different operating systems, developers need to <a target="_blank" href="https://docs.docker.com/desktop/install/windows-install/">install Docker Desktop on Windows</a> or <a target="_blank" href="https://docs.docker.com/desktop/install/mac-install/">Mac</a>, while Linux users can run Docker as it is. Once Docker is installed, developers can use a variety of commands to build and manage containers.</p>
<p>Once you have docker installed, you should be able to use the <code>docker</code> command, check the version of docker installed in your system using <code>docker -v</code></p>
<p>Let's start by running your very first docker image by running:</p>
<pre><code class="lang-bash">docker run -t hello-world
</code></pre>
<p>When you run the <code>docker run -t hello-world</code> command:</p>
<ol>
<li><p>Docker first checks if the <code>hello-world</code> image exists on your local machine.</p>
</li>
<li><p>If the image does not exist locally, Docker will download it from the Docker Hub registry.</p>
</li>
<li><p>Once the image is available, Docker creates a container from the image and then starts the container.</p>
</li>
<li><p>In this case, the <code>hello-world</code> container simply prints a message to the console, indicating that the Docker installation is working properly.</p>
</li>
</ol>
<h2 id="heading-building-your-own-container">Building your own Container!</h2>
<p>Now I will teach you how you can build your own container using Docker. For this example, we will use <a target="_blank" href="https://github.com/avionmission/smartfeedai/tree/42e8289e53c68207f09388dc72f8fbda760c689a">one of my open-source applications</a>. You can go to <a target="_blank" href="https://github.com/avionmission/smartfeedai/tree/42e8289e53c68207f09388dc72f8fbda760c689a">this link</a> and clone the app if you want to follow along:</p>
<ol>
<li><p><strong>The first step to building your Docker image is to write a Dockerfile</strong>. A Dockerfile is a text file that contains instructions on how to build your Docker image. You can simply name it <code>Dockerfile</code> (without any file extension) and store it in the root folder of your app.</p>
</li>
<li><p>Here's the code for the docker file of my application:</p>
<pre><code class="lang-makefile"> <span class="hljs-comment"># This Dockerfile builds the React client and API together</span>

 <span class="hljs-comment"># Build step #1: build the react front end</span>
 FROM node:14-alpine as build-step
 WORKDIR /app 
 ENV PATH /app/node_modules/.bin:$PATH
 COPY package.json package-lock.json ./
 COPY ./src ./src 
 COPY ./public ./public
 RUN npm install 
 RUN npm run build  

 <span class="hljs-comment"># Build step #2: build the API with the client as static files</span>
 FROM python:3.10
 WORKDIR /app
 COPY --from=build-step /app/build ./build

 RUN mkdir ./api
 COPY api/requirements.txt api/api.py api/.flaskenv ./api/
 RUN pip install -r ./api/requirements.txt
 ENV FLASK_ENV production

 EXPOSE 3000
 WORKDIR /app/api
 CMD [<span class="hljs-string">"gunicorn"</span>, <span class="hljs-string">"-b"</span>, <span class="hljs-string">":3000"</span>, <span class="hljs-string">"api:app"</span>]
</code></pre>
</li>
</ol>
<h3 id="heading-explanation-of-the-dockerfile">Explanation of the Dockerfile</h3>
<p>It's better to understand how to write a Dockerfile by example. <strong>Keep in mind that the Dockerfile is simply the instructions for how to build and run your app in the docker image/container.</strong></p>
<p>The above Dockerfile has two build steps and each step is defined by a <code>FROM</code> statement that sets the base image for that step.</p>
<p>The first build step starts by using the <code>node:14-alpine</code> base image to build the React front-end. It sets the working directory to <code>/app</code> and adds the <code>node_modules/.bin</code> directory to the system's <code>PATH</code>. The <code>package.json</code> and <code>package-lock.json</code> files are copied to the working directory, and the <code>npm install</code> command is run to install the necessary dependencies. Then, the <code>src</code> and <code>public</code> directories are copied to the working directory, and the <code>npm run build</code> command is run to build the React app.</p>
<p>The second build step starts with the <code>python:3.10</code> base image, and it copies the built React app from the previous build step by using the <code>--from</code> flag. Then, it creates a new directory called <code>api</code> and copies the <code>requirements.txt</code>, <a target="_blank" href="http://api.py"><code>api.py</code></a>, and <code>.flaskenv</code> files to it. After that, it installs the necessary Python packages by running <code>pip install -r ./api/requirements.txt</code> and setting the Flask environment variable to <code>production</code>. Finally, it exposes port 3000, sets the working directory <code>/app/api</code>, and starts the API by running the <code>CMD</code> command <code>gunicorn -b :3000 api:app</code>.</p>
<p>The docker will differ from project to project depending what are the steps and resources required to build and run the app.</p>
<p>Now, back to building our docker image...</p>
<ol>
<li><p><strong>Build the Docker image:</strong> Once you have your Dockerfile, you can use the <code>docker build</code> command to build your Docker image. In our case the Dockerfile is in the current directory, you can run the following command which follows the template <code>docker build -t username/myimage</code>:</p>
<pre><code class="lang-bash"> docker build -t avionmission/smartfeedai
</code></pre>
</li>
<li><p>That's it! this command will build the Docker image and tag it with <code>username/myimage</code> which in my case is <code>avionmission/smartfeedai</code> . After you have built your Docker image, you can test it by running a container based on the image. You can use the <code>docker run</code> command to start a container. For example:</p>
<pre><code class="lang-bash"> docker run -it 3000:3000 avionmission/smartfeedai
</code></pre>
<p> This command creates and starts a container based on the <code>avionmission/smartfeedai</code> image, opens an interactive session with the container, and maps the port <code>3000</code> in the container to the port <code>3000</code> on the host machine. You can use the app at localhost:3000 on your computer.</p>
</li>
</ol>
<h3 id="heading-pushing-your-docker-image-to-dockerhub">Pushing your Docker Image to DockerHub</h3>
<p>Dockerhub is the most commonly used Docker registry (a central repository where Docker images are stored and distributed). Once your docker image is uploaded to DockerHub, anyone from anywhere in the world can run your docker image in their system. <strong>Here are the steps to push your docker image to DockerHub:</strong></p>
<ol>
<li><p>First, ensure that you are logged in to Docker Hub on your local machine using the <code>docker login</code> command. You will need to provide your Docker Hub username and password to authenticate.</p>
<pre><code class="lang-bash"> docker login
</code></pre>
</li>
<li><p>Next, navigate to the directory where your Dockerfile and any necessary files are located.</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> /path/to/your/dockerfile
</code></pre>
</li>
<li><p>You can verify that your image was created in the previous step by running the <code>docker images</code> command.</p>
<pre><code class="lang-bash"> docker images
</code></pre>
</li>
<li><p>Finally, push your image to Docker Hub using the <code>docker push</code> command using the template <code>docker push username/myimage</code>:</p>
<pre><code class="lang-bash"> docker push avionmission/smartfeedai
</code></pre>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683302015115/c8b548e6-bd8e-440a-883b-a1263da42256.png" alt class="image--center mx-auto" /></p>
<p><strong>Congratulations!! 🎉🎉You've learned how to write a dockerfile, build a docker image, run your containerized application, and push it to Dockerhub.</strong></p>
<p>I hope this guide has been helpful in understanding the fundamentals of Docker and how it can be used to streamline the deployment process.</p>
<p>Follow me on Twitter <a target="_blank" href="https://twitter.com/avionmission">@avionmission</a> for more updates and insights into the world of DevOps. Let's continue on this exciting journey of mastering DevOps together!</p>
<p><strong>Remember, this is just the beginning of our DevOps journey! We will be covering a range of topics in this DevOps Essentials series. Don't miss an episode by subscribing to the newsletter.</strong> 👇</p>
]]></content:encoded></item><item><title><![CDATA[Building an Ai SaaS with MindsDB, GPT4, and React: SmartFeed.ai]]></title><description><![CDATA[I started building my open-source SaaS MVP called SmartFeedAi a week ago. Unaware of machine learning platforms like MindsDB, I started coding with React and Flask, excited to leverage Python's powerful machine learning libraries in the backend. But ...]]></description><link>https://blog.avionmission.com/building-an-ai-saas-with-mindsdb</link><guid isPermaLink="true">https://blog.avionmission.com/building-an-ai-saas-with-mindsdb</guid><category><![CDATA[MindsDBHackathon]]></category><category><![CDATA[mindsdb]]></category><category><![CDATA[GPT 4]]></category><category><![CDATA[AI]]></category><category><![CDATA[SaaS]]></category><dc:creator><![CDATA[Avinash Prasad]]></dc:creator><pubDate>Fri, 28 Apr 2023 05:07:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682594243925/5e9f6262-cbff-4b88-bd14-f6c4a7f05a07.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I started building my open-source SaaS MVP called <a target="_blank" href="https://github.com/avionmission/smartfeedai/">SmartFeedAi</a> a week ago. <strong>Unaware of machine learning platforms like MindsDB, I started coding with React and Flask</strong>, excited to leverage Python's powerful machine learning libraries in the backend. But as I started building, <strong>I realized the challenges that MLOps professionals and developers who build machine learning apps for production face (more on that later).</strong></p>
<p>When I discovered MindsDB on Twitter, I knew it was the solution my app needed. However, by the time I became aware of MindsDB and MindsDB hackathon, only 7 days remained until the end of the hackathon. <strong>I decided to scrap my Flask backend completely and use Express.js with MindsDB instead (even though I was unfamiliar with it at the time).</strong> It was really a race against time for me, but I got to learn so much and <strong>I'm excited to share my story, product, and learnings with all of you!</strong> 🚀</p>
<h2 id="heading-the-app-idea-and-future-of-content">📖 The App Idea (and Future of <em>Content</em>)</h2>
<p>There is a lot of fear-mongering on Twitter that the rise of generative AI will lead to a decline in human-generated content. I don't think so. On the contrary, <strong>I see AI as an opportunity to revolutionize the way we consume content.</strong></p>
<p>Introducing <a target="_blank" href="https://github.com/avionmission/smartfeedai">SmartFeed.ai</a> 🚀, the ultimate solution to help you browse through online content efficiently! Here's a quick Demo video:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/KuWdanSs7Bg">https://youtu.be/KuWdanSs7Bg</a></div>
<p> </p>
<p><strong>With the MVP version of</strong> <a target="_blank" href="https://github.com/avionmission/smartfeedai/"><strong>SmartFeed.ai</strong></a><strong>, you can easily generate short summaries of articles from just a URL using the powerful MindsDB NLP engine.</strong></p>
<p>The MVP has minimal features due to the time constraints of the hackathon but the potential and vision of SmartFeedai are immense. <strong>AI has the power to change and improve the way people consume content, and SmartFeedai is at the forefront of this revolution.</strong> As SmartFeedai continues to evolve, I believe it will become an essential tool for anyone who wants to stay informed and up-to-date in today's fast-paced world.</p>
<h2 id="heading-how-does-it-work">🔩 How does it work?</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/avionmission/smartfeedai/">SmartFeed.ai</a> uses MindsDB for GPT-4 model that can perform NLP tasks. <strong>MindsDB makes it easy for developers of all skill levels to integrate AI into their applications by automating and integrating top machine learning frameworks (including GPT-4) into the data stack as "AI Tables".</strong> This innovative approach allows you to train and use models directly with your database, speeding up the development process.</p>
</li>
<li><p>For the backend API, I chose to use Express.js, a flexible and minimalistic web framework for Node.js. <strong>It allowed me to quickly and easily set up the endpoints I needed to make requests and retrieve data from the server.</strong></p>
</li>
<li><p>To extract data from web pages, I turned to Cheerio, a fast and efficient library for web scraping in Node.js. <strong>With Cheerio, I was able to parse the HTML content of websites and extract the specific data I needed, which was essential for my project's functionality.</strong></p>
</li>
<li><p>I used React for the frontend of my project due to its component-based architecture and virtual DOM, which allowed for a dynamic and responsive user interface.</p>
</li>
<li><p><strong>Finally, I used</strong> <code>mindsdb-js-sdk</code> <strong>to access MindsDB Cloud's GPT-4 model. MindsDB Cloud is an excellent platform for training and using machine learning models without the need for extensive infrastructure setup.</strong> The SDK allowed me to connect to the MindsDB Cloud API and use the models for my project's predictions.</p>
</li>
</ul>
<h2 id="heading-how-to-use-smartfeedaihttpsgithubcomavionmissionsmartfeedai">💻 How to Use <a target="_blank" href="https://github.com/avionmission/smartfeedai/">SmartFeed.ai</a>?</h2>
<ol>
<li><p>Create a MindsDB cloud account - you can get your free account <a target="_blank" href="https://cloud.mindsdb.com/">here</a>. It's going to allow us to train a Machine Learning model in minutes!!</p>
</li>
<li><p><strong>We will use the MindsDB cloud editor to create a GPT-4 model</strong> that can take long text, understand it and provide a summary based on the given prompt. Here are the SQL commands you have to enter to create the model which will use:</p>
<pre><code class="lang-sql"> <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">MODEL</span> text_summary
 PREDICT text_summary
 <span class="hljs-keyword">USING</span>
     <span class="hljs-keyword">engine</span> = <span class="hljs-string">'openai'</span>,
     model_name = <span class="hljs-string">'gpt-4'</span>,
     input_column = <span class="hljs-string">'text_long'</span>,
     max_tokens = <span class="hljs-number">200</span>,
     prompt_template = <span class="hljs-string">'Summarize the following text, but only enough to inspire intrigue. text:{{text_long}}'</span>;
</code></pre>
<p> Notice how I have used the prompt in the <code>prompt_template</code> property, feel free to use your own prompts based on what kind of response you want from your AI reading assistant ;)</p>
</li>
<li><p>After pasting the above code into the MindsDB cloud editor, click <code>&gt; Run</code> to execute the query and wait for the model to be trained and ready to use.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682584142160/0f64a607-1461-49b7-a02c-fb257e4d57e4.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Clone the <a target="_blank" href="https://github.com/avionmission/smartfeedai">Smartfeedai repository</a>:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">clone</span> https://github.com/avionmission/
</code></pre>
</li>
<li><p>To run the backend, run this command (use the email and password of your MindsDB cloud account):</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> smartfeedai/api
 MINDSDB_USER=&lt;email&gt; MINDSDB_PASS=&lt;password&gt; npm start
</code></pre>
</li>
<li><p>To run the React Frontend, run:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> smartfeedai
 npm start
</code></pre>
</li>
<li><p>That's it! 🎉🎉 Now you can use <a target="_blank" href="https://github.com/avionmission/smartfeedai/">SmartFeed.ai</a> on your localhost port 3000.</p>
</li>
</ol>
<h2 id="heading-conclusion">🏂Conclusion</h2>
<p>In conclusion, <a target="_blank" href="https://github.com/avionmission/smartfeedai/">SmartFeed.ai</a> is a solution that has the potential to change the way we consume online content. <strong>This was made possible with the power of MindsDB and its integration of top machine learning frameworks, such as GPT-4, making it accessible to developers of all skill levels.</strong> As <a target="_blank" href="https://github.com/avionmission/smartfeedai/">SmartFeed.ai</a> continues to evolve, it has the potential to become an essential tool for anyone who wants to stay informed and up-to-date in today's fast-paced world.</p>
<p>I am happy about the partnership between <a target="_blank" href="https://hashnode.com/">Hashnode</a> and <a target="_blank" href="https://mindsdb.com/">MindsDB</a> that brought about this incredible hackathon. The event was a great opportunity to learn about machine learning tech and expand my skill set.</p>
<p>I highly recommend checking out their <a target="_blank" href="https://docs.mindsdb.com/what-is-mindsdb">official documentation</a> and joining their <a target="_blank" href="https://mindsdbcommunity.slack.com/join/shared_invite/zt-1syebtjn9-MLT4dYX2U7NVdorPPDnlRg">Slack community</a>. Start building your machine learning projects today by <a target="_blank" href="https://cloud.mindsdb.com/">creating a free account</a> on MindsDB Cloud and taking advantage of the incredible tools available to you. Thank you again for this opportunity! 🚀🙌🏼🤖</p>
]]></content:encoded></item><item><title><![CDATA[Using OAM and Napptive to Deploy an AI-powered React App]]></title><description><![CDATA[Are you curious about how a team of front-end and mobile developers learned about backend development and DevOps in just two days? My teammate, Siraj Alam, and I participated in the WeMakeDevs x Napptive Hackathon, where we got hands-on experience wi...]]></description><link>https://blog.avionmission.com/using-oam-and-napptive-to-deploy-an-ai-powered-react-app</link><guid isPermaLink="true">https://blog.avionmission.com/using-oam-and-napptive-to-deploy-an-ai-powered-react-app</guid><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[Napptive]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[Devops]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Avinash Prasad]]></dc:creator><pubDate>Sun, 16 Apr 2023 15:31:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1681664418149/2a134325-c5a4-472d-9718-f2d814ccc8a0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you curious about how a team of front-end and mobile developers learned about backend development and DevOps in just two days? My teammate, <a target="_blank" href="https://github.com/sirajlekhak">Siraj Alam</a>, and I participated in the WeMakeDevs x Napptive Hackathon, where <strong>we got hands-on experience with things we had zero knowledge about 3 days ago: setting up a web server, containerizing an application using Docker and Dockerhub, and deploying our application using Napptive</strong>. The last 3 days have been a wild ride.</p>
<p>Our background in front-end and mobile development made sure that we knew absolutely nothing about Docker let alone Kubernetes, getting into this hackathon, but we learned. Thanks to Napptive, you don't really need to know a lot about Kubernetes to start deploying your application (more on this later :).</p>
<p>In this blog post, I will share everything we learned: the use case for OAM and Napptive platform, and how we built an AI-powered React app for the hackathon and deployed it using Napptive. If you're interested in learning about backend development, DevOps, and Ai, this post is for you!</p>
<h2 id="heading-the-project-idea-ai-in-the-backend-react-in-the-frontend">The Project Idea: AI in the Backend, React in the Frontend</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681660306271/72d56ace-bb7b-4695-bfae-cc11bcd4481a.png" alt="A screenshot fo the demo video we made for the hackathon." class="image--center mx-auto" /></p>
<p>Are you worried that artificial intelligence will lead to the decline of blogging and written content by humans? Many people share that concern. However, my teammate Siraj Alam and I have a different perspective. We believe that AI can enhance the reading experience for people who like online, making it more efficient and enjoyable.</p>
<p>To showcase this, we built <a target="_blank" href="https://github.com/avionmission/smartfeedai">SmartFeedAi</a>, an AI-powered React app that provides users with summaries of articles and blogs. Our MVP version had limited features due to the time constraints of the hackathon, but we see huge potential for the full-fledged version.</p>
<p>During the hackathon, we spent a lot of time figuring out the algorithm for summarizing text using the NLP libraries of Python. <strong>We chose React as the front end and Python with Flask as the backend because Python has a lot of machine-learning libraries. While we initially tried using PyTorch for the text summarization task, it proved to be too heavy for the backend.</strong></p>
<p>Ultimately, we used NLTK and old-school NLP algorithms to summarize the text, which made our app much faster. We also want to emphasize that AI is not just machine learning.</p>
<p>Tokenization was one of the key concepts of NLP we learned and used in the project to build the algorithm for summarising text. It involves breaking text into smaller pieces called tokens. These tokens can be words, phrases, or sentences. Tokenization is an important part of NLP and is used in many AI applications.</p>
<p><strong>We also wanted to make it clear that AI is not just machine learning. Many other techniques and algorithms fall under the umbrella of AI. Our project was a great example of how AI can be used to solve real-world problems, even without using machine learning.</strong></p>
<h2 id="heading-but-wait-what-is-oam-again">But wait, what is OAM again?</h2>
<p>Deploying an application in Kubernetes can be a challenge for developers without much experience in DevOps. This is where Napptive comes in. <strong>Napptive helps developers deploy their applications in Kubernetes without requiring a heavy knowledge of Kubernetes. It does that by using something called OAM.</strong></p>
<p>OAM, or the Open Application Model, is a set of guidelines that simplifies the process of building and deploying cloud-based applications. It provides developers with standard building blocks like components, parameters, and traits, which makes it easier to create and manage cloud-based applications that work on any platform. <strong>With OAM, developers can focus on building the application without worrying about the underlying infrastructure.</strong> It will all make sense once you open <a target="_blank" href="https://playground.napptive.dev/">Napptive Playground</a> and start deploying your application.</p>
<p>Great! Now that you have a basic understanding of what OAM is and how Napptive can help you deploy your application, let's get started. But before we jump into the step-by-step process of deploying your application using Napptive, there is one crucial step that you must complete: <strong>Dockerize your application</strong>.</p>
<p>If you're new to the world of DevOps, you might not be familiar with Docker. Dockerization is the process of packaging an application and its dependencies into a single container, which can then be easily deployed to any environment that supports Docker. Don't know how to Dockerize your app? Neither did I 2 days ago! <a target="_blank" href="https://hashnode.com/post/docker-tutorial-for-beginners-cjrj2hg5001s2ufs1nker9he2">Go learn</a> and come back to this post.</p>
<p><strong>Dockerizing your application is the first step in deploying it in a cloud-native environment. Once you have Dockerized your application, you'll see how easy it is to define your application components using OAM and deploy your application on Napptive. So, let's get started!</strong></p>
<h2 id="heading-how-to-deploy-your-docker-image-on-napptive-playground-step-by-step">How to Deploy your Docker Image on Napptive Playground: Step by Step</h2>
<p>Once you create an account and sign in to <a target="_blank" href="https://playground.napptive.dev/">Napptive Playground</a>, you get a free environment with 1 CPU core, 4GB Ram, and 1GB memory which you can use to deploy your applications.</p>
<p>Here's how you can deploy your docker image to Napptive Playground:</p>
<p><strong>Step 1:</strong> Go to the Catalog section in the navigation area on the left of the screen.</p>
<p><strong>Step 2:</strong> Click on Upload App and fill in the details.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681659256234/d1d83295-4b63-4287-9023-9458f72deb67.png" alt class="image--center mx-auto" /></p>
<p><strong>Step 3:</strong> Click on "Select files to load" and this is now you need three files</p>
<p><strong>1)</strong> A <strong>YAML file that describes OAM specifications,</strong> here's ours:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">core.oam.dev/v1beta1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Application</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">smartfeedai</span>
  <span class="hljs-attr">description:</span> <span class="hljs-string">"An Ai powered React App for readers."</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-comment"># List of components that are part of the application.</span>
  <span class="hljs-attr">components:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">app</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">webservice</span>
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">avionmission/smartfeedai:latest</span>
        <span class="hljs-attr">cpu:</span> <span class="hljs-string">"200m"</span>
        <span class="hljs-attr">memory:</span> <span class="hljs-string">"256Mi"</span>
        <span class="hljs-attr">ports:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">3000</span>
            <span class="hljs-attr">exposes:</span> <span class="hljs-literal">true</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">LAUNCHER_TARGET_REPO</span>
            <span class="hljs-attr">value:</span> <span class="hljs-string">https://github.com/avionmission/smartfeedai</span>
      <span class="hljs-attr">traits:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">type:</span> <span class="hljs-string">napptive-ingress</span>
        <span class="hljs-attr">properties:</span>
          <span class="hljs-attr">port:</span> <span class="hljs-number">3000</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">/</span>
</code></pre>
<p><strong>2)</strong> A <strong>README.md</strong> that describes what your app does.</p>
<p><strong>3)</strong> An <strong>app-name.metadata.yaml</strong> that defines things like your logo which will appear in the Napptive Playground catalog and more. Here's what ours look like:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">core.napptive.com/v1alpha1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">ApplicationMetadata</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">"SmartFeedAi"</span>
<span class="hljs-attr">version:</span> <span class="hljs-string">"latest"</span>
<span class="hljs-attr">description:</span> <span class="hljs-string">An</span> <span class="hljs-string">ai</span> <span class="hljs-string">powered</span> <span class="hljs-string">react</span> <span class="hljs-string">app</span> <span class="hljs-string">for</span> <span class="hljs-string">readers</span>
<span class="hljs-attr">keywords:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">"smartfeedai"</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">"nlp"</span>
<span class="hljs-attr">license:</span> <span class="hljs-string">"SSPLv1"</span>
<span class="hljs-attr">url:</span> <span class="hljs-string">"https://github.com/avionmission/smartfeedai"</span>
<span class="hljs-attr">doc:</span> <span class="hljs-string">"https://github.com/avionmission/smartfeedai"</span>
<span class="hljs-attr">logo:</span>
  <span class="hljs-comment"># Do not hotlink images without permission :)</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">src:</span> <span class="hljs-string">"https://raw.githubusercontent.com/avionmission/blog/a76df3f27a343556a6f4028a38d1da005617fcf8/assets/smartfeedicon.svg"</span>
    <span class="hljs-attr">type:</span> <span class="hljs-string">"image/png"</span>
    <span class="hljs-attr">size:</span> <span class="hljs-string">"120x120"</span>
</code></pre>
<p><strong>Step 4:</strong> Click on Deploy! and go to the deployment area. You will see there's a log section that shows that your app is running and an endpoint URL to access your deployed app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681659771626/1711f349-780e-4fc8-8e97-1017277fbf48.png" alt class="image--center mx-auto" /></p>
<p><strong>Step 5:</strong> Done! 🎉 Congratulations you have deployed your app on the Napptive platform.</p>
]]></content:encoded></item><item><title><![CDATA[Mastering Navigation Menus in React Native: 3 Types You Must Know [With Examples]]]></title><description><![CDATA[Designing a mobile app navigation menu can make a big impact on the user experience. A clear and intuitive navigation menu can help users easily find the information and features they need, while a confusing or cluttered menu can lead to frustration ...]]></description><link>https://blog.avionmission.com/mastering-navigation-menus-in-react-native-3-types-you-must-know-with-examples</link><guid isPermaLink="true">https://blog.avionmission.com/mastering-navigation-menus-in-react-native-3-types-you-must-know-with-examples</guid><category><![CDATA[React Native]]></category><category><![CDATA[app development]]></category><category><![CDATA[best practices]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Avinash Prasad]]></dc:creator><pubDate>Mon, 03 Apr 2023 14:42:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682667419001/a9a674f2-0983-4a6d-b73b-9e0dc9e26bd3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Designing a mobile app navigation menu can make a big impact on the user experience. A clear and intuitive navigation menu can help users easily find the information and features they need, while a confusing or cluttered menu can lead to frustration and user drop-off.</p>
<p>In this post, we'll learn how to build different types of navigation menu that enhances the user experience, and how to build each one of them using React Native and <code>react-navigations</code> library.</p>
<p>Let's start with simple navigation from one screen to another.</p>
<h2 id="heading-1-simple-navigation-using-stack-navigator">1. Simple Navigation (using Stack Navigator)</h2>
<p><img src="https://www.avionmission.com/blog/images/2023/StackNavigator.gif" alt /></p>
<p><a target="_blank" href="https://github.com/react-navigation/react-navigation">React Navigation</a> is a popular library used for implementing navigation in React Native apps. It provides a flexible and easy-to-use API for managing the navigation hierarchy between screens in your app.</p>
<p>"The Stack Navigator" allows users to move between screens by pushing and popping them onto a stack. When a new screen is pushed onto the stack, it appears on top of the previous screen. When a screen is popped from the stack, it is removed from the navigation hierarchy, and the previous screen is displayed.</p>
<p>Let's use the Stack Navigator to create a navigation flow between two screens in a React Native app. We will define two screens, Screen1 and Screen2, and use the Stack Navigator to allow users to move between them.</p>
<h3 id="heading-step-1-set-up-a-new-react-native-project">Step 1: Set Up a New React Native Project</h3>
<p>First, create a new React Native project using the following command (this is the command I prefer to use):</p>
<pre><code class="lang-bash">npx create-expo-app NavigationExamples
</code></pre>
<p>This will create a new project called NavigationExample in your current directory.</p>
<h3 id="heading-step-2-install-dependencies">Step 2: Install Dependencies.</h3>
<p>Next, navigate to the project directory and install the required dependencies using the following commands:</p>
<p>cd NavigationExample npm install @react-navigation/native npm install @react-navigation/native-stack npm install react-native-screens react-native-safe-area-context</p>
<h3 id="heading-step-3-define-your-screens">Step 3: Define your Screens</h3>
<p>In order to navigate between screens, we need to create two screen components, so let's create two javascript files <code>Screen1.js</code> and <code>Screen2.js</code> in <code>\screens</code> directory:</p>
<p><strong>Screen1.js</strong> :</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {StyleSheet, View, Text, Button } <span class="hljs-keyword">from</span>  <span class="hljs-string">'react-native'</span>
<span class="hljs-keyword">import</span>  React  <span class="hljs-keyword">from</span>  <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span>  Screen1 = <span class="hljs-function">(<span class="hljs-params">{navigation}</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span>  <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Screen1<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>  <span class="hljs-attr">title</span>=<span class="hljs-string">"Go to Screen 2"</span>  <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span>  navigation.navigate('Screen2')}/&gt;
    <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
    )
} 

<span class="hljs-keyword">const</span>  styles = StyleSheet.create({
    <span class="hljs-attr">container</span>: {
    <span class="hljs-attr">flex</span>:  <span class="hljs-number">1</span>,
    <span class="hljs-attr">backgroundColor</span>:  <span class="hljs-string">'#fff'</span>,
    <span class="hljs-attr">alignItems</span>:  <span class="hljs-string">'center'</span>,
    <span class="hljs-attr">justifyContent</span>:  <span class="hljs-string">'center'</span>,
    },
});

<span class="hljs-keyword">export</span>  <span class="hljs-keyword">default</span>  Screen1;
</code></pre>
<p><strong>Screen2.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {StyleSheet, View, Text, Button } <span class="hljs-keyword">from</span>  <span class="hljs-string">'react-native'</span>
<span class="hljs-keyword">import</span>  React  <span class="hljs-keyword">from</span>  <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span>  Screen2 = <span class="hljs-function">(<span class="hljs-params">{navigation}</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span>  <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Screen1<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>  <span class="hljs-attr">title</span>=<span class="hljs-string">"Go to Screen 1"</span>  <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span>  navigation.navigate('Screen1')}/&gt;
    <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
    )
} 

<span class="hljs-keyword">const</span>  styles = StyleSheet.create({
    <span class="hljs-attr">container</span>: {
    <span class="hljs-attr">flex</span>:  <span class="hljs-number">1</span>,
    <span class="hljs-attr">backgroundColor</span>:  <span class="hljs-string">'#fff'</span>,
    <span class="hljs-attr">alignItems</span>:  <span class="hljs-string">'center'</span>,
    <span class="hljs-attr">justifyContent</span>:  <span class="hljs-string">'center'</span>,
    },
});

<span class="hljs-keyword">export</span>  <span class="hljs-keyword">default</span>  Screen2;
</code></pre>
<p>You'll notice we are passing the prop <code>navigation</code> to both <code>Screen1</code> and <code>Screen2</code> . React Navigation provides the <code>navigation</code> prop to screens. It contains methods and properties that allow us to navigate to other screens, customize the header, and pass parameters between screens. In the code example provided, we passed the <code>navigation</code> prop to the <code>Screen1</code> component so that we could use the <code>navigation.navigate</code> method to move to the <code>Screen2</code> component when the button is pressed.</p>
<h3 id="heading-step-4-create-a-stack-navigator">Step 4: Create a Stack Navigator</h3>
<p>To enable navigation between the screens, we need to create a Stack Navigator. A Stack Navigator is a type of navigator that allows users to move between screens by pushing and popping them on a stack. <strong>App.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { NavigationContainer } <span class="hljs-keyword">from</span> <span class="hljs-string">'@react-navigation/native'</span>;
<span class="hljs-keyword">import</span> { createNativeStackNavigator } <span class="hljs-keyword">from</span> <span class="hljs-string">'@react-navigation/native-stack'</span>;
<span class="hljs-keyword">import</span> { StatusBar } <span class="hljs-keyword">from</span> <span class="hljs-string">'expo-status-bar'</span>;
<span class="hljs-keyword">import</span> { StyleSheet } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> Screen1 <span class="hljs-keyword">from</span> <span class="hljs-string">'./screens/Screen1'</span>;
<span class="hljs-keyword">import</span> Screen2 <span class="hljs-keyword">from</span> <span class="hljs-string">'./screens/Screen2'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">const</span> Stack = createNativeStackNavigator();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavigationContainer</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Stack.Navigator</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Stack.Screen</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Screen1"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Screen1}/</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Stack.Screen</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Screen2"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Screen2}/</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Stack.Navigator</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">NavigationContainer</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  <span class="hljs-attr">container</span>: {
    <span class="hljs-attr">flex</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'#fff'</span>,
    <span class="hljs-attr">alignItems</span>: <span class="hljs-string">'center'</span>,
    <span class="hljs-attr">justifyContent</span>: <span class="hljs-string">'center'</span>,
  },
});
</code></pre>
<p>In the above code, we import the createStackNavigator function from React Navigation and use it to create a Stack Navigator. We then define two screens using the Stack.Screen component, giving each screen a unique name and component.</p>
<p>You can run the app using the command <code>npx expo start</code> and it should work perfectly.</p>
<h2 id="heading-2-navigation-drawer-in-react-native">2. Navigation Drawer in React Native</h2>
<p><img src="https://www.avionmission.com/blog/images/2023/DrawerNavigation.gif" alt /></p>
<p>A classic type of menu that slides in from the left or right side of the screen when users tap on a menu icon. This type of menu is useful for apps with a large number of sections or features.</p>
<h3 id="heading-step-1-install-dependencies">Step 1: Install Dependencies</h3>
<p>To use a navigation drawer, we need to install the <code>@react-navigation/drawer</code> package. Run the following command to install it:</p>
<pre><code class="lang-bash">npm install @react-navigation/drawer
</code></pre>
<h3 id="heading-step-2-define-your-screens">Step 2: Define Your Screens</h3>
<p>We will use the same two screens as before but remove the buttons on each screen.</p>
<h3 id="heading-step-3-setting-up-drawer-navigator">Step 3: Setting up Drawer Navigator</h3>
<p>We will import <code>createDrawerNavigator</code> from <code>@react-navigation/drawer</code> and used it to create the drawer navigator:</p>
<p><strong>App.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createDrawerNavigator } <span class="hljs-keyword">from</span> <span class="hljs-string">'@react-navigation/drawer'</span>;
<span class="hljs-keyword">import</span> { NavigationContainer } <span class="hljs-keyword">from</span> <span class="hljs-string">'@react-navigation/native'</span>;
<span class="hljs-keyword">import</span> { StyleSheet } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> Screen1 <span class="hljs-keyword">from</span> <span class="hljs-string">'./screens/Screen1'</span>;
<span class="hljs-keyword">import</span> Screen2 <span class="hljs-keyword">from</span> <span class="hljs-string">'./screens/Screen2'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">const</span> Drawer = createDrawerNavigator();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavigationContainer</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Drawer.Navigator</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Drawer.Screen</span> <span class="hljs-attr">name</span>=<span class="hljs-string">'Screen1'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Screen1}/</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Drawer.Screen</span> <span class="hljs-attr">name</span>=<span class="hljs-string">'Screen2'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Screen2}/</span>&gt;</span>  
      <span class="hljs-tag">&lt;/<span class="hljs-name">Drawer.Navigator</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">NavigationContainer</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  <span class="hljs-attr">container</span>: {
    <span class="hljs-attr">flex</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'#fff'</span>,
    <span class="hljs-attr">alignItems</span>: <span class="hljs-string">'center'</span>,
    <span class="hljs-attr">justifyContent</span>: <span class="hljs-string">'center'</span>,
  },
});
</code></pre>
<p>If you are getting any errors, it is possible you're missing some dependencies of React Navigation which you can install by running:</p>
<pre><code class="lang-bash">npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
</code></pre>
<h2 id="heading-3-bottom-navigation-bar">3. Bottom Navigation Bar</h2>
<p><img src="https://www.avionmission.com/blog/images/2023/TabNavigation.gif" alt /></p>
<p>A modern type of menu typically appears at the bottom of the screen and displays multiple tabs that users can switch between. This type of menu is ideal for apps with distinct sections or workflows.</p>
<p>Let's start by installing dependencies:</p>
<pre><code class="lang-bash">npm install @react-navigations/bottom-tabs
</code></pre>
<p>To implement a bottom navigation bar in React Native, we will define a <code>createBottomTabNavigator()</code> object and use to handle navigation like this:</p>
<p><strong>App.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createBottomTabNavigator } <span class="hljs-keyword">from</span> <span class="hljs-string">'@react-navigation/bottom-tabs'</span>;
<span class="hljs-keyword">import</span> { NavigationContainer } <span class="hljs-keyword">from</span> <span class="hljs-string">'@react-navigation/native'</span>;
<span class="hljs-keyword">import</span> { StyleSheet } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> Screen1 <span class="hljs-keyword">from</span> <span class="hljs-string">'./screens/Screen1'</span>;
<span class="hljs-keyword">import</span> Screen2 <span class="hljs-keyword">from</span> <span class="hljs-string">'./screens/Screen2'</span>;
<span class="hljs-keyword">import</span> {Ionicons} <span class="hljs-keyword">from</span> <span class="hljs-string">'@expo/vector-icons'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">const</span> Tab = createBottomTabNavigator();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavigationContainer</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Tab.Navigator</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Tab.Screen</span> <span class="hljs-attr">name</span>=<span class="hljs-string">'Screen1'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Screen1}/</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Tab.Screen</span> <span class="hljs-attr">name</span>=<span class="hljs-string">'Screen2'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Screen2}/</span>&gt;</span>  
      <span class="hljs-tag">&lt;/<span class="hljs-name">Tab.Navigator</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">NavigationContainer</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  <span class="hljs-attr">container</span>: {
    <span class="hljs-attr">flex</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'#fff'</span>,
    <span class="hljs-attr">alignItems</span>: <span class="hljs-string">'center'</span>,
    <span class="hljs-attr">justifyContent</span>: <span class="hljs-string">'center'</span>,
  },
});
</code></pre>
<p>When you run the app, you will notice that we have a bottom navigation bar which we can use to switch between <code>Screen1</code> and <code>Screen2</code>, but we have not se icons for those options. We can do that using <code>screenOptions</code> property of <code>Tab.Navigator</code> in this way:</p>
<p>First, you need to import:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {Ionicons} <span class="hljs-keyword">from</span>  <span class="hljs-string">'@expo/vector-icons'</span>
</code></pre>
<p>And then,</p>
<pre><code class="lang-javascript">&lt;Tab.Navigator
  screenOptions={<span class="hljs-function">(<span class="hljs-params">{route}</span>) =&gt;</span> ({
    <span class="hljs-attr">tabBarIcon</span>: <span class="hljs-function">(<span class="hljs-params">{focused, color, size}</span>) =&gt;</span> {
      <span class="hljs-keyword">let</span> iconName;

      <span class="hljs-keyword">if</span> (route.name === <span class="hljs-string">'Screen1'</span>) {
        iconName = focused ? <span class="hljs-string">'home'</span> : <span class="hljs-string">'home-outline'</span>
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (route.name === <span class="hljs-string">'Screen2'</span>) {
        iconName = focused ? <span class="hljs-string">'settings'</span> : <span class="hljs-string">'settings-outline'</span>
      }

      <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Ionicons</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{iconName}</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{size}</span> <span class="hljs-attr">color</span>=<span class="hljs-string">{color}/</span>&gt;</span></span>
    },
  })}
  &gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Tab.Screen</span> <span class="hljs-attr">name</span>=<span class="hljs-string">'Screen1'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Screen1}/</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Tab.Screen</span> <span class="hljs-attr">name</span>=<span class="hljs-string">'Screen2'</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Screen2}/</span>&gt;</span></span>  
&lt;/Tab.Navigator&gt;
</code></pre>
<p>The <code>route</code> the parameter is passed to the <code>screenOptions</code> function to determine which screen is currently active. The <code>focused</code>, <code>color</code>, and <code>size</code> parameters are used to style the icon based on its state.</p>
<p>The <code>if</code> statements are used to determine which icon to display based on the name of the route. If the route name is <code>Screen1</code>, the <code>home</code> icon is displayed if the tab is focused and the <code>home-outline</code> icon is displayed if the tab is not focused. If the route name is <code>Screen2</code>, the <code>settings</code> icon is displayed if the tab is focused and the <code>settings-outline</code> icon is displayed if the tab is not focused.</p>
<p>Finally, the <code>Ionicons</code> component is used to render the selected icon with the appropriate size and color.</p>
<p>With this knowledge, you'll be able to create navigation menus that are flexible, easy to use, and intuitive for your users. We hope that this article has provided you with the tools you need to create great navigation menus for your React Native apps.</p>
<p>If you have any questions or comments about this article, please leave them in the comment section below. And don't forget to <a target="_blank" href="https://twitter.com/avionmission">follow me on Twitter</a> for more tips and tutorials on React Native development. Happy coding! 👨‍💻</p>
<p><em>If you want me to turn your app idea into a fully functional MVP using React Native, don't hesitate to reach out! Contact me at</em> <a target="_blank" href="mailto:avionmission@gmail.com"><strong><em>avionmission@gmail.com</em></strong></a> <em>to discuss how I can help you bring your vision to life.</em></p>
]]></content:encoded></item><item><title><![CDATA[Basics of Jetpack Compose: Day 1 of #100DaysOfJetpackCompose]]></title><description><![CDATA[I think in 2023, Google is going to go all-in on Jetpack Compose, the way it did with Kotlin. And the industry is going to see a major shift from XML-based UI to Compose.
So, I'm starting a #100DaysOfJetpackCompose on Twitter today to document my lea...]]></description><link>https://blog.avionmission.com/basics-of-jetpack-compose-day-1-of-100daysofjetpackcompose</link><guid isPermaLink="true">https://blog.avionmission.com/basics-of-jetpack-compose-day-1-of-100daysofjetpackcompose</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[Android Studio]]></category><category><![CDATA[Jetpack Compose]]></category><dc:creator><![CDATA[Avinash Prasad]]></dc:creator><pubDate>Sat, 14 Jan 2023 17:48:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1673718355388/ab5d3e53-b063-474e-8759-49c81b42e5de.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I think in 2023, Google is going to go all-in on Jetpack Compose, the way it did with Kotlin. And the industry is going to see a major shift from XML-based UI to Compose.</p>
<p>So, I'm starting a <a target="_blank" href="https://twitter.com/search?q=%23100DaysOfJetpackCompose">#100DaysOfJetpackCompose</a> on <a target="_blank" href="https://twitter.com/avionmission">Twitter</a> today to document my learnings. Here's a blog post version of the Day 1 thread:</p>
<p>Let's Go 🚀🚀</p>
<h2 id="heading-composable-functions">Composable Functions</h2>
<p>In Jetpack Compose instead of defining the UI of an Activity in a separate layout file, you define the app's UI programmatically using "composable functions".</p>
<p>Composables are parts of UI that are defined separately and can be re-used effectively.</p>
<p>A composable function is a function with an <code>@Composable</code> annotation before it, like in this simple compose activity:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/*..imports..*/</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComposeActivity</span></span>() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)
        setContent{
            Header(<span class="hljs-string">"Android"</span>)
        }
    }
}

<span class="hljs-meta">@Composables</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Header</span><span class="hljs-params">(name: <span class="hljs-type">String</span>)</span></span> {
    Text(text = <span class="hljs-string">"Hello <span class="hljs-variable">$name</span>!"</span>)
}
</code></pre>
<h2 id="heading-previews">Previews</h2>
<p>To see a preview of your UI without running the app, create a separate composable with <code>@Preview</code> annotation, like this:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/*.. imports. .*/</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComponentAct ivity</span></span>() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">( saved InstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate( savedInstanceState)
        setContent {
            ComposeBasicsTheme {
                Surface( color = MaterialTheme.colors.background) {
                        Header(<span class="hljs-string">"Android"</span>)
                }
           }
        }
    }
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Header</span><span class="hljs-params">( name: <span class="hljs-type">String</span>)</span></span> {
    Text(text = <span class="hljs-string">"Hello <span class="hljs-variable">$name</span>! "</span>)
}

<span class="hljs-meta">@Preview( fontScale = 1.5f)</span>
<span class="hljs-meta">@Preview( showBackground = true)</span>
<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">DefaultPreview</span><span class="hljs-params">()</span></span> {
    ComposeBasicsTheme {
    Header(<span class="hljs-string">"Android"</span>)
}
</code></pre>
<p>The <code>@Preview</code> annotation allows you to check how your UI looks with changes in settings such as font scale and background as seen in the above example.  </p>
<p>And since I used <code>@Preview</code> with different parameters, we can see two different previews:</p>
<p><img src="http://pbs.twimg.com/media/FmcZ2buaYAEXzf1.jpg" alt /></p>
<p>You can create as many Preview functions as you want to see how your UI looks with different properties.</p>
<h2 id="heading-constraintlayout-is-gone">ConstraintLayout is gone!</h2>
<p>This is the new way to organize your UI elements is using <code>Rows</code> s and <code>Column</code> s like this:</p>
<p><img src="http://pbs.twimg.com/media/FmccEyVagAALxD7.jpg" alt /></p>
<p>That's it for today. I'll be back again tomorrow with more notes as I learn Compose. You can follow me on <a target="_blank" href="https://twitter.com/avionmission">Twitter</a> for updates. Till then, Keep building the Future!</p>
]]></content:encoded></item><item><title><![CDATA[How to Convert Python Code into an Android .apk [that doesn't crash!] | Kivymd, Buildozer Tutorial]]></title><description><![CDATA[You created an android app with python using Kivy or Kivymd, but it is still in .py format. How do you convert it into an installable .apk file that dose'nt crash for reasons you can't figure out and do it as quickly as possible? Don't worry, I got y...]]></description><link>https://blog.avionmission.com/how-to-convert-python-code-into-an-android-apk-kivymd-buildozer-tutorial</link><guid isPermaLink="true">https://blog.avionmission.com/how-to-convert-python-code-into-an-android-apk-kivymd-buildozer-tutorial</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[android app development]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Avinash Prasad]]></dc:creator><pubDate>Mon, 28 Mar 2022 08:35:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648456341919/E-SngyhL8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You created an android app with python using Kivy or Kivymd, but it is still in .py format. How do you convert it into an installable .apk file that dose'nt crash for reasons you can't figure out and do it as quickly as possible? Don't worry, I got you covered. Read on.</p>
<p>I created a <a target="_blank" href="https://github.com/avionmission/rockpaperscissor-gui">simple rock-paper-scissor app</a> with python using the kivy and <a target="_blank" href="https://kivymd.readthedocs.io/en/latest/getting-started/">kivymd</a> packages (you can check out it's code <a target="_blank" href="https://github.com/avionmission/rockpaperscissor-gui/blob/main/main.py">here</a>). And then I went on a frustating journey of trying to convert it into an installable android app that doesn't crash as soon as you open it. I did it. In this post I'll simplify the process for you and how to make sure your app dose not crash.</p>
<p>If you have no experience with Kivy or Kivymd, you can get started with this <a target="_blank" href="https://www.youtube.com/watch?v=3Q7ytIEacBc">tutorial</a> which teaches you to create a simple application in 9 minutes.
But even though the apps that you create using python and kivymd look great and have material design. They are still in <code>.py</code> format. So how do you convert your python programs into installable <code>.apk</code> files?</p>
<p>This is where the <a target="_blank" href="https://buildozer.readthedocs.io/en/latest/index.html">buildozer</a> and <a target="_blank" href="https://colab.research.google.com/?utm_source=scs-index">Google Collab</a> comes in. Buildozer is a tool for packaging mobiles application easily. It automates the entire build process and downloads the prerequisites like python-for-android, Android SDK, NDK, etc. And Google Colaboratory, or “Colab” for short, allows you to write and execute any python code through the browser. It requires no setup to use and provides free access to computing resources including GPUs from Google.</p>
<p>Here is a simple step-by-step process for converting <code>.py</code> to <code>.apk</code></p>
<h2 id="heading-step-1-use-these-pre-written-commands">STEP 1: Use these pre-written commands</h2>
<p>Open this <a target="_blank" href="https://colab.research.google.com/gist/kaustubhgupta/0d06ea84760f65888a2488bac9922c25/kivyapp-to-apk.ipynb">colab notebook</a>, and you will find some prewritten commands. But don't execute any command yet! Come back here after checking it out and wait for my commands ;-)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648456368158/gcV1rFAnD.png" alt="colab-buildozer-ss.png" /></p>
<p>Start executing the commands one by one until you reach this command <code>!buildozer init</code>, don't execute it yet.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648456390014/jGkuCdc_l.png" alt="colab-buildozer-ss2.png" /></p>
<h2 id="heading-step-2-import-your-py-file-and-assets-you-used-in-your-app">STEP 2: Import your .py file (and assets you used in your app)</h2>
<p>After you import your .py file, rename it to <code>main.py</code> otherwise buildozer won't recognize which python program it has to work on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648456402767/-0FR1KMZo.png" alt="colab-buildozer-ss3.png" /></p>
<h2 id="heading-step-3-run-the-buildozer-init-command">STEP 3: Run the "!buildozer" init command</h2>
<p>When you run the <code>!buildozer init</code> command, it will generate a <code>buildozer.spec</code> file, open it by double clicking on it. You can edit the contents of this file to change the package name of your app, application name, app icon, splash screen image, your baby's diapers and much more. Skim through it, see what changes you can make. But don't execute the <code>!buildozer -v android debug</code> command yet!! </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648456412967/0MyhGbMUC.png" alt="colab-buildozer-ss4.png" /></p>
<h2 id="heading-step-4-making-sure-your-app-doesnt-crash">STEP 4: Making sure your app doesn't crash!!</h2>
<p>I did all this and then I executed the next command, which is <code>!buildozer -v android debug</code>. It generated a .apk file, I happily transfered it to my phone and installed. But when I opened it, it crash. I tried debugging my app, I ventured into the deep forests of Stackoverflow and Quora discussions of people who were having similar problems, but nothing worked. It took me two days to figure it out. Here's how I solved the problem.</p>
<p>In the contents of <code>buildozer.spec</code> file there is a requirements section. And along with <code>python3</code>,<code>kivy</code> and <code>kivymd</code> you have to add <code>pillow</code> to the requirements. Okay, now, What the hell is <code>pillow</code>!? I don't remember using any package named "pillow" in my code. Well, turns out, pillow or PIL (Python Image Library) is python package which kivymd depends on for stuff. So this is how the requirements section of your <code>buildozer.spec</code> should look like (bottom image):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648456423985/f9WxMZ5Uy.png" alt="colab-buildozer-ss5.png" /></p>
<p>Don't forget to save your <code>buildozer.spec</code> file after making changes.</p>
<h2 id="heading-step-5-execute-buildozer-v-android-debug">STEP 5: Execute "!buildozer -v android debug"</h2>
<p>Run the <code>!buildozer -v android debug</code> and wait. It will probably take more than 15 minutes. It will ask you for confirmation by entering "y" one or two times in the middle of the process, so look out for that.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648456441384/qOZAryyB8.png" alt="colab-buildozer-ss6.png" /></p>
<p>Once it's done all the processing, you'll see a new folder has appeared on the left hand side by the name <code>bin</code>. Inside the <code>bin</code> you will find a <code>.apk</code> file, transfer it in your phone. Install it, test it, and hopefully it doesn't crash.</p>
]]></content:encoded></item></channel></rss>