<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Prajwal Kulkarni</title>
    <description>The latest articles on DEV Community by Prajwal Kulkarni (@prajwalkulkarni).</description>
    <link>https://dev.to/prajwalkulkarni</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F761242%2F72f77a1c-186d-4cc1-830d-96de36b75635.jpeg</url>
      <title>DEV Community: Prajwal Kulkarni</title>
      <link>https://dev.to/prajwalkulkarni</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prajwalkulkarni"/>
    <language>en</language>
    <item>
      <title>Metrics for a Successful Performance Test</title>
      <dc:creator>Prajwal Kulkarni</dc:creator>
      <pubDate>Sat, 27 Aug 2022 08:18:03 +0000</pubDate>
      <link>https://dev.to/prajwalkulkarni/metrics-for-a-successful-performance-test-5d27</link>
      <guid>https://dev.to/prajwalkulkarni/metrics-for-a-successful-performance-test-5d27</guid>
      <description>&lt;p&gt;Software testing is a broad category that consists of various types of tests. And in order to build a scalable system, it is important to verify and pass all the possible edge test cases to ensure a fit system. &lt;/p&gt;

&lt;p&gt;While some of the tests are &lt;a href="https://www.softwaretestinghelp.com/the-difference-between-unit-integration-and-functional-testing/#:~:text=Unit%20testing%20means%20testing%20individual,combined%20together%20as%20a%20group."&gt;directly administered&lt;/a&gt; on the system code (unit testing, integration testing) others are tested on the system in different environments (stress testing). &lt;/p&gt;

&lt;p&gt;Testing that includes both code-based and non-code-based tests is called an E2E testing or end-to-end testing.&lt;/p&gt;

&lt;p&gt;In this article, we are going to be focusing on non-code-based tests, specifically performance testing, and how these tests can provide you with valuable insights that can further help you improve your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Performance Testing?
&lt;/h2&gt;

&lt;p&gt;Before getting to the “why” part, let’s first answer the question “What is performance testing?”. So, performance testing is used to test how well software performs when used in the context of an integrated system. It is &lt;a href="https://www.javatpoint.com/non-functional-testing"&gt;non-functional&lt;/a&gt; in nature and is also referred to as load testing. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.blazemeter.com/blog/performance-testing-vs-load-testing-vs-stress-testing"&gt;Performance testing&lt;/a&gt; is used to evaluate the program's efficiency and speed. It examines the system's performance under the specified load and determines the overall speed, stability, and responsiveness of the system.&lt;/p&gt;

&lt;p&gt;Performance testing is an abstract concept in contrast to code-based testing. For example, in unit testing, the code is modularized and each unit of the code is individually tested.&lt;/p&gt;

&lt;p&gt;In the case of performance testing, the control flow differs and the approach varies from application to application, as different applications require varied types of testing to test the performance. To streamline the process, one can incorporate a standard process to carry out the test.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Process of Performance Testing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nUrohGmg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/htu6c7ccwzk0l1daxt7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nUrohGmg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/htu6c7ccwzk0l1daxt7x.png" alt="Process of performance testing" width="512" height="372"&gt;&lt;/a&gt;&lt;br&gt;
In performance testing, the first step is identifying the system environment. In it, you understand your production environment, physical test environment, and the testing resources that are available. Before you start the testing process, make sure to gain a thorough understanding of the hardware, software, and network settings that are being used. This will improve the effectiveness of your tests. It will also assist in identifying potential difficulties that testers might run into when doing performance testing processes.&lt;/p&gt;

&lt;p&gt;The next step is to identify performance acceptance criteria. This step involves identifying the parameters and their end goals, which include throughput, resource allocation, and response times. Outside of these objectives and restrictions, additional project success criteria must be defined. Because the project specifications frequently do not offer a broad enough array of performance benchmarks, testers should be given the authority to create performance criteria and goals.&lt;/p&gt;

&lt;p&gt;Moving ahead, the next step is designing the tests. This involves identifying essential scenarios in order to test for all potential use cases and determine how usage is likely to differ among end users. A range of end users must be simulated, performance test data must be planned, and the metrics to be measured must be specified.&lt;/p&gt;

&lt;p&gt;Once the implementation design is in place, the test environment should be set up accordingly. Before running the test, you may configure the necessary tools and other resources for this.&lt;/p&gt;

&lt;p&gt;After the setup is complete, execute the test design. Produce the performance tests in accordance with your test design.&lt;/p&gt;

&lt;p&gt;Lastly, compile, examine, and disseminate the test results. After that, tweak the app and test it to see if performance has improved or worsened. Stop testing when the CPU becomes the bottleneck because improvements often decline with each subsequent test. You may then want to think about upgrading CPU power.&lt;/p&gt;

&lt;h2&gt;
  
  
  Metrics for Performance Testing
