<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Web Applications - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Web Applications - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 18 May 2026 10:47:55 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/web-applications/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Perform Performance Testing on Your Web Applications ]]>
                </title>
                <description>
                    <![CDATA[ Performance testing is an important yet underrated field of software development. And it’s a must-have skill that can help you prevent common software failures that occur in production applications.  Performance testing is a routine software practice... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/performance-testing-for-web-applications/</link>
                <guid isPermaLink="false">66bb58d1074d8d7b12eae39a</guid>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Mon, 26 Feb 2024 19:52:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/performance-test2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Performance testing is an important yet underrated field of software development. And it’s a must-have skill that can help you prevent common software failures that occur in production applications. </p>
<p>Performance testing is a routine software practice which is carried out to determine the stability of a system in terms of scalability, reliability, and data management, among other parameters.</p>
<p>In this tutorial, I'll walk you through what performance testing entails, and the common tools used for backend testing. We'll also walk through a demo performance testing project together. </p>
<p>The tutorial is simplified and suitable for beginners, mid-level developers, and professional developers. Being proficient in performance testing is fundamental to growing as a backend developer, and this guide will serve as a good review even if you're more advanced in your career. With that said, let's dive in.</p>
<h3 id="heading-prerequisites">Prerequisites:</h3>
<ul>
<li>Intermediate knowledge of Node.js</li>
<li>Basic knowledge of JavaScript operations</li>
<li>Knowledge of API development\</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-performance-testing">What is Performance Testing?</a></li>
<li><a class="post-section-overview" href="#heading-examples-of-performance-testing-tools">Examples of Performance Testing Tools</a></li>
<li><a class="post-section-overview" href="#heading-demo-project">Demo Project</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-what-is-performance-testing">What is Performance Testing?</h2>
<p>Performance testing serves quite a lot of purposes – one of the most important of which is to test system efficiency in performing and sustaining tasks. It also serves as a standard you can use to compare systems of varying efficiency and builds and enables you to choose the most effective one.</p>
<p>Performance testing also helps reveal vulnerabilities. State-of-the-art testing tools are well optimized to efficiently analyze the code to detect any errors. They're quick to highlight the areas where these errors occur.</p>
<p>The end goal of performance testing is dependent how you're using the application. It might be concurrency-oriented or transaction rate-oriented, depending on whether the app involves end users or not. </p>
<p>Performance testing could also involve load testing, which is usually carried out to evaluate the behavior of a web service under a specific expected load. Other types of testing you can do include integration testing, spike testing, soak testing, and stress testing.</p>
<h2 id="heading-examples-of-performance-testing-tools">Examples of Performance Testing Tools</h2>
<p>There are many tools commonly used to test the efficacy and latency of web applications. In this section, I'll discuss some of the popular tools used, and highlight their strengths and use cases.</p>
<h3 id="heading-jest">Jest</h3>
<p><a target="_blank" href="https://www.npmjs.com/package/jest">Jest</a> is a multi-platform testing tool used to assess the correctness of JavaScript-based applications. It's the one we'll be using in this demo. </p>
<p>Jest was initially created to test the efficiency of React applications, but has since been extended to test the efficiency of Node.js apps as well. It also offers a code coverage feature.</p>
<h3 id="heading-mocha">Mocha</h3>
<p><a target="_blank" href="https://www.npmjs.com/package/mocha">Mocha</a> is a concise asynchronous JavaScript-based testing tool for Node.js applications. It is also used with assertion libraries such as <code>[Chai]( https://www.npmjs.com/package/chai)</code> and <code>[should]( https://www.npmjs.com/package/should)</code>.</p>
<h3 id="heading-pythagora">Pythagora</h3>
<p><a target="_blank" href="https://github.com/Pythagora-io/pythagora">Pythagora</a> offers a unique integrating testing feature to help test how different part of the application works together. It also has a code coverage feature.</p>
<h3 id="heading-artillery">Artillery</h3>
<p><a target="_blank" href="https://artillery.io">Artillery</a> is a stack agnostic testing tool. This means it can be used for multiple web applications based on different programming languages and still produce an optimal test outcome. </p>
<p>This tool provides efficient load testing features which help to determine the optimal status of the application when exposed to a large load of traffic. It also checks the speed at which an app responds to a user request without crashing. </p>
<h3 id="heading-ava">Ava</h3>
<p><a target="_blank" href="https://www.npmjs.com/package/ava">Ava</a> is a JavaScript-based performance unit testing tool used to test the efficacy of Node.js applications. It works asynchronously, running multiple concurrent tests to determine the suitability of multiple code units.</p>
<h3 id="heading-loadtest">Loadtest</h3>
<p><a target="_blank" href="https://www.npmjs.com/package/loadtest">Loadtest</a> is a special Node package which is used to load test Node.js applications. It evaluates their ability to cope with requests of varying volumes and it evaluates for efficiency and concurrency.</p>
<h3 id="heading-apache-j-meter">Apache J-meter</h3>
<p><a target="_blank" href="https://jmeter.apache.org">Apache J-meter</a> offers load-testing features for web applications. It has an in-built IDE to enable interaction with the user. It is multithreaded, increasing its ability to mimic several users.</p>
<p>There are other testing tools which are also useful. But in this tutorial, we will be utilizing <code>Jest</code> to test our back-end application.</p>
<h2 id="heading-demo-project">Demo Project</h2>
<h3 id="heading-install-jest">Install Jest</h3>
<p>We'll now perform a unit test on our code using the <code>Jest</code> testing tool. To do this, you'll need to install the <code>Jest</code> package in your code folder. Type <code>npm install jest</code> in the command prompt. A success message will be displayed when the installation is completed.</p>
<h3 id="heading-configure-packagejson">Configure <code>package.json</code></h3>
<p>In this tutorial, we'll test the efficiency of some selected routes in our Node.js application. This will necessitate writing different unit tests for each route and evaluating its correctness. </p>
<p>Now let’s optimize our file structure to successfully unit test our application. Navigate to the <code>package.json</code> file and edit it to include the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"test"</span>: <span class="hljs-string">" jest"</span>,
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"nodemon index.js"</span>
  },
</code></pre>
<p>Modifying the package.json file to include this code ensures that the Node.js server recognizes Jest as our default unit testing tool for the project. By so doing, any time we enter <code>npm test</code> in the command prompt, Jest gets activated.</p>
<h3 id="heading-set-up-the-test-environment">Set up the test environment</h3>
<p>Create a folder in the <code>root</code> directory named “tests”. This helps the Jest operator locate the specific files housing the routes to be tested. </p>
<p>Within the test folder, create a test file. The file can be named whatever you prefer, but the suffix <code>.test.js</code> should be added to enable <code>Jest</code> to recognize it and execute it.</p>
<p>After completing these steps, let’s get into the core details of unit testing in our project.</p>
<h3 id="heading-run-the-unit-tests">Run the unit tests</h3>
<p>The demo project we'll test in this tutorial is an eBook library application which contains some functions such as a <code>get all books</code> route, <code>Get a single book</code> route, <code>upload a book</code> route, and <code>delete a book</code> route.  We'll create unit tests for the <code>GetAllBooks</code> route in the example below, and then you can try to create your own for the other routes.</p>
<p>So firstly, we'll import the book database into the test.js file like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Book = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/Book'</span>)
</code></pre>
<p>The code above imports and initializes our default book MongoDB database model.</p>
<p>Then we'll import the functions that we'll test in each route:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Book =  <span class="hljs-built_in">require</span>(<span class="hljs-string">"../models/Book"</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">GetAllBooks</span> (<span class="hljs-params">req, res</span>)  </span>{
    <span class="hljs-keyword">try</span> {
<span class="hljs-keyword">const</span> allBooks =  <span class="hljs-keyword">await</span> Book.find();
res.status(<span class="hljs-number">200</span>)
res.send(allBooks)
    }
    <span class="hljs-keyword">catch</span> (err) {
res.status(<span class="hljs-number">500</span>)
res.send(err) 
    }
}
<span class="hljs-built_in">module</span>.exports = {GetAllBooks};
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> {GetAllBooks} = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../controllers/Books"</span>);
</code></pre>
<p>The code above imports the getAllBooks function from a controller folder. </p>
<p>Having imported the function, let's now go ahead to setup our Jest unit test function.</p>
<pre><code class="lang-javascript">jest.mock(<span class="hljs-string">"../models/Book"</span>);

<span class="hljs-keyword">const</span> req = {};
<span class="hljs-keyword">const</span> res = {
  <span class="hljs-attr">status</span>: jest.fn(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x),
  <span class="hljs-attr">send</span>: jest.fn(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x),
};

it(<span class="hljs-string">"it should return all the books in the database"</span>, <span class="hljs-keyword">async</span> () =&gt; {

Book.find.mockImplementationOnce(<span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">Title</span>: <span class="hljs-string">"black is king"</span>,
    <span class="hljs-attr">Author</span>: <span class="hljs-string">"black"</span>,
    <span class="hljs-attr">price</span>: <span class="hljs-string">"$23"</span>,
    <span class="hljs-attr">Summary</span>: <span class="hljs-string">"Hello"</span>,
  }));

  <span class="hljs-keyword">await</span> GetAllBooks(req, res);


expect(res.status).toHaveBeenCalledWith(<span class="hljs-number">200</span>);

expect(res.send).toHaveBeenCalledTimes(<span class="hljs-number">1</span>);
});
</code></pre>
<p>First of all, Jest offers you the ability to create a fake database by copying the structure of the default database. This is known as mocking. This enables the unit test to operate faster and eliminate the lag that comes with getting responses from large databases. </p>
<p>Testing which involves the real database is referred to as end-to-end testing as opposed to unit testing.</p>
<p>Here's how you can do that in Jest:</p>
<pre><code class="lang-javascript">jest.mock(<span class="hljs-string">"../models/Book"</span>);
</code></pre>
<p>The code above illustrates database mocking. In order to get a faster unit test, we have to mock the existing Book database model we're using in our application.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> req = {};
<span class="hljs-keyword">const</span> res = {
  <span class="hljs-attr">status</span>: jest.fn(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x),
  <span class="hljs-attr">send</span>: jest.fn(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x),
};
</code></pre>
<p>The above code contains the default sample requests and response objects. The sample response object contains both the status and send functions, which return a defined output if executed successfully or not.</p>
<pre><code class="lang-javascript">it(<span class="hljs-string">"it should return all the books in the database"</span>, <span class="hljs-keyword">async</span> () =&gt; {
Book.find.mockImplementationOnce(<span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">Title</span>: <span class="hljs-string">"black is king"</span>,
    <span class="hljs-attr">Author</span>: <span class="hljs-string">"black"</span>,
    <span class="hljs-attr">price</span>: <span class="hljs-string">"$23"</span>,
    <span class="hljs-attr">Summary</span>: <span class="hljs-string">"Hello"</span>,
  }));
  <span class="hljs-keyword">await</span> GetAllBooks(req, res); 