&lt;/h2&gt;

&lt;p&gt;To better assess performance, one should consider a few system-level factors that play a vital role in performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rNG5kZoz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jfpwswxux0by2g3mbea3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rNG5kZoz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jfpwswxux0by2g3mbea3.png" alt="Metrics for performance testing" width="512" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The foremost of all is memory utilization, which is the percentage of primary memory consumed for performing the operations. Similar to memory utilization is CPU utilization, which is the percentage of CPU or processing power used for processing the requests.&lt;/p&gt;

&lt;p&gt;To fine-tune the system for best performance, the throughput needs to be calculated. It gauges how many transactions an application can process in a second, or the number of requests a network or computer can process in a second. Based on the result, various system components can be adjusted to improve the throughput.&lt;/p&gt;

&lt;p&gt;Another metric to focus on is the connection pool, which is the number of user requests that pooled connections can handle. The performance will improve when more requests are met by connections in the pool. Bandwidth determines the amount of data that is transmitted each second. A greater bandwidth results in a higher connection speed and vice versa.&lt;/p&gt;

&lt;p&gt;Generally, the response time is used to check if an application is meeting the SLA or not. It indicates how fast a user request was processed and a response was generated. A lower response time implies better performance while a high response time signifies poor performance.&lt;/p&gt;

&lt;p&gt;The final two metrics are latency and error rate. Latency is the time taken by the system to process a request. A low latency means that the system is responding quickly while a high latency indicates that there is a problem with the system. The error rate is self-explanatory and it shows how many requests resulted in errors.&lt;/p&gt;

&lt;p&gt;All these metrics are important for performance testing and should be considered while assessing the performance of an application or system.&lt;/p&gt;

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

&lt;p&gt;Performance testing &lt;a href="https://www.thinksys.com/qa-testing/software-testing-metrics-kpis/"&gt;KPIs&lt;/a&gt; must be understood by organizations so they may determine the effectiveness of performance testing across the enterprise. The above-discussed metrics will aid you in assessing the performance testing process' progress and success. It is recommended that you utilize load and performance testing services from next-generation QA and independent software services to acquire a high-performing, high-quality, scalable, and robust software.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>performance</category>
    </item>
    <item>
      <title>Converting Web Traffic to Permanent Users with Seamless Authentication</title>
      <dc:creator>Prajwal Kulkarni</dc:creator>
      <pubDate>Fri, 29 Apr 2022 14:41:06 +0000</pubDate>
      <link>https://dev.to/prajwalkulkarni/converting-web-traffic-to-permanent-users-with-seamless-authentication-3bdj</link>
      <guid>https://dev.to/prajwalkulkarni/converting-web-traffic-to-permanent-users-with-seamless-authentication-3bdj</guid>
      <description>&lt;p&gt;One of the main factors that drive online business solutions is the conversion rate. Let's go over some basic terms before we get into the nitty-gritty of the strategies. &lt;/p&gt;

&lt;p&gt;Assume you've just launched your new online small business and are anticipating your first sales. The essential component is discoverability.  &lt;/p&gt;

&lt;p&gt;When a person visits a website that provides a solution/service/product(s), they are frequently interested in learning more about it. When all of their questions appear to be answered, they make a move to purchase/subscribe. Conversion is the process of converting a visit into a sale/subscription.&lt;/p&gt;

&lt;p&gt;A higher conversion or retention rate is an indication that a business is steering in the right direction. So what does it take to achieve a higher conversion rate? Let’s look at some of the ways to help your business grow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean Design
&lt;/h2&gt;

&lt;p&gt;When it comes to first impressions, the simplicity with which a site can be navigated is crucial. The visitor should be able to navigate around your site without difficulty, and the user interface, such as popup modals or sidebar widgets, should be elegant and motivate people to take action. At the same time, don't go overboard; otherwise, the visitor will feel pressured to act and frequently leave and never return. This is not what we want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be to the Point
&lt;/h2&gt;

&lt;p&gt;The primary goal of visiting a website is to discover more about a product or service. As a result, the content posted should be well-crafted and relevant. &lt;/p&gt;

&lt;p&gt;The material should express what the user is seeking while avoiding any potential for misunderstanding. The material should be prepared keeping in mind how much time a reader has to devote to something. &lt;/p&gt;

&lt;p&gt;All necessary information should be given in brief and to the point. All crucial details should be placed near the beginning, if not at the very beginning, as this motivates the visitor to read more and make judgments. If crucial elements are at the end and verbose, the user will lose interest and move away before even getting to the major part. You would have lost a potential customer due to incorrect information delivery. &lt;/p&gt;

&lt;p&gt;In a nutshell, keep the details and information short and sweet to avoid such errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smooth Authentication and Onboarding
&lt;/h2&gt;