expect(res.status).toHaveBeenCalledWith(<span class="hljs-number">200</span>);
expect(res.send).toHaveBeenCalledTimes(<span class="hljs-number">1</span>);
});
</code></pre>
<p>Now the <code>It</code> function contains a short description of what the test should be about. This is then coupled to an anonymous asynchronous function which contains a mock implementation of the database model with some dummy data.</p>
<p>After that, the getAllBooks request is triggered and executed with a null request passed to it and the format of the response object is included.</p>
<p>The <code>expect</code> statement returns <code>passed</code> if the function satisfies the requirements expected. For this code, the requirements are that the <code>response</code> object should return a status code of 200 and the <code>response.send</code> object should be called at least once with the response object included. If it fails, a failed status will be returned.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/test.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>Tests passing</em></p>
<p>You now know the basics of how to unit test functions. You can also try to test the <code>delete book</code> route, <code>upload a book</code> route and <code>find a specific book</code> route.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you've been able to harness the usefulness of testing tools in optimizing your web applications. </p>
<p>You've learned about various testing tools available and their use cases, and you also implemented a unit test in a web application.  </p>
<p>Following the steps highlighted in this tutorial, you will be able to perform unit tests on your coding projects.</p>
<p>I sincerely hope you learned something new and enjoyed this tutorial. Until next time, keep on coding.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Web Apps with Nuxt and Laravel ]]>
                </title>
                <description>
                    <![CDATA[ The Laravel framework is one of the most widely used technologies in the web development ecosystem. It's relatively straightforward, and it's easy to use for building websites.  Laravel is built upon PHP, a popular web programming language that’s use... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-web-apps-with-nuxt-and-laravel/</link>
                <guid isPermaLink="false">66b9d9c738655574e9f95267</guid>
                
                    <category>
                        <![CDATA[ Laravel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Nuxt.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abdulrahman Yusuf ]]>
                </dc:creator>
                <pubDate>Wed, 07 Feb 2024 10:59:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/pexels-pixabay-270557.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The Laravel framework is one of the most widely used technologies in the web development ecosystem. It's relatively straightforward, and it's easy to use for building websites. </p>
<p>Laravel is built upon PHP, a popular web programming language that’s used in over 75% of websites on the web. So knowing how to use a framework like Laravel can help make you a sought-after developer – and it also makes building websites and applications more seamless. </p>
<p>Nuxt is a Vue.js framework used for building rich and interactive web applications. It lets you choose between different rendering modes depending on the application requirements you want to build. You can choose between building a fully server-rendered app or client-rendered app. Nuxt also offers a mixture of both rendering modes, making applications much more powerful, efficient, and interactive.</p>
<p>In this article, you'll learn how to build full-stack applications using Nuxt and Laravel by building a Book Library App. The app will comprise a library API that we'll build using Laravel and a frontend using Nuxt. </p>
<p>We’ll talk about:</p>
<ul>
<li>Installing and setting up Laravel</li>
<li>Creating database models</li>
<li>Migrations</li>
<li>Controllers</li>
<li>API Testing</li>
<li>Form Validations</li>
<li>Data Fetching in Nuxt</li>
</ul>
<p>And more. Get ready, and let's dive in.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents:</strong></h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-laravel-on-your-machine">How to set up Laravel on your machine</a></li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-the-book-library-api">How to build the Book Library API</a></p>
<ul>
<li><a class="post-section-overview" href="#setting-up-our-database">Setting up our database</a></li>
<li><a class="post-section-overview" href="#creating-our-book-model">Creating our Book Model</a></li>
<li><a class="post-section-overview" href="#creating-our-book-controller">Creating our Book Controller</a></li>
<li><a class="post-section-overview" href="#defining-our-api-routes">Defining our API Routes</a></li>
<li><a class="post-section-overview" href="#testing-our-api">Testing our API</a><ul>
<li><a class="post-section-overview" href="#heading-creating-a-new-book-1">Creating a new book</a></li>
<li><a class="post-section-overview" href="#getting-our-list-of-books">Getting our list of books</a></li>
<li><a class="post-section-overview" href="#editing-our-book">Editing our book</a></li>
</ul>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-the-nuxt-frontend">How to Build the Nuxt Frontend</a></p>
</li>
<li><a class="post-section-overview" href="#heading-how-to-integrate-the-laravel-api-in-the-frontend">How to Integrate the Laravel API in the Frontend</a><ul>
<li><a class="post-section-overview" href="#getting-all-books-in-our-library">Getting all books in our library</a></li>
<li><a class="post-section-overview" href="#heading-creating-a-new-book-1">Creating a new book</a></li>
<li><a class="post-section-overview" href="#heading-editing-a-book">Editing a book</a></li>
<li><a class="post-section-overview" href="#heading-deleting-a-book">Deleting a book</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
<li><a class="post-section-overview" href="#heading-resources">Resources</a></li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<ol>
<li><a target="_blank" href="https://www.php.net">PHP</a> and <a target="_blank" href="https://getcomposer.org">Composer</a> are installed on your local machine.</li>
<li><a target="_blank" href="https://nodejs.org/">Node.js</a> is installed on your local machine.</li>
<li><a target="_blank" href="https://yarnpkg.com/">yarn</a> or <a target="_blank" href="https://www.npmjs.com">npm</a> installed on your local machine (npm comes pre-installed with Node).</li>
<li>A text editor installed, like <a target="_blank" href="https://code.visualstudio.com">VSCode</a>.</li>
<li>Basic knowledge of HTML, CSS, JavaScript, and the terminal.</li>
<li>Basic knowledge of PHP, Vue.js, and TypeScript.</li>
</ol>
<h2 id="heading-how-to-set-up-laravel-on-your-machine"><strong>How to Set Up Laravel on Your Machine</strong></h2>
<p>To begin the Laravel installation, open your terminal and bootstrap a new Laravel project using the command below: </p>
<pre><code class="lang-bash">composer create-project laravel/laravel library-api &amp;&amp; <span class="hljs-built_in">cd</span> library-api &amp;&amp; code .
</code></pre>
<p>This command creates a new Laravel project in your directory. <code>cd</code>'s into it, and open up VSCode using the <code>code .</code> command. (If you happen to be using a different editor, you can remove that command and open the directory manually).</p>
<p>To test your Laravel server and ensure everything works, let’s test the server by using the <code>php artisan serve</code> command in the terminal. This should make your API available on port 8000 and accessible in your browser.</p>
<p><img src="https://lh7-us.googleusercontent.com/Wd1K8FLTnBwThyGwMl8lYeTmpO2886t4IN2lJ6Nv2tShwvw0HGxNWhl3cneeAEVVdVL_Gvf9sB0feecPHqpRpXYbPz-dBRPPAnBxJAabWyMySW-FqSwJkUi1_bTOX7fLqo1luWJIRi1iEPlbSkVxh3U" alt="Image" width="1600" height="865" loading="lazy">
<em>Laravel Starter Application</em></p>
<h2 id="heading-how-to-build-the-book-library-api"><strong>How to Build the Book Library API</strong></h2>
<p>We will be creating a simple CRUD endpoint for our book library, that is the API should be able to achieve the following:</p>
<ul>
<li>Create new book entries</li>
<li>Get a list of all the book entries in the database</li>
<li>Edit previously added book entries</li>
<li>Delete book entries from the database</li>
</ul>
<h3 id="heading-setting-up-the-database">Setting up the database</h3>
<p>Laravel comes with a variety of databases you can use during development. By default, it automatically creates a configuration setup for MySQL. But for simplicity, we’ll be making use of a <a target="_blank" href="https://www.sqlite.org/index.html">SQLite</a> database in this tutorial. </p>
<p>Open the <code>.env</code> file in your root directory, change the <code>DB_CONNECTION</code> value from <code>mysql</code> to <code>sqlite</code>, and comment the remaining database configurations as you can see below:</p>
<p><img src="https://lh7-us.googleusercontent.com/NoxsSV5jfFxxzAsKDX04xAfWzUAESGajpJnam3zTA3LpBIil9-esqfxk4I1CJXjlK_jyjEk3twDTGu_Bi_Efw1DUXaU0yUcdCFcdKECCZ-V-hT4Y_03YKfeQCz8JQ5MVSznXcC3dYei8vBb9wTCo1_c" alt="Image" width="1018" height="294" loading="lazy">
<em>Environmental Variables (available in .env file)</em></p>
<p>Laravel automatically helps create the SQLite database when the migrations command is run. We’ll do that in a bit after creating our database models.</p>
<h3 id="heading-creating-the-book-model"><strong>Creating the Book model</strong></h3>
<p>When you're building backend APIs, a model acts as a template that’s used to set up your database tables. It contains high-level instructions for how the tables and columns should be created. </p>
<p>In Laravel, you can use the command below to create a <code>Book</code> model:</p>
<pre><code class="lang-bash">php artisan make:model Book -m
</code></pre>
<p>This creates your Book model in the <code>app/models</code> directory and also creates a new migration file for you in the <code>database/migrations</code> directory.</p>
<p>Navigate to the migrations directory and open the newly created migrations file. It should be in the format <code>current_date_create_books_table.php</code> like you can see below:</p>
<p><img src="https://lh7-us.googleusercontent.com/zW84PQRgiGuLMX9yvmCJ_NvDS4xZfraKtxh7g0Du6rhOoqSpuXGlWnxkCSlTT9yhqT3c6N_jfPAsiuKakLG_MULYgYD6_Qe-Eycxo4hxaozonEVzbjVe64ddSu2FOpdOGMexms1jPuSZc43HB-N0-hY" alt="Image" width="1600" height="1016" loading="lazy">
<em>Default Migrations</em></p>
<p>Edit the <code>up</code> function and add the following content:</p>
<pre><code class="lang-php">$table-&gt;string(<span class="hljs-string">'title'</span>);
$table-&gt;string(<span class="hljs-string">'author'</span>);
$table-&gt;string(<span class="hljs-string">'isbn'</span>);
$table-&gt;date(<span class="hljs-string">'published_date'</span>);
$table-&gt;text(<span class="hljs-string">'cover_image'</span>)-&gt;nullable();
$table-&gt;foreignIdFor(User::class);
</code></pre>
<p>Your migrations file should look like this now:</p>
<p><img src="https://lh7-us.googleusercontent.com/sgSaSbourHadcXleC2Jxn8DHAkulytaRIQfcAZC7ZUPvNTJJITJDr9rDEeYSNf-mNjJxxW285Kz1C5MQlFWBNlSMG7Gk0VEIShz8-AtaA6hRHChRuYYkrYQkIl9IwZ_I0-tO7cXMFd8f3OLen-bAm9o" alt="Image" width="1600" height="1240" loading="lazy">
<em>Updated Migrations</em></p>
<p>In summary, you added new fields to be created for the Book tables. <code>Title</code>, <code>author</code>, and <code>isbn</code> all have a data type of string, while <code>published_date</code> and <code>cover_image</code> have data types of date and text, respectively. </p>
<p>You also made the <code>cover_image</code> nullable, that is the field can be left out whenever a new book entry is created. </p>
<p>Lastly, you imported the <code>User</code> class and made it a <a target="_blank" href="https://www.educative.io/blog/what-is-foreign-key-database">foreign key</a> to your Book table, creating a many-to-one relationship with the User table.</p>
<p>Now, let’s create your tables by running the migrations file with the command below:</p>
<pre><code class="lang-php">php artisan migrate
</code></pre>
<p>You should get a prompt in the terminal asking if you want to create your SQLite database before the migrations. Select yes and press enter to proceed with the migrations.</p>
<p>Once the migration has been run successfully, navigate to the Book model and paste in the following code:</p>
<pre><code class="lang-php"> <span class="hljs-comment">/**
* The attributes that are mass assignable.
*
* <span class="hljs-doctag">@var</span> array&lt;int, string&gt;
*/</span>

<span class="hljs-keyword">protected</span> $fillable = [
    <span class="hljs-string">'user_id'</span>,
    <span class="hljs-string">'title'</span>,
    <span class="hljs-string">'author'</span>,
    <span class="hljs-string">'isbn'</span>,
    <span class="hljs-string">'published_date'</span>,
    <span class="hljs-string">'cover_image'</span>
];
</code></pre>
<p>This will allow mass assignment when passing data into the model (passing the data as a whole instead of individually). Your Book model should look like this now:</p>
<p><img src="https://lh7-us.googleusercontent.com/zjYcbtyiQXKFRJubxnDuL5M6PRyEI5u5PaHGHUAfYgju5A8lQqOJAxRSLdsaIkg0bjFCXOOUTBGHlQXuJhpuEfOW5K6XbPDl2aEQoUyNvjs-p-m5TfRQhF2dlnwnZKHDb0EXsR6JneIGIXCw0ol1plI" alt="Image" width="1600" height="779" loading="lazy">
<em>Updated Book Model</em></p>
<h3 id="heading-creating-the-book-controller"><strong>Creating the Book controller</strong></h3>
<p>The controller is responsible for housing the business logic for any API being created. The implementation logic for how we want to perform any CRUD operations with the library API will live here. </p>
<p>Laravel also provides a command for you to make this easier for developers. Paste the command below in your terminal to create our book controller:</p>
<pre><code class="lang-php">php artisan make:controller BookController
</code></pre>
<p>This should be accessible at <code>app\Http\Controllers\BookController.php</code>. Replace the content of your BookController class with the code snippet below:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Controllers</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">Book</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Carbon</span>\<span class="hljs-title">Carbon</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Request</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Log</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Storage</span>;


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Controller</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">store</span>(<span class="hljs-params">Request $request</span>)
    </span>{
        $data = $request-&gt;validate([
            <span class="hljs-string">'title'</span> =&gt; <span class="hljs-string">'required|string'</span>,
            <span class="hljs-string">'author'</span> =&gt; <span class="hljs-string">'required|string'</span>,
            <span class="hljs-string">'isbn'</span> =&gt; <span class="hljs-string">'required|string|unique:books'</span>,
            <span class="hljs-string">'published_date'</span> =&gt; <span class="hljs-string">'required|string'</span>,
            <span class="hljs-string">'cover_image'</span> =&gt; <span class="hljs-string">'nullable|image|max:2048'</span>,
        ]);

        <span class="hljs-keyword">try</span> {
            $published_date = Carbon::parse($data[<span class="hljs-string">'published_date'</span>])-&gt;toDateString();
            $data[<span class="hljs-string">'published_date'</span>] = $published_date;
            $data[<span class="hljs-string">'user_id'</span>] = <span class="hljs-number">1</span>; <span class="hljs-comment">// Making the assumption the id of the user is 1 </span>
        } <span class="hljs-keyword">catch</span> (\<span class="hljs-built_in">Exception</span> $e) {
            <span class="hljs-keyword">return</span> response()-&gt;json([<span class="hljs-string">'Error'</span> =&gt; <span class="hljs-string">'Bad Request'</span>], <span class="hljs-number">400</span>);
        }

        $book = <span class="hljs-keyword">new</span> Book($data);

        <span class="hljs-keyword">if</span> ($request-&gt;hasFile(<span class="hljs-string">'cover_image'</span>)) {
            $coverImage = $request-&gt;file(<span class="hljs-string">'cover_image'</span>);
            $coverImageName = time() . <span class="hljs-string">'.'</span> . $coverImage-&gt;getClientOriginalExtension();
            $coverImage-&gt;move(public_path(<span class="hljs-string">'images'</span>), $coverImageName);
            $book-&gt;cover_image = $coverImageName;
        }

        $book-&gt;save();

        <span class="hljs-keyword">return</span> response()-&gt;json([<span class="hljs-string">'message'</span> =&gt; <span class="hljs-string">'Book added successfully'</span>], <span class="hljs-number">201</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span>(<span class="hljs-params"></span>)
    </span>{
        $books = Book::all();

        <span class="hljs-keyword">return</span> response()-&gt;json([<span class="hljs-string">'books'</span> =&gt; $books], <span class="hljs-number">200</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">update</span>(<span class="hljs-params">Request $request, $id</span>)
    </span>{
        $book = Book::findOrFail($id);
        $data = $request-&gt;all();

        <span class="hljs-keyword">try</span> {
            $published_date = Carbon::parse($data[<span class="hljs-string">'published_date'</span>])-&gt;toDateString();
            $data[<span class="hljs-string">'published_date'</span>] = $published_date;
            $data[<span class="hljs-string">'user_id'</span>] = $book-&gt;user_id;
        } <span class="hljs-keyword">catch</span> (\<span class="hljs-built_in">Throwable</span> $th) {
            Log::error(<span class="hljs-string">'Error '</span>, $th);
            <span class="hljs-keyword">return</span> response()-&gt;json([<span class="hljs-string">'Error'</span> =&gt; <span class="hljs-string">'Bad Request'</span>], <span class="hljs-number">400</span>);
        }

        $book-&gt;update($data);

        <span class="hljs-keyword">if</span> ($request-&gt;hasFile(<span class="hljs-string">'cover_image'</span>)) {
            <span class="hljs-comment">// Delete the previous cover image if it exists</span>
            <span class="hljs-keyword">if</span> ($book-&gt;cover_image) {
                Storage::delete(<span class="hljs-string">'public/images/'</span> . $book-&gt;cover_image);
            }

            $coverImage = $request-&gt;file(<span class="hljs-string">'cover_image'</span>);
            $coverImageName = time() . <span class="hljs-string">'.'</span> . $coverImage-&gt;getClientOriginalExtension();
            $coverImage-&gt;storeAs(<span class="hljs-string">'public/images'</span>, $coverImageName);
            $book-&gt;cover_image = $coverImageName;
            $book-&gt;save();
        }

        <span class="hljs-keyword">return</span> response()-&gt;json([<span class="hljs-string">'message'</span> =&gt; <span class="hljs-string">'Book updated successfully'</span>], <span class="hljs-number">200</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">destroy</span>(<span class="hljs-params">$id</span>)
    </span>{
        $book = Book::findOrFail($id);

        <span class="hljs-comment">// Delete the cover image if it exists</span>
        <span class="hljs-keyword">if</span> ($book-&gt;cover_image) {
            Storage::delete(<span class="hljs-string">'public/images/'</span> . $book-&gt;cover_image);
        }

        $book-&gt;delete();

        <span class="hljs-keyword">return</span> response()-&gt;json([<span class="hljs-string">'message'</span> =&gt; <span class="hljs-string">'Book deleted successfully'</span>], <span class="hljs-number">200</span>);
    }
}
</code></pre>
<h3 id="heading-defining-the-api-routes"><strong>Defining the API Routes</strong></h3>
<p>Routing is one of the most important parts of building an API. Routes serve as access points through which developers, clients, or any other services can access an API. </p>
<p>The Laravel router allows you to register any routes that correspond to any HTTP verb being requested.</p>
<pre><code class="lang-php">Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
</code></pre>
<p>Navigate to the <code>routes/api.php</code> file and create the following routes for your API:</p>
<pre><code class="lang-php">Route::post(<span class="hljs-string">'/books'</span>, [BookController::class, <span class="hljs-string">'store'</span>]);
Route::get(<span class="hljs-string">'/books'</span>, [BookController::class, <span class="hljs-string">'index'</span>]);
Route::put(<span class="hljs-string">'/books/{id}'</span>, [BookController::class, <span class="hljs-string">'update'</span>]);
Route::delete(<span class="hljs-string">'/books/{id}'</span>, [BookController::class, <span class="hljs-string">'destroy'</span>]);
</code></pre>
<h3 id="heading-testing-the-api"><strong>Testing the API</strong></h3>
<p>Now, it’s time to test your API and ensure all your endpoints are accessible and working as expected. </p>
<p>Run the Laravel server using the command below:</p>
<pre><code class="lang-php">php artisan serve
</code></pre>
<p>You can test the API using any API client of your choice. We have quite a number of popular options to choose from – <a target="_blank" href="https://www.postman.com">Postman</a>, <a target="_blank" href="https://insomnia.rest">Insomnia</a>, <a target="_blank" href="https://www.thunderclient.com">Thunder Client</a>, and so on. I’ll be using Thunder Client here.</p>
<p>We’ll test for all CRUD operations in your API client by confirming if all your objectives for your API are met.</p>
<h3 id="heading-creating-a-new-book">Creating a new book</h3>
<p><img src="https://lh7-us.googleusercontent.com/pUy0u6hCbOEihAsLhLTtSS6p0l3a42PIKHceWRnq5m4-0MJHwwG2r4mL5Y8MCr_EG3g7AuvvmW6nEx9SZ4-GtHTQNFO5Som8f4PYBPjntJSTNJXzrV0sbjL9RYRGhILUWHo6eWFb9tX82XWmrwH70yI" alt="Image" width="1600" height="1096" loading="lazy">
<em>Create book endpoint</em></p>
<h3 id="heading-getting-a-list-of-books">Getting a list of books</h3>
<p><img src="https://lh7-us.googleusercontent.com/9QNUQRrxFzime9Dsl9bKuh82o0XzD6AY8fUaAmQB_mHP0-pyqviLOVPfesLUsINl9n54tYqbjPNOWYEkJwfoXkaVuREbjGhqhghYI5ifi8e7TTQrNSIIm4jU3rM_8akLtc4so-4AzeegJicMpL8IGZw" alt="Image" width="1600" height="1095" loading="lazy">
<em>Get books endpoint</em></p>
<h3 id="heading-editing-a-book">Editing a book</h3>
<p><img src="https://lh7-us.googleusercontent.com/ZTC04dUEXPF2BdxNH-l9RbfzjhkMqO338pQSHjcoEl_hfa3EZbRUtWS2Stgk7slAlwjXpl1_ypvALbuQX3AvLaDPO0gj2rzh5BpqO-uwK6yjSehztm1wJnrjWLzKM0-asFqOU2wMOTp1xffqVroewec" alt="Image" width="1600" height="939" loading="lazy">
<em>Edit book endpoint</em></p>
<h2 id="heading-how-to-build-the-nuxt-frontend">How to Build the Nuxt Frontend</h2>
<p>Setting up a new Nuxt app is as simple as running the command below:</p>
<pre><code class="lang-bash">npx nuxi@latest init nuxt-library-frontend
</code></pre>
<p>Open the newly created project when you’re done installing all the dependencies and start the development server using this command:</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>Your Nuxt app should now be accessible on port 3000:</p>
<p><img src="https://lh7-us.googleusercontent.com/ZOV-VAcrLLTW7i6SAmFNh5q8hRcxhY05wC4vZUXbxTwgR5tTsKop-An1SYlFdXEiquu1zCz1tx5TTwrY9WlDEPuiuNpHh4vDsVWwlUVGvZFWljmsTGgRYST3478Pk79jNcNeXJoGa7lQcAdbTx3YitI" alt="Image" width="1600" height="873" loading="lazy">
<em>Nuxt Starter Page</em></p>
<p>This is what your frontend should look like at the end of the tutorial:</p>
<p><img src="https://lh7-us.googleusercontent.com/FbnijAJw1D-VJTnT8VNPQBfl694-fW2PhYTqoEokTMxceEnsN5Oa-mBTmSAcoeU8xcqRFyDceWTQjElj43oidAg2xtW2KWSVamDbL0kmVDuCZktQc1mER5pbCbGkshNsYm0WJKqbgQy8GVymZ8-Bo5I" alt="Image" width="1600" height="871" loading="lazy">
<em>Sample of our completed application</em></p>
<p>I’ve created some <a target="_blank" href="https://github.com/Young-Einstein10/laravel-nuxt-app">boilerplate code</a> to help with the Nuxt frontend setup. This will enable us to focus on the implementation logic for consuming the Laravel API rather than spending time setting things up and styling. </p>
<p>For knowledge's sake, I created the UI components for the app using <a target="_blank" href="https://www.shadcn-vue.com">shadcn-vue</a>. It consists of an amazing collection of accessible, reusable UI components that you can customize to your taste. Check out the <a target="_blank" href="https://www.shadcn-vue.com/docs/installation/nuxt.html">installation</a> steps for more details on how easy it was to set up for the Nuxt app. </p>
<p>It also comes with an installation of the <a target="_blank" href="https://tailwindcss.com/">Tailwind CSS</a> utility library that’ll we'll use for styling in this tutorial.</p>
<p>Clone the boilerplate setup from the GitHub repo <a target="_blank" href="https://github.com/Young-Einstein10/laravel-nuxt-app">here</a> so we can get started.</p>
<p>Navigate to <code>pages/index.vue</code> and replace the content of the index page with this:</p>
<pre><code class="lang-vue">&lt;template&gt;
 &lt;main class="bg-white p-10 min-h-screen"&gt;
   &lt;div class="max-w-4xl mx-auto"&gt;
     &lt;header class="flex justify-between items-center mb-20"&gt;
       &lt;h1 class="font-semibold text-4xl"&gt;My Library&lt;/h1&gt;
       &lt;Button&gt;Add New Book&lt;/Button&gt;
     &lt;/header&gt;


     &lt;div v-if="isLoading"&gt;
       &lt;p class="italic text-2xl font-medium text-center"&gt;Loading...&lt;/p&gt;
     &lt;/div&gt;
     &lt;div class="mt-8"&gt;
       &lt;div class="flex flex-col gap-8"&gt;
         &lt;div class="flex gap-4" v-for="book in books"&gt;
           &lt;div
             v-if="book.cover_image"
             class="rounded-lg w-32 h-44 flex items-center justify-center"
           &gt;
             &lt;NuxtImg
               :src="`${API_BASE_URL}/images/${book.cover_image}`"
               :alt="book.title"
               class="w-full h-auto"
             /&gt;
           &lt;/div&gt;
           &lt;div v-else class="bg-slate-300 rounded-lg w-32 h-44"&gt;&lt;/div&gt;
           &lt;div class="flex items-center justify-between flex-1"&gt;
             &lt;div&gt;
               &lt;h3 class="font-medium text-xl mb-4"&gt;{{ book.title }}&lt;/h3&gt;
               &lt;p class="mb-2"&gt;
                 &lt;span&gt;by:&lt;/span&gt;
                 &lt;span class="italic"&gt; {{ book.author }} &lt;/span&gt;
               &lt;/p&gt;
               &lt;p&gt;
                 &lt;span&gt;Published:&lt;/span&gt;
                 {{ book.published_date }}
               &lt;/p&gt;
             &lt;/div&gt;
             &lt;div class="actions flex gap-4"&gt;
               &lt;Button&gt;Edit&lt;/Button&gt;
               &lt;Button variant="destructive"&gt; Delete &lt;/Button&gt;
             &lt;/div&gt;
           &lt;/div&gt;
         &lt;/div&gt;
       &lt;/div&gt;
     &lt;/div&gt;
   &lt;/div&gt;
 &lt;/main&gt;
&lt;/template&gt;


&lt;script lang="ts" setup&gt;
import { API_BASE_URL } from "@/utils/constants";
import type { BookProps } from "@/utils/types";


const isLoading = ref(false);
const books = ref&lt;BookProps[]&gt;([]);
&lt;/script&gt;
</code></pre>
<p>We’ll need to create a new folder called <code>utils</code> in your root project which will contain two files: <code>constants.ts</code> and <code>types.ts</code>. Paste the following code snippet in your <code>constants.ts</code> file:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> API_BASE_URL = <span class="hljs-string">"http://localhost:8000"</span>;
</code></pre>
<p>And the following in your <code>types.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> BookProps {
     id?: <span class="hljs-built_in">number</span>;
     title: <span class="hljs-built_in">string</span>;
     author: <span class="hljs-built_in">string</span>;
     isbn: <span class="hljs-built_in">string</span>;
     published_date: <span class="hljs-built_in">string</span>;
     cover_image?: <span class="hljs-built_in">string</span>;
     user_id?: <span class="hljs-built_in">number</span>;
     created_at?: <span class="hljs-built_in">string</span>;
     updated_at?: <span class="hljs-built_in">string</span>;
}
</code></pre>
<p>Save the <code>pages/index.vue</code> file. You should be able to see this result in your browser:</p>
<p><img src="https://lh7-us.googleusercontent.com/1M7J0_i-u7rUaHr6vX5na1sReyIh1e1s5VGFh1mZteE0j7sXM5lFUWBmPXZNDbLuobYM9nkJtodCvUTZig22KnJS471YHdOowjXmlmMBwkBuYpQ0J10rgi_xmJt8Vyfm_tHqsTEh6wdtqLx1q1X7KDc" alt="Image" width="1600" height="871" loading="lazy">
<em>Scaffolding the library frontend with Nuxt</em></p>
<p>Now, we need to create a side drawer and a dialog for adding new books and deleting added books from the database, respectively. </p>
<p>Create a new file called <code>BookDrawer.vue</code> in the component's root and add the following code in there:</p>
<pre><code class="lang-vue">&lt;script setup lang="ts"&gt;
import type { BookProps } from "@/utils/types";


type PickedProps = "title" | "author" | "isbn" | "published_date";
interface CustomBookProps extends Pick&lt;BookProps, PickedProps&gt; {
 cover_image?: string;
}


const props = defineProps&lt;{ open: boolean; book?: BookProps }&gt;();
const emit = defineEmits(["update:open", "refresh-data"]);


const isSubmitting = ref(false);
let form = reactive&lt;CustomBookProps&gt;({
 title: "",
 author: "",
 isbn: "",
 published_date: "",
 cover_image: undefined,
});


const onFileChange = async (e: any) =&gt; {
 form.cover_image = e.target.files[0];
};


const onSubmit = async () =&gt; {};


const closeDrawer = (openState: boolean) =&gt; emit("update:open", openState);
&lt;/script&gt;


&lt;template&gt;
 &lt;Sheet :open="open" @update:open="closeDrawer"&gt;
   &lt;SheetContent class="w-full bg-white"&gt;
     &lt;SheetHeader&gt;
       &lt;SheetTitle&gt;
         &lt;template v-if="book"&gt; Edit Book &lt;/template&gt;
         &lt;template v-else&gt;Add New Book&lt;/template&gt;
       &lt;/SheetTitle&gt;
       &lt;SheetDescription&gt;
         Make changes to your profile here. Click save when you're done.
       &lt;/SheetDescription&gt;
     &lt;/SheetHeader&gt;
     &lt;div class="grid gap-4 py-4"&gt;
       &lt;div class="grid grid-cols-4 items-center gap-4"&gt;
         &lt;Label for="bookTitle" class="text-right"&gt; Book Title &lt;/Label&gt;
         &lt;Input
           v-model:model-value="form.title"
           type="text"
           id="bookTitle"
           class="col-span-3"
           required
         /&gt;
       &lt;/div&gt;
       &lt;div class="grid grid-cols-4 items-center gap-4"&gt;
         &lt;Label for="author" class="text-right"&gt; Author &lt;/Label&gt;
         &lt;Input
           v-model:model-value="form.author"
           type="text"
           id="author"
           class="col-span-3"
           required
         /&gt;
       &lt;/div&gt;
       &lt;div class="grid grid-cols-4 items-center gap-4"&gt;
         &lt;Label for="isbn" class="text-right"&gt; ISBN &lt;/Label&gt;
         &lt;Input
           v-model:model-value="form.isbn"
           type="text"
           id="isbn"
           class="col-span-3"
           required
         /&gt;
       &lt;/div&gt;
       &lt;div class="grid grid-cols-4 items-center gap-4"&gt;
         &lt;Label for="published_date" class="text-right"&gt;
           Published Date
         &lt;/Label&gt;
         &lt;Input
           v-model:model-value="form.published_date"
           type="date"
           id="published_date"
           class="col-span-3"
           required
         /&gt;
       &lt;/div&gt;
       &lt;div class="grid grid-cols-4 items-center gap-4"&gt;
         &lt;Label for="cover_image" class="text-right"&gt; Book Cover &lt;/Label&gt;


         &lt;Input
           type="file"
           @change="onFileChange"
           id="cover_image"
           class="col-span-3"
           required
         /&gt;
       &lt;/div&gt;
     &lt;/div&gt;
     &lt;SheetFooter&gt;
       &lt;Button type="submit" @click="onSubmit"&gt;
         &lt;template v-if="isSubmitting"&gt;Saving...&lt;/template&gt;
         &lt;template v-else&gt; Save changes &lt;/template&gt;
       &lt;/Button&gt;
     &lt;/SheetFooter&gt;
   &lt;/SheetContent&gt;
 &lt;/Sheet&gt;
&lt;/template&gt;
</code></pre>
<p>Create another file called <code>DeleteBookDrawer.vue</code> and add the following code content to it: </p>
<pre><code class="lang-vue">&lt;script lang="ts" setup&gt;
const emit = defineEmits(["refresh-data", "update:open"]);
const props = defineProps&lt;{ open: boolean; book?: BookProps }&gt;();
&lt;/script&gt;


&lt;template&gt;
 &lt;AlertDialog
   :open="open"
   @update:open="(openState) =&gt; $emit('update:open', openState)"
 &gt;
   &lt;AlertDialogContent&gt;
     &lt;AlertDialogHeader&gt;
       &lt;AlertDialogTitle&gt;Are you absolutely sure?&lt;/AlertDialogTitle&gt;
       &lt;AlertDialogDescription&gt;
         This action cannot be undone. This will permanently delete your book
         and remove your data from the server.
       &lt;/AlertDialogDescription&gt;
     &lt;/AlertDialogHeader&gt;
     &lt;AlertDialogFooter&gt;
       &lt;AlertDialogCancel @click="$emit('update:open', false)"
         &gt;Cancel&lt;/AlertDialogCancel
       &gt;
       &lt;AlertDialogAction&gt;Continue&lt;/AlertDialogAction&gt;
     &lt;/AlertDialogFooter&gt;
   &lt;/AlertDialogContent&gt;
 &lt;/AlertDialog&gt;
&lt;/template&gt;
</code></pre>
<p>Import the newly created files in your index page as you can see below:</p>
<pre><code class="lang-vue">&lt;template&gt;
 &lt;main class="bg-white p-10 min-h-screen"&gt;
    ...

   &lt;BookDrawerDialog
     v-if="isBookDrawerOpen"
     :open="isBookDrawerOpen"
     @update:open="(open: boolean) =&gt; isBookDrawerOpen = open"
     :book="currentBook"
     @refresh-data="fetchBooks"
   /&gt;
   &lt;DeleteBookDialog
     v-if="isDeleteBookDialogOpen"
     :open="isDeleteBookDialogOpen"
     @update:open="(open: boolean) =&gt; isDeleteBookDialogOpen = open"
     :book="currentBook"
     @refresh-data="fetchBooks"
   /&gt;
 &lt;/main&gt;
&lt;/template&gt;
</code></pre>
<p>Now, we need to create a system for opening and closing the drawer and dialog, respectively. We’ll be creating a <a target="_blank" href="https://vuejs.org/guide/essentials/reactivity-fundamentals.html#ref">ref</a> to track the open/closed state for the drawer and dialog components in your index page. Paste the following code content in the script stage to enable that:</p>
<pre><code class="lang-vue">&lt;script lang="ts" setup&gt;

...

const currentBook = ref&lt;BookProps&gt;();


const isBookDrawerOpen = ref(false);
const isDeleteBookDialogOpen = ref(false);


const toggleAddBookDrawer = () =&gt; {
 isBookDrawerOpen.value = !isBookDrawerOpen.value;
};


const toggleEditBookDrawer = (book: BookProps) =&gt; {
 currentBook.value = book;
 isBookDrawerOpen.value = !isBookDrawerOpen.value;
};


const toggleDeleteDialog = (book: BookProps) =&gt; {
 currentBook.value = book;
 isDeleteBookDialogOpen.value = !isDeleteBookDialogOpen.value;
};
&lt;/script&gt;
</code></pre>
<p>Update the <code>Edit</code> and <code>Delete</code> buttons in your index page to include the toggle handler:</p>
<pre><code class="lang-vue">    ...

             &lt;div class="actions flex gap-4"&gt;
               &lt;Button @click="toggleEditBookDrawer(book)"&gt;Edit&lt;/Button&gt;
               &lt;Button @click="toggleDeleteDialog(book)" variant="destructive"&gt;
                 Delete
               &lt;/Button&gt;
             &lt;/div&gt;

           ...
</code></pre>
<p>Include the <code>toggleAddDrawer</code> in your Add Book button too:</p>
<pre><code class="lang-vue">&lt;Button @click="toggleAddBookDrawer"&gt;Add New Book&lt;/Button&gt;
</code></pre>
<p>Save the file changes and view in your browser. You should have the drawer active now:  </p>
<p><img src="https://lh7-us.googleusercontent.com/82AHDkwCX-oTW6pOpcwi735-8i5HluzloFnwDGnidH5gNKP8dkj3pXxr-Oa6gpMcQGZA-FnzsCP5nzpP0uGPDMhyTMkNqvxLXnVaK0TWFTBG-IrQPGU74-vhPpqCz1y7CcRULG7AUWcJsmejfdR5O2k" alt="Image" width="1600" height="816" loading="lazy">
<em>Add New Book Drawer</em></p>
<p>Moving on, we need to be sure the EditDrawer and Delete Dialog work. We’ll create a temporary array of mock book data to test that so you can see the result on your page. Update the value of the <code>books</code> ref to the data you have below (and don’t forget to update the books ref value to an empty array – that is <code>books = ref&lt;BookProps&gt;([])</code>):</p>
<pre><code class="lang-vue">const books = ref&lt;BookProps[]&gt;([
     {
       title: "Atomic Habits",
       author: "James Clear",
       isbn: "XYEOUIUEHEJ2902",
       published_date: "2020-09-01",
       cover_image: "",
     },
     {
       title: "The Power of Habits",
       author: "Charles Duhigg",
       isbn: "WIUIQUEWHSDBSD28",
       published_date: "2012-02-28",
       cover_image: "",
     },
]);
</code></pre>
<p>Save the changes and check out the EditDrawer and DeleteDialog in action:</p>
<p><img src="https://lh7-us.googleusercontent.com/_kiROvQBeLBq1UV9Zj4n0tVYOdW9nLUUjb5qlxGtgFGvAJtHsGJ0CvoEyYHxB4BIQ31SznXfwkiXhg_5VowECEMuSCYnIhfEHWeiHAt-hhA9dETiyTOgqNjsxxAenIhx0gl2koYaLVGYnohdpTV13KU" alt="Image" width="1519" height="824" loading="lazy">
<em>Delete dialogue</em></p>
<p><img src="https://lh7-us.googleusercontent.com/YSTKDAEOpLp45EXn61OlRYTTW3hYmOF-ur3SES7emDWMyigINQNvpAozgscEF84-RgiZrgCkTIxtZehFYDMIntzWmy589khRcP7FV4OpdacfXvsi8xRlJG9qWBuXc8Csbal0C_Tr-_lrDt6AatSnVIg" alt="Image" width="1513" height="821" loading="lazy">
<em>EditDrawer</em></p>
<h2 id="heading-how-to-integrate-the-laravel-api-in-the-frontend">How to Integrate the Laravel API in the Frontend</h2>
<h3 id="heading-getting-all-books-in-the-library">Getting all books in the library</h3>
<p>So far, we only have the UI of our frontend working, and the data being displayed is not from the API. To make the app fully dynamic, you'll need to make an HTTP request to the server to get all the data you need for your page. </p>
<p>Update the body of the <code>fetchBooks</code> function in the index page to the following code:</p>
<pre><code class="lang-vue">const fetchBooks = async () =&gt; {
 try {
   isLoading.value = true;
   const response = await $fetch&lt;{ books: BookProps[] }&gt;(
     `${API_BASE_URL}/api/books`
   );


   books.value = response.books.sort(
     (a, b) =&gt;
       Number(new Date(b.created_at as string)) -
       Number(new Date(a.created_at as string))
   );


 } catch (error) {
   console.log(error);
 } finally {
   isLoading.value = false;
 }
};


onMounted(() =&gt; {
 fetchBooks();
});
</code></pre>
<p>Basically, you're calling your <code>fetchBooks</code> function when the page mounts using one of the <a target="_blank" href="https://vuejs.org/api/composition-api-lifecycle.html#onmounted">lifecycle hooks</a> available in Vue.js. When the function is called, it executes the instruction you created in the body:</p>
<ul>
<li>Set the loading state of the app to true.</li>
<li>Make a GET HTTP request to the books endpoint of your API and set the response to the books ref you created earlier.</li>
<li>When the request-response has been completed, set the loading state of the app back to false to indicate to the user the process has been completed.</li>
</ul>
<p>Save the changes, and you should see the results in the browser:</p>
<p><img src="https://lh7-us.googleusercontent.com/SGyND7gBGa7NmUXM4k-7Jn8pyuRizWhMJOOGnwZMMe7NIz6Jzt_qC0D3JUf-7X9IlGJMdm8XLbzGHG8cuKcJ6z83XpxOrrSGdAgOFaaUd6tDmo6-bDY-3PZG1lLRW4mywF77A86ABoIggR6NGwDDK5A" alt="Image" width="1509" height="818" loading="lazy">
<em>Fetching the book list</em></p>
<h3 id="heading-creating-a-new-book-1">Creating a new book</h3>
<p>For your book creation to be successful, you need to include the logic for creating a book in your <code>BookDrawer</code>. Add the following code in the <code>BookDrawer.vue</code> file:</p>
<pre><code class="lang-vue">...

const isSubmitting = ref(false);


const addNewBook = async (data: any) =&gt; {
 const response = await $fetch(`${API_BASE_URL}/api/books`, {
   method: "POST",
   body: data,
   headers: {
     Accept: "application/json",
   },
 });
 return response;
};


const onSubmit = async () =&gt; {
 try {
   const formData = new FormData();
   Object.keys(form).forEach((key) =&gt; {
     // @ts-ignore
     if (form[key]) {
       formData.append(key, form[key as never]);
     }
   });
   isSubmitting.value = true;
   const data = await addNewBook(formData);
   closeDrawer(false);
   emit("refresh-data");
 } catch (error) {
   console.log(error);
 } finally {
   isSubmitting.value = false;
 }
};

...
</code></pre>
<p>Similar to the implementation for fetching your books, the only difference here is that you're making a POST HTTP request instead. You use this method whenever you need to mutate data on the server.</p>
<p><img src="https://lh7-us.googleusercontent.com/7zQhG_V35mPWJW9sxMyTP8QjnezzoVg1eX08pdJ3Mw7EiXPwcHiTLdYHUD8HWqXg54SjvXymxrBCVWUjXbiuVNCAdj5vccdPyFl6KFJuuKAFTC9sYUQkkGYnESKr3aVHgUONnyOqAf1-fkafeqgyifE" alt="Image" width="1600" height="778" loading="lazy">
<em>Creating a new book</em></p>
<h3 id="heading-editing-a-book-1">Editing a book</h3>
<p>Update your <code>BookDrawer</code> with the following code to enable editing of the books that have been added:</p>
<pre><code class="lang-vue">&lt;script setup lang="ts"&gt;

...

onMounted(() =&gt; {
 if (props.book) {
   form = props.book;
 }
});


const editBook = async () =&gt; {
 try {
   isSubmitting.value = true;
   const resp = await $fetch(`${API_BASE_URL}/api/books/${props?.book?.id}`, {
     method: "PUT",
     body: formData,
   });
   closeDrawer(false);
   emit("refresh-data");
 } catch (error) {
   console.log(error);
 } finally {
   isSubmitting.value = false;
 }
};

...
&lt;/script&gt;
</code></pre>
<p>Update the save button with the toggle handler also:</p>
<pre><code class="lang-vue">&lt;Button
  type="submit"
  @click="() =&gt; (book?.id ? editBook() : onSubmit())"
&gt;
  &lt;template v-if="isSubmitting"&gt;Saving...&lt;/template&gt;
  &lt;template v-else&gt; Save changes &lt;/template&gt;
&lt;/Button&gt;
</code></pre>
<p>And here's the result:</p>
<p><img src="https://lh7-us.googleusercontent.com/aUGh8K6y9u8qXRwckj_PRphjvbnTR2DXf8jnHVehD2aaKtaCdCK1SVPjW-AbWwp_CXZROabKsTk0JBCaUjLAAzEbDHlFCbG6sjkpcVdW9VaKPqoYkVp2aoEtec5vPpjxFtNVAdFFWp3E3T_ZWNdxtYc" alt="Image" width="1600" height="867" loading="lazy">
<em>Updating a book</em></p>
<h3 id="heading-deleting-a-book">Deleting a book</h3>
<p>Paste the following in the <code>DeleteBookDialog.vue</code> file:</p>
<pre><code class="lang-vue">const refreshData = () =&gt; emit("refresh-data");
const closeDialog = () =&gt; emit("update:open", false);


const deleteBook = async () =&gt; {
 await $fetch(`${API_BASE_URL}/api/books/${props?.book?.id}`, {
   method: "DELETE",
 });
 closeDialog();
 refreshData();
};
</code></pre>
<p>This works fine also:</p>
<p><img src="https://lh7-us.googleusercontent.com/KyP9Y8L7qzkvvQCfyuFSBCQvrV30hE-rpQ72Q2Z1-DL-6rzkXnFAuwWEAL0Y1t110slYV813RPXyTKlxxKG5gHFQitUdVuT_7a-gkPxpJXtYOtRsxHWI0JSt9nFDeM6ywNf3ReoCxeIsKzguzZosw_E" alt="Image" width="1600" height="816" loading="lazy">
<em>Deleting a book</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Building full-stack web apps with Laravel and Nuxt is a very rewarding experience as you can enjoy the benefits and rewards from the best of both worlds. </p>
<p>Since Laravel is a feature-rich backend framework, it comes with many modules and packages that you can install whenever a feature or implementation needs to be worked on. </p>
<p>And Nuxt, as a Vue framework, gives you the superpower of building single-page applications that are fast, accessible, and responsive, giving end-users a delightful experience.</p>
<p>In this tutorial, we went over how we can build full-stack applications using Nuxt and the Laravel framework. I hope you were able to learn something new and are excited to explore this further. Feel free to reach out if you have any questions or ideas. </p>
<p>The full code for the tutorial can be found in the GitHub repo <a target="_blank" href="https://github.com/Young-Einstein10/laravel-nuxt-app/tree/final">here</a>.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><a target="_blank" href="https://laravel.com/docs/10.x">Laravel Docs</a></li>
<li><a target="_blank" href="https://nuxt.com/docs/getting-started/installation">Nuxt Documentation</a></li>
<li><a target="_blank" href="https://www.shadcn-vue.com">Shadcn-vue</a>, ready-made UI components that can be copy-pasted anytime</li>
<li><a target="_blank" href="https://vuejs.org">Vue Docs</a>  </li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Work with Third-Party APIs in React by Building a Crypto Exchange Rate Web App ]]>
                </title>
                <description>
                    <![CDATA[ Working with APIs is crucial to any web application. And as a frontend developer, knowing how to connect your apps with third-party APIs is an important skill to have. In this article, you'll learn how to connect your app and fetch data from a third-... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/work-with-third-party-libraries-in-react/</link>
                <guid isPermaLink="false">66d45dd7c7632f8bfbf1e3e7</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Chidera Humphrey ]]>
                </dc:creator>
                <pubDate>Wed, 10 Jan 2024 15:24:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/20240105_040821_0000-3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Working with APIs is crucial to any web application. And as a frontend developer, knowing how to connect your apps with third-party APIs is an important skill to have.</p>
<p>In this article, you'll learn how to connect your app and fetch data from a third-party API by building a crypto exchange web application in React.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#how-to-set-up-the-project">How to Set Up the Project</a></p>
<ul>
<li><p><a class="post-section-overview" href="#initialize-a-new-react-project">Initialize a new React project</a></p>
</li>
<li><p><a class="post-section-overview" href="#install-the-necessary-dependencies">Install the necessary dependencies</a></p>
</li>
<li><p><a class="post-section-overview" href="#set-up-your-project-structure">Set up your project structure</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#how-to-build-the-ui">How to Build the UI</a></p>
</li>
<li><p><a class="post-section-overview" href="#how-to-fetch-data-with-react-query">How to Fetch Data with React Query</a></p>
</li>
<li><p><a class="post-section-overview" href="#how-to-display-data-in-the-ui">How to Display Data in the UI</a></p>
</li>
<li><p><a class="post-section-overview" href="#error-handling">Error Handling</a></p>
</li>
<li><p><a class="post-section-overview" href="#conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>This tutorial assumes you have foundational knowledge of React. Also, you should be able to work with Axios, specifically for making API calls.</p>
<p>Also, you will need an API key from <a target="_blank" href="https://rapidapi.com">RapidAPI</a> to follow along with this tutorial.</p>
<h2 id="heading-how-to-set-up-the-project">How to Set Up the Project</h2>
<h3 id="heading-initialize-a-new-react-project">Initialize a new React project</h3>
<p>Use the following command to initialize a new React project using Vite: <code>npm create vite@latest</code></p>
<p>Then follow the prompts that come after.</p>
<p><a target="_blank" href="https://vitejs.dev/guide/">Vite</a> is a build tool that enables fast reloading of your React apps. For more information on Vite, you can check out their official documentation.</p>
<h3 id="heading-install-the-necessary-dependencies">Install the necessary dependencies</h3>
<p>For this tutorial, you will need a few packages:</p>
<ul>
<li><p>Axios: a library for making promise-based API calls.</p>
</li>
<li><p>react-query: a data fetching library that handles caching, loading, and error state of our API call.</p>
</li>
<li><p>antd (Ant Design): a UI library of pre-built React components.</p>
</li>
</ul>
<p>Use the following command to install these packages: <code>npm install react-query antd axios</code></p>
<h3 id="heading-set-up-your-project-structure">Set up your project structure</h3>
<p>In this section, you are going to create some folders inside the <code>src</code> folder. This is to keep your app structure clean and easy to work with.</p>
<p>Inside the <code>src</code> folder, create a new folder called <code>components</code>.</p>
<p>Inside of the <code>components</code> folder, create three folders: <code>fetchData</code>, <code>UI</code>, and <code>currencies</code>.</p>
<p>With the project setup out of the way, let's move to building the application.</p>
<h2 id="heading-how-to-build-the-ui">How to Build the UI</h2>
<p>In this section, you are going to create the UI of the app. There will be little to no logic.</p>
<p>Navigate to the <code>UI</code> folder inside the <code>components</code> folder.</p>
<p>Create a new file, <code>ExchangeRateUI.jsx</code>, inside of the <code>UI</code> folder.</p>
<p>Add the following code inside the <code>ExchangeRateUI.jsx</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Typography, Card } <span class="hljs-keyword">from</span> <span class="hljs-string">"antd"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ExchangeRateUI</span>(<span class="hljs-params">props</span>) </span>{
 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"exchange-rate-ui"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">Card</span>
       <span class="hljs-attr">extra</span>=<span class="hljs-string">{3}</span>
       <span class="hljs-attr">bordered</span>=<span class="hljs-string">{false}</span>
       <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">width:</span> <span class="hljs-attr">350</span>, <span class="hljs-attr">backgroundColor:</span> "#<span class="hljs-attr">4d4add</span>", <span class="hljs-attr">color:</span> "#<span class="hljs-attr">fff</span>" }}
       <span class="hljs-attr">size</span>=<span class="hljs-string">"default"</span>
     &gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">Typography.Paragraph</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> "#<span class="hljs-attr">fff</span>" }}&gt;</span>Bitcoin<span class="hljs-tag">&lt;/<span class="hljs-name">Typography.Paragraph</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
 );
}
</code></pre>
<p>In the code above, you used the <code>Card</code> and <code>Typography</code> components of the Ant Design UI library to create the UI of our app.</p>
<p>Next, navigate to the <code>currencies</code> folder and create a <code>currencies.jsx</code> file.</p>
<p>Add the following code inside <code>currencies.jsx</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> cryptocurrencies = [
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"BTC"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Bitcoin"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"ETH"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Ethereum"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"BCH"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Bitcoin Cash"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"XRP"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Ripple"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"SOL"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Solana"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"ADA"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Cardano"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"BNB"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Binance Coin"</span> },
];

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> fiatCurrencies = [
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"USD"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"US Dollar"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"GBP"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"British Pound"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"EUR"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Euro"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"NGN"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Naira"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"CNY"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Chinese Yuan"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"RUB"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Russian Ruble"</span> },
  { <span class="hljs-attr">value</span>: <span class="hljs-string">"SGD"</span>, <span class="hljs-attr">label</span>: <span class="hljs-string">"Singaporean Dollar"</span> },
];
</code></pre>
<p>In the code above, you created two arrays, <code>fiatCurrencies</code> and <code>cryptocurrencies</code>, and exported those arrays. They will be used by the Ant Design <code>Select</code> components.</p>
<p>Next, create a file, <code>ExchangeRate.jsx</code>, inside the <code>components</code> folder.</p>
<p>Add the following code inside the <code>ExchangeRate.jsx</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { Typography, Select } <span class="hljs-keyword">from</span> <span class="hljs-string">"antd"</span>;
<span class="hljs-keyword">import</span> { cryptocurrencies, fiatCurrencies } <span class="hljs-keyword">from</span> <span class="hljs-string">"./currencies/currencies.jsx"</span>;
<span class="hljs-keyword">import</span> { ExchangeRateUI } <span class="hljs-keyword">from</span> <span class="hljs-string">"./UI/ExchangeRateUI.jsx"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ExchangeRate</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [fromCurrency, setFromCurrency] = useState(cryptocurrencies[<span class="hljs-number">0</span>].value);
  <span class="hljs-keyword">const</span> [toCurrency, setToCurrency] = useState(fiatCurrencies[<span class="hljs-number">0</span>].value);

  <span class="hljs-keyword">const</span> handleFromCurrencyChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setFromCurrency(e);
    <span class="hljs-built_in">console</span>.log(e);
  };

  <span class="hljs-keyword">const</span> handleToCurrencyChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setToCurrency(e);
    <span class="hljs-built_in">console</span>.log(e);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"exchange-rate"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Typography.Title</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> "#<span class="hljs-attr">4d4add</span>" }} <span class="hljs-attr">level</span>=<span class="hljs-string">{2}</span>&gt;</span>
        Exchange Rate
      <span class="hljs-tag">&lt;/<span class="hljs-name">Typography.Title</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Typography.Text</span>&gt;</span>
        Get the latest exchange rate of cryptocurrencies in your favorite
        currency
      <span class="hljs-tag">&lt;/<span class="hljs-name">Typography.Text</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"select-group"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> "<span class="hljs-attr">flex</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">1rem</span>", <span class="hljs-attr">gap:</span> "<span class="hljs-attr">1rem</span>", <span class="hljs-attr">justifyContent:</span> "<span class="hljs-attr">space-around</span>" }}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Select</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{cryptocurrencies[0].value}</span> <span class="hljs-attr">options</span>=<span class="hljs-string">{cryptocurrencies}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleFromCurrencyChange}</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Select</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{fiatCurrencies[0].value}</span> <span class="hljs-attr">options</span>=<span class="hljs-string">{fiatCurrencies}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleToCurrencyChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">1rem</span>" }}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ExchangeRateUI</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExchangeRate;
</code></pre>
<p>In the <code>ExchahgeRate</code> component, you imported the <code>fiatCurrencies</code> and <code>cryptocurrencies</code> arrays from the <code>currencies</code> folder. The <code>fiatCurrencies</code> and <code>cryptocurrencies</code> arrays are used by the <code>Select</code> component to render the selected currencies you wish to convert.</p>
<p>The <code>useState</code> hook is used to keep track of the selected currencies.</p>
<p>The <code>return</code> statement renders the <code>ExchangeRateUI</code> component.</p>
<p>Update your <code>App.jsx</code> file with the following code: <code>import ExchangeRate from './components/ExchangeRate.jsx' function App(){ return ( &lt;ExchangeRate/&gt; ) } export default App;</code></p>
<p>If you followed each step correctly, your web app should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/GIF-240109_045936-1-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>GIF of the crypto app UI</em></p>
<p>Now that the app's UI is set up, let's move on to implementing the data fetching logic.</p>
<h2 id="heading-how-to-fetch-data-with-react-query">How to Fetch Data with React Query</h2>
<p>In this section, you are going to implement the data fetching logic.</p>
<p>Replace the code in the <code>App.jsx</code> file with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { QueryClient, QueryClientProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-query"</span>;
<span class="hljs-keyword">import</span> ExchangeRate <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/ExchangeRate.jsx"</span>;

<span class="hljs-keyword">const</span> queryClient = <span class="hljs-keyword">new</span> QueryClient(); <span class="hljs-comment">// Instantiate a new QueryClient instance</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">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">QueryClientProvider</span> <span class="hljs-attr">client</span>=<span class="hljs-string">{queryClient}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ExchangeRate</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">QueryClientProvider</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In the code above, you created a <code>queryClient</code> using <code>QueryClient()</code> from <code>react-query</code>. The <code>queryClient</code> is passed to the <code>QueryClientProvider</code> via the <code>client</code> props. This allows the child components to have access to the <code>queryClient</code>, which will be used for data fetching.</p>
<p>React-query comes with good default configurations, but you are going to alter some of these default configurations. This is to avoid rate limiting due to excessive requests to the API.</p>
<p>Replace the <code>queryClient</code> declaration with the following code in your <code>App.jsx</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// previous code</span>

<span class="hljs-keyword">const</span> queryClient = <span class="hljs-keyword">new</span> QueryClient({
  <span class="hljs-attr">defaultOptions</span>: {
    <span class="hljs-attr">queries</span>: {
      <span class="hljs-attr">method</span>: <span class="hljs-string">"GET"</span>, <span class="hljs-comment">// Default HTTP method for queries</span>
      <span class="hljs-attr">refetchOnWindowFocus</span>: <span class="hljs-literal">false</span>, <span class="hljs-comment">// Disable automatic refetching on window focus</span>
      <span class="hljs-attr">refetchInterval</span>: <span class="hljs-number">60000</span>, <span class="hljs-comment">// Refetch queries every 60 seconds</span>
    },
  },
});

<span class="hljs-comment">// remaining code</span>
</code></pre>
<p>In the code above, you are stopping the component from refetching when you refocus on the web page. Also, you are increasing the background refetching time to six seconds.</p>
<p>After making the changes, your <code>App.jsx</code> should look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { QueryClient, QueryClientProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-query"</span>;

<span class="hljs-keyword">const</span> queryClient = <span class="hljs-keyword">new</span> QueryClient({
  <span class="hljs-attr">defaultOptions</span>: {
    <span class="hljs-attr">queries</span>: {
      <span class="hljs-attr">refetchOnWindowFocus</span>: <span class="hljs-literal">false</span>, <span class="hljs-comment">// Disable automatic refetching on focus</span>
      <span class="hljs-attr">refetchInterval</span>: <span class="hljs-number">60000</span>, <span class="hljs-comment">// Refetch queries every 60 seconds</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">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">QueryClientProvider</span> <span class="hljs-attr">client</span>=<span class="hljs-string">{queryClient}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ExchangeRate</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">QueryClientProvider</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Next, you are going to create the data fetching function in the <code>fetchData</code> folder.</p>
<p>Create a new file called <code>fetchData.jsx</code> in the <code>fetchData</code> folder.</p>
<p>Add the following code in the <code>fetchData.jsx</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span> 

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getExchangeRate</span>(<span class="hljs-params">fromCurrency, toCurrency</span>)</span>{ 

    <span class="hljs-keyword">const</span> options = { 
        <span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>, 
        <span class="hljs-attr">url</span>: <span class="hljs-string">'https://alpha-vantage.p.rapidapi.com/query'</span>, 
        <span class="hljs-attr">params</span>: { <span class="hljs-attr">from_currency</span>: fromCurrency, <span class="hljs-attr">function</span>: <span class="hljs-string">'CURRENCY_EXCHANGE_RATE'</span>, <span class="hljs-attr">to_currency</span>: toCurrency }, 
        <span class="hljs-attr">headers</span>: { <span class="hljs-string">'X-RapidAPI-Key'</span>: <span class="hljs-string">'YOUR API KEY'</span>, <span class="hljs-string">'X-RapidAPI-Host'</span>: <span class="hljs-string">'alpha-vantage.p.rapidapi.com'</span> } 
    }; 

    <span class="hljs-keyword">return</span> axios.request(options)
        .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> { <span class="hljs-keyword">return</span> res.data; })
        .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> { <span class="hljs-keyword">return</span> err; }) 

}
</code></pre>
<p>In the code above, you used Axios to fetch data from the AlphaVantage API through RapidAPI.</p>
<p>Remember to replace <code>YOUR API KEY</code> with your API key from RapidAPI.</p>
<p>Navigate to your <code>ExchangeRate</code> component, and add the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-query'</span>;
<span class="hljs-keyword">import</span> { getExchangeRate } <span class="hljs-keyword">from</span> <span class="hljs-string">'./fetchData/fetchData.jsx'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ExchangeRate</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// previous code</span>

  <span class="hljs-keyword">const</span> dependencies = {
    <span class="hljs-attr">fromCurrency</span>: fromCurrency,
    <span class="hljs-attr">toCurrency</span>: toCurrency,
  };

  <span class="hljs-keyword">const</span> { data, isLoading, isError, error } = useQuery({
    <span class="hljs-attr">queryKey</span>: [<span class="hljs-string">"exchangeRate"</span>, dependencies],
    <span class="hljs-attr">queryFn</span>: <span class="hljs-function">() =&gt;</span> fetchData(fromCurrency, toCurrency),
    <span class="hljs-attr">staleTime</span>: <span class="hljs-number">1000</span> * <span class="hljs-number">60</span>,
    <span class="hljs-attr">retry</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">retryDelay</span>: <span class="hljs-number">6000</span>,
  });

  <span class="hljs-comment">// further code</span>
}
</code></pre>
<p>In the code above, you used the <code>useQuery</code> hook to fetch the exchange rate data with specified parameters.</p>
<p>The <code>useQuery</code> hook returns an object with many properties – but the following are the properties that are of interest:</p>
<ul>
<li><p><code>data</code>: holds the fetched data.</p>
</li>
<li><p><code>isLoading</code>: indicates if the data is still being fetched.</p>
</li>
<li><p><code>isError</code>: indicates if an error occurred during fetching.</p>
</li>
<li><p><code>error</code>: contains the error details if there's an issue.</p>
</li>
</ul>
<p>The <code>queryKey</code> is an array representing a unique identifier for this query, and <code>staleTime</code> sets the cache to consider data stale after a minute. <code>retry</code> and <code>retryDelay</code> control retry attempts.</p>
<p>Let's look at the <code>data</code> property.</p>
<p>The <code>data</code> property is the response object that is successfully returned from our call to the AlphaVantage API.</p>
<p>The <code>data</code> property looks like this:</p>
<pre><code class="lang-sh">{
  <span class="hljs-string">"Realtime Currency Exchange Rate"</span>: {
    <span class="hljs-string">"1. From_Currency Code"</span>: <span class="hljs-string">"BTC"</span>,
    <span class="hljs-string">"2. From_Currency Name"</span>: <span class="hljs-string">"Bitcoin"</span>,
    <span class="hljs-string">"3. To_Currency Code"</span>: <span class="hljs-string">"USD"</span>,
    <span class="hljs-string">"4. To_Currency Name"</span>: <span class="hljs-string">"United States Dollar"</span>,
    <span class="hljs-string">"5. Exchange Rate"</span>: <span class="hljs-string">"44138.96000000"</span>,
    <span class="hljs-string">"6. Last Refreshed"</span>: <span class="hljs-string">"2024-01-05 00:16:03"</span>,
    <span class="hljs-string">"7. Time Zone"</span>: <span class="hljs-string">"UTC"</span>,
    <span class="hljs-string">"8. Bid Price"</span>: <span class="hljs-string">"44138.96000000"</span>,
    <span class="hljs-string">"9. Ask Price"</span>: <span class="hljs-string">"44138.97000000"</span>
  }
}
</code></pre>
<p>We are only interested in the <code>5. Exchange Rate</code> property of the <code>data</code> property as it contains the exchange rate.</p>
<p>Since we only need the <code>5. Exchange Rate</code>, pass it as props to the <code>ExchangeRateUI</code> component.</p>
<p>After making the changes, your <code>ExchangeRate</code> component should look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Typography, Select, Spin } <span class="hljs-keyword">from</span> <span class="hljs-string">'antd'</span>;
<span class="hljs-keyword">import</span> { cryptocurrencies, fiatCurrencies } <span class="hljs-keyword">from</span> <span class="hljs-string">'./currencies/currencies.jsx'</span>;
<span class="hljs-keyword">import</span> { ExchangeRateUI } <span class="hljs-keyword">from</span> <span class="hljs-string">'./UI/ExchangeRateUI.jsx'</span>;
<span class="hljs-keyword">import</span> { useQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-query'</span>;
<span class="hljs-keyword">import</span> { fetchData } <span class="hljs-keyword">from</span> <span class="hljs-string">'./fetchData/fetchData.jsx'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ExchangeRate</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [fromCurrency, setFromCurrency] = useState(cryptocurrencies[<span class="hljs-number">0</span>].value);
  <span class="hljs-keyword">const</span> [toCurrency, setToCurrency] = useState(fiatCurrencies[<span class="hljs-number">0</span>].value);
  <span class="hljs-keyword">const</span> [currencySymbol, setCurrencySymbol] = useState(<span class="hljs-string">"Bitcoin"</span>);

  <span class="hljs-keyword">const</span> handleFromCurrencyChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setFromCurrency(e);
    <span class="hljs-built_in">console</span>.log(e);
  };

  <span class="hljs-keyword">const</span> handleToCurrencyChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setToCurrency(e);
    <span class="hljs-built_in">console</span>.log(e);
  };

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> fromCurrencyLabel = cryptocurrencies.find(<span class="hljs-function"><span class="hljs-params">currency</span> =&gt;</span> currency.value === fromCurrency)?.label;
    setCurrencySymbol(fromCurrencyLabel);
  }, [fromCurrency]);

  <span class="hljs-keyword">const</span> dependencies = { <span class="hljs-attr">fromCurrency</span>: fromCurrency, <span class="hljs-attr">toCurrency</span>: toCurrency };
  <span class="hljs-keyword">const</span> { data, isLoading, isError, error } = useQuery({
    <span class="hljs-attr">queryKey</span>: [<span class="hljs-string">"exchangeRate"</span>, dependencies],
    <span class="hljs-attr">queryFn</span>: <span class="hljs-function">() =&gt;</span> fetchData(fromCurrency, toCurrency),
    <span class="hljs-attr">staleTime</span>: <span class="hljs-number">1000</span> * <span class="hljs-number">60</span>,
    <span class="hljs-attr">retry</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">retryDelay</span>: <span class="hljs-number">60000</span>
  });

  <span class="hljs-built_in">console</span>.log(data);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"exchange-rate"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Typography.Title</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> "#<span class="hljs-attr">4d4add</span>" }} <span class="hljs-attr">level</span>=<span class="hljs-string">{2}</span>&gt;</span>Exchange Rate<span class="hljs-tag">&lt;/<span class="hljs-name">Typography.Title</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Typography.Text</span>&gt;</span>Get the latest exchange rate of cryptocurrencies in your favorite currency<span class="hljs-tag">&lt;/<span class="hljs-name">Typography.Text</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"select-group"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> "<span class="hljs-attr">flex</span>", <span class="hljs-attr">marginTop:</span> "<span class="hljs-attr">1rem</span>", <span class="hljs-attr">gap:</span> "<span class="hljs-attr">1rem</span>", <span class="hljs-attr">justifyContent:</span> "<span class="hljs-attr">space-around</span>" }}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Select</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{cryptocurrencies[0].value}</span> <span class="hljs-attr">options</span>=<span class="hljs-string">{cryptocurrencies}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleFromCurrencyChange}</span> /&gt;</span>{' '}
        <span class="hljs-tag">&lt;<span class="hljs-name">Select</span> <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{fiatCurrencies[0].value}</span> <span class="hljs-attr">options</span>=<span class="hljs-string">{fiatCurrencies}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleToCurrencyChange}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginTop:</span> '<span class="hljs-attr">1rem</span>' }}&gt;</span>
        {isLoading ? (
          <span class="hljs-tag">&lt;<span class="hljs-name">Spin</span> <span class="hljs-attr">tip</span>=<span class="hljs-string">"Fetching results"</span> <span class="hljs-attr">spinning</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"large"</span> /&gt;</span>
        ) : isError ? (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Error: {error.message}<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">ExchangeRateUI</span> <span class="hljs-attr">price</span>=<span class="hljs-string">{data[</span>"<span class="hljs-attr">Realtime</span> <span class="hljs-attr">Currency</span> <span class="hljs-attr">Exchange</span> <span class="hljs-attr">Rate</span>"]["<span class="hljs-attr">5.</span> <span class="hljs-attr">Exchange</span> <span class="hljs-attr">Rate</span>"]} <span class="hljs-attr">dataObj</span>=<span class="hljs-string">{dependencies}</span> <span class="hljs-attr">currencySymbol</span>=<span class="hljs-string">{currencySymbol}</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">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExchangeRate;
</code></pre>
<p>In the code above, you used the ternary operator to render different content based on the state of the data fetching.</p>
<p><code>currencySymbol</code> is used to keep track of the cryptocurrency you're checking the exchange rate of.</p>
<p>Open your console and you should see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Screenshot_20240105-015827-1-.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now that you're done implementing the data fetching logic, let's display the data in the UI.</p>
<h2 id="heading-how-to-display-the-data-in-the-ui">How to Display the data in the UI</h2>
<p>In this section, you are going to add the final touches to the web app.</p>
<p>Update your <code>ExchangeRateUI.jsx</code> file with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { Typography, Card } <span class="hljs-keyword">from</span> <span class="hljs-string">"antd"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ExchangeRateUI</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">const</span> { price, dataObj, currencySymbol } = props;
  <span class="hljs-keyword">const</span> toCurrency = dataObj.toCurrency;
  <span class="hljs-keyword">let</span> value = <span class="hljs-built_in">Number</span>(price);
  <span class="hljs-keyword">let</span> currencyCode = toCurrency;

  <span class="hljs-keyword">let</span> currency = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.NumberFormat(<span class="hljs-string">'en-US'</span>, {
    <span class="hljs-attr">style</span>: <span class="hljs-string">'currency'</span>,
    <span class="hljs-attr">currency</span>: currencyCode,
  });

  <span class="hljs-keyword">let</span> formattedCurrency = currency.format(value);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"exchange-rate-ui"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Card</span> <span class="hljs-attr">extra</span>=<span class="hljs-string">{currencySymbol}</span> <span class="hljs-attr">bordered</span>=<span class="hljs-string">{false}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">width:</span> <span class="hljs-attr">350</span>, <span class="hljs-attr">backgroundColor:</span> "#<span class="hljs-attr">4d4add</span>", <span class="hljs-attr">color:</span> '#<span class="hljs-attr">fff</span>' }} <span class="hljs-attr">size</span>=<span class="hljs-string">"default"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Typography.Paragraph</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> "#<span class="hljs-attr">fff</span>" }}&gt;</span>{formattedCurrency}<span class="hljs-tag">&lt;/<span class="hljs-name">Typography.Paragraph</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Let's understand what's going on in the code above.</p>
<p>First, you take the raw price representing the exchange rate, ensure it's treated as a number, determine the currency code, and then format the numeric value into a user-friendly currency string. This formatted currency is used for display in the user interface to provide a clear and standardized representation of the exchange rate.</p>
<p>Next, the formatted currency is displayed within a styled <code>Card</code> component from Ant Design. The <code>Card</code> includes the <code>currencySymbol</code> as an extra element. The background color, width, and text color are styled for a visually appealing UI.</p>
<p>Your app should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/GIF-240109_050748-1-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>GIF of complete working crypto app</em></p>
<p>Congratulations. You have built a crypto exchange rate web app in React.</p>
<h2 id="heading-error-handling">Error Handling</h2>
<p>Error handling is a crucial aspect of developing web apps. This is because web apps and software in general can experience crashes and down time.</p>
<p>In React, when your app crashes, it usually shows a white/blank screen. This doesn't make for a good user experience. You'll want to display some kind of information to your users if your app crashes.</p>
<p>In this section, you are going to use the <code>ErrorBoundary</code> component to handle app crashes.</p>
<p>Create a file called <code>ErrorBoundary.jsx</code> in the <code>src</code> folder.</p>
<p>Add the following code in the <code>ErrorBoundary.jsx</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { Typography } <span class="hljs-keyword">from</span> <span class="hljs-string">"antd"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ErrorBoundary</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props);
    <span class="hljs-built_in">this</span>.state = { <span class="hljs-attr">hasError</span>: <span class="hljs-literal">false</span> };
  }

  <span class="hljs-keyword">static</span> getDerivedStateFromError(error) {
    <span class="hljs-comment">// Update state so the next render will show the fallback UI.</span>
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">hasError</span>: <span class="hljs-literal">true</span> };
  }

  componentDidCatch(error, errorInfo) {
    <span class="hljs-comment">// You can also log the error to an error reporting service</span>
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Caught error: "</span>);
  }

  render() {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.state.hasError) {
      <span class="hljs-comment">// You can render any custom fallback UI</span>
      <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Typography.Title</span> <span class="hljs-attr">level</span>=<span class="hljs-string">{4}</span>&gt;</span>Something went wrong.<span class="hljs-tag">&lt;/<span class="hljs-name">Typography.Title</span>&gt;</span></span>;
    }

    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.props.children;
  }
}
</code></pre>
<p>In the code above, you are rendering the message "Something went wrong" if there's an error rendering your app.</p>
<p>Update your <code>index.jsx</code> file with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> ErrorBoundary <span class="hljs-keyword">from</span> <span class="hljs-string">'./ErrorBoundary'</span>;

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ErrorBoundary</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ErrorBoundary</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>Visit the <a target="_blank" href="https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary">React docs</a> for more information on ErrorBoundary.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article walked you through how to work with third-party APIs in React by building a crypto exchange rate web app.</p>
<p>But don't stop here. You can improve this project by adding a news feature and styling it to your taste. Also, you can decide to support more currencies.</p>
<h3 id="heading-additional-resources">Additional resources</h3>
<ul>
<li><p><a target="_blank" href="https://tanstack.com/query/v3/docs/react/guides/paginated-queries">React-query documentation</a></p>
</li>
<li><p><a target="_blank" href="https://ant.design/components">Ant Design UI library</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy Your Websites and Apps – User-Friendly Deployment Strategies ]]>
                </title>
                <description>
                    <![CDATA[ Deploying your application is a key aspect of software development. Typically, having an app on your local system isn't enough – it needs to be accessible online. So choosing a suitable and user-friendly hosting and deployment plan is vital. The key ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deploy-websites-and-applications/</link>
                <guid isPermaLink="false">66b9f47675413b5a1215b325</guid>
                
                    <category>
                        <![CDATA[ deployment ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ website development, ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ijeoma Igboagu ]]>
                </dc:creator>
                <pubDate>Wed, 09 Aug 2023 14:23:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/cover-friendly-deploy.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Deploying your application is a key aspect of software development. Typically, having an app on your local system isn't enough – it needs to be accessible online. So choosing a suitable and user-friendly hosting and deployment plan is vital.</p>
<p>The key to making the right decision lies in understanding the goal of your application. Perhaps it’s a simple website, a one-page app, or it requires serverless or cloud functions. Having clarity about these aspects will significantly ease the deployment process.</p>
<p>In this article, we will look at a few popular methods for deploying your application that will help tackle these challenges.</p>
<h2 id="heading-what-well-cover">What we'll cover:</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-to-consider-when-deploying-to-a-hosting-platform">What to consider when deploying a hosting platform</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-deploy-a-website-or-app-with-render">How to deploy a website or app with Render</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-deploy-a-website-or-app-with-surge">How to deploy a website or app with Surge</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-deploy-a-website-or-app-with-vercel">How to deploy a website or app with Vercel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-deploy-a-website-or-app-with-github-pages">How to deploy a website or app with GitHub Pages</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-deploy-a-website-or-app-with-netlify">How to deploy a website or app with Netlify</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-what-to-consider-when-deploying-to-a-hosting-platform">What to Consider when Deploying to a Hosting Platform</h2>
<p>There are several factors to take into account when selecting a hosting platform:</p>
<ol>
<li><p><strong>Purpose</strong>: Before you host your application, consider the technologies you used to build it and how much storage the platform can handle.</p>
</li>
<li><p><strong>Interface</strong>: A good interface is essential for a hosting platform. Look for a control panel or dashboard that allows you to easily administer your website.</p>
</li>
<li><p><strong>Reviews</strong>: Look at the hosting service's reviews and read what other clients have to say.</p>
</li>
<li><p><strong>Security</strong>: To safeguard your website and data, it is essential to have the right security measures in place.</p>
</li>
<li><p><strong>Support</strong>: You should always have someone there to help you out when you need it.</p>
</li>
</ol>
<h3 id="heading-why-is-deploying-an-application-important">Why is Deploying an Application Important?</h3>
<p>If you've built an app, there are various reasons you may want or need to deploy it, such as:</p>
<ol>
<li><p>It showcases professionalism and credibility to users.</p>
</li>
<li><p>It increases the accessibility of the application to a broader audience.</p>
</li>
<li><p>It enables user interaction and feedback.</p>
</li>
<li><p>It facilitates data analysis and provides insights for informed decision-making.</p>
</li>
<li><p>It identifies areas for improvement in the application.</p>
</li>
</ol>
<h3 id="heading-whats-the-benefit-of-choosing-a-user-friendly-deployment-method">What's the Benefit of Choosing a User-Friendly Deployment Method?</h3>
<p>Opting for a more approachable deployment method brings significant advantages:</p>
<ol>
<li><p><strong>Collaboration</strong>: When working together as a team, it’s useful to have straightforward methods to deploy your application. This makes collaboration and teamwork easy. These will encourage cooperation throughout the deployment process.</p>
</li>
<li><p><strong>Efficiency</strong>: A user-friendly deployment method simplifies the process.</p>
</li>
<li><p><strong>Simplicity</strong>: Choosing a hosting platform that is easy to understand will benefit everyone involved.</p>
</li>
<li><p><strong>Reliability</strong>: easy to use deployment methods ensure a more reliable application and minimise potential disruptions.</p>
</li>
</ol>
<h2 id="heading-how-to-deploy-a-website-or-app-with-render">How to Deploy a Website or App with Render</h2>
<p>Render provides an interface for quick and straightforward publishing of static web content. Let's now go through how to deploy an app to Render step by step.</p>
<p>Step 1: First, ensure you have deployed your work or code from your editor to your GitHub account.</p>
<p>Step 2: Open a new browser tab and navigate to the <a target="_blank" href="https://render.com/">Render website</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743002851078/4bf085d2-7c38-432b-93bf-95f2b02368e7.gif" alt="render website" class="image--center mx-auto" width="1920" height="920" loading="lazy"></p>
<p><em>Render website</em></p>
<p>Step 3: Select the “GET STARTED” button on Render's home page to get going.</p>
<ul>
<li><p>You can use your GitHub, GitLab, or Bitbucket account when signing up. Choose the GitHub option and follow the steps to grant Render access to your GitHub account.</p>
</li>
<li><p>If you already have a Render account, click the “Sign in” button to be redirected to the Sign-in page. You can sign in via email and authenticate using your Google account or your GitHub account.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743002894595/542d8097-4fcc-409a-bc80-a599656152c9.gif" alt="Render sign in page" class="image--center mx-auto" width="1920" height="991" loading="lazy"></p>
<p><em>Sign in page</em></p>
<p>Step 4: Once you access the dashboard, click the “New” button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743002941009/36239b95-8cf3-4633-9b27-fb966a133270.png" alt="Render dashboard" class="image--center mx-auto" width="1704" height="536" loading="lazy"></p>
<p><em>Dashboard of Render</em></p>
<p>Step 5: Upon doing so, a drop-down menu will appear. It'll show you a comprehensive list of services provided by Render.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003263069/d8053161-5ef1-4c1b-a047-c635c75df2eb.png" alt="List of services offered by render" class="image--center mx-auto" width="1600" height="481" loading="lazy"></p>
<p><em>List of Services offered by render</em></p>
<p>Step 6: Clicking “Static Site” from the drop-down menu will lead you to the “Create a New Static Site” page. From there, you can select the repository you wish to host.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003315411/fe9a7eb8-2303-48ad-b83a-fb471e821e05.png" alt="Create a new static site page" class="image--center mx-auto" width="1600" height="826" loading="lazy"></p>
<p><em>Create a New Static Site</em></p>
<p>Step 7: After selecting the repository you wish to host, you will be directed to the deployment platform. There, you can provide the necessary information to host the application and click the “Create Static Site” button for it to deploy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003358045/c37346e8-5793-40a3-95fc-17c388b110ed.png" alt="Render deployment" class="image--center mx-auto" width="1838" height="1292" loading="lazy"></p>
<p><em>Deploying the app using Render</em></p>
<p>Here's what the final output should look like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003407878/76f120fe-8754-4e7c-8746-6107f47d7425.png" alt="Hosted application" class="image--center mx-auto" width="893" height="759" loading="lazy"></p>
<p><em>Hosted application</em></p>
<h3 id="heading-pros-of-deploying-with-render">Pros of Deploying With Render</h3>
<ul>
<li><p>Render has a free tier for hosting basic static websites.</p>
</li>
<li><p>It provides a flexible price structure that ensures transparency and cost-effectiveness.</p>
</li>
<li><p>It makes deployment easy. They provide an interface and connection with standard development tools and platforms. It also supports a wide range of programming languages, frameworks, and databases.</p>
</li>
<li><p>It delivers a variety of integrated features that improve the hosting experience.</p>
</li>
<li><p>It has good customer service support.</p>
</li>
</ul>
<h3 id="heading-cons-of-deploying-with-render">Cons of Deploying With Render</h3>
<ul>
<li><p>Render specializes in static websites, Docker containers, and serverless functions.</p>
</li>
<li><p>For more complex/bigger applications, there's a paid plan. You'll need to go through their price structure and understand the charges related to your usage.</p>
</li>
<li><p>There is a learning curve, especially for newcomers to the platform.</p>
</li>
</ul>
<h2 id="heading-how-to-deploy-a-website-or-app-with-surge">How to Deploy a Website or App with Surge</h2>
<p>This friendly platform and tool make it quick and easy to deploy static websites online.</p>
<p>Deploying your static files to <a target="_blank" href="https://https//surge.sh/">surge.sh</a> is easy using the command-line interface (CLI).</p>
<p>This command-line interface (CLI) streamlines the process of hosting and distributing your online projects.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003449591/4825b5da-69a7-4780-924c-8c2206c82a96.png" alt="Surge website" class="image--center mx-auto" width="1600" height="825" loading="lazy"></p>
<p><em>Surge website</em></p>
<h3 id="heading-steps-to-deploy-your-site-using-surge">Steps to Deploy Your Site Using Surge</h3>
<p>First, in the terminal of your project, type the command <code>npm i -g surge</code>.</p>
<p>Then type the command <code>surge</code>.</p>
<p>And that's it! You can deploy your app without logging in into your GitHub account.</p>
<p>To see what you have deployed, first copy the successful link in the terminal. Then paste it into your browser. You should see something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003506734/70e7d551-2aa9-4023-980c-53a8fdd34d2d.png" alt="Hosted site with Surge" class="image--center mx-auto" width="1231" height="467" loading="lazy"></p>
<p><em>Hosted site with Surge</em></p>
<p>Like I mentioned before, Surge doesn't need extra code. You can easily deploy your app right from your editor's terminal by typing the command <code>surge</code>.</p>
<h3 id="heading-pros-of-deploying-with-surge">Pros of Deploying with Surge</h3>
<ul>
<li><p><strong>Easy to Use:</strong> Surge provides a simple deployment for static websites.</p>
</li>
<li><p><strong>Fast Deployment:</strong> It has a quick deployment time.</p>
</li>
<li><p><strong>Custom Domains:</strong> It allows you to use your domain name for your website.</p>
</li>
<li><p><strong>SSL Support:</strong> It provides free SSL certificates.</p>
</li>
<li><p><strong>Support for Single-Page Applications (SPAs):</strong> It's well-suited for deploying single-page applications.</p>
</li>
</ul>
<h3 id="heading-cons-of-deploying-with-surge">Cons of Deploying with Surge</h3>
<ul>
<li><p><strong>Limited Functions:</strong> Surge is designed for static websites.</p>
</li>
<li><p><strong>No Custom Server Configurations:</strong> It streamlines the deployment process by abstracting away server configurations.</p>
</li>
<li><p><strong>Premium Features:</strong> This platform offers free hosting for basic usage, but you'll have to pay for more features.</p>
</li>
</ul>
<h2 id="heading-how-to-deploy-a-website-or-app-with-vercel">How to Deploy a Website or App with Vercel</h2>
<p>Vercel is a hosting and deployment platform that specializes in modern web applications.</p>
<p>It is particularly well-suited for single-page applications, serverless operations, and static websites. It integrates with popular frameworks like Next.js and Gatsby.js, making deployments fast and simple.</p>
<h3 id="heading-steps-to-deploy-your-site-using-vercel">Steps to Deploy Your Site Using Vercel</h3>
<p>First, ensure that you have deployed your work or code from your editor to your GitHub account.</p>
<p>Then open a new browser tab and navigate to <a target="_blank" href="https://vercel.com/">Vercel’s website</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003556995/7c48e8dc-6955-45c2-a068-c6c1b0e15cf6.png" alt="Vercel website" class="image--center mx-auto" width="1600" height="818" loading="lazy"></p>
<p><em>Vercel website</em></p>
<p>Head to the Vercel website and click the “Sign up” button on the homepage.</p>
<ul>
<li><p>Sign up using your GitHub account and follow the steps to grant Vercel access to your GitHub account. If you already have a Vercel account, click the “Login” button and enter your login information.</p>
</li>
<li><p>After signing up or logging in, Vercel will request access to specific information from your GitHub account. Review the required permissions and permit Vercel to proceed.</p>
</li>
</ul>
<p>Next, click on “Add New…” on the Vercel dashboard. This action will reveal a drop-down menu. From the menu, select “Project,” which will navigate you to the next page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003587862/a04db892-e3fe-4218-a60f-ed134e143006.gif" alt="Vercel add new project" class="image--center mx-auto" width="1920" height="991" loading="lazy"></p>
<p><em>Add New Project</em></p>
<p>On the next page, you will import your repository for deployment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003630267/265499e1-d1cd-4083-a05c-68dc4c9e9741.gif" alt="Vercel deployment" class="image--center mx-auto" width="1920" height="991" loading="lazy"></p>
<p><em>Vercel Deployment</em></p>
<p>Here's what the final output should look like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003666437/b418d602-42ca-4610-ae43-dc69bed0d954.gif" alt="Vercel hosted site" class="image--center mx-auto" width="1920" height="991" loading="lazy"></p>
<p><em>Hosted site</em></p>
<p>When deploying your application to Vercel, you may encounter some errors, often caused by routing issues.</p>
<p><strong>To fix this:</strong></p>
<ul>
<li><p>Create a file under the root of your application called <code>vercel.json</code>.</p>
</li>
<li><p>Inside the file, write the following code:</p>
</li>
</ul>
<p><code>vercel.json</code></p>
<pre><code class="lang-bash">{ <span class="hljs-string">"rewrites"</span>: [{ <span class="hljs-string">"source"</span>: <span class="hljs-string">"/(.*)"</span>, <span class="hljs-string">"destination"</span>: <span class="hljs-string">"/"</span> }] }
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003723518/6c44d496-331e-4d09-b221-f3c3dc6c688c.png" alt="Vercel error fix" class="image--center mx-auto" width="1743" height="826" loading="lazy"></p>
<p><em>Inside your editor</em></p>
<h3 id="heading-pros-of-deploying-with-vercel">Pros of Deploying With Vercel</h3>
<ul>
<li><p><strong>Collaboration:</strong> Vercel offers tools for effective teamwork, access control, and cooperative deployments.</p>
</li>
<li><p><strong>Simple Deployment:</strong> it simplifies delivering your web apps with ease.</p>
</li>
<li><p><strong>Preview Deployments:</strong> it allows you to share and review changes before they go live. This promotes collaboration and ensures a smooth and efficient workflow.</p>
</li>
<li><p><strong>Scalability and Performance:</strong> It still guarantees great performance even with a large number of people using it.</p>
</li>
<li><p><strong>Git Integration:</strong> it makes Git integration easy.</p>
</li>
</ul>
<h3 id="heading-cons-of-deploying-with-vercel">Cons of Deploying With Vercel</h3>
<ul>
<li><p>If you are new to Vercel, you must understand how to deploy and configure your application. Reading <a target="_blank" href="https://vercel.com/docs">Vercel’s documentation</a> can help you get up to speed.</p>
</li>
<li><p>Vercel is great for small to medium-sized projects, but it may not be the best fit for large-scale applications with complex backend needs. In such cases, developers may need a hosting solution that offers more customization and scalability.</p>
</li>
</ul>
<h2 id="heading-how-to-deploy-a-website-or-app-with-github-pages">How to Deploy a Website or App with GitHub Pages</h2>
<p>GitHub Pages is a straightforward and cost-free hosting service. You can use it to host static web pages or documentation.</p>
<p>You can publish your site using GitHub Pages by submitting your code to a GitHub account and setting up a repository. Let's go through the process now.</p>
<h3 id="heading-steps-to-deploy-your-site-using-github-pages">Steps to Deploy Your Site Using GitHub Pages</h3>
<p>To use GitHub Pages to host your website, follow these simple steps:</p>
<p>First, go to GitHub's <a target="_blank" href="https://https//github.com/">website</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003758359/0d8d7328-a8ad-4b79-a814-3a55b3a04bb1.png" alt="GitHub landing page" class="image--center mx-auto" width="1835" height="483" loading="lazy"></p>
<p><em>Github website</em></p>
<p>Then create a GitHub repository. If you don’t have a GitHub account, you'll need to click on “sign up”, or just click “sign in” if you already have an account.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003801213/5362aa34-2ec8-430f-8809-01b42f574495.png" alt="Github signin button and signup buttons" class="image--center mx-auto" width="233" height="127" loading="lazy"></p>
<p><em>Github sign in button and sign up buttons</em></p>
<p>Create a new repository by clicking the New button in the upper-right corner of your GitHub profile.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003843884/8c918dbf-64bf-40c8-8f32-25fa6fef157d.png" alt="Creating a new repo" class="image--center mx-auto" width="594" height="428" loading="lazy"></p>
<p><em>Creating a new repository</em></p>
<p>Give your repository a name that reflects your website.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003887101/51f0ab61-14b5-420c-95fb-27926b4dc566.gif" alt="Entering repo name on GitHub" class="image--center mx-auto" width="1920" height="991" loading="lazy"></p>
<p><em>Repository name</em></p>
<p>Once you have finished the previous step, go back to your Editor. Copy the generated code and paste it into your editor.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003942149/3c063b52-2bc2-4897-84af-e30ca8da18cd.png" alt="Code generated from new repository" class="image--center mx-auto" width="1600" height="142" loading="lazy"></p>
<p><em>Code generated from new repository</em></p>
<p>The code in the image above is generated when creating a new repository.</p>
<p>Go to the settings page of the newly created repository.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003981000/6a55ae7c-2b69-44bd-bbe2-deaa695b63a5.png" alt="GitHub repo settings" class="image--center mx-auto" width="1600" height="766" loading="lazy"></p>
<p><em>Clicking on settings</em></p>
<p>Click on the settings option to redirect to the settings section. Locate and click on “Pages” in the left-hand side menu.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004028760/9130f72b-0e6a-4a18-a72a-da948eb67fec.gif" alt="Settings section GitHub pages" class="image--center mx-auto" width="1920" height="920" loading="lazy"></p>
<p><em>GitHub pages section on the settings page</em></p>
<p>To access GitHub Pages, click on the “Pages” section. Once you’re on the GitHub Pages section, click in the drop-down menu and choose either the “master” or “main” branch. Remember to save your selection.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004108894/40fa0220-afba-4932-8900-1106046cf9e0.gif" alt="Enabling GitHub Pages to host your site" class="image--center mx-auto" width="1920" height="920" loading="lazy"></p>
<p><em>Enabling GitHub Pages to host your site</em></p>
<p>Refresh the page to find the link leading to your published website.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004156941/3364fd42-d47e-40ea-b147-0fc0fa4f25c6.gif" alt="GitHub seeing your hosted site" class="image--center mx-auto" width="1920" height="920" loading="lazy"></p>
<p><em>Seeing your hosted site</em></p>
<h3 id="heading-pros-of-deploying-with-github-pages">Pros of Deploying With GitHub Pages</h3>
<ul>
<li><p>GitHub Pages are simple to set up – and you can build your website there.</p>
</li>
<li><p>It's free.</p>
</li>
<li><p>GitHub’s version control system makes it simple to keep track of changes and work with others.</p>
</li>
<li><p>GitHub Pages updates your website’s code whenever you make changes to it.</p>
</li>
<li><p>It offers collaboration on projects with other developers.</p>
</li>
<li><p>It ensures your website is safe through <code>HTTPS</code> (Hyper Text Transfer Protocol) encryption.</p>
</li>
</ul>
<h3 id="heading-cons-of-deploying-with-github-pages">Cons of Deploying With GitHub Pages</h3>
<p>While GitHub Pages offer many advantages, there are a few considerations to keep in mind:</p>
<ul>
<li><p>If your website becomes too large due to file size, this can cause some performance issues.</p>
</li>
<li><p>GitHub Pages may only support simple functions.</p>
</li>
<li><p>Understanding Git, the version control system used by GitHub, is essential for managing your website’s code.</p>
</li>
</ul>
<h2 id="heading-how-to-deploy-a-website-or-app-with-netlify">How to Deploy a Website or App with Netlify</h2>
<p>Netlify integrates with Git repositories and works well with static web pages and single-page apps.</p>
<h3 id="heading-steps-to-deploy-your-site-using-netlify">Steps to Deploy Your Site Using Netlify</h3>
<p>First, you'll need to make sure that you have deployed your work or code from your editor to your GitHub account.</p>
<p>Then, open a new browser tab and navigate to the <a target="_blank" href="https://www.netlify.com/">Netlify website</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004199311/04a14b1c-d034-4274-8657-1a9eeaaf1839.png" alt="Netlify website" class="image--center mx-auto" width="1600" height="825" loading="lazy"></p>
<p><em>Netlify website</em></p>
<p>Head to the Netlify website and click the “Sign up” button on the homepage.</p>
<ul>
<li><p>Create an account by signing up with your GitHub, GitLab, or Bitbucket credentials.</p>
</li>
<li><p>Select the GitHub option and follow the steps to grant Netlify access to your GitHub account.</p>
</li>
<li><p>If you already have a Netlify account, click the “Login” button and enter your login information. After signing up or logging in, Netlify will request access to specific information from your GitHub account. Review the required permissions and permit Netlify to proceed.</p>
</li>
</ul>
<p>Once you have finished registering, go to the dashboard where you will host your repository.</p>
<p>Netlify has two ways to host your project:</p>
<ol>
<li><p>Drag-n-drop</p>
</li>
<li><p>Importing the source code from your repository to the site.</p>
</li>
</ol>
<h4 id="heading-using-the-drag-n-drop-feature">Using the Drag-n-Drop feature:</h4>
<p>Once you have logged in, navigate to the left-hand side of the dashboard and select the “site” option.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004230273/ef1debf2-c475-4cd1-8930-4b5c0fd2c412.png" alt="Netlify dashboard" class="image--center mx-auto" width="1600" height="766" loading="lazy"></p>
<p><em>Netlify dashboard</em></p>
<p>Before deploying your project, it’s important to include an “index.html” file. Netlify recognizes this file as the main folder for hosting your project.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004285308/0387adf5-f015-44e0-bb91-1fb718bfdc04.png" alt="Root index.html file" class="image--center mx-auto" width="1485" height="620" loading="lazy"></p>
<p><em>Root</em> <code>index.html</code> <em>file</em></p>
<p>Go back to the website click on “site” and scroll down, you will see the drag-n-drop zone where you can drag and drop your file or you upload the folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004356707/d7285059-51a0-4802-af41-1d81b560754f.png" alt="Netlify drag and drop" class="image--center mx-auto" width="1872" height="567" loading="lazy"></p>
<p><em>Netlify drag and drop</em></p>
<p>By using this feature your project will be deployed.</p>
<h4 id="heading-importing-the-source-code-from-your-repository-to-the-site">Importing the source code from your repository to the site:</h4>
<p>First, upload your code to GitHub.</p>
<p>Then access the Netlify dashboard.</p>
<p>To access the option (drop-down) menu, click on “Add New Site”. Select “Import existing project.”</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004398011/0de1ad8d-3f36-47e9-8faa-626b399fb27e.png" alt="Netlify import existing project" class="image--center mx-auto" width="1600" height="812" loading="lazy"></p>
<p><em>Import existing project</em></p>
<p>When you click on “Import existing project,” the system will direct you to a new page. Then you can import your repository from your GitHub account or any other storage account where you stored your source code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004440693/669cf508-588e-47f9-8542-24552c073009.png" alt="Netlify connect to Git provider" class="image--center mx-auto" width="1600" height="825" loading="lazy"></p>
<p><em>Connect to Git provider</em></p>
<p>When you click on this button, it will navigate you to the next page where you can choose the desired repository from the available options.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004493978/578f1241-8b07-432d-a40a-ed6549aecb53.png" alt="578f1241-8b07-432d-a40a-ed6549aecb53" class="image--center mx-auto" width="1920" height="990" loading="lazy"></p>
<p><em>Choosing repository from Netlify</em></p>
<p>After selecting the repository, the next step is configuring and deploying your site.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004531244/4f5d1691-6cd7-4c86-8be8-fa423a6e8772.gif" alt="Deploying from Netlify" class="image--center mx-auto" width="1920" height="920" loading="lazy"></p>
<p><em>Deploying from Netlify</em></p>
<p>Here's the result:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004569842/d7f6c8cf-855e-4d12-847b-9ec22b6bc177.gif" alt="Netlify hosted app" class="image--center mx-auto" width="1920" height="920" loading="lazy"></p>
<p><em>Hosted App</em></p>
<p>When deploying your application to Netlify, you may encounter errors, often caused by routing issues.</p>
<p><strong>To fix this:</strong></p>
<p>Create a file called <code>_redirects</code>, and inside write the following code:</p>
<p><code>_redirect file</code></p>
<pre><code class="lang-bash">/* /index.html 200
</code></pre>
<p><strong>Example</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004628305/2fa06275-812f-42ed-8bf0-b30765a0a821.png" alt="Encounter error during deployment which is caused by routing issue" class="image--center mx-auto" width="1280" height="491" loading="lazy"></p>
<p><em>Encounter error during deployment which is caused by routing issue</em></p>
<h3 id="heading-pros-of-deploying-with-netlify">Pros of Deploying with Netlify</h3>
<ul>
<li><p><strong>Form handling capabilities:</strong> Netlify makes handling forms on your websites easy. It has a simple API that allows you to collect and process form submissions. It also integrates with popular form providers like Zapier, Mailchimp, and Slack.</p>
</li>
<li><p><strong>It’s easy to configure custom domains for your websites</strong>: it makes it simple to manage your website’s domain and security. It also ensures that your websites are secure with <code>HTTPS</code>.</p>
</li>
<li><p><strong>Web Hosting:</strong> Netlify helps you host your websites and applications. It offers static site hosting, allowing you to deploy <code>HTML</code>, <code>CSS</code>, and <code>JavaScript</code> files straight from a Git repository or by drag-and-drop.</p>
</li>
<li><p><strong>Simple Deployment:</strong> it makes deploying your website or web app straightforward. When you connect your repository, it will deploy any changes you make.</p>
</li>
<li><p><strong>Continuous Deployment:</strong> When you make updates to your source code, Netlify builds and publishes your website for you. This ensures that your website always reflects the latest changes you’ve made.</p>
</li>
</ul>
<h3 id="heading-cons-of-deploying-with-netlify">Cons of Deploying With Netlify</h3>
<ul>
<li><p><strong>Project size:</strong> This hosting platform is an excellent choice for small to medium-sized projects. But you should explore other hosting and deployment options as your website or app grows.</p>
</li>
<li><p><strong>Limited Backend Capabilities:</strong> Netlify prioritizes front-end development and static websites. Although it does have some backend functions, it may not be the best option for projects that need complex server-side processing.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, deploying an application is crucial so that users can access it and others can see your work. User-friendly deployment methods offer significant benefits, including collaboration, efficiency, simplicity, and reliability.</p>
<p>Here's a quick review of what we've covered here:</p>
<ul>
<li><p>Render offers a simple interface, affordable pricing, and built-in features.</p>
</li>
<li><p>Surge offers fast deployment speeds, making deploying static websites a breeze.</p>
</li>
<li><p>Vercel is an expert in creating cutting-edge web apps with scalability and preview deployments.</p>
</li>
<li><p>If you’re looking for an easy-to-use option, consider GitHub Pages. It provides several advantages, including simplicity, free hosting, version control, and <code>HTTPS</code> encryption. But, it has limited functionality and technological limitations for more sophisticated applications.</p>
</li>
<li><p>Netlify is a user-friendly platform that's great for quickly deploying static websites and web apps. It's perfect for projects that want easy setup, automatic deployment, and modern development features</p>
</li>
</ul>
<p>What you choose will depend on the particular needs and objectives of your application and the technical know-how of the developers working on it.</p>
<p>And if you want to improve your Git skills, you can read this Git Command article.</p>
<p>If you found this tutorial helpful, please share it with fellow developers who may also find it interesting. You can also stay updated on my latest projects by following me on <a target="_blank" href="https://https//twitter.com/ijaydimples">Twitter</a> and <a target="_blank" href="https://https//www.linkedin.com/in/ijeoma-igboagu/">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Rendering Patterns for Web Apps – Server-Side, Client-Side, and SSG Explained ]]>
                </title>
                <description>
                    <![CDATA[ Hi everyone! In this article we're going to take a look at the different rendering pattern options available nowadays for web applications. I'll start by explaining what a rendering pattern is, then go through each of the main options available. Fina... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/rendering-patterns/</link>
                <guid isPermaLink="false">66d45f1dd1ffc3d3eb89ddfa</guid>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ German Cocca ]]>
                </dc:creator>
                <pubDate>Mon, 06 Mar 2023 18:22:40 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/sebastian-svenson-8QgqOLJAL8k-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi everyone! In this article we're going to take a look at the different rendering pattern options available nowadays for web applications.</p>
<p>I'll start by explaining what a rendering pattern is, then go through each of the main options available. Finally we'll compare them, explaining the pros and cons and when one might be more beneficial than another.</p>
<p>Let's go!</p>
<h1 id="heading-table-of-contents">Table of Contents</h1>
<ul>
<li><p><a class="post-section-overview" href="#heading-whats-a-rendering-pattern">What's a rendering pattern?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-different-rendering-pattern-options">Different rendering pattern options</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-static-websites">Static websites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-single-page-applications-spas-with-client-side-rendering-csr">Single page applications (SPAs) with client side rendering (CSR)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-server-side-rendering-ssr">Server side rendering (SSR)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-static-site-generation-ssg">Static site generation (SSG)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-incremental-static-regeneration-isr">Incremental static regeneration (ISR)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-concept-of-hydration">The concept of hydration</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-islands">Islands</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-streaming-ssr">Streaming SSR</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-comparing-the-different-patterns">Comparing the different patterns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrap-up">Wrap up</a></p>
</li>
</ul>
<h1 id="heading-whats-a-rendering-pattern">What's a Rendering Pattern?</h1>
<p>In web development, a rendering pattern refers to the way in which the HTML, CSS, and JavaScript code is all processed and rendered in a web application or website.</p>
<p>Different rendering patterns are used to achieve different performance and user experience goals. The most common rendering patterns in web development are:</p>
<ol>
<li><p><strong>Server-side rendering (SSR)</strong>: In SSR, the web server generates the HTML content of a web page on the server-side and sends it to the client's browser. This approach can improve initial loading times and SEO (search engine optimization) but can be slower for dynamic content.</p>
</li>
<li><p><strong>Client-side rendering (CSR)</strong>: In CSR, the client's browser generates the HTML content of a web page on the client-side using JavaScript. This approach can provide a fast and interactive user experience but can be slower for initial loading times and bad for SEO.</p>
</li>
<li><p><strong>Static site generation (SSG)</strong>: In SSG, the HTML content of a web page is generated at build time and served to the client as a static file. This approach can provide excellent performance and security but can be less flexible for dynamic content.</p>
</li>
</ol>
<p>In summary, a rendering pattern is a strategy for processing and rendering web content in web development. The choice of rendering pattern depends on the specific needs and requirements of a project, such as performance, SEO, user experience, and flexibility.</p>
<p>Now that we have an idea of what a rendering pattern is, let's examine in detail the many options available nowadays.</p>
<h1 id="heading-different-rendering-pattern-options">Different Rendering Pattern Options</h1>
<h2 id="heading-static-websites">Static Websites</h2>
<p>A static website is a type of website that consists of a set of HTML, CSS, and JavaScript files that are served to the client's browser without any server-side processing or database integration.</p>
<p>Static websites are typically created using static site generators, such as <a target="_blank" href="https://jekyllrb.com/">Jekyll</a>, <a target="_blank" href="https://gohugo.io/">Hugo</a>, or <a target="_blank" href="https://www.gatsbyjs.com/">Gatsby.js</a>. These generators compile templates, markdown files, or other data sources into a set of static files that are then deployed to a web server or <a target="_blank" href="https://www.youtube.com/watch?v=RI9np1LWzqw">content delivery network (CDN)</a>.</p>
<p>Static websites are often used for small to medium-sized websites that do not require complex dynamic features or server-side processing. They are easy to deploy, scale, and maintain, as they do not require a server-side application or database.</p>
<p>They also provide excellent security and performance, as the content is served directly from a web server or CDN without any server-side processing.</p>
<p>Static websites can be enhanced with client-side JavaScript, such as React or Vue, to provide interactive features or dynamic content. But any data that is required for these features must be loaded through client-side API requests, as there is no server-side processing to generate or retrieve the data.</p>
<p>In summary, a static website is a type of website that consists of a set of static files that are served to the client's browser without any server-side processing or database integration. They are simple, fast, secure, and scalable, and are suitable for small to medium-sized websites that do not require complex dynamic features or server-side processing.</p>
<h2 id="heading-single-page-applications-spas-with-client-side-rendering-csr">Single Page Applications (SPAs) with Client Side Rendering (CSR)</h2>
<p>A Single Page Application (SPA) is a type of web application rendered with Client-side rendering (CSR). This means that all necessary HTML, CSS, and JavaScript files are loaded at once when the user first loads the page. Then Javascript dynamically updates the content as the user interacts with the page, without requiring a full page reload.</p>
<p>In an SPA, the client-side JavaScript application is responsible for rendering the HTML and processing the user's interactions. The JavaScript application interacts with a backend API to retrieve data and update the user interface dynamically. Typically, this interaction is achieved using AJAX (Asynchronous JavaScript and XML) requests or Fetch API requests.</p>
<p>SPAs provide a fast and interactive user experience because only the necessary content is loaded and rendered dynamically, reducing the need for full page reloads. They also provide a more fluid user experience because the application can respond to user input without refreshing the entire page.</p>
<p>However, SPAs require a more complex setup and may have longer initial loading times compared to server-side rendering (SSR) or static site generation (SSG) approaches.</p>
<p>They also require additional considerations for search engine optimization (SEO) and accessibility, as search engines and assistive technologies may have difficulty indexing or navigating the content.</p>
<p>In summary, a Single Page Application (SPA) or Client-side rendering (CSR) is a type of web application that loads all necessary HTML, CSS, and JavaScript files at once and then dynamically updates the content as the user interacts with the page, without requiring a full page reload.</p>
<p>They provide a fast and interactive user experience but require a more complex setup and additional considerations for SEO and accessibility.</p>
<h2 id="heading-server-side-rendering-ssr">Server Side Rendering (SSR)</h2>
<p>Server-side rendering (SSR) is a technique for rendering web pages on the server-side before sending them to the client's browser. In SSR, the server generates the HTML content of a web page based on the requested URL and data, and sends it to the client's browser as a complete HTML document.</p>
<p>SSR provides several benefits, including improved performance, better SEO, and more robust accessibility.</p>
<p>By rendering the HTML on the server-side, SSR reduces the amount of JavaScript code that needs to be loaded and executed on the client's browser. This results in faster initial loading times and better performance on low-end devices or slow networks.</p>
<p>Additionally, SSR enables search engines and social media crawlers to index the web pages more accurately, as the complete HTML content is available on the initial page load. This can improve the visibility and ranking of the website in search engine results pages.</p>
<p>SSR also ensures that the web pages are accessible to users with assistive technologies, such as screen readers or keyboard navigation, as the HTML content is available from the initial page load.</p>
<p>However, SSR has some limitations, such as increased server-side processing requirements and limited interactivity compared to client-side rendering (CSR) or single-page applications (SPAs).</p>
<p>In summary, Server-side rendering (SSR) is a technique for rendering web pages on the server-side before sending them to the client's browser. It provides improved performance, better SEO, and more robust accessibility, but requires more server-side processing and has some limitations in interactivity.</p>
<h2 id="heading-static-site-generation-ssg">Static Site Generation (SSG)</h2>
<p>Static site generation (SSG) is a technique for building web pages by pre-generating HTML, CSS, and JavaScript files at build time instead of rendering them on the server or client-side.</p>
<p>In SSG, a static site generator tool like Jekyll, Hugo, or Gatsby.js is used to compile the website's content from data sources such as markdown files, JSON files, or <a target="_blank" href="https://www.youtube.com/watch?v=nrbpOmNC_mM">CMS</a> data, and generate a set of static files that can be served directly to the browser without any server-side processing.</p>
<p>The generated static files can be deployed on a web server or a content delivery network (CDN) and served quickly to the end-users with low latency. SSG offers several benefits such as fast loading times, improved security, and scalability.</p>
<p>Since SSG renders web pages at build time, there is no need to generate pages dynamically on the server or client-side. This reduces the processing overhead and enables faster loading times.</p>
<p>Static sites are also less vulnerable to server-side attacks and require fewer server resources, making them more scalable and easier to maintain.</p>
<p>But SSG has some limitations in terms of dynamic content and interactivity. Since the content is generated at build time, any dynamic data or user interactions need to be handled by client-side JavaScript code or serverless functions.</p>
<p>In summary, Static Site Generation (SSG) is a technique for building web pages by pre-generating HTML, CSS, and JavaScript files at build time instead of rendering them on the server or client-side. It offers several benefits such as fast loading times, improved security, and scalability, but has some limitations in terms of dynamic content and interactivity.</p>
<h2 id="heading-incremental-static-regeneration-isr">Incremental Static Regeneration (ISR)</h2>
<p>Incremental Static Regeneration (ISR) is a technique for building static sites that combines the benefits of both Server-Side Rendering (SSR) and Static Site Generation (SSG).</p>
<p>In ISR, the static site generator tool pre-generates a set of static pages at build time, but also includes additional metadata that enables the pages to be re-generated dynamically on the server-side when requested by the user. This metadata could include information such as expiration times or dependencies on specific data sources.</p>
<p>When a user requests a page that has expired or has dependencies that have changed, the server-side logic can regenerate the page with the updated content and serve it to the user, without requiring a full rebuild of the site.</p>
<p>This enables the site to maintain the benefits of static site generation, such as fast load times and low server processing overhead, while also allowing for dynamic content and personalized experiences for users.</p>
<p>ISR is particularly useful for sites that have content that changes frequently or for sites with a large number of pages that would be inefficient to rebuild in their entirety each time a change is made.</p>
<p>It allows for the best of both worlds: the performance and security benefits of static sites combined with the flexibility and personalization of server-side rendering.</p>
<p>In summary, Incremental Static Regeneration (ISR) is a technique for building static sites that combines the benefits of both Server-Side Rendering (SSR) and Static Site Generation (SSG). It allows for dynamic content and personalized experiences for users while maintaining the performance and security benefits of static sites.</p>
<h2 id="heading-the-concept-of-hydration">The Concept of Hydration</h2>
<p>In web development, "hydration" refers to the process of taking an HTML document that was initially rendered on the server and adding dynamic interactivity to it on the client-side.</p>
<p>Hydration is commonly used in Single-Page Applications (SPAs) that use client-side rendering (CSR).</p>
<p>During hydration, the browser parses the HTML document generated by the server and constructs a Document Object Model (DOM) tree, which represents the page's structure and content.</p>
<p>The browser then executes the JavaScript code that is responsible for adding dynamic behavior to the page, such as event handling, data fetching, and component rendering.</p>
<p>The JavaScript code retrieves the initial state and props of the components from the server-generated HTML and uses them to rehydrate the components on the client-side, effectively turning them into interactive elements.</p>
<p>This process ensures that the initial state of the page on the client-side matches the server-generated HTML and provides a seamless transition from the initial server-rendered view to the interactive client-side view.</p>
<p>Hydration is important for several reasons. First, it provides better performance and user experience by minimizing the time to interactive and enabling the user to interact with the page immediately.</p>
<p>Second, it enables search engine crawlers to access the page's content and metadata, improving SEO.</p>
<p>Finally, it ensures that the content is accessible and usable even if JavaScript is disabled in the user's browser.</p>
<p>In summary, hydration is the process of taking an HTML document that was initially rendered on the server and adding dynamic interactivity to it on the client-side.</p>
<p>It is commonly used in Single-Page Applications (SPAs) that use client-side rendering (CSR) and provides better performance, SEO, and accessibility.</p>
<h2 id="heading-islands">Islands</h2>
<p>The Islands pattern is a web development technique that involves breaking down a large, complex web page into smaller, self-contained components, each with its own HTML, CSS, and JavaScript code.</p>
<p>Each component is rendered independently on the server and is then rehydrated on the client-side, allowing it to become interactive.</p>
<p>The term "islands" refers to the individual components, each of which represents a separate island of content and functionality within the larger page.</p>
<p>By breaking the page into smaller islands, each with its own state and behavior, the application becomes more modular, easier to reason about and maintain, and can provide a more seamless user experience.</p>
<p>The Islands pattern is closely related to the concept of hydration because it relies on the same basic principle: rendering static HTML on the server and then hydrating it on the client-side with JavaScript to add interactivity.</p>
<p>In this case, each individual island is rendered on the server with its own static HTML, which is then hydrated on the client-side to enable dynamic functionality.</p>
<p>Hydration in the Islands pattern typically involves using a client-side framework or library to attach event handlers, manage state, and render dynamic content within each component. The framework or library must be capable of rehydrating the component on the client-side, ensuring that the initial state and behavior of the component matches that of the server-rendered HTML.</p>
<p>One benefit of using the Islands pattern with hydration is that it can improve the performance of large, complex web applications by reducing the amount of JavaScript that needs to be downloaded and executed on the client-side. By rendering each component independently on the server and rehydrating it on the client-side, the application can provide a more seamless user experience without sacrificing performance or scalability.</p>
<p>In summary, the Islands pattern is a web development technique that involves breaking down a large, complex web page into smaller, self-contained components, each with its own HTML, CSS, and JavaScript code. It relies on the same principle of hydration as other rendering patterns, rendering static HTML on the server and then adding interactivity with JavaScript on the client-side.</p>
<p>The Islands pattern can improve the performance and scalability of large web applications by reducing the amount of JavaScript that needs to be downloaded and executed on the client-side.</p>
<h2 id="heading-streaming-ssr">Streaming SSR</h2>
<p>Streaming Server-Side Rendering (SSR) is a rendering pattern for web development that involves sending the server-generated HTML to the client as soon as it becomes available, rather than waiting for the entire page to be rendered before sending it.</p>
<p>With traditional SSR, the server would wait for the entire page to be rendered before sending it to the client, resulting in a longer time to first byte (TTFB) and a slower user experience.</p>
<p>Streaming SSR allows the server to send the HTML to the client in chunks as it is generated, providing a faster TTFB and a more responsive user experience.</p>
<p>Streaming SSR is particularly useful for rendering large or complex web pages that take a long time to render, such as e-commerce product pages or news articles.</p>
<p>With streaming SSR, the user can start interacting with the page as soon as the first chunk of HTML is received, without having to wait for the entire page to be rendered.</p>
<p>To implement streaming SSR, the server must use a technique called "chunking" to break the server-generated HTML into smaller chunks and send them to the client as they become available. The client then uses JavaScript to append each chunk of HTML to the page as it is received, effectively streaming the content to the user.</p>
<p>One challenge with streaming SSR is ensuring that the chunks of HTML are sent to the client in the correct order and that the page remains coherent as it is rendered.</p>
<p>To address this, developers may use techniques such as critical CSS, which involves identifying and rendering the most important styles first, or template-based chunking, which involves breaking the HTML into smaller chunks based on templates or components.</p>
<p>In summary, Streaming Server-Side Rendering (SSR) is a rendering pattern for web development that involves sending the server-generated HTML to the client in chunks as it is generated, providing a faster TTFB and a more responsive user experience. It is particularly useful for rendering large or complex web pages.</p>
<p>To implement streaming SSR, the server must use a technique called "chunking" to break the HTML into smaller chunks, and the client must use JavaScript to append each chunk to the page as it is received.</p>
<h1 id="heading-comparing-the-different-patterns">Comparing the Different Patterns</h1>
<p>Awesome, so now we have a clear idea of each of the common options available. Let's now quickly go through the main characteristics of each pattern and mention the situations in which each of them might be more beneficial.</p>
<h3 id="heading-static-websites-1">Static Websites</h3>
<p><strong>Main characteristics:</strong></p>
<ul>
<li><p>Pre-built HTML, CSS, and JavaScript files that are served to the client as-is.</p>
</li>
<li><p>No dynamic content, as all content is pre-rendered and does not change.</p>
</li>
<li><p>Fast load times due to the lack of server processing.</p>
</li>
</ul>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Extremely fast load times and low server costs.</p>
</li>
<li><p>Great for sites with little to no dynamic content, such as portfolios or blogs.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Limited interactivity and functionality, as all content is pre-rendered.</p>
</li>
<li><p>Not suitable for sites that require dynamic content or user input.</p>
</li>
</ul>
<p><strong>Best for:</strong></p>
<ul>
<li>Sites with limited dynamic content or sites that do not require dynamic functionality.</li>
</ul>
<h3 id="heading-single-page-applications-spas">Single Page Applications (SPAs)</h3>
<p><strong>Main characteristics:</strong></p>
<ul>
<li><p>All content is dynamically rendered client-side through JavaScript.</p>
</li>
<li><p>Only a single page is loaded, with content updates handled by JavaScript.</p>
</li>
<li><p>Dynamic content can be easily added through APIs.</p>
</li>
</ul>
<p><strong>Pros:</strong></p>
<ul>
<li><p>High interactivity and functionality, as all content is dynamic and can be updated without refreshing the page.</p>
</li>
<li><p>Ideal for complex, data-driven applications that require frequent content updates.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Slower initial load times due to the need to load JavaScript and dynamically render content.</p>
</li>
<li><p>Can be difficult to implement proper SEO techniques due to the lack of pre-rendered content.</p>
</li>
</ul>
<p><strong>Best for:</strong></p>
<ul>
<li>Applications that require complex interactivity or frequent content updates.</li>
</ul>
<h3 id="heading-server-side-rendering-ssr-1">Server Side Rendering (SSR):</h3>
<p><strong>Main characteristics:</strong></p>
<ul>
<li><p>Server Side Rendering (SSR) is a process in which web pages are generated on the server and sent to the client as fully rendered HTML.</p>
</li>
<li><p>The server sends a complete HTML response to the client, which includes all the dynamic content, after processing the data on the server.</p>
</li>
</ul>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Improved SEO because search engine crawlers can easily parse the complete HTML content.</p>
</li>
<li><p>Better performance because the initial HTML is sent in a single response, which reduces the time for the browser to load and display the content.</p>
</li>
<li><p>Works well for content-rich applications or dynamic web applications that require data to be fetched from APIs.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Higher server overhead because every request is processed on the server.</p>
</li>
<li><p>More complex to set up because it requires a server-side framework that supports SSR.</p>
</li>
<li><p>Less interactive because interactions require additional server requests.</p>
</li>
</ul>
<p><strong>Best for:</strong></p>
<ul>
<li><p>Applications with content that changes frequently.</p>
</li>
<li><p>Applications with dynamic data that needs to be processed on the server before sending the response.</p>
</li>
</ul>
<h3 id="heading-static-site-generation-ssg-1">Static Site Generation (SSG):</h3>
<p><strong>Main characteristics:</strong></p>
<ul>
<li><p>Static Site Generation (SSG) is a process in which web pages are pre-built as static files during the build process and served to the client as static HTML pages.</p>
</li>
<li><p>The server sends static HTML pages to the client, which includes all the content, without processing any data on the server.</p>
</li>
</ul>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Very fast and efficient because static pages can be served from a CDN or cache.</p>
</li>
<li><p>Lower server overhead because the server only needs to serve static files.</p>
</li>
<li><p>Can be deployed on a static file host or serverless environments like AWS Lambda.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Not suitable for dynamic content that changes frequently.</p>
</li>
<li><p>Interactions require additional client-side JavaScript.</p>
</li>
</ul>
<p><strong>Best for:</strong></p>
<ul>
<li><p>Applications with mostly static content and few interactions.</p>
</li>
<li><p>Applications with limited interactivity.</p>
</li>
</ul>
<h3 id="heading-incremental-static-regeneration-isr-1">Incremental Static Regeneration (ISR):</h3>
<p><strong>Main characteristics:</strong></p>
<ul>
<li>Incremental Static Regeneration (ISR) is a hybrid approach between SSG and SSR, where pages are pre-rendered as static HTML pages during the build process, and then the content is regenerated periodically or on-demand as required.</li>
</ul>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Faster time-to-content because static pages are served initially, but content can be updated quickly.</p>
</li>
<li><p>Lower server overhead because static pages can be served from a CDN or cache, and dynamic content is regenerated only when required.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>Limited dynamic content because content regeneration requires a server request.</p>
</li>
<li><p>Requires a complex caching strategy to ensure that stale content is not served to clients.</p>
</li>
</ul>
<p><strong>Situations:</strong></p>
<ul>
<li><p>Applications with content that changes frequently but can tolerate some latency.</p>
</li>
<li><p>Applications with limited dynamic content.</p>
</li>
</ul>
<h3 id="heading-islands-1">Islands:</h3>
<p><strong>Main Characteristics:</strong></p>
<ul>
<li><p>The Island rendering pattern refers to rendering parts of the page on the server while other parts are rendered on the client-side.</p>
</li>
<li><p>The server renders the critical content, while the client fetches the rest of the content.</p>
</li>
<li><p>The server-side rendering can improve the initial page load speed and improve SEO.</p>
</li>
<li><p>The client-side rendering can improve the interactivity and reduce server overhead.</p>
</li>
</ul>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Faster page load times because the server renders critical content while the client fetches the rest.</p>
</li>
<li><p>Works well for applications that require partial server-side rendering and partial client-side rendering.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p>More complex to set up because it requires a hybrid framework that can support both server-side and client-side rendering.</p>
</li>
<li><p>May result in inconsistencies if the server and client render different versions of the content.</p>
</li>
</ul>
<p><strong>Best for:</strong></p>
<ul>
<li><p>Applications with dynamic content that require some server-side processing.</p>
</li>
<li><p>Applications that require a fast initial page load.</p>
</li>
</ul>
<h3 id="heading-streaming-ssr-1">Streaming SSR:</h3>
<p><strong>Main Characteristics:</strong></p>
<ul>
<li><p>The server sends the HTML response in a streaming fashion, which enables the client to start rendering the content as soon as possible.</p>
</li>
<li><p>The client can see content being rendered progressively, which improves the user experience.</p>
</li>
</ul>
<p><strong>Pros:</strong></p>
<ul>
<li><p>Improved time-to-content because the client can start rendering the content while the server is still processing the request.</p>
</li>
<li><p>Better user experience because the client can see content being rendered progressively.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li>More complex to set up because it requires a server framework that supports streaming.</li>
</ul>
<p><strong>Best for:</strong></p>
<ul>
<li><p>Applications with large pages or media that require a long time to load.</p>
</li>
<li><p>Applications that require a smooth user experience with minimal waiting time.</p>
</li>
</ul>
<h1 id="heading-wrap-up">Wrap up</h1>
<p>Well everyone, as always, I hope you enjoyed the article and learned something new.</p>
<p>If you want, you can also follow me on <a target="_blank" href="https://www.linkedin.com/in/germancocca/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/CoccaGerman">Twitter</a>. See you in the next one!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/out-disappear.gif" alt="Image" width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Accessibility Best Practices – What to Remember When Building Accessible Web Apps ]]>
                </title>
                <description>
                    <![CDATA[ Anyone should be able to use your websites and apps - both people with disabilities and those without. This will make your website accessible. Think about the last site you built, or your favorite site. Are you confident that anyone can use your site... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/accessibility-best-practices-to-make-web-apps-accessible/</link>
                <guid isPermaLink="false">66b99cc84ed1a5964b77008a</guid>
                
                    <category>
                        <![CDATA[ a11y ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Accessibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Shruti Kapoor ]]>
                </dc:creator>
                <pubDate>Fri, 16 Dec 2022 21:01:26 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/12/ben-kolde-bs2Ba7t69mM-unsplash-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Anyone should be able to use your websites and apps - both people with disabilities and those without. This will make your website accessible.</p>
<p>Think about the last site you built, or your favorite site. Are you confident that anyone can use your site and perform the critical actions it requires? Have you considered folks with motor disabilities, visual disabilities, cognitive disabilities, and auditory disabilities?</p>
<p>Accessibility is often left as an after-thought. When it is time to ship a feature, we do an accessibility test and find out that our site wasn't accessible and do a hacky fix. </p>
<p>Making a site accessible is a huge undertaking. But if we keep accessibility in mind from the get-go, it makes it much easier to build an accessible web app. </p>
<p>In this post, I will go over 5 things you can keep in mind WHILE building your app so you don't have to do a hacky slap together at the end.</p>
<h2 id="heading-5-things-to-remember-for-good-accessibility">5 Things to Remember for Good Accessibility</h2>
<ol>
<li>Semantinc HTML</li>
<li>Tabindex</li>
<li>Aria attributes</li>
<li>Role</li>
<li>Keyboard navigation and screen readers</li>
</ol>
<p>In short, S.T.A.R.K.</p>
<p>If you need help remembering this, think of Tony Stark. </p>
<p><img src="https://cdn.vox-cdn.com/uploads/chorus_image/image/55400215/ktokatitmir0.0.jpg" alt="TonyStark" width="3000" height="1779" loading="lazy"></p>
<p>Let's go through each of these to understand how to use them in your web apps.</p>
<h3 id="heading-what-is-semantic-html">What is Semantic HTML?</h3>
<p>Using semantic HTML is important for accessibility. This is because assistive technologies such as screen readers are able to interpret what's on the page by parsing the HTML of the page. They enable users to take actions based on the elements. </p>
<p>For example, if a screen reader encounters a <code>button</code>, it signals to the user that they should click on it. </p>
<p>Let's consider some use-cases of what can happen when you don't use semantic HTML:</p>
<h4 id="heading-creating-buttons-by-using-div-instead-of-button">Creating buttons by using <code>div</code> instead of <code>button</code>:</h4>
<p><code>div</code>s are container elements, so when a screen reader encounters a div, it automatically thinks it is a presentational element. </p>
<p>When a screen reader user encounters a <code>div</code> that has content or children within it, the screen reader announces <code>role="group"</code> and the user will completely miss that the <code>div</code> is interactive. So make sure you use the proper semantic element for its purpose. You get accessibility for free.</p>
<h4 id="heading-using-css-to-fake-headings-instead-of-using-h1-6-tags">Using CSS to fake headings instead of using <code>h1-6</code> tags:</h4>
<p>Heading tags such as <code>&lt;h1&gt;</code> and <code>&lt;h2&gt;</code> let an assitive technology know that this is important text, and the screen reader will announce "Heading". </p>
<p>When you use CSS to make a heading instead of using correct semantics, the significance of the text is lost to a screen reader.</p>
<p>So just make sure to use semantic HTML whenever possible.</p>
<h3 id="heading-what-is-tabindex">What is Tabindex?</h3>
<p>Adding a <code>tabindex</code> makes interactive elements keyboard-navigable. When you add <code>tabindex</code> to an element, a user is able to navigate to it using only their keyboard and/or assitive technologies.</p>
<ol>
<li>You use a tabindex of <code>0</code> to set focus to an element in the default tabbing order,</li>
<li>You use a tabindex of <code>-1</code> to programmatically focus an element using JavaScript.</li>
<li>Do not assign a value of &gt; 1 to tabindex.</li>
</ol>
<p>A word of caution though - you should only add <code>tabindex</code> to interactive elements. It is not a good practie to add <code>tabindex</code> to elements such as <code>div</code>. </p>
<p>Instead of adding tabindex in that case, use a semantic element, such as a <code>button</code> since semantic elements already are tabbable and do not need an additional <code>tabindex</code> value.</p>
<h3 id="heading-what-are-aria-attributes">What are ARIA attributes?</h3>
<p>Aria attributes such as <code>aria-checked</code>, <code>aria-label</code> give additional information to assistive technologies.</p>
<p>Aria attributes are a set of HTML attributes that you use to provide additional information about the purpose and state of elements on a web page. These attributes are especially beneficial to assistive technologies to provide more context and better navigation for users.</p>
<p>Some common aria-attributes include:</p>
<ol>
<li><code>aria-label</code>: used to provide a label or name for an element.</li>
<li><code>aria-hidden</code>: used to indicate that an element should be hidden from assistive technologies. This can be useful for elements that are used for layout purposes but are not relevant to the content of the page.</li>
<li><code>aria-describedby</code>: used to associate an element with a description, which helps to provide context of an element.</li>
<li><code>aria-liv</code>e: used to indicate that an element's content may change dynamically, and that assistive technologies should pay attention to changes in the element's content.</li>
</ol>
<p>You can use these attributes in combination with each other and with standard HTML attributes to create more accessible and user-friendly web content.</p>
<h3 id="heading-what-is-the-aria-role-attribute">What is the <code>aria-role</code> attribute?</h3>
<p>You use the <code>aria-role</code> attribute to define the purpose of an HTML element and provide its semantic meaning. </p>
<p>For example, if you are building a grid component with the help of CSS and divs, you can use <code>role="grid"</code> to let assistive technologies know about the semantics of the component.</p>
<p>Some common <code>aria-role</code>s include:</p>
<ol>
<li><code>button</code>: used to indicate that an element should be treated as a button.</li>
<li><code>alert</code>: used to indicate that an element is an alertbox.</li>
<li><code>presentation</code>: used to indicate that an element is only presentational.</li>
</ol>
<p>It is important to exercise caution with <code>aria-role</code>. Remember to not overdo it.</p>
<h3 id="heading-how-to-handle-keyboard-navigation-and-screen-readers">How to handle keyboard navigation and screen readers</h3>
<p>Many users with motor disabilities rely on their keyboard and assitive technologies to navigate the web. So it's critical that every component be navigable using a keyboard and screen reader. </p>
<p>You can test keyboard accessibility by navigating a site using only your keyboard. Here are some common keys:</p>
<ol>
<li><code>tab</code> key to navigate to different sections of the site.</li>
<li><code>spacebar</code> to select elements, such as a checkbox.</li>
<li><code>enter</code> to press buttons.</li>
</ol>
<p>While testing keyboard navigation, make sure you think about the following:</p>
<ol>
<li>Focus remains visible: Ensure that you can clearly see which element is being focused on the page. Focus should always remain visible.</li>
<li>Tab order: When tabbing through sections, the order of tabbing should follow the natural flow and logical structure of the website. It should not jump back and forth between sections.</li>
<li>Keyboard traps: Ensure that when navigating with the keyboard, the focus doesn't get trapped on an element. For example, this could happen when a modal is opened, or the focus is navigated to a widget, such as calendar or emoji picker. Ensure that when you select an element in the widget, you are able to navigate back to the site.</li>
</ol>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Overall, testing for accessibility during development is an important part of the process that can help to create more usable and accessible software for all users. Testing for accessibility early helps to provide a great user experience for everyone.</p>
<p>In the next article, I will talk about the various accessibility tools and how to debug an accessibility issue. You can <a target="_blank" href="http://tinyletter.com/shrutikapoor">sign up to get it in your inbox here.</a></p>
<p>Until then, enjoy your holidays!</p>
<p>Feliz Navidad.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is the Jamstack? Tutorial for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ You may have heard the term Jamstack and have been wondering what it means. Well, the Jamstack is nothing more than a modern way of building web applications. Jamstack takes advantage of existing technologies – which we'll discuss in a minute. The re... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/jamstack-for-beginners/</link>
                <guid isPermaLink="false">66d45e0847a8245f78752a1e</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ markup ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Damilola Oladele ]]>
                </dc:creator>
                <pubDate>Thu, 10 Nov 2022 18:30:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/Damilola-Oladele-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You may have heard the term Jamstack and have been wondering what it means. Well, the Jamstack is nothing more than a modern way of building web applications.</p>
<p>Jamstack takes advantage of existing technologies – which we'll discuss in a minute. The result is better performance, improved security, and easier scalability for web applications.</p>
<p>In this article, you'll learn what Jamstack means and the benefits of using this approach in your projects.</p>
<h2 id="heading-what-is-the-jamstack">What is the Jamstack?</h2>
<p>Jamstack is a web development architecture. Matt Biilmann, the CEO of Netlify, popularized it with his presentation at Smashing Conference 2016.</p>
<p>Jamstack is an acronym for Javascript, APIs, and Markup, and is a technology stack you use to build your apps.</p>
<p>This is like the MERN stack (MongoDB, ExpressJS, ReactJS and NodeJS) and the MEAN stack (MongoDB, ExpressJS, Angular and NodeJS) – just with different tools.</p>
<p>Now let's discuss the various components of a Jamstack web application:</p>
<h3 id="heading-javascript">Javascript</h3>
<p>Javascript is the core programming language of the web. It has been around for decades and you can use it both on the client side and the backend with NodeJS.</p>
<p>Javascript is the programming language you use for handling the client side of your Jamstack applications.</p>
<h3 id="heading-apis">APIs</h3>
<p>API is an acronym for <strong>Application Programming Interface</strong>. It's an interface which helps two or more computer programs communicate with each other.</p>
<p>In Jamstack apps, you use APIs to communicate with your backend.</p>
<h3 id="heading-markup">Markup</h3>
<p>Markup refers to standard text-encoding systems consisting of a set of symbols inserted into a text document. Examples of markup languages are <strong>HTML</strong>, <strong>XML</strong>, and templating languages such as <strong>JSX</strong>.</p>
<p>In the Jamstack, markup refers to the content of a Jamstack application. Note that we use markup here in its broader sense. It doesn't refer to text content only but also to the assets of the web application, such as images.</p>
<h2 id="heading-important-features-of-jamstack-apps">Important Features of Jamstack Apps</h2>
<p>To consider an application a Jamstack app, it should meet the following conditions:</p>
<h3 id="heading-distributed-architecture">Distributed Architecture</h3>
<p>This refers to the decoupling of the client side from the backend. The client side handles the presentation of the user interface, and the backend handles business logic and data.</p>
<p>Communication between the frontend and backend happens via a dedicated API. This means that a change or upgrade in one will not affect the other. This results in easier maintenance of the entire web application.</p>
<h3 id="heading-static-sites">Static Sites</h3>
<p>It is important for Jamstack applications to serve static web pages and not dynamic ones.</p>
<p>Traditional web applications are dynamic sites. This means that when you request a page, the backend will have to reach a database to retrieve the data. The data is then used to generate HTML files, and then sent back to the client.</p>
<p>The disadvantage of dynamic sites is how long it takes to complete these steps.</p>
<p>For static sites, the pages are already pre-rendered at build time. So every time you request a page, you get the pre-rendered page.</p>
<p>This eliminates the time that dynamic sites spend in obtaining data, generating HTML files, and sending it back to the client. You can serve your static sites from a <a target="_blank" href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">content delivery network (CDN).</a> This will lead to improved speed and reduced costs.</p>
<p>Examples of static site generators that you can use for your Jamstack web applications include:</p>
<ul>
<li><p>NextJS</p>
</li>
<li><p>Gatsby</p>
</li>
<li><p>Hugo</p>
</li>
<li><p>Jekyll</p>
</li>
<li><p>Nuxt</p>
</li>
</ul>
<h2 id="heading-why-should-you-use-the-jamstack-for-your-web-applications">Why Should You Use the Jamstack for your Web Applications?</h2>
<p>Let's now discuss some of the reasons the Jamstack web architecture has become so popular in recent times and why you should consider adopting it:</p>
<h3 id="heading-jamstack-apps-are-scalable">Jamstack Apps Are Scalable</h3>
<p>You can serve most Jamstack applications from a CDN. This allows for the speedy transfer of assets needed for loading web pages.</p>
<p>As a result of the distributed nature of CDNs, your web application will also be able to handle more traffic at a reduced cost.</p>
<h3 id="heading-jamstack-apps-are-easy-to-maintain">Jamstack Apps Are Easy to Maintain</h3>
<p>Jamstack applications are easier to maintain since their client side is decoupled from their backends.</p>
<p>This means that you can maintain one part without requiring major modifications to the other.</p>
<h3 id="heading-jamstack-apps-load-faster">Jamstack Apps Load Faster</h3>
<p>As stated earlier, serving your site from a CDN increases the speed with which it loads.</p>
<p>Also, in Jamstack applications, web pages are prebuilt, saving time that would normally be spent retrieving and generating HTML files every time you make a request.</p>
<h3 id="heading-jamstack-apps-are-cheaper">Jamstack Apps Are Cheaper</h3>
<p>Since Jamstack applications are easier to maintain and deploy, they are cheaper compared to their traditional counterparts.</p>
<h3 id="heading-jamstack-apps-are-more-secure">Jamstack Apps Are More Secure</h3>
<p>Since you do not have to constantly maintain a server in Jamstack applications and the pages are constructed on read-only files (that is, the pages are static), you can worry less about the security of your applications.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Despite the fact that more and more projects are being built using the Jamstack architecture, we're still in the relatively early stages of its adoption.</p>
<p>I believe that more large and small businesses will adopt it in the near future in place of costly monolithic architectures.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Architect a Full-Stack Application from Start to Finish ]]>
                </title>
                <description>
                    <![CDATA[ Software architecture is a massive topic. That said, I think I can give you a simple method you can use to approach the architecture of a full-stack application.  In particular, I want to talk about the order in which you should think about and build... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-full-stack-application-from-start-to-finish/</link>
                <guid isPermaLink="false">66b9e9e8a29acc044a5aff50</guid>
                
                    <category>
                        <![CDATA[ full stack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Lane Wagner ]]>
                </dc:creator>
                <pubDate>Tue, 04 Oct 2022 17:49:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/jeremy-thomas-FO7bKvgETgQ-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Software architecture is a massive topic. That said, I think I can give you a simple method you can use to approach the architecture of a full-stack application. </p>
<p>In particular, I want to talk about the <em>order</em> in which you should think about and build out the pieces of a typical web application.</p>
<p>My advice is that <strong>for each feature</strong> you should:</p>
<ol>
<li>Design the front-end</li>
<li>Build the front-end</li>
<li>Build the persistence layer (back-end database and data models)</li>
<li>Build the API (back-end application)</li>
</ol>
<p><em>The best way is a front -&gt; back -&gt; middle approach.</em></p>
<h2 id="heading-why-start-with-the-front-end">Why Start with the Front-End?</h2>
<p>Assuming you're working with a good product team (or maybe you're a team of one so you <em>are</em> the product team) the most important thing is the end-user experience. As a result, it makes the most sense to start on the front-end. </p>
<p>Only by designing and building the front-end will you learn what kinds of requirements you'll have for the back-end of your application.</p>
<p>The user of front-end code is the customer. The user of back-end code is front-end code.</p>
<h2 id="heading-how-do-you-build-a-front-end-without-a-back-end-to-connect-to">How Do you Build a Front-End without a Back-End to Connect to?</h2>
<p>This is the beauty of starting with the front-end. Start by mocking up all of the data that fills in your UI. For example, instead of writing code like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> resp = <span class="hljs-keyword">await</span> fetch(userUrl)
<span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> resp.json()
</code></pre>
<p>You would simply write:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> user = {
    <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">username</span>: <span class="hljs-string">"bobbyjoe"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"bobbyjoe@example.com"</span>,
    <span class="hljs-attr">profilePictureUrl</span>: <span class="hljs-string">"https://fakewebsite.com/fakeimageurl.jpeg"</span>
}
</code></pre>
<p>Then you would write all the rest of the front-end code like you normally would. By the time you're done, you'll know <em>exactly</em> what kind of data you'll need your back-end to store and serve. </p>
<p>And by the time you do get around to building the back-end, you can just swap out those mock JSON objects for <code>fetch</code> requests.</p>
<h2 id="heading-create-the-data-model-and-database-schema">Create the Data Model and Database Schema</h2>
<p>Okay, so you've built out the front-end for your new feature, and you've mocked all the data that you've decided will need to be stored on the back-end. Now it's time to decide how you'll model that data inside your database.</p>
<p>I like to go straight from the front-end to the database. This is because the way you store data in the database is more important to get right than the way you serve the data from your API – well, at least if the consumer of your API is your own team (or you).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/well.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Obi Wan writing APIs for himself</em></p>
<p><a target="_blank" href="https://wagslane.dev/posts/keep-your-data-raw-at-rest/">Changing database schemas is <em>hard</em></a>. It's much easier to slap a <code>/v2</code> endpoint on your back-end than to rewrite your persistence layer. </p>
<p>For that reason, thinking about how you're going to store your data, and giving priority to that design, will generally lead to less headache down the road.</p>
<p>Typically, once you have the front-end built you have all the information you need to design a solid database schema.</p>
<p>For example, maybe you know you need:</p>
<ul>
<li>To store users, each with an email and profile picture</li>
<li>To allow users to join, create, and leave organizations</li>
</ul>
<p>With that in mind, and assuming you're using a relational SQL database like Postgres, you can probably start with something like:</p>
<ul>
<li>A <code>users</code> table with <code>id</code>, <code>created_at</code>, <code>email</code>, and  <code>profile_picture_url</code> fields</li>
<li>A <code>organizations</code> table with <code>id</code>, <code>created_at</code>, and <code>name</code> fields</li>
<li>A <code>users_organizations</code> table with <code>id</code>, <code>user_id</code>, <code>organization_id</code>, and <code>role</code> fields</li>
</ul>
<p>Users go in the <code>users</code> table, organizations go in the <code>organizations</code> table, and the <code>users_organizations</code> table is a joining table to keep track of which users are a part of which organizations and what their role is. For example, they might be an <code>admin</code> or a <code>member</code>. </p>
<p>If you're unfamiliar with all this SQL terminology, you can check out my <a target="_blank" href="https://boot.dev/learn/learn-sql">Learn SQL course</a> on <a target="_blank" href="https://boot.dev/">Boot.dev</a>.</p>
<h2 id="heading-lastly-build-the-back-end-application">Lastly, Build the Back-end Application</h2>
<p>Now that you know which data your front-end needs, and how you can best model it in your database, you final task is to glue it all together with a back-end API. </p>
<p>Start with the simplest API you can.</p>
<p>Don't build complex joining capabilities to start. Don't build crazy pagination or filtering features if you don't need them. You can always add new endpoints and parameters later in order to fulfill performance needs as they arise. I'm a big fan of <a target="_blank" href="https://wagslane.dev/posts/optimize-for-simplicit-first/">optimizing for simplicity first</a>.</p>
<p>Anyhow, that's not to say you won't need anything more complex than a few CRUD endpoints – you might. If you do, at least you have all the information in front of you in order to make a well-informed decision. </p>
<p>Don't build more than what the front-end requires, and try to use the simple data models you created in the database.</p>
<p>With all that in mind, expect to go back and forth on a few things. Don't feel bad if you missed a feature on the front-end and need to go back and add it. Or maybe you overlooked how slow a certain view in your app would load if you store the data in a certain way in your database. This can be an iterative process, and it should be.</p>
<h2 id="heading-one-final-note-dont-do-waterfall">One Final Note: Don't Do Waterfall</h2>
<p>I want to double stress the fact that you should be doing this on a <em>per-feature</em> basis. I'm not advocating that you plan an entire application up front. You should still be practicing iterative product development.</p>
<p>Good luck, and if you need help learning back-end development feel free to check out what I'm building over on <a target="_blank" href="https://boot.dev/">Boot.dev</a>!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy a Machine Learning Model as a Web App Using Gradio ]]>
                </title>
                <description>
                    <![CDATA[ You've built your Machine Learning model with 99% accuracy and now you are ecstatic. You are like yaaaaaaaaay! My model performed well. Then you paused and you were like – now what? Well first, you might have thought of uploading your code to GitHub ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deploy-your-machine-learning-model-as-a-web-app-using-gradio/</link>
                <guid isPermaLink="false">66d45f393a8352b6c5a2aa6f</guid>
                
                    <category>
                        <![CDATA[ deployment ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ibrahim Ogunbiyi ]]>
                </dc:creator>
                <pubDate>Wed, 01 Jun 2022 15:14:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/05/deploy-ml-models-article.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You've built your Machine Learning model with 99% accuracy and now you are ecstatic. You are like yaaaaaaaaay! My model performed well.</p>
<p>Then you paused and you were like – now what?</p>
<p>Well first, you might have thought of uploading your code to GitHub and showing people your Jupyter notebook file. It comprises those gorgeous-looking visualizations you created using Seaborn, those extremely powerful ensemble models, and how they are able to pass their evaluation metrics and so on.</p>
<p>But then you noticed that no one is interacting with it.</p>
<p>Well, my friend, why not try deploying the model as a web app so that non-techies can interact with the model, too? Because only programmers like you will likely understand that first approach.</p>
<p>There are several methods for deploying your model, but we will focus on one of them in this article: using Gradio. I can tell you're excited. Well, relax and enjoy, because this is going to be an exciting ride.</p>
<h1 id="heading-prerequisites">Prerequisites</h1>
<p>Before beginning this journey, I assume you have the following knowledge:</p>
<ol>
<li><p>You know how to create a user-defined function in Python</p>
</li>
<li><p>You can build and fit an ML model</p>
</li>
<li><p>Your environment is all set up</p>
</li>
</ol>
<h1 id="heading-what-is-gradio">What is Gradio?</h1>
<p><a target="_blank" href="https://gradio.app/">Gradio</a> is a free and open-source Python library that allows you to develop an easy-to-use customizable component demo for your machine learning model that anyone can use anywhere.</p>
<p>Gradio integrates with the most popular Python libraries, including Scikit-learn, PyTorch, NumPy, seaborn, pandas, Tensor Flow, and others.</p>
<p>One of its advantages is that it allows you to interact with the web app you are currently developing in your Jupyter or Colab notebook. It has a lot of unique features that can help you construct a web app that users can interact with.</p>
<h1 id="heading-how-to-install-gradio">How to Install Gradio</h1>
<p>To use Gradio, we must first install its library on our local PC. So go to your Conda PowerShell or terminal and run the following command. If you are using Google Colab you can also type the following:</p>
<pre><code class="lang-javascript">pip install gradio
</code></pre>
<p>We now have Gradio installed on our local PC. Let's go through some of the fundamentals of Gradio so we can become acquainted with the library.</p>
<p>To begin, we must import the library into our notebook or IDE, whichever you are using. We can do this by typing the following command:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> gradio <span class="hljs-keyword">as</span> gr
</code></pre>
<h1 id="heading-how-to-create-your-first-web-app">How to Create Your First Web App</h1>
<p>In this tutorial, we'll create an example greeting app to familiarize ourselves with the fundamentals of Gradio.</p>
<p>To do so, we'll need to write a greeting function because Gradio works with Python user defined functions. As a result, our greeting function looks like this:</p>
<pre><code class="lang-py"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet_user</span>(<span class="hljs-params">name</span>):</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello "</span> + name + <span class="hljs-string">" Welcome to Gradio!😎"</span>
</code></pre>
<p>We now need to deploy the Python function on Gradio so that it can act as a web app. To do this, we type:</p>
<pre><code class="lang-py">app =  gr.Interface(fn = greet_user, inputs=<span class="hljs-string">"text"</span>, outputs=<span class="hljs-string">"text"</span>)
app.launch()
</code></pre>
<p>Let’s walk through and have a grok about what is going on in the above code before we run it.</p>
<p><code>gr.Interface</code>: This attribute serves as the bedrock of anything in Gradio. It is the user interface that displays all the components that will be shown on the web.</p>
<p>The parameter <code>fn</code>: This is the Python function you created and want to provide to Gradio.</p>
<p>The <code>inputs</code> parameter: These are the components that you wish to pass into the function that you created, such as words, images, numbers, audio, and so on. In our case, the function we created required text, so we entered it into the inputs parameters.</p>
<p>The <code>output</code> parameter: This is a parameter that allows you to display the component on the interface that you want to see. Because the function we created in this example needs to display text, we supply the text component to the outputs parameter.</p>
<p><code>app.launch</code> is used to launch the app. You should have something like this when you run the above code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/05/Gradio-pro.png" alt="alt_text" width="600" height="400" loading="lazy"></p>
<p>Once the Gradio interface comes up, just type your name and hit submit. Then it outputs the result in the function we created above. Now that we are done with that, let’s go over one more thing in Gradio before we learn how to deploy our model.</p>
<p>We will create a Gradio app that can accept two inputs and provides one output. This app just asks for your name and a value and then outputs your names as well as multiples of the value you entered. To do that just type the below code:</p>
<pre><code class="lang-py"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">return_multiple</span>(<span class="hljs-params">name, number</span>):</span>
    result = <span class="hljs-string">"Hi {}! 😎. The Mulitple of {} is {}"</span>.format(name, number, round(number**<span class="hljs-number">2</span>, <span class="hljs-number">2</span>))
    <span class="hljs-keyword">return</span> result

app = gr.Interface(fn = return_multiple, inputs=[<span class="hljs-string">"text"</span>, gr.Slider(<span class="hljs-number">0</span>, <span class="hljs-number">50</span>)], outputs=<span class="hljs-string">"text"</span>)
app.launch()
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/05/gradio-2.png" alt="alt_text" width="600" height="400" loading="lazy"></p>
<p>Now that we’ve done that let’s quickly go through some of the things we did here that you might not be familiar with.</p>
<p>Input Parameter: In the input parameter we created a list that involves two components, the text and the slider. The slider is also one of Gradio's attributes that returns a float value when you slide across a given range. We used this because in the function we created we are expecting a text and a value.</p>
<p>We have to order the component in the input parameter the way our attributes are ordered in the function we created above. That is, text first before the number. So what we are expecting for the output is actually a string. We just did some formatting in the above function.</p>
<p>Now that we’ve familiarized ourselves with some of the basics of Gradio, let’s create a model that we will deploy.</p>
<h1 id="heading-how-to-deploy-a-machine-learning-model-on-gradio">How to Deploy a Machine Learning Model on Gradio</h1>
<p>In this section, I will use a classification model that I've previously trained and saved in a pickle file.</p>
<p>When you create a model that takes a long time to train, the most effective approach to deal with it is to save it in a pickle file once it is finished training so that you don't have to go through the stress of training the model again.</p>
<p>If you want to save a model as a pickle file, let me show you how you can do that. First import the pickle library and then type the code below. Let’s say I just want to fit a model like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pickle
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-keyword">from</span> sklearn.ensemble <span class="hljs-keyword">import</span> RandomForestClassifier
clf = RandomForestClassifier(random_state=<span class="hljs-number">42</span>)
clf.fit(X_train, y_train) 

# If you<span class="hljs-string">'ve fitted the model just type this to save it: Remember to change the file name
with open("filename.pkl", "wb") as f:
pickle.dump(clf, f)</span>
</code></pre>
<p>Now if you wish to load it you can type the following code as well:</p>
<pre><code class="lang-py"><span class="hljs-keyword">with</span> open(<span class="hljs-string">"filename.pkl"</span>, <span class="hljs-string">"rb"</span>) <span class="hljs-keyword">as</span> f:
    clf  = pickle.load(f)
</code></pre>
<p>Now that we’ve understood that, let’s create a function that we will be able to pass into Gradio so that it can make the predictions.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">make_prediction</span>(<span class="hljs-params">age, employment_status, bank_name, account_balance</span>):</span>
    <span class="hljs-keyword">with</span> open(<span class="hljs-string">"filename.pkl"</span>, <span class="hljs-string">"rb"</span>) <span class="hljs-keyword">as</span> f:
        clf  = pickle.load(f)
        preds = clf.predict([[age, employment_status, bank_name, account_balance]])
    <span class="hljs-keyword">if</span> preds == <span class="hljs-number">1</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-string">"You are eligible for the loan"</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"You are not eligible for the loan"</span>

<span class="hljs-comment">#Create the input component for Gradio since we are expecting 4 inputs</span>

age_input = gr.Number(label = <span class="hljs-string">"Enter the Age of the Individual"</span>)
employment_input = gr.Number(label= <span class="hljs-string">"Enter Employement Status {1:For Employed, 2: For Unemployed}"</span>)
bank_input = gr.Textbox(label = <span class="hljs-string">"Enter Bank Name"</span>)
account_input = gr.Number(label = <span class="hljs-string">"Enter your account Balance:"</span>)
<span class="hljs-comment"># We create the output</span>
output = gr.Textbox()


app = gr.Interface(fn = make_prediction, inputs=[age_input, employment_input, bank_input, account_input], outputs=output)
app.launch()
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/05/bank2.png" alt="alt_text" width="600" height="400" loading="lazy"></p>
<p>So let’s unwrap what we have above:</p>
<p>We'll start at the point where we created the input component. You can choose to create the component in the <code>gr.Interface</code>, but in the following code, I built it directly outside of the <code>gr.Interface</code> and then provided the variable into the <code>gr.Interface</code>.</p>
<p>So, if you want to make a component that receives numbers, use <code>gr.Number</code>, and then from the output variable I created, you can pass text as we did earlier in our first app (the " text" string is shorthand for textbox if you don't want to declare the attribute explicitly).</p>
<p>Also I used the label parameter in each component so that the user will know what to do. We are already familiar with the other code mentioned above. And now that we've done that our model is deployed. 🎉🎉😎🥳🥳.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Thank you for reading this tutorial. We covered a lot in this article. Just remember that learning Gradio does not stop here – you can check out more on their <a target="_blank" href="https://gradio.app/">website</a>. They have pretty intuitive documentation on how you can create your web app.</p>
<p>Thanks once again for reading. If you enjoyed this article, you can support me by following me on <a target="_blank" href="https://www.linkedin.com/in/ibrahimogunbiyi/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/Comejoinfolks">Twitter</a>. Gracias, and happy deployment😀</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Azure Static Web Apps to Deploy an Angular App ]]>
                </title>
                <description>
                    <![CDATA[ CI/CD has changed the way IT teams release new software versions.  In this tutorial I'll share my experience with Azure Static Web Apps – Azure's PaaS solution. I'll show you how you can take advantage of its flexibility to deploy an Angular App just... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-azure-static-web-apps-to-deploy-angular-app/</link>
                <guid isPermaLink="false">66bdff650b4523e3b8b99095</guid>
                
                    <category>
                        <![CDATA[ Angular ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Azure ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marco Venturi ]]>
                </dc:creator>
                <pubDate>Thu, 14 Apr 2022 23:42:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/cover_2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>CI/CD has changed the way IT teams release new software versions. </p>
<p>In this tutorial I'll share my experience with Azure Static Web Apps – Azure's PaaS solution. I'll show you how you can take advantage of its flexibility to deploy an Angular App just by pushing your code to a Git repository.</p>
<p>There’s a lot of literature about CI/CD on the web, and in this article, I want to focus on Azure Web Apps to show you how it can dramatically simplify your workflow. </p>
<p>If you want to know more about CI/CD, Atlassian’s <a target="_blank" href="https://www.atlassian.com/continuous-delivery/principles/continuous-integration-vs-delivery-vs-deployment">blog</a> has some good info. And here's a helpful in-depth and <a target="_blank" href="https://www.freecodecamp.org/news/how-to-setup-a-ci-cd-pipeline-with-github-actions-and-aws/">project-based guide on the subject</a>.</p>
<h2 id="heading-what-do-we-need-for-this-project">What do we need for this project?</h2>
<p>During this tutorial, we'll use the following technologies and tools:</p>
<ul>
<li>A GitHub account </li>
<li>Node.js (you can download it <a target="_blank" href="https://nodejs.org/en/download/">here</a>)</li>
<li>Npm (Node.js package manager. Included with Node installation.)</li>
<li>Angular CLI (a command-line interface tool to create, develop and maintain your Angular app. You can download it <a target="_blank" href="https://angular.io/cli">here</a>.)</li>
<li>Azure account (you can start for free by creating your account <a target="_blank" href="https://azure.microsoft.com/en-us/free/">here</a>. Once your free trial expires, have a look at the costs you are incurring. Cloud technologies are very powerful and can make your life easier. But they can be expansive if not well managed.)</li>
</ul>
<p>If you want to follow along with me during this article and replicate what I’m building, you need to be all set with these tools.</p>
<h2 id="heading-what-well-build-here-the-big-picture">What We'll Build Here – the Big Picture</h2>
<p>Let’s see how to create our Angular App and deploy it with Azure Web App. We'll create our Angular app locally and push it to a GitHub repository we specifically create for this project. </p>
<p>The repository will have two branches: “main” and “develop”. We'll create a static web app on Azure and connect it to the “main” branch of the repository. </p>
<p>Back to your machine, edit the code and push it to the “develop” branch. Then you merge the “develop” branch with the “main” one and see the new version of your app online.</p>
<p>Just to be clearer, I think a quick list will help us recap every single step:</p>
<ul>
<li>You'll create your Angular app locally with Angular CLI</li>
<li>You'll push it to a GitHub repository</li>
<li>You’ll create a static web app on Azure and connect it to the “main” branch of the project’s repository</li>
<li>You’ll create a “develop” repository</li>
<li>You’ll edit the app code locally and push it to the “develop” repository</li>
<li>You’ll create a pull request on your GitHub project from “develop” to “main” and merge it</li>
<li>You’ll check if the new app version is available on the web app</li>
</ul>
<h2 id="heading-step-1-create-the-angular-app-locally">Step 1 – Create the Angular App Locally</h2>
<p>First, let's create a specific directory on your computer and move into it. I’m on Mac, so I'll open my terminal and type:</p>
<pre><code>mkdir angular_azure
cd angular azure
</code></pre><p>Once there, create your new Angular app called “angular_app”:</p>
<pre><code>ng <span class="hljs-keyword">new</span> angular_app
</code></pre><p>Angular CLI asks you a few questions:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/0.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We want to add Angular router and we also want to use CSS for styling the app. Once you receive positive feedback from Angular CLI, start your app locally to see if everything is working fine:</p>
<pre><code>ng serve —-open
</code></pre><p>The option “--open” tells Angular CLI that you want to open the application with your default browser. This means that you don’t need to copy and paste the URL into your browser’s address bar. So, this is what you should see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Looks like everything is working fine. You can stop the application (Ctrl + C) and move to the next step</p>
<h2 id="heading-step-2-push-the-angular-app-to-your-github-repository">Step 2 – Push the Angular App to Your GitHub Repository</h2>
<p>You should have created a new repository on your GitHub account dedicated to this project. I called mine “angular-app-with-azure”. If you don’t know how to create a new repository, you can <a target="_blank" href="https://docs.github.com/en/get-started/quickstart/create-a-repo">read more about that here</a>.</p>
<p>Once the repository is ready, push your Angular app from your machine to your repository. If you don’t add a README file when creating your repo, you should see the instructions on how to push your code directly on your repository page. However, I'll repeat these instructions also here:</p>
<pre><code>git init
git add .
git commit -m <span class="hljs-string">"first commit"</span>
git branch -M main
git remote add origin https:<span class="hljs-comment">//github.com/&lt;REPO&gt;.git</span>
git push -u origin main
</code></pre><p>Once you run these commands successfully, you should see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/4-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let’s go ahead now.</p>
<h2 id="heading-step-3-time-to-switch-to-azure">Step 3 – Time to Switch to Azure</h2>
<p>Now you'll create a brand new Azure Static Web App and connect it to your repository. First of all, enter the Azure portal <a target="_blank" href="https://portal.azure.com">here</a>, and go to your Resource Group. Then you'll see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/5-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Hit “create” and you'll see the list of resources available on Azure. Filter resources by “Static Web App” and select it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/6.a.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then move to Azure’s wizard to create the resource. Let’s see how you should fill it out.</p>
<p>First of all, choose the subscription and resource group. Then go with the Static Web App details: choose the name – “angular-app” – and stick with the Free plan. Then select your region – mine is “Central US”.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/6-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then go ahead with a few more pieces of information:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/7-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can synch your GitHub account in the “Deployment Details” section, and then specify the Organization, Repository, and branch you'll get your codebase from. </p>
<p>As I said at the beginning of this tutorial, I choose the “main” branch as the production one. </p>
<p>Now let’s focus on the “Build Details”. You'll choose “Angular” as “Build Presets”, and specify that the App is located at the root directory on “App Location”. </p>
<p>Then you'll type the path of the output location (“dist” directory plus name-of-project directory. In my case, it's “dist/angular-app”. This is where Angular CLI locates the build of your project. I spent a lot of time looking for this info and I think it’s good to share it with you).</p>
<p>So, now you're ready to create your Static Web App. Hit “create” and see what happens. This is the overview of my app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/555-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, hit the “URL” link and this is what you should see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/33.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-ia"> </h2>
<p>Step 4 – Create a New Branch </p>
<p>So now you'll go back to your codebase locally and create your “develop” branch and check it out:</p>
<pre><code>git checkout -b develop
</code></pre><p>Then go to:</p>
<pre><code>src/app/app.component.html
</code></pre><p>Edit the code like this:</p>
<pre><code>&lt;p&gt;Pushed to develop&lt;/p&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">router-outlet</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-outlet</span>&gt;</span></span>
</code></pre><p>And then push the new branch to the remote repository:</p>
<pre><code>git push origin develop
</code></pre><h2 id="heading-step-5-time-to-merge">Step 5 – Time to Merge</h2>
<p>Your angular App is still online with the old version. You need to merge your "develop" branch to "main" to see the changes online.</p>
<p>Create a pull request on GitHub and merge it. This is what you should see at the end:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/999.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Wait a couple of minutes and then you'll see the new version of your app online:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/888-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-a-quick-recap-and-useful-resources">A Quick Recap and Useful Resources</h2>
<p>I hope this tutorial showed you how you can easily deploy your code to a production environment with CI/CD and Azure Static Web App. </p>
<p>While practicing with these technologies, I found a lot of interesting content on the web about them. I thought it would be good for you to have all of them in one place:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/what-is-git-learn-git-version-control/">What is Git? A beginner's guide to Git version control</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/practical-git-and-git-workflows/">How to use Git and Git Workflows – a practical guide</a></li>
<li><a target="_blank" href="https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions">GitHub Actions docs</a></li>
<li><a target="_blank" href="https://angular.io/">Angular docs</a></li>
<li><a target="_blank" href="https://github.com/mventuri/angular-app-with-azure">My repo on GitHub</a></li>
</ul>
<p>And don't forget... Keep learning, and keep coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Your First Web App in Julia with Genie.jl 🧞‍♂️ ]]>
                </title>
                <description>
                    <![CDATA[ By Logan Kilpatrick Julia is a high-level, dynamic, and open-source programming language. It's designed to be as easy to use as Python while remaining as performant as C or C++.  Many early use cases for Julia were in the scientific domains where mas... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-web-apps-in-julia/</link>
                <guid isPermaLink="false">66d460133bc3ab877dae220a</guid>
                
                    <category>
                        <![CDATA[ Julialang ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Julia ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 01 Feb 2022 21:33:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/01/Web-applications-in-Julia.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Logan Kilpatrick</p>
<p>Julia is a high-level, dynamic, and open-source programming language. It's designed to be as easy to use as Python while remaining as performant as C or C++. </p>
<p>Many early use cases for Julia were in the scientific domains where massive computational processing was and still is required. But as the language has continued to grow, more and more use cases are gaining steam (hint: web development). </p>
<p>If you are totally new to Julia and want to get a handle on the syntax before you dive into creating your first web application, <a target="_blank" href="https://www.freecodecamp.org/news/learn-julia-programming-language/">check out this article on freeCodeCamp</a>.</p>
<p>It goes over the basics, how to install Julia, steps to install packages, and much more! </p>
<p>We will focus this tutorial on all the necessary steps to build your first web application in Julia from the ground up. So let's begin by checking out the Genie website: <a target="_blank" href="https://genieframework.com">https://genieframework.com</a>.</p>
<h2 id="heading-what-is-geniejl">What is Genie.jl? 🧐</h2>
<p>Genie is a modern and highly productive web framework written in Julia. In the project's own words:</p>
<blockquote>
<p>Genie is a full-stack web framework that provides a streamlined and efficient workflow for developing modern web applications. It builds on Julia's strengths (high-level, high-performance, dynamic, JIT-compiled), exposing a rich API and a powerful toolset for productive web development.</p>
</blockquote>
<p>Genie is very similar to the <a target="_blank" href="https://www.djangoproject.com">Django Project</a> in that Genie is more than a single framework. Instead, it is an entire ecosystem with extensions and the like. </p>
<p>But why do we need Genie? The simple answer is that as Julia continues to grow in popularity, more and more developers are looking to leverage Julia across their entire stack. Genie provides the ability to deploy websites with Julia code running on the server-side so you can do things like deploy machine learning models as part of your Genie app.</p>
<p>Before we dive into getting started with Genie, you might want to check out a live deployed Genie app to get a sense of what is possible: <a target="_blank" href="https://pkgs.genieframework.com">https://pkgs.genieframework.com</a>. </p>
<p>This project is a community resource where you can query the number of package downloads during a certain time frame for a specific package. Type in "genie" to see the number of daily downloads.</p>
<p>You might also be interested in learning more about other GUI and web development frameworks in Julia. To learn more broadly about the ecosystem, <a target="_blank" href="https://towardsdatascience.com/6-julia-frameworks-to-create-desktop-guis-and-web-apps-9ae1a941f115">check out this article</a>.</p>
<h2 id="heading-how-to-install-genie">How to Install Genie ⤵️</h2>
<p>To get Genie installed, all we need to do is open the Julia REPL and type <code>] add Genie</code> . This will take care of everything you need. If everything works, you should be able to do:</p>
<pre><code class="lang-julia">julia&gt; <span class="hljs-keyword">using</span> Genie
</code></pre>
<p>without any issues. You are now all set to begin trying out Genie.</p>
<h2 id="heading-how-to-map-urls-to-julia-functions">How to Map URLs to Julia Functions 🗺</h2>
<p>A core part of the Genie framework is the idea of a router. Routers take the user action of visiting a specific URL and associate it with a Julia function being called.</p>
<p>Let's look at a simple example of this. In the REPL, type the following:</p>
<pre><code class="lang-julia">julia&gt; <span class="hljs-keyword">using</span> Genie, Genie.Router

julia&gt; route(<span class="hljs-string">"/hello"</span>) <span class="hljs-keyword">do</span>
           <span class="hljs-string">"Hello freeCodeCamp"</span>
       <span class="hljs-keyword">end</span>
[GET] /hello =&gt; <span class="hljs-comment">#5 | :get_hello</span>
</code></pre>
<p>In this example, we defined the "/hello" URL to return the text "Hello freeCodeCamp". We can verify that this works by starting the server:</p>
<pre><code class="lang-julia">julia&gt; up() <span class="hljs-comment"># start server</span>
┌ Info: 
└ Web Server starting at http://<span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>:<span class="hljs-number">8000</span> 
Genie.AppServer.ServersCollection(<span class="hljs-built_in">Task</span> (runnable) @<span class="hljs-number">0x000000011c5c5bb0</span>, <span class="hljs-literal">nothing</span>)
</code></pre>
<p>Now that the server is up and running, we can visit <a target="_blank" href="http://127.0.0.1:8000"><code>http://127.0.0.1:8000</code></a> in our browser. You will notice we get a 404 page, which is expected since the only route we defined was "/hello". So let's add that to the URL and see what we get:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screen-Shot-2022-01-29-at-8.25.53-AM.png" alt="Browser window showing nothing but the text &quot;Hello freeCodeCamp&quot;" width="600" height="400" loading="lazy"></p>
<p>And there we go! Our first step towards building a fully functional web application is complete. We can also confirm that the page is loading correctly by checking the REPL which shows this:</p>
<pre><code class="lang-julia">julia&gt; ┌ Error: GET / <span class="hljs-number">404</span>
└ @ Genie.Router ~/.julia/packages/Genie/UxbVJ/src/Router.jl:<span class="hljs-number">163</span>
┌ Error: GET /favicon.ico <span class="hljs-number">404</span>
└ @ Genie.Router ~/.julia/packages/Genie/UxbVJ/src/Router.jl:<span class="hljs-number">163</span>
[ Info: GET /hello <span class="hljs-number">200</span>
</code></pre>
<p>We see the first attempt where the result was a 404 and on the 2nd attempt where we successfully got the response (the 200 message means everything is okay).</p>
<p>Now that we have a basic example working, let's now try and build on this with some more depth. </p>
<p>To do this, we will create a new file. I will be using VS Code but you are welcome to use any IDE you find useful. Before we look at the next piece of code, we need to make sure we shut down the server by typing <code>down()</code> into the REPL. </p>
<p>Okay, onto the next example:</p>
<pre><code class="lang-julia"><span class="hljs-keyword">using</span> Genie, Genie.Router
<span class="hljs-keyword">using</span> Genie.Renderer, Genie.Renderer.Html, Genie.Renderer.Json

route(<span class="hljs-string">"/"</span>) <span class="hljs-keyword">do</span>
    html(<span class="hljs-string">"Hey freeCodeCamp"</span>)
<span class="hljs-keyword">end</span>

route(<span class="hljs-string">"/hello.html"</span>) <span class="hljs-keyword">do</span>
  html(<span class="hljs-string">"Hello freeCodeCamp (in html)"</span>)
<span class="hljs-keyword">end</span>

route(<span class="hljs-string">"/hello.json"</span>) <span class="hljs-keyword">do</span>
  json(<span class="hljs-string">"Hi freeCodeCamp (in json)"</span>)
<span class="hljs-keyword">end</span>

route(<span class="hljs-string">"/hello.txt"</span>) <span class="hljs-keyword">do</span>
   respond(<span class="hljs-string">"Hiya freeCodeCamp (in txt format)"</span>, :text)
<span class="hljs-keyword">end</span>

<span class="hljs-comment"># Launch the server on a specific port, 8002</span>
<span class="hljs-comment"># Run the task asynchronously</span>
up(<span class="hljs-number">8002</span>, async = <span class="hljs-literal">true</span>)
</code></pre>
<p>A lot is going on in this example, so let's walk through what is taking place. </p>
<p>We start by loading in the packages we want. Then, we define 4 different routes. The first one is the index route. So when the user visits <a target="_blank" href="http://127.0.0.1:8002"><code>http://127.0.0.1:8002</code></a> they will see "Hey freeCodeCamp". The routes after the index highlight that each route can give a custom output. In some cases, it can be HTML, in others, it could be JSON or plain text. </p>
<p>The last line of this example showcases the server launching code. As the comment states, we can set the specific port number and choose if we want the routes to run asynchronously or not. We have now successfully created our first <a target="_blank" href="https://genieframework.com/docs/tutorials/Getting-Started.html#developingasimplegeniescript">Genie Script</a>! </p>
<h2 id="heading-how-to-create-a-basic-web-service">How to Create a Basic Web Service 🕸</h2>
<p>Now that we have gotten our hands dirty with the basics, we will now begin to get closer to building a fully-fledged web application. </p>
<p>Before we go all the way there, we are going to take the first step which is creating a basic web service. To do so, we will go into the REPL and switch our current directory to one which is easily accessible. I will use my desktop in this tutorial:</p>
<pre><code class="lang-julia">shell&gt; cd Desktop
/Users/logankilpatrick/Desktop
</code></pre>
<p>To enter shell mode which is shown above, simply type a ";" into the REPL. Now that we have our active directory set to the desktop in my case, we will use the handy generator function to create the service:</p>
<pre><code class="lang-julia">julia&gt; Genie.newapp_webservice(<span class="hljs-string">"freeCodeCampApp"</span>)

[ Info: Done! New app created at /Users/logankilpatrick/Desktop/freeCodeCampApp
[ Info: Changing active directory to /Users/logankilpatrick/Desktop/freeCodeCampApp
    /var/folders/tc/<span class="hljs-number">519</span>vfm453fj_x5bmd8pwx9480000gn/T/jl_bO1R8h/FreeCodeCampApp/Project.toml
[ Info: Project.toml has been generated
[ Info: Installing app dependencies
...
</code></pre>
<p>The <code>newapp_webservice</code> is a very helpful function that automatically creates all the pieces we need for our first web service. Now that we have a project created, we need to open it up in an IDE (in my case, VS Code). You should see the following if you open up the correct folder:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screen-Shot-2022-01-30-at-7.39.23-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>There are a lot of files created for us automatically. The main one we will look at is <code>routes.jl</code> which is used to create routes as we did in the section above. </p>
<p>The function we called to generate these folders automatically starts the server, so let's take a quick look at the existing landing page by visiting <a target="_blank" href="http://127.0.0.1:8000">http://127.0.0.1:8000</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screen-Shot-2022-01-30-at-7.51.16-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you might notice, my page looks a little different than yours might because I went in and edited the <code>welcome.html</code> page found in the public folder. </p>
<p>As you can see in <code>routes.jl</code>, when the user visits the main URL <code>/</code>, we route them to the welcome page. We can add in additional routes as we did in the section above and expand this. You are welcome to pause here and play around. We already have a pretty robust website setup.</p>
<p>If you take a peek into some of the other folders like <code>config/env</code>, you will see details around setting the port, host URL, and other relevant parameters. Again, feel free to play around there but we will not go into all the detail of those files in this tutorial. </p>
<p>Before we dive into the next topic, let's take a look at a few more of the files generated for our basic web service:</p>
<ul>
<li>The public folder has all of the front end files (HTML and CSS)</li>
<li>The <code>src</code> folder has the entry point to the web service (in my case <code>freeCodeCampApp.jl</code>)</li>
<li>bin contains some additional dependencies we will again ignore</li>
<li>Manifest.toml and Project.toml are the key Julia files that allow us to maintain our Julia dependencies. When you created the web service, the script automatically activated your current project environment (which is the app we just created). You can verify this by typing "]" into the REPL which will show the active space in blue:</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screen-Shot-2022-01-30-at-7.59.49-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This just means that if we try to add a package, it will add it to the project and manifest file specifically for this project, instead of the globally shared one.</p>
<h2 id="heading-how-to-create-a-fully-functioning-web-app-with-a-database">How to Create a Fully Functioning Web App With a Database 💽</h2>
<p>Now that we have explored the basics, we are going to dive into a full-on web app. Again, Genie provides some nice functions to get us started. Before we create it, we will need to navigate back to the desktop:</p>
<pre><code class="lang-julia">shell&gt; pwd
/Users/logankilpatrick/Desktop/freeCodeCampApp

shell&gt; cd ..
/Users/logankilpatrick/Desktop

shell&gt;
</code></pre>
<p>Remember, you can type <code>;</code> to enter the shell mode and backspace to exit the shell mode. Now, let's create the app:</p>
<pre><code class="lang-julia">julia&gt; Genie.newapp_mvc(Genie.newapp_mvc(<span class="hljs-string">"freeCodeCampMVC"</span>))
   Resolving package versions...
   ...
</code></pre>
<p>You will be prompted to choose a database backend. For this example, we will use SQLite:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/Screen-Shot-2022-01-30-at-8.08.31-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you want to use a different database backend, feel free to do so as well. But note that you will need to create the database file automatically. Genie only creates an SQLite file for you. </p>
<p>We now have a MVC app created. But you might be asking yourself, what is an MVC? </p>
<p>The Model-View-Controller paradigm is very common across application development. In the interest of not getting into the weeds on it, I will <a target="_blank" href="https://www.freecodecamp.org/news/mvc-architecture-what-is-a-model-view-controller-framework/">refer you to this post</a> where you can read about the details. From our perspective as developers, there is not much impact. </p>
<p>Just like we did when we created the last project, we need to open it in the IDE again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/Screen-Shot-2022-02-01-at-6.44.21-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Again, we will see much of the same stuff as before with the new addition of the <code>app</code> folder which will contain a lot of critical code. We can see what the new project looks like by typing:</p>
<pre><code class="lang-julia">julia&gt; loadapp()

julia&gt; up()
</code></pre>
<p>and then navigating too: <a target="_blank" href="http://127.0.0.1:8000">http://127.0.0.1:8000</a>.</p>
<p>Next up, we will need to connect our database to the web app we created. To do this, head to <code>db/connection.yml</code> and edit the following section:</p>
<pre><code class="lang-yml"><span class="hljs-attr">env:</span> <span class="hljs-string">ENV["GENIE_ENV"]</span>

<span class="hljs-attr">dev:</span>
  <span class="hljs-attr">adapter:</span> <span class="hljs-string">SQLite</span>
  <span class="hljs-attr">database:</span> <span class="hljs-string">db/freeCodeCamp_courses.sqlite</span>
</code></pre>
<p>You can leave the rest of the fields blank for now. Then, we need to run:</p>
<pre><code class="lang-julia">julia&gt; include(joinpath(<span class="hljs-string">"config"</span>, <span class="hljs-string">"initializers"</span>, <span class="hljs-string">"searchlight.jl"</span>))
</code></pre>
<p>which will load the database configuration. Next up, we will continue to configure the database such that we can save data from our app into persistent storage.</p>
<p>We begin this process by creating a new resource:</p>
<pre><code class="lang-julia">julia&gt; Genie.newresource(<span class="hljs-string">"course"</span>)
</code></pre>
<p>Once we have defined a resource, the next step is to go and edit the database migrations table which can be found at <code>db/migrations/2022020115190055_create_table_courses.jl</code> in my case. </p>
<p>By default, the table is already populated with some placeholder text based on the last few commands we ran. It should look something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/Screen-Shot-2022-02-01-at-7.22.35-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We will edit the file to match the specific scheme we want. This will be entirely dependent on the application itself. Since I am making courses on this site, I will enter all of the course details as follows:</p>
<pre><code class="lang-julia"><span class="hljs-keyword">module</span> CreateTableCourses

<span class="hljs-keyword">import</span> SearchLight.Migrations: create_table, column, columns, pk, add_index, drop_table, add_indices

<span class="hljs-keyword">function</span> up()
  create_table(:courses) <span class="hljs-keyword">do</span>
    [
      pk()
      column(:title, :string, limit = <span class="hljs-number">200</span>)
      column(:authors, :string, limit = <span class="hljs-number">250</span>)
      column(:year, :integer, limit = <span class="hljs-number">4</span>)
      column(:rating, :string, limit = <span class="hljs-number">10</span>)
      column(:categories, :string, limit = <span class="hljs-number">100</span>)
      column(:description, :string, limit = <span class="hljs-number">1_000</span>)
      column(:cost, :float, limit = <span class="hljs-number">1000</span>)
    ]
  <span class="hljs-keyword">end</span>

  add_index(:courses, :title)
  add_index(:courses, :authors)
  add_index(:courses, :categories)
  add_index(:courses, :description)

<span class="hljs-keyword">end</span>

<span class="hljs-keyword">function</span> down()
  drop_table(:courses)
<span class="hljs-keyword">end</span>

<span class="hljs-keyword">end</span>
</code></pre>
<p>Again, these are arbitrary and can be whatever you want them to be. </p>
<p>It is worth noting that adding the index is optional. The reason you would add it is that it speeds up the queries, but there are other tradeoffs and you can't actually load all the columns as indexes. You can read more about some of these tradeoffs <a target="_blank" href="https://stackoverflow.com/questions/5447987/why-cant-i-simply-add-an-index-that-includes-all-columns/5448055#5448055">here</a> and <a target="_blank" href="https://stackoverflow.com/questions/107132/what-columns-generally-make-good-indexes">here</a>.</p>
<p>Now that we have the database table updated, we need to propagate these updates. To do so, we will use <code>SearchLight.jl</code> which functions as our app's migration system:</p>
<pre><code class="lang-julia">julia&gt; <span class="hljs-keyword">using</span> SearchLight

julia&gt; SearchLight.Migration.create_migrations_table()
┌ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">11</span> CREATE TABLE <span class="hljs-string">`schema_migrations`</span> (
│       <span class="hljs-string">`version`</span> varchar(<span class="hljs-number">30</span>) NOT NULL DEFAULT '',
│       PRIMARY KEY (<span class="hljs-string">`version`</span>)
└     )
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">11</span> Created table schema_migrations

julia&gt; SearchLight.Migration.status()
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">20</span> SELECT version FROM schema_migrations ORDER BY version DESC
|   | <span class="hljs-built_in">Module</span> name &amp; status                     |
|   | File name                                |
|---|------------------------------------------|
|   |                 CreateTableCourses: DOWN |
| <span class="hljs-number">1</span> | <span class="hljs-number">2022020115190055_</span>create_table_courses.jl |

julia&gt; SearchLight.Migration.last_up()
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">29</span> SELECT version FROM schema_migrations ORDER BY version DESC
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">29</span> CREATE TABLE courses (id INTEGER PRIMARY KEY , title TEXT  , authors TEXT  , year INTEGER (<span class="hljs-number">4</span>) , rating TEXT  , categories TEXT  , description TEXT  , cost FLOAT (<span class="hljs-number">1000</span>) )
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">29</span> CREATE  INDEX courses__idx_title ON courses (title)
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">29</span> CREATE  INDEX courses__idx_authors ON courses (authors)
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">29</span> CREATE  INDEX courses__idx_categories ON courses (categories)
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">29</span> CREATE  INDEX courses__idx_description ON courses (description)
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">29</span> INSERT INTO schema_migrations VALUES ('<span class="hljs-number">2022020115190055</span>')
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">37</span>:<span class="hljs-number">29</span> Executed migration CreateTableCourses up
</code></pre>
<p>We have now successfully completed the migrations. If you were to make a change to the schema, you would need to re-run the commands above for those database changes to take effect. </p>
<p>The last step in this process is to define our model. This will allow us to create objects in Julia code and then save them to the database we just defined. We need to navigate to <code>app/resources/courses/Courses.jl</code> or the equivalent path to make these final updates: </p>
<pre><code class="lang-julia"><span class="hljs-keyword">module</span> Courses

<span class="hljs-keyword">import</span> SearchLight: AbstractModel, DbId
<span class="hljs-keyword">import</span> Base: <span class="hljs-meta">@kwdef</span>

<span class="hljs-keyword">export</span> Course

<span class="hljs-meta">@kwdef</span> <span class="hljs-keyword">mutable struct</span> Course &lt;: AbstractModel
  id::DbId = DbId()
  title::<span class="hljs-built_in">String</span> = <span class="hljs-string">""</span>
  authors::<span class="hljs-built_in">String</span> = <span class="hljs-string">""</span>
  year::<span class="hljs-built_in">Int</span> = <span class="hljs-number">0</span>
  rating::<span class="hljs-built_in">String</span> = <span class="hljs-string">""</span>
  categories::<span class="hljs-built_in">String</span> = <span class="hljs-string">""</span>
  description::<span class="hljs-built_in">String</span> = <span class="hljs-string">""</span>
  cost::<span class="hljs-built_in">Float64</span> = <span class="hljs-number">0.0</span>
<span class="hljs-keyword">end</span>

<span class="hljs-keyword">end</span>
</code></pre>
<p>Again, this should be the same as the content you previously defined. To make sure this worked, we can do:</p>
<pre><code class="lang-julia">julia&gt; <span class="hljs-keyword">using</span> Courses
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">43</span>:<span class="hljs-number">51</span> Precompiling Courses [top-level]
</code></pre>
<p>and then try creating a course via:</p>
<pre><code class="lang-julia">
julia&gt; c = Course(title = <span class="hljs-string">"Web dev with Genie.jl"</span>, authors=<span class="hljs-string">"Logan Kilpatrick"</span>)
Course
| KEY                 | VALUE                 |
|---------------------|-----------------------|
| authors::<span class="hljs-built_in">String</span>     | Logan Kilpatrick      |
| categories::<span class="hljs-built_in">String</span>  |                       |
| cost::<span class="hljs-built_in">Float64</span>       | <span class="hljs-number">0.0</span>                   |
| description::<span class="hljs-built_in">String</span> |                       |
| id::DbId            | NULL                  |
| rating::<span class="hljs-built_in">String</span>      |                       |
| title::<span class="hljs-built_in">String</span>       | Web dev with Genie.jl |
| year::<span class="hljs-built_in">Int64</span>         | <span class="hljs-number">0</span>                     |
</code></pre>
<p>We have successfully created our first object! But it is not saved to the database right away. We can verify this by doing:</p>
<pre><code class="lang-julia">julia&gt; ispersisted(c)
<span class="hljs-literal">false</span>
</code></pre>
<p>so we need to run:</p>
<pre><code class="lang-julia">julia&gt; save(c)
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">47</span>:<span class="hljs-number">04</span> INSERT  INTO courses (<span class="hljs-string">"title"</span>, <span class="hljs-string">"authors"</span>, <span class="hljs-string">"year"</span>, <span class="hljs-string">"rating"</span>, <span class="hljs-string">"categories"</span>, <span class="hljs-string">"description"</span>, <span class="hljs-string">"cost"</span>) VALUES ('Web dev with Genie.jl', 'Logan Kilpatrick', <span class="hljs-number">0</span>, '', '', '', <span class="hljs-number">0.0</span>) 
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">07</span>:<span class="hljs-number">47</span>:<span class="hljs-number">04</span> ; SELECT CASE WHEN last_insert_rowid() = <span class="hljs-number">0</span> THEN -<span class="hljs-number">1</span> ELSE last_insert_rowid() END AS LAST_INSERT_ID
<span class="hljs-literal">true</span>
</code></pre>
<p>and now the course is saved! But to really test this out, we need the user to be able to create a course. Let's head back to <code>routes.jl</code> and enable that:</p>
<pre><code class="lang-julia"><span class="hljs-keyword">using</span> Genie, Genie.Router, Genie.Renderer.Html, Genie.Requests
<span class="hljs-keyword">using</span> Courses

form = <span class="hljs-string">"""
&lt;form action="/" method="POST" enctype="multipart/form-data"&gt;
  &lt;input type="text" name="name" value="" placeholder="What's the course name?" /&gt;
  &lt;input type="text" name="author" value="" placeholder="Who is the course author?" /&gt;

  &lt;input type="submit" value="Submit" /&gt;
&lt;/form&gt;
"""</span>

route(<span class="hljs-string">"/"</span>) <span class="hljs-keyword">do</span>
  html(form)
<span class="hljs-keyword">end</span>

route(<span class="hljs-string">"/"</span>, method = POST) <span class="hljs-keyword">do</span>
  c = Course(title=postpayload(:name, <span class="hljs-string">"Placeholder"</span>), authors=postpayload(:author, <span class="hljs-string">"Placeholder"</span>))
  save(c)
  <span class="hljs-string">"Course titled <span class="hljs-subst">$(c.title)</span> created successfully!"</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>We started by defining a simple HTML form (nothing new or exciting here), then, we made it so the default route <code>/</code> renders the HTML form. Lastly, we create another route for the <code>/</code> URL, but specifically for the POST method. Inside that route, we create a new course by pulling the info we want from the form out of the payload via <code>postpayload</code>. </p>
<p>You can try this by navigating back to: <a target="_blank" href="http://127.0.0.1:8000">http://127.0.0.1:8000</a></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/02/Screen-Shot-2022-02-01-at-8.11.38-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can try and enter some of the details and then press submit. To make sure the submissions worked, you can do:</p>
<pre><code class="lang-julia">julia&gt; all(Course)
[ Info: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">08</span>:<span class="hljs-number">10</span>:<span class="hljs-number">19</span> SELECT <span class="hljs-string">"courses"</span>.<span class="hljs-string">"id"</span> AS <span class="hljs-string">"courses_id"</span>, <span class="hljs-string">"courses"</span>.<span class="hljs-string">"title"</span> AS <span class="hljs-string">"courses_title"</span>, <span class="hljs-string">"courses"</span>.<span class="hljs-string">"authors"</span> AS <span class="hljs-string">"courses_authors"</span>, <span class="hljs-string">"courses"</span>.<span class="hljs-string">"year"</span> AS <span class="hljs-string">"courses_year"</span>, <span class="hljs-string">"courses"</span>.<span class="hljs-string">"rating"</span> AS <span class="hljs-string">"courses_rating"</span>, <span class="hljs-string">"courses"</span>.<span class="hljs-string">"categories"</span> AS <span class="hljs-string">"courses_categories"</span>, <span class="hljs-string">"courses"</span>.<span class="hljs-string">"description"</span> AS <span class="hljs-string">"courses_description"</span>, <span class="hljs-string">"courses"</span>.<span class="hljs-string">"cost"</span> AS <span class="hljs-string">"courses_cost"</span> FROM <span class="hljs-string">"courses"</span> ORDER BY courses.id ASC
┌ Warning: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">08</span>:<span class="hljs-number">10</span>:<span class="hljs-number">19</span> Unsupported SQLite declared <span class="hljs-keyword">type</span> INTEGER (<span class="hljs-number">4</span>), falling back to <span class="hljs-built_in">Int64</span> <span class="hljs-keyword">type</span>
└ @ SQLite ~/.julia/packages/SQLite/aDggE/src/SQLite.jl:<span class="hljs-number">416</span>
┌ Warning: <span class="hljs-number">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">01</span> <span class="hljs-number">08</span>:<span class="hljs-number">10</span>:<span class="hljs-number">19</span> Unsupported SQLite declared <span class="hljs-keyword">type</span> FLOAT (<span class="hljs-number">1000</span>), falling back to <span class="hljs-built_in">Float64</span> <span class="hljs-keyword">type</span>
└ @ SQLite ~/.julia/packages/SQLite/aDggE/src/SQLite.jl:<span class="hljs-number">416</span>
<span class="hljs-number">3</span>-element <span class="hljs-built_in">Vector</span>{Course}:
 Course
| KEY                 | VALUE                 |
|---------------------|-----------------------|
| authors::<span class="hljs-built_in">String</span>     | Logan Kilpatrick      |
| categories::<span class="hljs-built_in">String</span>  |                       |
| cost::<span class="hljs-built_in">Float64</span>       | <span class="hljs-number">0.0</span>                   |
| description::<span class="hljs-built_in">String</span> |                       |
| id::DbId            | <span class="hljs-number">1</span>                     |
| rating::<span class="hljs-built_in">String</span>      |                       |
| title::<span class="hljs-built_in">String</span>       | Web dev with Genie.jl |
| year::<span class="hljs-built_in">Int64</span>         | <span class="hljs-number">0</span>                     |

 Course
| KEY                 | VALUE       |
|---------------------|-------------|
| authors::<span class="hljs-built_in">String</span>     | Logan K     |
| categories::<span class="hljs-built_in">String</span>  |             |
| cost::<span class="hljs-built_in">Float64</span>       | <span class="hljs-number">0.0</span>         |
| description::<span class="hljs-built_in">String</span> |             |
| id::DbId            | <span class="hljs-number">2</span>           |
| rating::<span class="hljs-built_in">String</span>      |             |
| title::<span class="hljs-built_in">String</span>       | Test course |
| year::<span class="hljs-built_in">Int64</span>         | <span class="hljs-number">0</span>           |
</code></pre>
<p>which should show that the entries were saved in the database.</p>
<h2 id="heading-wrapping-up">Wrapping up 🎁</h2>
<p>Wow, that was a lot. We covered a tremendous amount of ground in this single tutorial. </p>
<p>With that said, there is even more to learn about Genie. I highly suggest checking out the <a target="_blank" href="https://genieframework.com/docs/tutorials/Overview.html">docs here</a>, which has lots more tutorials on topics like REST API's, Authentication, and much more. </p>
<h2 id="heading-getting-help-with-geniejl">Getting help with Genie.jl 🚨</h2>
<p>If you run into issues with this tutorial or when using Genie, please post a question on Stack Overflow with the <code>genie.jl</code> and <code>julia</code> tag or on the <a target="_blank" href="https://discourse.julialang.org">Julia Discourse</a>. After that, feel free to tweet the link to the question at me and I will do my best to help: <a target="_blank" href="https://twitter.com/OfficialLoganK">https://twitter.com/OfficialLoganK</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What Items Should Be Configurable in an Application? ]]>
                </title>
                <description>
                    <![CDATA[ By Kenneth Angelo Reyes Configuration is an essential part of every application. It helps enhance an application's flexibility and maintainability.  With this in mind, it's very important that developers are able to correctly identify what items shou... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-should-be-configurable-in-apps/</link>
                <guid isPermaLink="false">66d460c7787a2a3b05af43f2</guid>
                
                    <category>
                        <![CDATA[ configuring settings ]]>
                    </category>
                
                    <category>
                        <![CDATA[ configuration ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 27 Oct 2021 20:30:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/10/sigmund-f0dJjQMhfXo-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Kenneth Angelo Reyes</p>
<p>Configuration is an essential part of every application. It helps enhance an application's flexibility and maintainability. </p>
<p>With this in mind, it's very important that developers are able to correctly identify what items should be in configuration.</p>
<p>In this article, I'll walk you through 8 items that should be configurable in your applications.</p>
<h2 id="heading-define-configuration">Define "Configuration"</h2>
<p>We will not be aligning with any existing platforms out there.</p>
<p>For the context of this article, an application configuration has the following characteristics:</p>
<ul>
<li>A set of simple or complex values that can affect an application's behavior</li>
<li>Values can easily be changed without requiring any code deployment</li>
</ul>
<p>With that out of the way, let's go to our list!</p>
<h2 id="heading-the-configurables">The "Configurables"</h2>
<p>Here are the 8 items that should be configurable in your applications.</p>
<h3 id="heading-magic-numbers">Magic Numbers</h3>
<p>These are special numbers that are used in certain displays, validations, or business rules.</p>
<p><strong>Examples:</strong></p>
<ul>
<li>Number of days before an SLA (Service Level Agreement) is breached</li>
<li>Number of decimal places when rendering a currency</li>
</ul>
<h3 id="heading-urls">URLs</h3>
<p>When connecting to 3rd-party services, there's no knowing when their URLs will change. It's best to keep these values configurable. Additionally, configurable URLs can help you control the value in different environments.</p>
<p><strong>Examples:</strong></p>
<ul>
<li>API Endpoints</li>
<li>External websites</li>
</ul>
<h3 id="heading-feature-toggle">Feature Toggle</h3>
<p>This is helpful when there is a feature that's already in production, but which can only be enabled after a certain time.</p>
<p>An example of this is a feature that can only be enabled after a live stream event. Normally, this can be a Boolean value, but you can also use Date Time for this. This just means that the feature will automatically be enabled once that time has passed.</p>
<h3 id="heading-regex-patterns">Regex Patterns</h3>
<p>Some Regex patterns, especially those used in validation, have the potential to change regularly.</p>
<p>An example of this is phone number validation. Initially, your application might allow phone numbers from several countries. Then, perhaps a change in requirements came about where you now have to allow only phone numbers from specific countries. </p>
<p>If your validation pattern is in configuration, then you can quickly make this change.</p>
<h3 id="heading-special-dates">Special Dates</h3>
<p>Not the romantic ones! In some applications, there's a need to "block" certain dates from being selected by users.</p>
<p>A perfect example of this are public holidays. Since these dates can change regularly, they should be placed in configuration.</p>
<h3 id="heading-connection-strings">Connection Strings</h3>
<p>Database connection strings should never be placed in your code! When you place connection strings in configuration, you'll also be able to set a different value per environment.</p>
<h3 id="heading-formulas">Formulas</h3>
<p>For finance-related applications, making formulas configurable is very important. For these type of applications, adapting to policy or regulatory changes as soon as possible is a must.</p>
<h3 id="heading-special-messages">Special Messages</h3>
<p>This may be more applicable to non-CMS applications. In some cases, the regular changes in text messages are tied to legal or regulatory policies. Therefore, these messages should be easy to update.</p>
<p>A good example of this is an announcement that shows whether the application is currently facing any issues or is under maintenance.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>These are the 8 items that I believe should be configurable in every application. I'm sure you have other items on your mind. Let me know! Looking forward to hearing from you.</p>
<p>Glad you reached the end of this article. I hope you learned something new from me today.</p>
<p>_<a target="_blank" href="https://unsplash.com/photos/f0dJjQMhfXo">Cover photo</a> <a target="_blank" href="https://unsplash.com/@sigmund?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">f</a>rom <a target="_blank" href="https://unsplash.com/s/photos/settings?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>_</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ MVC Architecture – What is a Model View Controller Framework? ]]>
                </title>
                <description>
                    <![CDATA[ Model–View–Controller is a popular software pattern used to break up the logic of your application into three different components.  In this article, I will break down the three components behind the MVC pattern, provide some history, and show you ho... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/mvc-architecture-what-is-a-model-view-controller-framework/</link>
                <guid isPermaLink="false">66b8da16ce55d3ba4d93599b</guid>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jessica Wilkins ]]>
                </dc:creator>
                <pubDate>Fri, 24 Sep 2021 17:36:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/radowan-nakif-rehan-cYyqhdbJ9TI-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Model–View–Controller is a popular software pattern used to break up the logic of your application into three different components. </p>
<p>In this article, I will break down the three components behind the MVC pattern, provide some history, and show you how it can be used in an application.</p>
<h2 id="heading-history-of-the-modelviewcontroller-pattern">History of the Model–View–Controller Pattern</h2>
<p>The MVC pattern was first introduced in 1979 by computer scientist Trygve Mikkjel Heyerdahl Reenskaug. He wanted to come up with a solution on how to break up a complex user application into smaller manageable components. </p>
<p>The MVC pattern was first used in the programming language Small Talk. One of the original names for the pattern was going to be Model-View-Editor but it was changed to Model-View-Controller.</p>
<p>Throughout the 1980's and early 90's, the MVC pattern was primarily used in desktop applications. But by the late 1990's, it became pretty popular within web applications. </p>
<p>In today's web applications, the MVC pattern is a popular design choice for organizing your code. </p>
<p>Here is a list of a few popular web frameworks that use the MVC pattern.</p>
<ul>
<li>Ruby on Rails</li>
<li>ASP.NET MVC</li>
<li>Laravel</li>
<li>Angular</li>
</ul>
<h2 id="heading-what-are-the-three-components-behind-the-modelviewcontroller">What are the three components behind the Model–View–Controller?</h2>
<p>This is a basic breakdown of the MVC pattern:</p>
<ul>
<li><strong>Model</strong> – This is responsible for the data logic behind the application</li>
<li><strong>View</strong> – This is what the user sees and interacts with in the application</li>
<li><strong>Controller</strong> – This acts as the brains behind the application and communicates with the Model and View. </li>
</ul>
<h2 id="heading-how-does-the-mvc-pattern-work-in-a-web-application">How does the MVC pattern work in a web application?</h2>
<p>To better understand how the MVC pattern works, it would be best to show you in a <a target="_blank" href="https://mvc-demo-app.netlify.app/">demo application</a>. </p>
<p>This MERN (MongoDB, Express, React, Node) stack application greets a fictional office manager and shows them a table of recently hired high school coaches. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-2.49.20-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>It also shows which coaches have not completed their TB tests, Covid vaccines, new coach application, and background checks. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-2.49.54-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The office manager can send reminder emails to those coaches who are missing their documents. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-2.51.04-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-model-component">The Model Component</h3>
<p>The Model is responsible for the data logic of our application. I am using MongoDB for the database of coaches. </p>
<p>I first had to define the properties that will be applied to each coach in the database. Each coach will have a <code>name</code>, <code>email</code>, <code>program</code>, <code>application</code>, <code>backgroundCheck</code>, <code>tbTest</code> and <code>covidTest</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> coachSchema = <span class="hljs-keyword">new</span> Schema({
    <span class="hljs-attr">name</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,
        <span class="hljs-attr">trim</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">maxLength</span>: <span class="hljs-number">32</span>,
        <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-attr">email</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,
        <span class="hljs-attr">trim</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">maxLength</span>: <span class="hljs-number">32</span>,
        <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-attr">program</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,
        <span class="hljs-attr">trim</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">maxLength</span>: <span class="hljs-number">32</span>,
        <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-attr">application</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>,
        <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-attr">backgroundCheck</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>,
        <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-attr">tbTest</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>,
        <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-attr">covidTest</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>,
        <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>
    }
}, { <span class="hljs-attr">timestamps</span>: <span class="hljs-literal">true</span> })
</code></pre>
<p><code>type:Boolean</code> represents a true or false value for the <code>application</code>, <code>backgroundCheck</code>, <code>tbTest</code> and <code>covidTest</code> properties.</p>
<p>If the coach has any of those four properties marked as false, then that means they haven't completed that part of the application process. </p>
<p>I created seven entries for our coach database and that information is being stored in MongoDB Atlas. </p>
<p>Here is an example of one of the database entries.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-3.26.02-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The Controller component is going to communicate with the database and get the necessary information to send to the View component. </p>
<h3 id="heading-the-view-component">The View Component</h3>
<p>The View component is responsible for all of the visual aspects of the application. I used React to display this data to the user. </p>
<p>When the application first loads, you see a welcome message displayed on the screen. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-2.48.25-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>When you click on the View Dashboard button, it takes you to the coaches table and missing documents list. </p>
<p>The View is not communicating directly with the database because our Controller is doing that. The Controller provides that information to the View so it can be displayed on the page.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-2.49.20-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is what the code looks like when the View makes a fetch call to get the data from the Controller:</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://mvc-project-backend.herokuapp.com/coaches'</span>)
</code></pre>
<p>We then use the <code>map()</code> method to go through each coach and display their name, email address, and program in the table.</p>
<pre><code>    coachData.map(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> (
                        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">tr</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{data._id}</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{data.name}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{data.email}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{data.program}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span></span>
                      ))
</code></pre><p>For the missing documents section, we fetch data from the backend to get the list of coaches who are missing applications, TB tests, Covid vaccines and Background Checks. </p>
<p>We use the <code>map()</code> method again to display the names for each category. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-2.49.54-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>When the <code>Send reminder email</code> button is clicked, that information is sent from React to the backend. The Controller is responsible for sending the email and communicating with the View on whether or not the message went through.</p>
<p>Based on the information it receives from the Controller, the View will display a success message or failure message to the user. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-4.11.16-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-5.03.48-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-controller-component">The Controller Component</h3>
<p>The Controller communicates with both the Model and View components and takes care of all the logic for our application. This section of the code was built in Node.JS and Express. </p>
<p>The Controller is going to get that complete list of coaches from the Model and send that information to the View. </p>
<p>The Controller is also responsible for filtering through the Model and providing the lists of coaches who have not completed the four missing document categories. </p>
<p>All of that data is sent to the View so it can be displayed to the user. </p>
<p>For the email functionality, the Controller is responsible for checking to make sure the sender's email is valid before sending the email.</p>
<p>I used Nodemailer here to send the emails.</p>
<pre><code class="lang-js">   transporter.sendMail(mailOptions, <span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (err) {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Applications: There was an error sending the message: <span class="hljs-subst">${err}</span>`</span>)
            res.json({ <span class="hljs-attr">status</span>: <span class="hljs-string">'Email failure'</span> })
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Applications Success: Email was sent`</span>)
            res.json({ <span class="hljs-attr">status</span>: <span class="hljs-string">"Email sent"</span> });
        }
    })
</code></pre>
<p>If the email was successful in going through, then the user is notified and the email message shows up in the demo email account.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-24-at-4.52.44-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If there is an error in sending the message, then the Controller will send that information to the View so the error message can be displayed to the user. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Model–View–Controller is a popular software pattern used to break up the logic of your application into three different components. </p>
<p>While the MVC pattern was initially used in desktop applications, it became popular to use in web applications during the late 1990's. </p>
<p>The Model is responsible for the data logic behind the application.</p>
<p>The View is what the user sees and interacts with in the application.</p>
<p>The Controller acts as the brains behind the application and communicates with the Model and View. </p>
<p>Web frameworks that use the MVC pattern include, Ruby on Rails, ASP.NET MVC, Laravel, and Angular. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Dynamic Navigation in Next.js – How to Render Nav-Items Dynamically in a Next App ]]>
                </title>
                <description>
                    <![CDATA[ By Caleb Olojo I've lately been noticing a pattern in React applications: developers protect certain routes on a web app from unauthorized users. In such cases, the navigation item (nav-item) on the navigation bar/Header of the web won't be visible t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/dynamic-navigation-in-nextjs/</link>
                <guid isPermaLink="false">66d45dd7b3016bf139028d25</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 16 Sep 2021 17:32:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/dynamic-nav-cover.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Caleb Olojo</p>
<p>I've lately been noticing a pattern in React applications: developers protect certain routes on a web app from unauthorized users.</p>
<p>In such cases, the navigation item (nav-item) on the navigation bar/Header of the web won't be visible to an unauthorized user.</p>
<p>In this short guide, we're going to take a look at how to do this in NextJS. We are going to render a nav-item dynamically on the navigation bar of a simple webpage that we'll be building here.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before you read this article any further, you should have some basic knowledge of:</p>
<ul>
<li>How React works</li>
<li>NextJS, a production ready framework of React.</li>
<li>Conditional rendering in React.</li>
<li>PropTypes checking in React</li>
<li>import and export statements in JavaScript. You can take a look at this <a target="_blank" href="https://seven.hashnode.dev/understanding-import-and-export-statements-in-javascript">article</a> to get familiar with it.</li>
</ul>
<h2 id="heading-getting-started">Getting Started</h2>
<p>Since this article focuses on Next.js, we'll start by creating a Next.js project. Type the command below in your terminal to install it:</p>
<pre><code class="lang-bash">npx create-next-app [name-of-your-webapp/website]
</code></pre>
<p>The command above gets all the dependencies we need to get our Next app up and running in no time. </p>
<p>Keep in mind that the file structure of a Next app is quite different from the ubiquitous create-react-app architecture.</p>
<p>Let's take a look at the important files that we will be interacting with in this article: </p>
<pre><code class="lang-md">|--pages
|   |-- <span class="hljs-emphasis">_app.js
|   |-- index.js
|   |-- about.js
|   |-- blog.js
|   |<span class="hljs-strong">__ services.js
|--src
|   |-- components
|   |      |-- Header.js
|   |      |__</span> NavItem.js 
|   |-- data.js
|<span class="hljs-strong">__</span></span>
</code></pre>
<p>The file structure above is an excerpt of the files in the Next.js app architecture. Now let's see what's going on here.</p>
<h2 id="heading-the-components-in-our-nextjs-app">The Components in Our Next.js App</h2>
<p>We'll take a look at all the components you see above and their roles. We'll start by breaking down the files in the <code>pages</code> folder.</p>
<ul>
<li><code>_app.js</code>: this is the root file of the code base. It is quite like the <code>index.js</code> file in <code>create-react-app</code>. Here, you can apply any global style(s), add new themes, provide context to the whole application, and so on.</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.Fragment</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"theme-color"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"#3c1742"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Head</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">React.Fragment</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyApp;
</code></pre>
<p>The snippet above shows the content of <code>_app.js</code>. The <code>Head</code> component that gets imported from <code>"next/head"</code> is so we can add document titles to the unique pages and a lot of <code>meta</code> tags for the sake of SEO.</p>
<ul>
<li><code>index.js</code>: Nextjs abstracts away the need to start using <code>BrowserRouter</code> from the <code>react-router-dom</code> library to set up the routes in your applications. Instead, any file that is inside the <code>pages</code> folder becomes a route. <code>index.js</code> becomes accessible at <code>https://localhost:3000/</code> once we start the development server with <code>npm run dev</code>.</li>
</ul>
<p>You might notice that we've already imported the <code>Header</code> component from the <code>src/component</code> folder. Do not fret. We'll get to that section soon.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;
<span class="hljs-keyword">import</span> Header <span class="hljs-keyword">from</span> <span class="hljs-string">"../src/components/Header"</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;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Caleb's article examples<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/ico"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/img/goals.ico"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Head</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Header</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Home Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"contact"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"section-title"</span>&gt;</span>Contact Us<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"section-body"</span>&gt;</span>
            You can Contact us via our various social media handles
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">HomeWrapper</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<ul>
<li>The remaining page components: <code>about.js</code>, <code>blog.js</code> and <code>services.js</code> can be accessed at <code>http://localhost:3000/about</code>, <code>http://localhost:3000/blog</code> and <code>http://localhost:3000/about</code> respectively</li>
</ul>
<h2 id="heading-how-to-map-array-items-onto-the-header-component">How to Map Array Items onto the Header Component</h2>
<p>Instead of hard-coding the user interface of the nav-bar, we can use JavaScript's <code>map()</code> function to render a list of items on the Header component.</p>
<p>To do this, we need to move into the <code>data.js</code> file in the <code>src: source</code> folder. We'll create an array of objects that will hold the information or items that we would like to render.</p>
<p>The snippet below shows the list of items we want to render. Notice that the last object has a <code>path</code> property that is quite different from the others. Instead of a <code>"/contact"</code> value, it has a <code>"#contact"</code> value. This is because the contact section is on the home page.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> navLinks = [
  { <span class="hljs-attr">name</span>: <span class="hljs-string">"Home"</span>, 
   <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span> 
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"About Us"</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">"/about"</span>,
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Services"</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">"/services"</span>,
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Blog"</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">"/blog"</span>,
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Contact Us"</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">"#contact"</span>,
  },
];
</code></pre>
<p>Let's continue on to create the Header component by mapping the array of objects that we have in <code>data.js</code>. To do that, we have to import the array from that file so we can have access to its properties.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { navLinks } <span class="hljs-keyword">from</span> <span class="hljs-string">"../utils/data"</span>;
<span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">"next/link"</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">Header</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">header</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"brand"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Example<span class="hljs-tag">&lt;/<span class="hljs-name">h3</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">nav</span>&gt;</span>
        {navLinks.map((link, index) =&gt; {
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{link.path}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>{link.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
          );
        })}
      <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span></span>
  );
}
</code></pre>
<p>With what we have in the snippet above, if we click on the <strong>"Contact Us"</strong> nav-item, the current route will be: <code>https://localhost:3000/#contact</code>. </p>
<p>The browser scrolls to the HTML element that has an id of "contact". If there isn't any such section, nothing is being scrolled to in the viewport.   </p>
<p>That is why we need to render this particular nav-item only on pages that have the corresponding section. Let's take a look at how to achieve that in the next section.</p>
<h2 id="heading-how-to-conditionally-render-the-nav-item-with-the-nextjs-userouter-hook">How to Conditionally Render the Nav-Item with the Next.js <code>useRouter</code> Hook</h2>
<p>We have to know when another page/route is currently active or "in-view" in a browser tab so that we can set a condition for rendering the nav-item in the appropriate page.</p>
<p>Fortunately for us, Next's <code>useRouter</code> hook lets us do that. Let's see how:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/router"</span>;
<span class="hljs-keyword">import</span> propTypes <span class="hljs-keyword">from</span> <span class="hljs-string">"prop-types"</span>;

<span class="hljs-keyword">const</span> NavItem = <span class="hljs-function">(<span class="hljs-params">{ item }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> router = useRouter();
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;&gt;</span>{router.pathname === "/" ? item : ""}<span class="hljs-tag">&lt;/&gt;</span></span>;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NavItem;

<span class="hljs-comment">// proptypes check</span>
NavItem.propTypes = {
  <span class="hljs-attr">item</span>: propTypes.string,
};
</code></pre>
<p>The snippet above is quite straightforward. We're passing <code>item</code> as props to the <code>NavItem</code> component so that it makes it dynamic to use in any case, not for the contact nav-item only.</p>
<p>See how we assigned the <code>useRouter()</code> hook to the <code>router</code> variable? With that, we can access the properties of the hook itself. You can read about the properties of the hook <a target="_blank" href="https://nextjs.org/docs/api-reference/next/router#router-object">here</a>.</p>
<pre><code class="lang-js">router.pathname === <span class="hljs-string">"/"</span> ? item : <span class="hljs-string">""</span>
</code></pre>
<p>The ternary operation above checks if the <code>pathname</code> of the page is equal to the homepage, that is <code>"/"</code>.</p>
<p>If the result is true, it assigns the value as props to the component (which will always be a string, because of the prop validation check). If not, it assigns an empty string to the component, which in turn ends up as nothing in the Header component.</p>
<h2 id="heading-final-touches">Final Touches</h2>
<p>Now, let's edit the last item in the <code>navLinks</code> array to look like the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> NavLink <span class="hljs-keyword">from</span> <span class="hljs-string">"./NavLink"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> navLinks = [
  { <span class="hljs-attr">name</span>: <span class="hljs-string">"Home"</span>, 
   <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span> 
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"About Us"</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">"/about"</span>,
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Services"</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">"/services"</span>,
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Blog"</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">"/blog"</span>,
  },
  {
    <span class="hljs-attr">name</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">item</span>=<span class="hljs-string">"Contact Us"</span> /&gt;</span></span>,
    path: <span class="hljs-string">"#contact"</span>,
  },
];
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Here's the end result of what we've been building. You'll see that I added some content to illustrate the smooth scroll behaviour to the contact section.</p>
<p>At the click event of the other routes, the contact nav-item isn't on the Header anymore.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/fixed.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Thank you for reading this article! I hope it has helped you gain insight on how to render UI dynamically, based on certain conditions. Kindly share this piece with your peers. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Laravel Subdomains – How to Create and Manage Subdomains in Your Apps ]]>
                </title>
                <description>
                    <![CDATA[ Modern web applications usually perform more than one function. They often have more than one section, offer more than one service, and have a couple of clients. But the more functionality the app has, the clumsier your route paths will get.  What if... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/laravel-subdomians/</link>
                <guid isPermaLink="false">66c4c69f1b22d2d8d9040eca</guid>
                
                    <category>
                        <![CDATA[ Laravel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zubair Idris Aweda ]]>
                </dc:creator>
                <pubDate>Thu, 16 Sep 2021 17:19:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/subdomain-structure.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Modern web applications usually perform more than one function. They often have more than one section, offer more than one service, and have a couple of clients.</p>
<p>But the more functionality the app has, the clumsier your route paths will get. </p>
<p>What if there was a way to separate all these parts into smaller components with better and cleaner routes? Something that users could easily access and use independently, under the same website?</p>
<p>Fortunately, there is such a way: <strong>Subdomains</strong>.</p>
<h2 id="heading-what-is-a-subdomain">What is a Subdomain?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/image-75.png" alt="Image" width="600" height="400" loading="lazy">
<em>Credit: <a target="_blank" href="https://www.google.com/url?sa=i&amp;url=https%3A%2F%2Fblog.electroica.com%2Fgoogles-top-searches-india-2019%2F&amp;psig=AOvVaw2bx9ZwYjA8ldb4CuGhccN-&amp;ust=1631749915996000&amp;source=images&amp;cd=vfe&amp;ved=0CAwQjhxqFwoTCMiBuKbU__ICFQAAAAAdAAAAABAh">Electroica Blog</a></em></p>
<p>Here's a <a target="_blank" href="https://www.domain.com/blog/subdomain/">basic definition of a subdomain</a>:</p>
<blockquote>
<p>A subdomain is, as the name would suggest, an additional section of your main <strong>domain name</strong>. You create subdomains to help organize and navigate to different sections of your main website. Within your main domain, you can have as many subdomains as necessary to get to all of the different pages of your website.</p>
</blockquote>
<p>So let's say you have a website called mysite.com. You have a blog section, a store section, and a general website section for about and contact pages. The website could have subdomains like blog.mysite.com and store.mysite.com, where the main website would use the main domain.</p>
<h2 id="heading-why-should-you-use-subdomains">Why Should You Use Subdomains?</h2>
<p>Subdomains are pretty useful, and here are some of their main advantages:</p>
<ul>
<li>Users can easily remember you website domains, which means they'll likely use your site more.</li>
<li>You'd be able to split your large application into smaller groups, so it will be easier to manage, debug, and update or upgrade.</li>
<li>Subdomains also allow for personalisation – for example, a blog app could give each user their own subdomain (like <em>username.domain.com</em>).</li>
<li>Subdomains also let developers test version of their application before pushing to production. You could have a <em>beta.site.com</em> to preview changes before deploying them to the main site.</li>
</ul>
<p>Let's see how all this works by building an actual project and testing it out.</p>
<h2 id="heading-how-to-create-new-laravel-project">How to Create New Laravel Project</h2>
<p>I have <a target="_blank" href="https://www.docker.com/">Docker</a> setup on my laptop, so I'll be using the <a target="_blank" href="https://laravel.com/docs/8.x/sail">Sail</a> setup that <a target="_blank" href="https://laravel.com/docs/8.x/">Laravel</a> ships with.</p>
<pre><code class="lang-bash">curl -s <span class="hljs-string">"https://laravel.build/example-app"</span> | bash
</code></pre>
<blockquote>
<p><em>You can use any other method you feel comfortable with. See the <a target="_blank" href="https://laravel.com/docs/8.x/installation">docs</a> for help.</em></p>
</blockquote>
<h3 id="heading-start-the-laravel-server">Start the Laravel Server</h3>
<pre><code class="lang-bash">./vendor/bin/sail up -d
</code></pre>
<h2 id="heading-how-to-configure-the-route-files">How to Configure the Route Files</h2>
<p>In your <code>web.php</code> file, you can define individual routes with their domain (or subdomain) like this:</p>
<pre><code class="lang-php">Route::get(<span class="hljs-string">'/'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">'First sub domain'</span>;
})-&gt;domain(<span class="hljs-string">'blog.'</span> . env(<span class="hljs-string">'APP_URL'</span>));
</code></pre>
<p>Now you can access the page at <em>blog.domain.com</em>.</p>
<p>But more often than not, you'll have more than one path in an application, like a domain and subdomains. So, it's a good idea to use a route group to cover all the routes in the same domain or subdomain.</p>
<pre><code class="lang-php">Route::domain(<span class="hljs-string">'blog.'</span> . env(<span class="hljs-string">'APP_URL'</span>))-&gt;group(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    Route::get(<span class="hljs-string">'posts'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Second subdomain landing page'</span>;
    });
    Route::get(<span class="hljs-string">'post/{id}'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$id</span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">'Post '</span> . $id . <span class="hljs-string">' in second subdomain'</span>;
    });
});
</code></pre>
<p>Now, all the routes for the domain can be handled in one place.</p>
<h2 id="heading-how-to-make-subdomains-dynamic">How to Make Subdomains Dynamic</h2>
<p>As I mentioned earlier, you can use subdomains to allow personalisation in web applications, so they need to be dynamic. For example, <a target="_blank" href="https://medium.com">Medium</a> gives authors domains like <em>username.domain.com</em>.</p>
<p>You can do this easily in Laravel as subdomains may be assigned route parameters just like route URIs. This allows you to capture a portion of the subdomain for usage in your route closure or controller.</p>
<pre><code class="lang-php">Route::domain(<span class="hljs-string">'{username}.'</span> . env(<span class="hljs-string">'APP_URL'</span>))-&gt;group(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    Route::get(<span class="hljs-string">'post/{id}'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$username, $id</span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">'User '</span> . $username . <span class="hljs-string">' is trying to read post '</span> . $id;
    });
});
</code></pre>
<p>In this example, you could have a domain like <em>zubair.domain.com</em> with route parameters, too<em>.</em></p>
<h2 id="heading-route-service-providers">Route Service Providers</h2>
<p>For very large applications, the <code>web.php</code> could get a bit messy if the routes keep increasing. It is best to split the routes into different files, preferably by subdomain.</p>
<p>In your <code>RouteServiceProvider.php</code> file, you'll see this code in the <code>boot</code> method:</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">boot</span>(<span class="hljs-params"></span>)
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;configureRateLimiting();

        <span class="hljs-keyword">$this</span>-&gt;routes(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            Route::prefix(<span class="hljs-string">'api'</span>)
                -&gt;middleware(<span class="hljs-string">'api'</span>)
                -&gt;namespace(<span class="hljs-keyword">$this</span>-&gt;namespace)
                -&gt;group(base_path(<span class="hljs-string">'routes/api.php'</span>));

            Route::middleware(<span class="hljs-string">'web'</span>)
                -&gt;namespace(<span class="hljs-keyword">$this</span>-&gt;namespace)
                -&gt;group(base_path(<span class="hljs-string">'routes/web.php'</span>));
        });
    }
</code></pre>
<p>This is Laravel's default route configuration to separate API routes from web routes. We'll use this same file to separate subdomains.</p>
<p>Add the following to the method:</p>
<pre><code class="lang-php">Route::domain(<span class="hljs-string">'blog.'</span> . env(<span class="hljs-string">'APP_URL'</span>))
                -&gt;middleware(<span class="hljs-string">'web'</span>)
                -&gt;namespace(<span class="hljs-keyword">$this</span>-&gt;namespace)
                -&gt;group(base_path(<span class="hljs-string">'routes/blog.php'</span>));
</code></pre>
<p>This is telling Laravel that whenever someone hits the <em>blog.domain.com</em> endpoint, look for the route in the blog.php (that we are yet to create).</p>
<p>We can go on to create the <code>blog.php</code> file in the <code>routes</code> folder, and add the following content:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Route</span>;

Route::get(<span class="hljs-string">'/'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">'Route using separate file'</span>;
});
</code></pre>
<p>At this point, you're done with all the code! All that's left is some server configuration.</p>
<h2 id="heading-server-configuration">Server Configuration</h2>
<p>If you're using a service such as <a target="_blank" href="https://laravel.com/docs/8.x/valet">Laravel Valet</a>, it is way easier to setup.</p>
<p>In the root directory of your project, run:</p>
<pre><code class="lang-bash">valet link domain
valet link blog.domain
</code></pre>
<p>And if you're not using Laravel Valet, you can add this to your <code>/etc/hosts/</code> file:</p>
<pre><code><span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>       domain.test
<span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>       blog.domain.test
</code></pre><p>This is basically just mapping the domain to the IP.</p>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<p>Now you know how to set up and manage subdomains in your Laravel apps. You can find all the code for this article <a target="_blank" href="https://github.com/Zubs/subdomain-test">here</a>.</p>
<p>If you have any questions or relevant advice, please get in touch with me to share them.</p>
<p>To read more of my articles or follow my work, you can connect with me on <a target="_blank" href="https://www.linkedin.com/in/idris-aweda-zubair-5433121a3/">LinkedIn</a>, <a target="_blank" href="https://twitter.com/AwedaIdris">Twitter</a>, and <a target="_blank" href="https://github.com/Zubs">Github</a>. It’s quick, it’s easy, and it’s free!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