&lt;p&gt;If you meet the above requirements, the visitor has had their questions answered, is interested in the given product/service, and is ready to place an order. At this point, if they are unable to do so, that is bad. &lt;/p&gt;

&lt;p&gt;The common problem for this is authentication problems. Of course, one must verify that the user is who they claim to be to avoid fraudulent or unethical acts. But a complex authentication system is typically time-consuming and costly. At the same time, authentication cannot be taken lightly. It is, without a doubt, one of the most crucial aspects of the website. &lt;/p&gt;

&lt;p&gt;A good solution to this is using a free user management tool like Frontegg’s &lt;a href="https://docs.frontegg.com/docs/using-login-box-builder" rel="noopener noreferrer"&gt;login box builder&lt;/a&gt;, which offers a myriad of options to ensure there’s enough flexibility on how a login/sign-up widget can be built. Take your time, and experiment around to choose what suits you best. Frontegg provides user management that can handle everything from authentication through checkout. We'll see a full implementation of authentication in this section.&lt;/p&gt;

&lt;p&gt;The login/sign-up widget is currently available for sites built on React, Angular, and Vue. This article focuses on integrating the authentication system in &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;. However, a similar approach can be adapted to achieve the same in other frameworks too. &lt;/p&gt;

&lt;p&gt;Building an authentication system using Frontegg is pretty simple and requires only three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Design&lt;/li&gt;
&lt;li&gt;Integrate&lt;/li&gt;
&lt;li&gt;Deploy&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Design
&lt;/h2&gt;

&lt;p&gt;Once you sign up, you land on a page that says ‘Build your login box’, ‘Integrate’, etc. Click the ‘Start’ beside ‘Build your login box’. Here’s where you’ll be setting the aesthetics and authentication type. There’s a free hand to this and no restrictions on how the authentication system should be built. &lt;/p&gt;

&lt;p&gt;For example, under the authentication style, you can set the auth system to be either password-based or password less. To get more control, you can click on ‘configure’ to add custom settings. Additionally, you can also include &lt;a href="https://docs.frontegg.com/docs/adding-social-logins" rel="noopener noreferrer"&gt;social logins&lt;/a&gt; from various platforms. Once you are done adding the right auth system, the next part is designing. Click on ‘style’ in the tabbed menu, besides ‘Login methods’.&lt;/p&gt;

&lt;p&gt;Here, you can set the theme, colors, image logos, and much more. Click on ‘Publish Changes’ to save changes.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Integrate
&lt;/h2&gt;

&lt;p&gt;Now that the login/sign-up box is ready, the next step is to integrate the widget into your site. The integration could be either hosted or embedded. &lt;/p&gt;

&lt;p&gt;In this article, we’ll be going ahead with hosted login, but you’re free to take up embedded login as well. Install ‘react-router-dom’ and ‘@frontegg/react’ by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @frontegg/react react-router-dom@5.3.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your index.js, Wrap the root component with the &lt;code&gt;FrontEgg&lt;/code&gt; component, this is to maintain the integrity of private routes and know the auth state overall. It should be something like below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';

import { FronteggProvider } from '@frontegg/react';

const contextOptions = {
  baseUrl: 'https://YOUR_BASE_URL.frontegg.com',
  clientId: 'YOUR_CLiENT_ID’'
};

ReactDOM.render(
    &amp;lt;FronteggProvider contextOptions={contextOptions} hostedLoginBox={true}&amp;gt;
        &amp;lt;App /&amp;gt;
    &amp;lt;/FronteggProvider&amp;gt;,
    document.getElementById('root')
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To obtain your base URL, head to &lt;strong&gt;Go live&amp;gt;Add your domain&lt;/strong&gt; to “Allowed Origin” list where you can see your base URL. For the client ID, click on your profile in the bottom-left corner and click on workspace settings in the expanded menu.&lt;/p&gt;

&lt;p&gt;Moving ahead, to check whether a user is authenticated or not, we can use the &lt;code&gt;useAuth&lt;/code&gt; hook provided by frontegg. This hook returns the user details (if authenticated) and authenticated state (boolean value). You can conditionally render different information based on the boolean value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const {user, isAuthenticated} = useAuth()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below is a sample snippet demonstrating the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import './App.css';
import { useEffect } from "react";
import {
  useAuth,
  useLoginWithRedirect
} from "@frontegg/react";
import {ContextHolder} from "@frontegg/rest-api";


function App() {
  const { user, isAuthenticated } = useAuth();

  const loginWithRedirect = useLoginWithRedirect();

  console.log('user - ', user);
  console.log('isAuthenticated - ', isAuthenticated);
  console.log('user - ', user);

  useEffect(() =&amp;gt; {
    if (!isAuthenticated) {
      console.log('user is not logged-on. going to loginWithRedirect')
      loginWithRedirect();
    }
  }, [isAuthenticated, loginWithRedirect]);

  const logout = () =&amp;gt; {
    const baseUrl = ContextHolder.getContext().baseUrl;
    window.location.href = `${baseUrl}/oauth/logout?post_logout_redirect_uri=${window.location}`;
  };

  return (
    &amp;lt;div className="App"&amp;gt;
      {isAuthenticated ? (
        &amp;lt;div&amp;gt;
          &amp;lt;div&amp;gt;
            &amp;lt;img src={user?.profilePictureUrl} alt={user?.name} /&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div&amp;gt;
            &amp;lt;span&amp;gt;Logged in as: {user?.name}&amp;lt;/span&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div&amp;gt;
            &amp;lt;button onClick={() =&amp;gt; logout()}&amp;gt;Click to logout&amp;lt;/button&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      ) : (
        &amp;lt;div&amp;gt;
          &amp;lt;button onClick={loginWithRedirect}&amp;gt;Click me to login&amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; hook redirects the user to sign in if he is not authenticated. You may tweak this to suit your needs, although redirecting users to authenticate is a good idea. The above snippet is taken from the official &lt;a href="https://github.com/frontegg-samples/react-hosted-login-box" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; of Frontegg. &lt;/p&gt;

&lt;p&gt;Next, you need to enable hosted login from your Frontegg dashboard. To do that, select “Settings” under Authentication, and click on Manage for Hosted Login. Below is the image depicting the same:&lt;/p&gt;

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

&lt;p&gt;Next, you’ve to toggle the enable switch to enable the hosted login functionality and add “&lt;a href="http://localhost:3000/oauth/callback%E2%80%9D" rel="noopener noreferrer"&gt;http://localhost:3000/oauth/callback”&lt;/a&gt; in the redirected URL input field (given that you are running on localhost).&lt;/p&gt;

&lt;p&gt;After making the above-mentioned additions/changes, click on “save” at the bottom to save the changes.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Go Live
&lt;/h2&gt;

&lt;p&gt;The final step is to add the weblink to be allowed under &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" rel="noopener noreferrer"&gt;CORS&lt;/a&gt; policy.&lt;/p&gt;

&lt;p&gt;Click on the “Go live” option present in the top tab and click on "Add your domain" in the populated options. Under the “Domains” section, scroll to the bottom to whitelist your domain in the “Allowed Origins” section. This should prepare the widget to go live.&lt;br&gt;
The hosted widget will look something like this.&lt;/p&gt;

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

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

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

&lt;p&gt;And that is it! We have successfully implemented a fully working authentication widget in almost no time without compromising on the design part. &lt;/p&gt;

&lt;p&gt;Frontegg is not just an authentication widget but does much more. You can also add user-wise authorization levels to restrict them from performing certain actions. In brief, it is a complete end-to-end solution for user management.&lt;/p&gt;

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

&lt;p&gt;While there are numerous aspects that contribute to a higher conversion rate, the postures described above are among the most essential. A good authentication system, in particular, can improve the onboarding experience while simultaneously saving developers time and allowing them to focus on core functionalities.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webtraffic</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Learning the Basics of web dev by Building a Weather App</title>
      <dc:creator>Prajwal Kulkarni</dc:creator>
      <pubDate>Mon, 04 Apr 2022 16:34:39 +0000</pubDate>
      <link>https://dev.to/prajwalkulkarni/learning-the-basics-of-web-dev-by-building-a-weather-app-2lno</link>
      <guid>https://dev.to/prajwalkulkarni/learning-the-basics-of-web-dev-by-building-a-weather-app-2lno</guid>
      <description>&lt;p&gt;Now that you've started learning the basics of web development, what should you do next? &lt;/p&gt;

&lt;p&gt;This is a typical dilemma faced by every newbie developer. If you're new to the web world and are learning web development, the next step is applying your learnings.&lt;/p&gt;

&lt;p&gt;It is important to apply/implement the concepts as you learn them. This helps you gain in-depth knowledge about the functioning of a language/library/framework, etc. So that is exactly what we will be doing. &lt;/p&gt;

&lt;p&gt;Here, we'll be going through some code snippets and a few important concepts of APIs. We will simultaneously be building an application. This article presumes that you have got a basic idea about HTML/CSS/JS.&lt;/p&gt;

&lt;p&gt;So, without any further ado, let's get started.&lt;/p&gt;

&lt;h3&gt;
  
  
  What we'll be building
&lt;/h3&gt;

&lt;p&gt;The article aims to introduce you to new concepts of web development. Hence, we will be building a simple yet out-of-the-box weather application using HTML, CSS, and Vanilla JavaScript to hone your web dev skills.&lt;/p&gt;

&lt;p&gt;The features of this application will include providing real-time weather for any place searched by the user and displaying visuals of the weather using Google Maps and Tomorrow.io's Weather API. &lt;/p&gt;

&lt;h3&gt;
  
  
  The setup
&lt;/h3&gt;

&lt;p&gt;API stands for application programming interface, which provides an interface to a service/function that usually intends to return a set of information/results that we could make use of in our application. &lt;/p&gt;

&lt;p&gt;To query such information, we'd want to supply a token (API key) along with the request so that the server knows where the request is coming from and where to send the response.&lt;/p&gt;

&lt;p&gt;Before we get started, we should get our API keys from the data providers - Google Maps SDK and Tomorrow.io Weather API. Both APIs are free-to-use. The &lt;a href="https://tomorrow.io/weather-api"&gt;weather API&lt;/a&gt; provides features such as real-time weather details with over 30 metrics (e.g. temperature, wind speed, etc). It can also be used to extract meteorological details from a location over a period of time, track weather along a route, and more. So, quickly head to the sites and create the accounts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the webpage
&lt;/h3&gt;

&lt;h4&gt;
  
  
  HTML
&lt;/h4&gt;

&lt;p&gt;Once you've created your accounts and gained access to different the respective API keys, let us set up the project structure.&lt;br&gt;
Create a directory, this is the main directory where all our files go. Within this create an &lt;code&gt;assets&lt;/code&gt; dir, which further contains 3 directories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Images&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;JS
So your project directory should look something like this:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ROOT_DIR:
    -ASSETS
       -IMAGES
       -CSS
       -JS
    -index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can start by writing some HTML code. Create a new HTML file named &lt;code&gt;index&lt;/code&gt;, and add the below code:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;index.html&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Simple Map app&amp;lt;/title&amp;gt;
    &amp;lt;script src="https://polyfill.io/v3/polyfill.min.js?features=default"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;link rel="stylesheet" href="./assets/css/styles.css"/&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;

    &amp;lt;div class="container"&amp;gt;

      &amp;lt;p style="font-size: 5rem;font-family: Arial, Helvetica, sans-serif;"&amp;gt;&amp;lt;b&amp;gt;Weather Man&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;
      &amp;lt;input type="search" placeholder="Search for a place..." id="search"/&amp;gt;

          &amp;lt;div class="card"&amp;gt;
            &amp;lt;div&amp;gt;
                &amp;lt;h1 id="weather"&amp;gt;Weather: &amp;lt;/h3&amp;gt;
                &amp;lt;h4 id="temperature"&amp;gt;Temperature: 69 C&amp;lt;/h4&amp;gt;
                &amp;lt;h4 id="humidity"&amp;gt;Humidity: 25%&amp;lt;/h4&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;img src="./assets/images/normal.png" height="100" width="100"/&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div id="map"&amp;gt;&amp;lt;/div&amp;gt;  

    &amp;lt;/div&amp;gt;

    &amp;lt;!-- Async script executes immediately and must be after any DOM elements used in callback. --&amp;gt;
    &amp;lt;script
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&amp;amp;callback=initMap&amp;amp;libraries=&amp;amp;v=weekly"
      async
    &amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="./assets/js/script.js"&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the above code consists of simple HTML tags like &lt;code&gt;p&lt;/code&gt;,&lt;code&gt;h&lt;/code&gt;, and &lt;code&gt;div&lt;/code&gt;s. This is to setup a basic structure for our webpage with some static information (Like Dummy weather information) which will later show real-time weather for the searched place dynamically using JavaScript. &lt;/p&gt;

&lt;p&gt;If you're an absolute beginner, you might be wondering, why is the &lt;code&gt;div&lt;/code&gt; tag with the &lt;code&gt;id&lt;/code&gt;, map, empty. This is because we'll be injecting Google maps into this &lt;code&gt;div&lt;/code&gt; using JS. &lt;/p&gt;

&lt;p&gt;Before directly copying over the given code, I'd suggest you to first look through it and try understanding the markup, and preferably writing it on your own, this would serve as a good practice.&lt;/p&gt;

&lt;h4&gt;
  
  
  JavaScript
&lt;/h4&gt;

&lt;p&gt;In the beginning, I mentioned that this will be an out-of-box weather app. So what makes this stand out? On the map we'll be adding a data layer that shows any metric(temperature, precipitation) visually, this would make the map view more appealing and would also help the user assess the real time weather with more clarity.&lt;br&gt;
Although this seems like a complicated task to accomplish, surprisingly this is fairly simple, all thanks to &lt;a href="https://docs.tomorrow.io/reference/get-map-tile"&gt;tomorrow.io's map view API&lt;/a&gt;. The creation and fetching of the data layers are outsourced to the said API.&lt;/p&gt;

&lt;p&gt;Before implementing the core features, let's firstly establish a connection between our HTML file and JS, create a new file named &lt;strong&gt;script.js&lt;/strong&gt; (Feel free to name anything you'd want, but make sure to update the name in the &lt;code&gt;src&lt;/code&gt; attribute in the HTML file).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;script.js&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const searchElement = document.querySelector("#search")
const cardElement = document.querySelector('.card')
const temperatureElement = document.querySelector("#temperature")
const humidityElement = document.querySelector("#humidity")
const weatherElement = document.querySelector("#weather")
const imageElement = document.getElementsByTagName('img')[0]

const API_KEY = 'YOUR TOMORROW.IO API KEY HERE'; 

const MAPS_API = 'YOUR GOOGLE MAPS API KEY HERE'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;document&lt;/code&gt; is a global window object in the browser, so we're using the &lt;code&gt;document&lt;/code&gt; object to gain the reference to various HTML elements using their selectors(id or class). The reference of elements can be gained by their id's, class name, tag name, etc.&lt;br&gt;
The whole point of doing this is to, manipulate the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction"&gt;DOM&lt;/a&gt; further, as and when required.&lt;/p&gt;

&lt;p&gt;Now that we've captured the elements, we can go ahead to initialize the map onto the &lt;code&gt;div&lt;/code&gt;.&lt;br&gt;
Create a function called &lt;code&gt;initMap&lt;/code&gt; (again, could be anything).&lt;br&gt;
And add the following code, right after the initialization of elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myLatlng = { 
  lat: 42.355438,
  lng: -71.059914 
};

function initMap(){
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 7,
    center: myLatlng
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will load the map into our webpage, pointing to the location of the given coordinates, which happens to be Boston in this case.&lt;/p&gt;

&lt;p&gt;Moving ahead, we would want the users to be able to search for a place by entering the name of it and showing that place on the map.&lt;br&gt;
This could be done using Google's geocoding API, which comes with the maps API.&lt;br&gt;
So before the &lt;code&gt;initMap()&lt;/code&gt; function, add this event handler to handle the search logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;res.addEventListener('keypress',(e)=&amp;gt;{

  if(e.key==='Enter'){
    fetch(`https://maps.googleapis.com/maps/api/geocode/json?address=${e.target.value}&amp;amp;key=${MAPS_API}`)
    .then(res=&amp;gt;res.json())
    .then(obj=&amp;gt;{
      const latitude = obj.results[0].geometry.location.lat
      const longitude = obj.results[0].geometry.location.lng

      myLatlng.lat = latitude
      myLatlng.lng = longitude
      initMap()
    })
    .catch(err=&amp;gt;console.log(err))
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;keypress&lt;/code&gt; listener is hooked with the input search element, meaning the callback function is triggered every time a keypress action occurs(Including delete/backspace, as those come under keypress as well). But we'd want to make a search action only when the user completes entering in the input field and clicks enter to search, hence the conditional check &lt;code&gt;if(e.key === 'Enter')&lt;/code&gt;.&lt;br&gt;
In the &lt;code&gt;if&lt;/code&gt; block, we're sending a network request to geocoding API to return us the coordinates for the searched place. &lt;br&gt;
This is done using the &lt;code&gt;fetch&lt;/code&gt; function that returns a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;promise&lt;/a&gt;, which is then resolved to convert it to &lt;a href="https://www.w3schools.com/whatis/whatis_json.asp"&gt;JSON&lt;/a&gt; format.&lt;/p&gt;

&lt;p&gt;This will enable to map the searched location onto the Google map. Thus far, our &lt;strong&gt;script.js&lt;/strong&gt; should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const API_KEY = 'YOUR TOMORROW.IO API'; 
const MAPS_API = 'YOUR GOOGLE MAPS API'

const searchElement = document.querySelector("#search")

const cardElement = document.querySelector('.card')
const temperatureElement = document.querySelector("#temperature")
const humidityElement = document.querySelector("#humidity")
const weatherElement = document.querySelector("#weather")
const imageElement = document.getElementsByTagName('img')[0]

const myLatlng = { 
  lat: 42.355438,
  lng: -71.059914 
};

searchElement.addEventListener('keypress',(e)=&amp;gt;{

  if(e.key==='Enter'){
    // console.log(e.target.value)

    fetch(`https://maps.googleapis.com/maps/api/geocode/json?address=${e.target.value}&amp;amp;key=${MAPS_API}`)
    .then(res=&amp;gt;res.json())
    .then(obj=&amp;gt;{
      const latitude = obj.results[0].geometry.location.lat
      const longitude = obj.results[0].geometry.location.lng

      myLatlng.lat = latitude
      myLatlng.lng = longitude
      initMap()
    })
  }
})
// initialize the map
function initMap() {

  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 7,
    center: myLatlng
  });

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

&lt;/div&gt;



&lt;p&gt;If you're not seeing the map yet, don't worry, it's because we haven't specified the dimensions of the map container, which we'll do in CSS.&lt;br&gt;
Showing the place on the map for a searched location is cool, but what's even cooler is overlaying the real-time weather over the searched location. So it is basically like you search for a place and on the map, you're shown the location along with the real-time weather atop of it. We'll be using the tile overlay feature of the tomorrow.io API.&lt;br&gt;
Before adding the overlay, we'd want to define a few parameters, namely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Data field: What visual information should we overlay, e.g: &lt;code&gt;temperature&lt;/code&gt;, &lt;code&gt;precipitationIntensity&lt;/code&gt; etc. You can find the complete list &lt;a href="https://docs.tomorrow.io/reference/data-layers-core"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Timestamp: For what range of duration do we want the data field information.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While, you can always finetune the values as per your requirement, but for demonstration purposes, in this article, I'll be using the timestamp to be NOW and the data field to be &lt;code&gt;precipitationIntensity&lt;/code&gt;.&lt;br&gt;
So append the following constants at the beginning of the &lt;code&gt;script.js&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const DATA_FIELD = 'precipitationIntensity';
const TIMESTAMP = (new Date()).toISOString(); //The API accepts the time in ISO string format, hence we're converting the regular time format into ISO string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;initMap()&lt;/code&gt; function, add the below code after the map initialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  let res
  let timeout
  var imageMapType = new google.maps.ImageMapType({
    getTileUrl: function(coord, zoom) {
      if (zoom &amp;gt; 12) {
        return null;
      }


       if(timeout){
         clearTimeout(timeout)
       }
       timeout = setTimeout(()=&amp;gt;{
         res = `https://api.tomorrow.io/v4/map/tile/${zoom}/${coord.x}/${coord.y}/${DATA_FIELD}/${TIMESTAMP}.png?apikey=${API_KEY}`
       },2000)


    return res   
    },
    tileSize: new google.maps.Size(256, 256)
  });

  map.overlayMapTypes.push(imageMapType);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;getTileUrl&lt;/code&gt; function is called every time a zoom action occurs, if you are on free-tier you're likely to face the &lt;code&gt;429 error&lt;/code&gt; due to rate limiting. To avoid such a barrier, we've used the concept of &lt;a href="https://www.youtube.com/watch?v=Zo-6_qx8uxg"&gt;debouncing&lt;/a&gt; by using timeouts and intervals, but here you'd have to compromise with the resolution of the tiles. &lt;/p&gt;

&lt;p&gt;The visual overlay functionality is now successfully added. We can now move further to show the weather details (Like temperature, humidity) in words. For this, we again send an API request to the timelines endpoint of tomorrow.io's API.&lt;/p&gt;

&lt;p&gt;Paste the give code after the overlay logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; fetch('https://api.tomorrow.io/v4/timelines',{
    method:'POST',
    headers:{
      'apiKey':'Kc4HFO75TNUmBRla3S661V2DkxJb4uiS',
      'Content-Type':'application/json',
    },
    body:JSON.stringify({
      "location": {
          "type": "Point",
          "coordinates": [
              myLatlng.lng,
              myLatlng.lat
          ]
      },
      "fields": [
          "temperature",
          "humidity",
          "weatherCode"
      ],
      "timesteps": [
          "current"
      ]
   })
  })
  .then(res=&amp;gt;res.json())
  .then(data=&amp;gt;{
    const values = data.data.timelines[0].intervals[0].values

    const temperatureData = values.temperature
    const humidityData = values.humidity
    const weatherData = values.weatherCode
    const weatherDataInWords = getWeather(weatherData)
    temperatureElement.innerHTML = "Temperature: 
    "+temperatureData+"C"
    humidityElement.innerHTML = "Humidity: "+humidityData+"%"
    weatherElement.innerHTML = "Weather: 
    "+weatherDataInWords.description
    imageElement.src = 
 `./assets/images/${weatherDataInWords.description.toLowerCase()}.png`
//^ DOM manipulation to inject the weather data into the respective fields.

   cardElement.style.backgroundImage = weatherDataInWords.colorGradient
   weatherElement.style.color = weatherDataInWords.fontColor
   humidityElement.style.color = weatherDataInWords.fontColor
   temperatureElement.style.color = weatherDataInWords.fontColor
  })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, we're sending an API request using the &lt;code&gt;fetch&lt;/code&gt; function along with a body that contains the details(coordinates) for the place for which the weather details need to be fetched. Here, I am interested in getting the &lt;code&gt;temperature&lt;/code&gt;, &lt;code&gt;humidity&lt;/code&gt;, and &lt;code&gt;weatherCode&lt;/code&gt; which can be translated to weather in literal speech( Clear, Windy, Rainy). The list of &lt;code&gt;weatherCode&lt;/code&gt; can be found &lt;a href="https://docs.tomorrow.io/reference/data-layers-core#data-layers-weather-codes"&gt;here&lt;/a&gt;.&lt;br&gt;
Depending on the current weather, we're also changing the image(Assets available in the source code at the end of the article). This is done with the help of our helper function &lt;code&gt;getWeather&lt;/code&gt;, following is the code for the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function getWeather(weatherCode){
  // console.log(weatherCode)

  switch(weatherCode){
    case 1000:
    case 1100:
      return {
        description:"Clear",
        colorGradient:'linear-gradient(to bottom, #ffa970,#c5c5c5)',
        fontColor:'#000000'
      }
    case 1102:
    case 1001:
      return {
        description:"Cloudy",
        colorGradient:'linear-gradient(to bottom, #949494,#c5c5c5)',
        fontColor:"#ffffff"
      }
    case 4000:
    case 4200:
    case 4001:
      return {
        description:"Rainy",
        colorGradient:'linear-gradient(to bottom, #65b6fc,#8cc9ff)',
        fontColor:"#ffffff"
      }

    default:
      return {
        description:"Normal",
        colorGradient: 'linear-gradient(to bottom, #aed8fc,#cce7ff)',
        fontColor:"#000000"
      }

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

&lt;/div&gt;



&lt;p&gt;So, we're using a simple &lt;code&gt;switch&lt;/code&gt; statement to convert the weather code into corresponding weather in words with the help of the weather code table. We're also setting the font color and color gradient of the information container dynamically. Note, this function is designed to return only some weather types(Rainy, cloudy, Clear/sunny), for the rest of the weather a default "Normal" weather is returned, you can edit the code to add more details.&lt;br&gt;
This completes our JavaScript coding. We can now move on to styling the elements and the page.&lt;/p&gt;
&lt;h4&gt;
  
  
  CSS
&lt;/h4&gt;

&lt;p&gt;Since this is a single webpage with minimal features, we require only a single stylesheet to add stylings, dimensions and, alignment to the body.&lt;br&gt;
Create a new file &lt;code&gt;styles.css&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* Always set the map height explicitly to define the size of the div
       * element that contains the map. */

       html,
      body {
        height: 100%;
        margin: 0;
        padding: 0;
        background-image: url('./assets/images/wallpapaer.png');
      }

       .container{
         display: flex;
         flex-direction: column;
         /* justify-content: center; */
         align-items: center;
         padding: 2rem;
       }

       input[type=search]{
        width: 50%;
        background-color: rgb(226, 225, 225);
        border-radius: 0.5rem;
        height: 2rem;
        border-width: 0px;
        padding:0.2rem;
      }

       .info_container{
         display: flex;
         /* flex-wrap: wrap; */
         flex-direction: row;
         width: 80%;
         margin:1rem;
         justify-content: space-between;

       }

       .card{
        border:1px solid rgb(148, 148, 148);
        font-family: Arial, Helvetica, sans-serif;
        margin:1rem;
        padding: 1rem;
        width: 49%;
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        flex-wrap: wrap;
        border-radius: 1rem;
        box-shadow: grey 1px 1px 2px 2px;
      }

       #map {
        margin: 1rem;
        height: 300px;
        width: 49%;
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To align the contents across the webpage, we're using &lt;a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/"&gt;flexbox&lt;/a&gt; styling.&lt;/p&gt;

&lt;p&gt;This will be pretty much everything that's required to create this project. &lt;br&gt;
Phew, tha was a lot of code, But, I hope you did enjoy learning new things and creating a cool weather app.&lt;/p&gt;

&lt;p&gt;The webpage would look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ISbrOR5p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lq47d2dhwa37to6c1990.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ISbrOR5p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lq47d2dhwa37to6c1990.png" alt="Weather details of Paris" width="764" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--roeQslFg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z4xlmxh4wv4ahacg7138.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--roeQslFg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z4xlmxh4wv4ahacg7138.png" alt="Precipitation overlay and dynamic UI" width="764" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Weather man - &lt;a href="https://github.com/prajwalkulkarni/weather-app"&gt;Source code&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Final thoughts
&lt;/h3&gt;

&lt;p&gt;That was all about creating an interactive weather application. I hope you got to learn something new. I'd also encourage you to extend the features of this application to make it more interactive like adding animations, loading states while fetching weather data, color themes, and everything you can imagine of, the sky is the limit. If you liked the article, show some love by liking the article and sharing it with your friends &amp;amp; colleagues. You can also connect with me on &lt;a href="https://linkedin.com/prajwal-kulkarni"&gt;LinkedIn&lt;/a&gt; /&lt;a href="https://twitter.com/prajwalinbizz"&gt;Twitter&lt;/a&gt; for more.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
