<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: DEVLOKER</title>
    <description>The latest articles on DEV Community by DEVLOKER (@devloker).</description>
    <link>https://dev.to/devloker</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1417261%2Fcab31bde-18e3-4d92-b35f-a31a07b636dd.png</url>
      <title>DEV Community: DEVLOKER</title>
      <link>https://dev.to/devloker</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devloker"/>
    <language>en</language>
    <item>
      <title>Getting Started with Building Chrome Extensions Using React &amp; TypeScript</title>
      <dc:creator>DEVLOKER</dc:creator>
      <pubDate>Tue, 23 Jul 2024 07:00:26 +0000</pubDate>
      <link>https://dev.to/devloker/getting-started-with-building-chrome-extensions-using-react-typescript-3i4g</link>
      <guid>https://dev.to/devloker/getting-started-with-building-chrome-extensions-using-react-typescript-3i4g</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hello, dev community!&lt;br&gt;
I'm  &lt;a href="https://dev-loker.com" rel="noopener noreferrer"&gt;DEVLOKER&lt;/a&gt;, today, I want to share my recent project about a chrome extension that lets users toggle between dark and light themes on any webpage. It doesn’t matter if the page originally supports dark mode, the extension applies a CSS filter: invert to achieve the effect. This can be particularly useful for users who prefer reading in a dark mode but visit websites that don’t have built-in support for it.&lt;/p&gt;

&lt;p&gt;You can find the complete code on my &lt;a href="https://github.com/DEVLOKER/theme-switcher" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Chrome extension structure
&lt;/h1&gt;

&lt;p&gt;The extension consists of several files, each playing a specific role in the overall functionality. Let's go through the main files and their purposes:&lt;/p&gt;
&lt;h2&gt;
  
  
  manifest.json
&lt;/h2&gt;

&lt;p&gt;The manifest file is the configuration file for the Chrome extension. It includes metadata about the extension such as its name, version, description, icons, permissions, and the scripts it uses (background, content, and popup). It defines the structure and behavior of the extension, specifying how it interacts with the browser and the web pages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;manifest_version&lt;/strong&gt;: Specifies the manifest file format version. Here, version 3 is used, which is the latest standard for Chrome extensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;name&lt;/strong&gt; and &lt;strong&gt;description&lt;/strong&gt;: Provide the name and a brief description of the extension. These fields help users understand the purpose of the extension.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;version&lt;/strong&gt;: Indicates the current version of the extension. This is useful for version management and updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;icons&lt;/strong&gt;: Defines the different sizes of the extension’s icon. Icons are used in the browser toolbar and the Chrome Web Store.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;permissions&lt;/strong&gt;: Lists the permissions requested by the extension:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;tabs&lt;/strong&gt;: Allows the extension to interact with the browser’s tabs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;activeTab&lt;/strong&gt;: Grants access to the currently active tab.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;storage&lt;/strong&gt;: Enables the use of Chrome’s storage API for saving user preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;scripting&lt;/strong&gt;: Allows the extension to execute scripts in the context of web pages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;background&lt;/strong&gt;: Configures the background service worker that handles background tasks and event listeners.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;type&lt;/strong&gt;: "module" allows using ES6 modules in the background script.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;service_worker&lt;/strong&gt;: Specifies the script file that acts as the background worker.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;content_scripts&lt;/strong&gt;: Defines scripts that are injected into web pages:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;matches&lt;/strong&gt;: Determines which URLs the content script will be injected into. &lt;em&gt;&lt;/em&gt; ensures it runs on all pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;js&lt;/strong&gt;: Lists the JavaScript files to be injected. Here, content.js contains the logic to apply the dark/light mode styles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;type&lt;/strong&gt;: "module" indicates that the script is an ES6 module.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;action&lt;/strong&gt;: Specifies the default popup that appears when the extension’s icon is clicked. index.html is the popup’s HTML file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;host_permissions&lt;/strong&gt;: Allows the extension to request permissions for all hosts (&lt;em&gt;://&lt;/em&gt;/*). This is required for interacting with any webpage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Popup
&lt;/h2&gt;

&lt;p&gt;The popup is the user interface of the Chrome extension that appears when the user clicks on the extension icon in the browser toolbar. It’s typically used to provide a quick way for users to interact with the extension.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The popup’s lifecycle is short-lived compared to other components.&lt;/li&gt;
&lt;li&gt;It is not persistent and is created anew each time it is opened.&lt;/li&gt;
&lt;li&gt;Communication with other parts of the extension is typically done using &lt;em&gt;chrome.runtime.sendMessage&lt;/em&gt; and &lt;em&gt;chrome.runtime.onMessage&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lifecycle&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initialization&lt;/strong&gt;: When the user clicks the extension icon, Chrome creates a new popup window and loads the HTML, CSS, and JavaScript specified for the popup in &lt;em&gt;manifest.json&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active&lt;/strong&gt;: While the popup is open, its scripts (JS) are active and can interact with the DOM and perform actions based on user input.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close&lt;/strong&gt;: The popup closes when the user clicks outside of it, or it can close programmatically. When closed, the popup’s JavaScript context is terminated.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  background script
&lt;/h2&gt;

&lt;p&gt;The background script runs in the background and is responsible for handling events that affect the extension, such as browser actions, alarms, or network requests. It can also manage extension-wide state and perform tasks that need to be available continuously.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It can be either a persistent background page (old model) or a service worker (new model).&lt;/li&gt;
&lt;li&gt;It’s ideal for long-running tasks, event handling, and managing global state.&lt;/li&gt;
&lt;li&gt;Communication is often done using &lt;em&gt;chrome.runtime.sendMessage&lt;/em&gt;, &lt;em&gt;chrome.tabs.sendMessage&lt;/em&gt; and &lt;em&gt;chrome.runtime.onMessage&lt;/em&gt;, or &lt;em&gt;chrome.storage&lt;/em&gt; for managing state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lifecycle&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initialization&lt;/strong&gt;: The background script starts when the extension is first installed or when Chrome is started. It persists across browser sessions (if using persistent background pages) or is recreated each time (if using service workers).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active&lt;/strong&gt;: While running, it handles events and messages from other parts of the extension and can interact with the browser API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Termination&lt;/strong&gt;: If using a persistent background page, it remains active until Chrome is closed or the extension is uninstalled. If using a service worker, it only stays active as long as it’s needed and is terminated when idle.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  content scripts
&lt;/h2&gt;

&lt;p&gt;Content scripts run in the context of web pages. They can interact with the DOM of the pages they are injected into, allowing the extension to modify or read content from those pages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They run in isolated environments and have access to the web page’s DOM but not to other parts of the extension or the Chrome API directly (except the limited &lt;em&gt;chrome.runtime&lt;/em&gt; and &lt;em&gt;chrome.storage&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;They can be specified to run at different times (e.g., when the DOM is fully loaded) using &lt;em&gt;run_at&lt;/em&gt; in &lt;em&gt;manifest.json&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lifecycle&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initialization&lt;/strong&gt;: Content scripts are injected into web pages based on the rules specified in &lt;em&gt;manifest.json&lt;/em&gt; (e.g., URL patterns). They start when a page matching the specified patterns is loaded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active&lt;/strong&gt;: They execute their code within the page’s context and can interact with the page’s DOM. They can also communicate with the background script using &lt;em&gt;chrome.runtime.sendMessage&lt;/em&gt; and &lt;em&gt;chrome.runtime.onMessage&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Termination&lt;/strong&gt;: Content scripts are automatically removed when the user navigates away from the page or when the page is refreshed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Why Choose React and TypeScript?
&lt;/h2&gt;

&lt;p&gt;Using React and TypeScript for developing the Chrome extension brought numerous benefits. React’s component-based architecture and efficient rendering, combined with TypeScript’s type safety and improved developer experience, resulted in a more maintainable, scalable, and robust extension. These tools not only enhance the development process but also ensure that the extension is reliable and performant for users.&lt;/p&gt;
&lt;h2&gt;
  
  
  Project Folder Structure
&lt;/h2&gt;

&lt;p&gt;When setting up a Chrome extension with React and TypeScript using &lt;a href="https://vitejs.dev" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;, a well-organized project folder structure is crucial. Here's an overview of the &lt;a href="https://github.com/DEVLOKER/theme-switcher" rel="noopener noreferrer"&gt;folder structure&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;theme-switcher/
│
├── public/
│   ├── icons/
│   │   ├── icon-16.png
│   │   ├── icon-32.png
│   │   ├── icon-48.png
│   │   └── icon-128.png
│   └── manifest.json
│
├── src/
│   ├── scripts/
│   │   ├── service-worker/
│   │   │   └── background.ts
│   │   ├── injection/
│   │   │   └── content.ts
│   ├── types/
│   │   ├── TMessage.ts
│   │   └── TTheme.ts
│   ├── utils/
│   │   ├── helpers.ts
│   ├── constants/
│   │   └── theme.ts
│   ├── features/
│   │   └── Popup.tsx
│   ├── styles/
│   │   └── styles.css
│   ├── index.html
│   ├── index.tsx
│
├── dist/
│
├── .gitignore
├── package.json
├── tsconfig.json
└── vite.config.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s explain the most important chrome extension components (popup, background, content):&lt;/p&gt;

&lt;h3&gt;
  
  
  Popup Component (Popup.tsx)
&lt;/h3&gt;

&lt;p&gt;The popup component is the user interface of the extension that appears when the extension icon is clicked. It allows users to switch between dark and light themes and is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initializing the Theme&lt;/strong&gt;: Upon opening, the popup sends an "&lt;strong&gt;INIT_THEME&lt;/strong&gt;" message to the background script to get the current theme and set it in the state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Displaying the Current Theme&lt;/strong&gt;: The popup displays the current theme (dark or light) based on the state managed in the component.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handling User Input&lt;/strong&gt;: When the user selects a different theme, the popup updates the state and sends an "&lt;strong&gt;APPLY_THEME&lt;/strong&gt;" message to the background script to apply the new theme.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Background Script (background.ts)
&lt;/h3&gt;

&lt;p&gt;The background script serves as the central hub of the extension. It runs in the background and listens for messages from the popup and content scripts. Its main responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initializing the Theme&lt;/strong&gt;: When the popup or content script sends an "&lt;strong&gt;INIT_THEME&lt;/strong&gt;" message, the background script loads the stored theme from the browser's storage, updates the extension's badge, and sends the theme back to the sender.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Applying the Theme&lt;/strong&gt;: When the user changes the theme in the popup, the background script receives the "&lt;strong&gt;APPLY_THEME&lt;/strong&gt;" message. It then asks the content script to apply the new theme to the current webpage, updates the badge to reflect the new theme, and saves the theme in the browser's storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Updating the Badge&lt;/strong&gt;: The badge text and color on the extension icon are updated based on the current theme (dark or light) to provide a visual indication of the active theme.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Content Script (content.ts)
&lt;/h3&gt;

&lt;p&gt;The content script is injected into all web pages specified in the manifest. It interacts directly with the web pages and is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Applying the Theme&lt;/strong&gt;: When the content script is first loaded, it sends an "&lt;strong&gt;INIT_THEME&lt;/strong&gt;" message to the background script to get the current theme. Upon receiving the theme, it applies the appropriate styles to the webpage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listening for Theme Changes&lt;/strong&gt;: The content script listens for "&lt;strong&gt;APPLY_THEME&lt;/strong&gt;" messages from the background script. When a theme change is detected, it updates the webpage styles accordingly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managing Styles&lt;/strong&gt;: It dynamically creates and removes a style element to apply the dark mode styles to the webpage, ensuring that elements like the background, text, and images are appropriately styled for the active theme.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This schema illustrates the workflow of the extension:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Configuring vite.config.ts for Building
&lt;/h2&gt;

&lt;p&gt;This section specifies the entry points for the build process. Each entry point corresponds to a different part of the Chrome extension:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;popup: The HTML file that serves as the popup's entry point.&lt;/li&gt;
&lt;li&gt;background: The TypeScript file for the background script.&lt;/li&gt;
&lt;li&gt;content: The TypeScript file for the content script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This section customizes the output file names based on the entry point name:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the chunk name is "popup", it outputs as "popup.js".&lt;/li&gt;
&lt;li&gt;If the chunk name is "background", it outputs as "background.js".&lt;/li&gt;
&lt;li&gt;If the chunk name is "content", it outputs as "content.js".&lt;/li&gt;
&lt;li&gt;Otherwise, it uses the default naming convention [name].js.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// https://vitejs.dev/config/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
    &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;rollupOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;popup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;service-worker&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;injection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;entryFileNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;popup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;popup.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[name].js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building the Extension
&lt;/h2&gt;

&lt;p&gt;To build the extension, run the following command: &lt;code&gt;npm run build&lt;/code&gt;&lt;br&gt;
This command triggers Vite to compile and bundle the extension's code, generating the output files in the &lt;strong&gt;dist&lt;/strong&gt; folder.&lt;/p&gt;

&lt;p&gt;To test the extension in Chrome, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Chrome and go to &lt;strong&gt;chrome://extensions/&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enable "&lt;strong&gt;Developer mode&lt;/strong&gt;" by toggling the switch in the top right corner.&lt;/li&gt;
&lt;li&gt;Click on the "&lt;strong&gt;Load unpacked&lt;/strong&gt;" button.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;dist&lt;/strong&gt; folder that was generated by the build process.
This will load the unpacked extension into Chrome, allowing you to test its functionality directly in the browser.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;now, let's open any website for testing (eg: &lt;a href="https://www.google.com" rel="noopener noreferrer"&gt;https://www.google.com&lt;/a&gt;), and these are the results for google light/dark:&lt;/p&gt;

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

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

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Creating a Chrome extension with React and TypeScript offers a robust way to build modern web tools. This guide covered developing an very simple extension that switches between dark and light modes using: React's component-based architecture and TypeScript's type-checking for enhancing code maintainability and scalability.&lt;/p&gt;

&lt;p&gt;We also set up the project using Vite, simplifying the development and build process. The vite.config.ts configuration was essential for correctly bundling the popup, background script, and content script.&lt;/p&gt;

&lt;p&gt;While the invert method provided a quick way to implement dark mode, it &lt;strong&gt;doesn't always&lt;/strong&gt; produce perfect results, as some elements may not invert correctly. Despite this, it remains effective for most cases.&lt;/p&gt;

&lt;p&gt;And finally, you can find the complete code on my &lt;a href="https://github.com/DEVLOKER/theme-switcher" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. Feel free to check it out, contribute, or use it as a reference for your own projects.&lt;/p&gt;

&lt;p&gt;Thanks for reading, and happy coding!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Mathematics secret behind AI on Digit Recognition</title>
      <dc:creator>DEVLOKER</dc:creator>
      <pubDate>Sat, 15 Jun 2024 20:45:29 +0000</pubDate>
      <link>https://dev.to/devloker/mathematics-secret-behind-ai-on-digit-recognition-49lc</link>
      <guid>https://dev.to/devloker/mathematics-secret-behind-ai-on-digit-recognition-49lc</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hi everyone! I’m &lt;a href="https://www.dev-loker.com"&gt;devloker&lt;/a&gt;, and today I’m excited to share a project I’ve been working on: a digit recognition system implemented using pure math functions in Python. This project aims to help beginners grasp the mathematics behind AI and digit recognition without relying on high-level libraries like &lt;a href="https://www.tensorflow.org/"&gt;TensorFlow&lt;/a&gt; or &lt;a href="https://pytorch.org/"&gt;PyTorch&lt;/a&gt;.&lt;br&gt;
You can find the complete code on my &lt;a href="https://github.com/DEVLOKER/Pure-Math-Digit-Recognition"&gt;GitHub repository&lt;/a&gt;. &lt;/p&gt;
&lt;h1&gt;
  
  
  Fundamental concepts in AI world
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Artificial Intelligence (AI)
&lt;/h2&gt;

&lt;p&gt;Artificial Intelligence (AI) is a broad field of computer science focused on creating systems capable of performing tasks that typically require human intelligence. These tasks include problem-solving, understanding natural language, recognizing patterns, and making decisions. AI can be categorized into several subdomains, each with its own focus and techniques.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvo8dv8ye9ooj6btocpo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvo8dv8ye9ooj6btocpo.jpg" alt="Image description" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Artificial Neural Networks (ANN)
&lt;/h2&gt;

&lt;p&gt;Artificial Neural Networks are a type of machine learning model inspired by the structure and function of the human brain. They consist of layers of interconnected nodes (or neurons), each performing simple computations.&lt;/p&gt;

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

&lt;p&gt;Neurons are the basic building blocks of artificial neural networks, inspired by biological neurons in the human brain. In AI, a neuron is a mathematical function that receives one or more inputs, applies weights to these inputs, sums them up, applies an activation function, and produces an output. In the context of artificial neural networks, a neuron performs the following operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input Features&lt;/strong&gt;: The neuron takes multiple input features, each input represents a characteristic or attribute of the input data which represented as: &lt;code&gt;x1 ,x2 , ..., xn&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weights&lt;/strong&gt;: Each input feature is associated with a weight &lt;code&gt;w1, w2, ...,wn&lt;/code&gt;. which indicates the importance of the feature in making the prediction. During training, these weights are adjusted to learn the optimal values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summation Function&lt;/strong&gt;: Each input is multiplied by its weight, the weighted inputs are summed together, often with an added bias term: &lt;code&gt;z = sum(xi * wi for xi, wi in zip(x, w)) + b&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bias&lt;/strong&gt;: The bias b is an additional parameter that allows to make adjustments that are independent of the input, which helps the model make accurate predictions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activation Function&lt;/strong&gt;: This function decides whether the neuron should be fired or not based on weighted sum, introducing non-linearity to the model. Common activation functions include &lt;em&gt;softmax&lt;/em&gt;, &lt;em&gt;sigmoid&lt;/em&gt;, and &lt;em&gt;ReLU&lt;/em&gt; &lt;em&gt;(Rectified Linear Unit)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output&lt;/strong&gt;: the neuron's output is the obtained result after applying the activation function. This output can be fed as input to the next layer of neurons or can be the final output in the case of the output layer, the final output represents the decision or prediction based on the input and the weights.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;These operations work together to enable a neuron to learn and make predictions, while a single neuron can only solve linearly separable problems, combining multiple neurons into layers allows the creation of more complex models capable of solving non-linear problems. This structure forms the basis of multi-layer neural networks used in deep learning.&lt;/p&gt;
&lt;h2&gt;
  
  
  Deep Learning (DL)
&lt;/h2&gt;

&lt;p&gt;Deep Learning is a subfield of machine learning that focuses on neural networks with many layers (hence "deep" networks). These networks are capable of learning from vast amounts of data and can model complex, high-dimensional patterns. Deep learning has been particularly successful in fields like speech &amp;amp; image recognition, natural language processing, medical diagnosis, and game playing. These models require vast amounts of data and computational power to train effectively but can achieve remarkable accuracy and performance.&lt;/p&gt;

&lt;p&gt;Deep learning models consist of multiple layers of neurons. The common types of layers include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input Layer&lt;/strong&gt;: The first layer, which receives the initial data (e.g., pixel values of an image).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden Layers&lt;/strong&gt;: Intermediate layers that transform the input of previous layer into more abstract representations through weighted connections and activation functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output Layer&lt;/strong&gt;: The final layer, which produces the final prediction or classification (e.g., the probabilities of each digit in digit recognition).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Training deep networks involves adjusting the weights and biases of the network to minimize the error in predictions. This is done using backpropagation and optimization algorithms like &lt;a href="https://en.wikipedia.org/wiki/Gradient_descent"&gt;gradient descent&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Forward Propagation&lt;/strong&gt;: Calculate the output of the network for given inputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loss Computation&lt;/strong&gt;: Measure the error between the predicted output and the actual output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backword Propagation&lt;/strong&gt;: Compute the gradient of the loss function with respect to each weight and bias, propagating the error backward through the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weight Update&lt;/strong&gt;: during training, the perceptron learns by adjusting its weights and bias based on the difference between the predicted output and the true output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Types of Deep Neural Networks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Feedforward Neural Networks (FNNs)&lt;/strong&gt;: The simplest type where connections between the nodes do not form a cycle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Convolutional Neural Networks (CNNs)&lt;/strong&gt;: Primarily used for image processing, recognizing patterns using convolutional layers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recurrent Neural Networks (RNNs)&lt;/strong&gt;: Suitable for sequence data like time series or text, where outputs from previous steps are fed as inputs to the next step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generative Adversarial Networks (GANs)&lt;/strong&gt;: Consist of two networks (generator and discriminator) that compete against each other, useful for generating synthetic data.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Digits recognition process
&lt;/h1&gt;

&lt;p&gt;Digit recognition is a classic application of neural networks where the goal is to correctly identify handwritten digits (0-9) from images. This task involves several key steps:&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Preparing the Data
&lt;/h2&gt;

&lt;p&gt;To start with digit recognition, we first need to prepare our data. We'll be using the &lt;a href="https://en.wikipedia.org/wiki/MNIST_database"&gt;MNIST dataset&lt;/a&gt;, a standard dataset consisting of 60,000 training images and 10,000 testing images of handwritten digits (0-9).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Loading the Data&lt;/strong&gt;: Load the MNIST dataset, which contains images of handwritten digits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalizing&lt;/strong&gt;: Normalization involves scaling pixel values to a range of 0 to 1. This helps the model converge faster during training. Each pixel value, originally between 0 and 255, is divided by 255.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reshaping&lt;/strong&gt;: Each image in the MNIST dataset is 28x28 pixels. We'll reshape these 2D arrays into 1D vectors of 784 elements (28 * 28). This reshaped vector will serve as the input features for our model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a sample code snippet for data preparation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;keras.datasets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;mnist&lt;/span&gt;

&lt;span class="c1"&gt;# Load the MNIST dataset
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mnist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Normalize the images to values between 0 and 1
&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X_train&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;
&lt;span class="n"&gt;X_test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X_test&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;

&lt;span class="c1"&gt;# Reshape the images from (28, 28) to (784,)
&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;X_test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X_test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;X_train&lt;/em&gt;: A numpy array containing the training images. Each image is a &lt;em&gt;28x28&lt;/em&gt; pixel grayscale image of a handwritten digit (0-9). The shape of &lt;em&gt;X_train&lt;/em&gt; is typically &lt;em&gt;(60000, 28, 28)&lt;/em&gt;, where &lt;em&gt;60000&lt;/em&gt; is the number of training images.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Y_train&lt;/em&gt;: A numpy array containing the labels for the training images. Each label is an integer (0-9) representing the digit shown in the corresponding training image. The shape of &lt;em&gt;Y_train&lt;/em&gt; is typically &lt;em&gt;(60000,)&lt;/em&gt;, where &lt;em&gt;60000&lt;/em&gt; is the number of training labels.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;X_test&lt;/em&gt;: A numpy array containing the testing images. Similar to &lt;em&gt;X_train&lt;/em&gt;, each image is a &lt;em&gt;28x28&lt;/em&gt; pixel grayscale image. The shape of X_test is typically &lt;em&gt;(10000, 28, 28)&lt;/em&gt;, where &lt;em&gt;10000&lt;/em&gt; is the number of testing images.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Y_test&lt;/em&gt;: A numpy array containing the labels for the testing images. Each label is an integer &lt;em&gt;(0-9)&lt;/em&gt; representing the digit shown in the corresponding testing image. The shape of &lt;em&gt;Y_test&lt;/em&gt; is typically &lt;em&gt;(10000,)&lt;/em&gt;, where &lt;em&gt;10000&lt;/em&gt; is the number of testing labels.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Model Architecture
&lt;/h2&gt;

&lt;p&gt;Our neural network will consist of an input layer, two hidden layers, and an output layer. The structure and sizes of weights and biases for each layer are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input Layer&lt;/strong&gt;: &lt;em&gt;784&lt;/em&gt; neurons (one for each pixel in the image).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden Layer 1&lt;/strong&gt;: &lt;em&gt;10&lt;/em&gt; neurons.

&lt;ul&gt;
&lt;li&gt;Each neuron is connected with &lt;em&gt;784&lt;/em&gt; input neurons from the previous layer, so have &lt;em&gt;10*784&lt;/em&gt; different weights, and we can store them in a matrix &lt;em&gt;W1&lt;/em&gt; with size of &lt;em&gt;(10, 784)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Each neuron has own bais, in total we have &lt;em&gt;10&lt;/em&gt; different biases, and we can store them in vector &lt;em&gt;B1&lt;/em&gt; with size of &lt;em&gt;(10,1)&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden Layer 2&lt;/strong&gt;: &lt;em&gt;10&lt;/em&gt; neurons.

&lt;ul&gt;
&lt;li&gt;Each neuron is connected with &lt;em&gt;784&lt;/em&gt; input neurons from the previous layer, so have &lt;em&gt;10*10&lt;/em&gt; different weights, and we can store them in a matrix &lt;em&gt;W2&lt;/em&gt; with size of &lt;em&gt;(10, 10)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Each neuron has own bais, in total we have &lt;em&gt;10&lt;/em&gt; different biases, and we can store them in vector &lt;em&gt;B2&lt;/em&gt; with size of &lt;em&gt;(10,1)&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output Layer&lt;/strong&gt;: &lt;em&gt;10&lt;/em&gt; neurons (one for each digit &lt;em&gt;0-9&lt;/em&gt;).

&lt;ul&gt;
&lt;li&gt;Each digit assigns by one neuron, and each neuron represents the probability of the assigned digit.&lt;/li&gt;
&lt;li&gt;the predicted digit is the one corresponding to the neuron with the highest probability.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the structure of our model:&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Initialize weights and biases
&lt;/span&gt;&lt;span class="n"&gt;W1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;784&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;B1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;W2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;B2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Training the Model
&lt;/h2&gt;

&lt;p&gt;Training the model involves forward propagation, loss and accuracy calculation, backward propagation, and updating weights and biases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Initialize the neural network's weights W1, W2 and biases B1, B2 with random float between 0 and 1.
For each epoch from 1 to epochs (inclusive):
- Forward Propagation: Compute the activations A1 and A2 (output of each layer) using the current weights and biases.
- Compute error: quantifies the error in the predictions using output A2 and the true labels Y_train.
- Compute Accuracy, which is the proportion of correctly predicted labels (evaluate the performance of the model).
- Backward Propagation: compute the gradients of the error with respect to the weights and biases. Witch indicate how much each parameter needs to change to reduce the error.
- Update the model parameters: Adjust the weights W1, W2 and biases B1, B2 using the computed gradients and the learning rate.
End For Loop
Return the last version of the trained model parameters (weights W1, W2 and biases B1, B2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Forward Propagation&lt;/strong&gt;: Calculating the activations of each layer using the weights and biases. We'll use the ReLU (Rectified Linear Unit) activation function for the hidden layers and softmax for the output layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="n"&gt;exp_z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;exp_z&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;exp_z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keepdims&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward_propagation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;Z1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B1&lt;/span&gt;
    &lt;span class="n"&gt;A1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Z1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;Z2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B2&lt;/span&gt;
    &lt;span class="n"&gt;A2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Z2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Z1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Z2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Loss and Accuracy Calculation&lt;/strong&gt;: Using cross-entropy loss to measure the model's performance and calculating accuracy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_loss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_accuracy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;predictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;argmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predictions&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Backward Propagation&lt;/strong&gt;: Calculating gradients using derivatives to adjust the weights and biases. The chain rule is applied here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;backward_propagation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;dZ2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;A2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;
    &lt;span class="n"&gt;dW2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dZ2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="n"&gt;dB2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dZ2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keepdims&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="n"&gt;dZ1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;W2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dZ2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dW1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dZ1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="n"&gt;dB1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dZ1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keepdims&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dW1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dB1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dW2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dB2&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_parameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dW1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dB1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dW2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dB2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;learning_rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;W1&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;learning_rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dW1&lt;/span&gt;
    &lt;span class="n"&gt;B1&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;learning_rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dB1&lt;/span&gt;
    &lt;span class="n"&gt;W2&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;learning_rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dW2&lt;/span&gt;
    &lt;span class="n"&gt;B2&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;learning_rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dB2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Training Loop&lt;/strong&gt;: Iteratively performing forward and backward propagation, and updating weights and biases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;learning_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;
&lt;span class="n"&gt;epochs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;epoch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;forward_propagation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compute_loss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;accuracy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compute_accuracy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dW1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dB1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dW2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dB2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;backward_propagation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;W1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;W2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;update_parameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;W2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dW1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dB1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dW2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dB2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;learning_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# print results for each 10 iterations
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;epoch&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Epoch &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;epoch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Loss: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Accuracy: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;accuracy&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Evaluating and Reusing the Model
&lt;/h2&gt;

&lt;p&gt;After training, we evaluate the model's performance on the test set and discuss how to save and reuse the model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saving the Model&lt;/strong&gt;: The trained model, represented by its weights and biases, can be saved to a file for future use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;

&lt;span class="n"&gt;model_parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;W1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;W1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;B1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;W2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;W2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;B2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;digit_recognition_model.pkl&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_parameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Loading and Evaluating the Model&lt;/strong&gt;: Load the saved model and evaluate its performance.&lt;br&gt;
In the context of digit recognition and neural networks, &lt;em&gt;accuracy&lt;/em&gt; is a key metric used to evaluate the performance of the model. It represents the proportion of correctly predicted digits out of the total number of predictions made. High accuracy indicates that the model is effectively learning and generalizing from the training data to make correct predictions on unseen data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;digit_recognition_model.pkl&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;model_parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;W1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;W1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;B1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;B1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;W2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;W2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;B2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;B2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Evaluate the model on the test set
&lt;/span&gt;&lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;forward_propagation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;test_accuracy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compute_accuracy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Test Accuracy: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;test_accuracy&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By following these steps, we can build, train, and evaluate a neural network for digit recognition using the MNIST dataset. This process highlights the importance of data preparation, model architecture, training, and evaluation in developing effective machine learning models.&lt;/p&gt;

&lt;h1&gt;
  
  
  The implementation overview
&lt;/h1&gt;

&lt;p&gt;In this section, we will describe the implementation of a digit recognition system using Python. The system consists of two main components:&lt;br&gt;
&lt;strong&gt;User Interface (UI)&lt;/strong&gt;: Built using &lt;em&gt;PyQt6&lt;/em&gt;, this provides an interactive interface for drawing digits, training the model using (&lt;em&gt;epochs&lt;/em&gt;, &lt;em&gt;target accuracy&lt;/em&gt; and &lt;em&gt;learning rate&lt;/em&gt;) parameters, loading a pre-trained model, and predicting the drawn digit.&lt;br&gt;
&lt;strong&gt;Backend Script&lt;/strong&gt;: Contains the &lt;em&gt;NeuralNetworkModel&lt;/em&gt; class, which handles the core functionalities of training the model and making predictions.&lt;/p&gt;

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

&lt;p&gt;run main python file &lt;code&gt;app.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Configure the training parameters (&lt;em&gt;epochs&lt;/em&gt;, &lt;em&gt;target accuracy&lt;/em&gt;, and &lt;em&gt;learning rate&lt;/em&gt;) and click on the "Train" button, or alternatively, load a pre-trained model using the "Load" button.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: For optimal results, ensure you train your model until achieving a high accuracy (e.g. greater than &lt;em&gt;95%&lt;/em&gt;) by setting the target accuracy to &lt;em&gt;0.95&lt;/em&gt;. Note that reaching high training accuracy may require a significant amount of time (several minutes or longer).&lt;/p&gt;

&lt;p&gt;Once trained, draw a digit on the left side (e.g., &lt;strong&gt;6&lt;/strong&gt;), and click the "Recognize" button. The system will display the probability for each digit, with the highest probability indicating the most likely digit (e.g. digit: &lt;strong&gt;6&lt;/strong&gt;, probability: &lt;strong&gt;97.04%&lt;/strong&gt;).&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;By implementing digit recognition using pure math functions, we’ve demystified the math behind AI. I hope this helps you understand the fundamentals and encourages you to dive deeper into the world of machine learning.&lt;/p&gt;

&lt;p&gt;You can find the complete code on my &lt;a href="https://github.com/DEVLOKER/Pure-Math-Digit-Recognition"&gt;GitHub repository&lt;/a&gt;. &lt;br&gt;
For further reading, check out this video &lt;a href="https://www.youtube.com/watch?v=aircAruvnKk"&gt;But what is a neural network? | Chapter 1, Deep learning&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Playwright Scraping infinite loading &amp; pagination</title>
      <dc:creator>DEVLOKER</dc:creator>
      <pubDate>Wed, 01 May 2024 10:20:08 +0000</pubDate>
      <link>https://dev.to/devloker/playwright-scraping-infinite-loading-pagination-4pid</link>
      <guid>https://dev.to/devloker/playwright-scraping-infinite-loading-pagination-4pid</guid>
      <description>&lt;h1&gt;
  
  
  Before to start
&lt;/h1&gt;

&lt;p&gt;Web data scraping itself isn’t illegal, but it can be illegal (or in a grey area) depending on these three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The type of data you are scraping (personal, copyrighted…)&lt;/li&gt;
&lt;li&gt;How you plan to use the scraped data&lt;/li&gt;
&lt;li&gt;How you extracted the data from the website&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, before to start scraping data make sure to double-check the plan to ensure you’re conducting both legal and ethical web scraping with these checks: &lt;strong&gt;&lt;em&gt;Am I scraping personal or copyrighted data? Am I scraping data from behind a login? Am I violating the Terms and Conditions?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your answers to all of these questions is &lt;strong&gt;No&lt;/strong&gt;, then your web scraping is legal. However, if you answer &lt;strong&gt;Yes&lt;/strong&gt; to any of them, then you should take a step back and do a full legal review of your web scraping to ensure you’re not scraping the web illegally.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://en.wikipedia.org/wiki/Web_scraping#Legal_issues" rel="noopener noreferrer"&gt;this&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; is a powerful tool developed by Microsoft, it allows developers to write reliable end-to-end tests and perform browser automation tasks with ease. What sets Playwright apart is its ability to work seamlessly across multiple browsers (Chrome, Firefox, and WebKit), it provides a consistent and efficient way to interact with web pages, extract data, and automate repetitive tasks. Moreover, it supports various programming languages such as Node.js, Python, Java, and .NET, that’s making it a versatile choice for web scraping projects.&lt;br&gt;
Whether you're scraping public data for analysis, building a web crawler, or automating manual workflows, Playwright has you covered.&lt;/p&gt;

&lt;h1&gt;
  
  
  Scraping process
&lt;/h1&gt;

&lt;p&gt;In this post, we'll explore how to harness the power of Playwright for web scraping using JavaScript, you can find the full code on &lt;a href="https://github.com/DEVLOKER/playwright-scraping" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;br&gt;
In our scenario will try to extract public products from an e-commerce website, note that the scraping is not explicitly prohibit in its &lt;a href="https://www.ouedkniss.com/terms" rel="noopener noreferrer"&gt;terms of service&lt;/a&gt;, and in order to avoid a lot of requests that could impact the server resources will try to extract only the first three pages of products (just for learning purposes).&lt;br&gt;
Detail the steps involved in scraping process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;- Waiting for the page to load.&lt;/li&gt;
&lt;li&gt;- Scrolling down to load more content.&lt;/li&gt;
&lt;li&gt;- Scraping products from the current page.&lt;/li&gt;
&lt;li&gt;- Clicking on the next page link and repeating the process.&lt;/li&gt;
&lt;li&gt;- Save scraped data to (&lt;strong&gt;csv&lt;/strong&gt; or &lt;strong&gt;json&lt;/strong&gt;) file, and download photos.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h1&gt;
  
  
  Coding using playwright
&lt;/h1&gt;

&lt;p&gt;Let's dive in and discover how to use playwright to extract content from multiple pages by following the next page link.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;em&gt;scrollDownUntilNoMoreContent&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;This function is designed to scroll down a web page until no more content is loaded. Here's a breakdown of its functionality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Presses the "End" key to scroll to the bottom of the page.&lt;/li&gt;
&lt;li&gt;Waits for a search container element &lt;em&gt;".search .v-lazy:nth-child(4) .search-view-item"&lt;/em&gt; to appear on the page.&lt;/li&gt;
&lt;li&gt;Scrolls down the page incrementally until the bottom is reached, using a timer-based approach (&lt;em&gt;setInterval&lt;/em&gt;) to simulate scrolling behavior.&lt;/li&gt;
&lt;li&gt;Waits for the page to reach a stable state with no network activity &lt;em&gt;"networkidle"&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;span class="cm"&gt;/**
 * Scrolls down the page until no more content is loaded.
 * @param {Page} page - The Playwright page object.
 * @param {number} nbPage - The page number for logging purposes.
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scrollDownUntilNoMoreContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nbPage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`scroll down until no more content in page : &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nbPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Presses the "End" key to scroll to the bottom of the page.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;down&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;End&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Waits for the search container element to appear on the page.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchContainerPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Scrolls down the page until the bottom is reached.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;totalHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;scrollHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;scrollHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scrollBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;totalHeight&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;totalHeight&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;scrollHeight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Waits for the page to reach a stable state with no network activity.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForLoadState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;networkidle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  2. &lt;em&gt;scrapePageContent&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;This function is responsible for scraping the content of a web page, particularly products, and extracting relevant information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calls the &lt;strong&gt;scrollDownUntilNoMoreContent&lt;/strong&gt; function to ensure all content is loaded before scraping.&lt;/li&gt;
&lt;li&gt;Utilizes Playwright's &lt;em&gt;page.evaluate&lt;/em&gt; method to execute JavaScript code within the context of the page, extracting product data based on CSS selectors.&lt;/li&gt;
&lt;li&gt;Constructs an array of objects containing product information, including &lt;em&gt;ID, image URL, title, price,...&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Returns the array of scraped product data.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/**
 * Scrapes the content of the current page.
 * @param {Page} page - The Playwright page object.
 * @param {number} nbPage - The page number for logging purposes.
 * @returns {Array} - An array containing the scraped products.
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scrapePageContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nbPage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Scrolls down the page until no more content is loaded.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;scrollDownUntilNoMoreContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nbPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Logs the page URL being scraped.&lt;/span&gt;
    &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Scraping content of page &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nbPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Evaluates JavaScript in the context of the page to scrape product data.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPageProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="cm"&gt;/**
         * Extracts product information from the page.
         * @param {string} searchContainerPath - The CSS selector for the search items.
         * @returns {Array} - An array containing the scraped product data.
         */&lt;/span&gt;
        &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;searchContainerPath&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchContainerPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.v-card.o-announ-card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imgEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.o-announ-card-image img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;titleEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h3.o-announ-card-title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;priceEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;span.price &amp;gt; span &amp;gt; div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;infosEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div.col.py-0.px-0.my-1 &amp;gt; span.v-chip&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;othersEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.mb-1.d-flex.flex-column.flex-gap-1.line-height-1 &amp;gt; span&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="na"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imgEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;titleEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                        &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;priceEl&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;priceEl&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="p"&gt;},&lt;/span&gt;
                        &lt;span class="na"&gt;infos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;infosEl&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
                            &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;othersEl&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;timeAgo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;othersEl&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;};&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;searchContainerPath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Logs the number of scraped results.&lt;/span&gt;
    &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Scrap results: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;currentPageProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Returns the scraped product data.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;currentPageProducts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  3. &lt;em&gt;navigateToNextPage&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;This function is responsible for navigating to the next page of search results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Waits for the next page link to appear on the page.&lt;/li&gt;
&lt;li&gt;Locates the next page link element &lt;em&gt;“.v-pagination&lt;/em&gt;&lt;em&gt;next”&lt;/em&gt; using the provided CSS selector.&lt;/li&gt;
&lt;li&gt;If the next page link is found:

&lt;ul&gt;
&lt;li&gt;Clicks the link to navigate to the next page.&lt;/li&gt;
&lt;li&gt;Waits for the search container element to appear, ensuring the page is fully loaded.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If the next page link is not found, it throws an error indicating the inability to navigate to the next page.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/**
 * Navigates to the next page of search results.
 * @param {Page} page - The Playwright page object.
 * @param {number} nbPage - The page number for logging purposes.
 * @throws {Error} - If unable to navigate to the next page.
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigateToNextPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nbPage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Waits for the next page link to appear on the page.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextPageLinkPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Locates the next page link element on the page.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextPageLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextPageLinkPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Checks if the next page link is found.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextPageLink&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Clicks the next page link and waits for the search container element to appear.&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="nx"&gt;nextPageLink&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchContainerPath&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="c1"&gt;// Logs the navigation to the next page.&lt;/span&gt;
        &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Navigating to the next page &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nbPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Throws an error if unable to navigate to the next page.&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s2"&gt;`Can't navigate to the next page: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nbPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  4. &lt;em&gt;saveData&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;This function provides a convenient way to organize and store scraped data in multiple formats (JSON, CSV), facilitating further analysis and processing, it also allows optionally download images associated with the scraped products:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a directory to store the results and images, ensuring it exists recursively.&lt;/li&gt;
&lt;li&gt;Constructs the filename for the JSON and CSV files based on the product type.&lt;/li&gt;
&lt;li&gt;Saves the scraped data to a JSON file using the &lt;strong&gt;saveToJsonFile&lt;/strong&gt; function.&lt;/li&gt;
&lt;li&gt;Saves the scraped data to a CSV file using the *&lt;em&gt;saveToCsvFile *&lt;/em&gt; function.&lt;/li&gt;
&lt;li&gt;If the &lt;strong&gt;withDownloadingImages&lt;/strong&gt; flag is set to true:

&lt;ul&gt;
&lt;li&gt;Constructs the path for the images directory within the results directory.&lt;/li&gt;
&lt;li&gt;Downloads images associated with the scraped products to the images directory using the &lt;strong&gt;downloadImages&lt;/strong&gt; function.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/**
 * Saves scraped data to JSON, CSV, and optionally downloads images.
 * @param {string} productType - The type of product being saved.
 * @param {Array} products - An array containing the scraped product data.
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;saveData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Creates a directory to store results, including images.&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultsDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imagesPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultsDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;images&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imagesPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Constructs the filename for JSON and CSV files.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultsDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Saves scraped data to JSON file.&lt;/span&gt;
    &lt;span class="nf"&gt;saveToJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Saves scraped data to CSV file.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveToCsvFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.csv`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Optionally downloads images associated with the scraped data.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;withDownloadingImages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;downloadImages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imagesPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  5. Main
&lt;/h4&gt;

&lt;p&gt;This is the main function, it orchestrates the web scraping process by performing the following tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launches a new Chromium browser instance and opens a new page in the browser context and navigates to URL products.&lt;/li&gt;
&lt;li&gt;Retrieves the total number of pages to scrape from the pagination element on the page.&lt;/li&gt;
&lt;li&gt;Iterates over each page to scrape content, accumulating products in an array.&lt;/li&gt;
&lt;li&gt;Navigates to the next page if not the last page.&lt;/li&gt;
&lt;li&gt;Saves scraped data to JSON, CSV, and optionally downloads images.&lt;/li&gt;
&lt;li&gt;Closes the browser and exits the process.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/**
 * Main function to orchestrate the web scraping process.
 */&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Launches a new Chromium browser instance.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Consider making headless: true for production&lt;/span&gt;

    &lt;span class="c1"&gt;// Creates a new browser context.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Opens a new page in the browser context.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Navigates to the specified URL and waits for the page to load.&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paginationPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Retrieves the total number of pages to scrape.&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;totalPages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="cm"&gt;/**
             * Retrieves the total number of pages from the pagination element.
             * @param {string} paginationPath - The CSS selector for the pagination element.
             * @returns {number} - The total number of pages to scrape.
             */&lt;/span&gt;
            &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;paginationPath&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paginationElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paginationPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;paginationElement&lt;/span&gt;
                    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paginationElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;length&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;paginationPath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Logs the URL, number of pages to scrape, and separator.&lt;/span&gt;
        &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s2"&gt;`
            #######################################################
            URL: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
            Pages to scrape: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
            #######################################################
        `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Array to store scraped products.&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nbPages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numberOfPagesToScrape&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Iterates over each page to scrape content.&lt;/span&gt;
        &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;nbPages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPageProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;scrapePageContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;currentPageProducts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// Navigates to the next page if not the last page.&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;nbPages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;navigateToNextPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Logs the total number of scraped products.&lt;/span&gt;
        &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s2"&gt;`
            #######################################################
            Total scraped products : &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
            #######################################################
        `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Saves scraped data to JSON, CSV, and optionally downloads images.&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Logs any errors that occur during scraping.&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error while scraping:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Closes the browser and exits the process.&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You can find the full code on &lt;a href="https://github.com/DEVLOKER/playwright-scraping" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Web scraping with Playwright opens up a world of possibilities for developers seeking to extract data from the web efficiently and responsibly. By harnessing the power of Playwright's automation capabilities and cross-browser compatibility, developers can streamline their web scraping workflows and extract valuable insights from a wide range of websites, but it's essential to navigate this process with legal and ethical considerations in mind.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Implementing Authentication with JWT Tokens in React and Express.js</title>
      <dc:creator>DEVLOKER</dc:creator>
      <pubDate>Sat, 20 Apr 2024 21:22:32 +0000</pubDate>
      <link>https://dev.to/devloker/authentication-with-jwt-tokens-in-react-and-expressjs-5o9</link>
      <guid>https://dev.to/devloker/authentication-with-jwt-tokens-in-react-and-expressjs-5o9</guid>
      <description>&lt;p&gt;Hello developers!&lt;/p&gt;

&lt;p&gt;Authentication is a crucial aspect of modern web development, ensuring that users can securely access resources and data. One popular method for implementing authentication is through the use of JSON Web Tokens (JWT). In this post, we'll delve into the concept of JWT tokens (accessToken &amp;amp; refreshToken), how they work, and then explore a practical implementation using React for the client-side and Express.js for the server-side.&lt;/p&gt;

&lt;h1&gt;
  
  
  Understanding JWT Tokens
&lt;/h1&gt;

&lt;p&gt;JSON Web Tokens (JWT) are an open, industry standard &lt;a href="https://tools.ietf.org/html/rfc7519" rel="noopener noreferrer"&gt;RFC 7519&lt;/a&gt; method for representing claims securely between two parties. They provide a compact and self-contained way to transmit information between parties as a JSON object. JWT tokens consist of three parts: a header, a payload, and a signature.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Header
&lt;/h3&gt;

&lt;p&gt;The header typically consists of two parts: the type (&lt;strong&gt;typ&lt;/strong&gt;) of token which is "JWT", and the signing algorithm (&lt;strong&gt;alg&lt;/strong&gt;) being used, such as HMAC SHA256 or RSA.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"typ"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JWT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HS256"&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  

&lt;ol&gt;
&lt;li&gt;Payload
&lt;/li&gt;
&lt;/ol&gt;
&lt;/h3&gt;


&lt;p&gt;The payload contains the claims such as the expiration-time (&lt;strong&gt;exp&lt;/strong&gt;) and Issued-at (&lt;strong&gt;iat&lt;/strong&gt;), which are statements about the user and additional data. Custom claims are usually also included, depending on the purpose of the token.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1713636257&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Issued-at&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1713636557&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;expiration-time&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ab86a1e1ef70dff97959067b723c5c24"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;custom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;claim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;userId&lt;/span&gt;&lt;span class="w"&gt;&lt;br&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  

&lt;ol&gt;
&lt;li&gt;Signature
&lt;/li&gt;
&lt;/ol&gt;
&lt;/h3&gt;


&lt;p&gt;The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way. The signature is created by combining the encoded header, the encoded payload, a secret key, and the specified algorithm.&lt;/p&gt;

&lt;p&gt;The three parts (header, a payload, and a signature) are encoded separately using Base64url Encoding &lt;a href="https://datatracker.ietf.org/doc/html/rfc4648" rel="noopener noreferrer"&gt;RFC 4648&lt;/a&gt;, and concatenated using periods to produce the JWT, something like this &lt;a href="https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImFiODZhMWUxZWY3MGRmZjk3OTU5MDY3YjcyM2M1YzI0IiwiaWF0IjoxNzEzNjQyMDUxLCJleHAiOjE3MTM2NDIzNTF9.hfRGkwX3ASdMm-tzR5NA_vy6DrTL7i6Doxt1U99LGUE" rel="noopener noreferrer"&gt;jwt.io&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImFiODZhMWUxZWY3MGRmZjk3OTU5MDY3YjcyM2M1YzI0IiwiaWF0IjoxNzEzNjQyMDUxLCJleHAiOjE3MTM2NDIzNTF9.hfRGkwX3ASdMm-tzR5NA_vy6DrTL7i6Doxt1U99LGUE&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Authentication with JWT Tokens
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Access Token
&lt;/h3&gt;

&lt;p&gt;In the context of authentication, the access token is a JWT token that represents the authorization granted to the user. It typically contains information such as the user's ID and any relevant permissions. Access tokens have a short lifespan to minimize the risk if they are intercepted. They are used to access protected resources on the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refresh Token
&lt;/h3&gt;

&lt;p&gt;Alongside the access token, a refresh token is often issued to the client during authentication. The refresh token is also a JWT token but with a longer lifespan. Its purpose is to obtain a new access token once the current one expires. Refresh tokens are securely stored on the client-side and are only sent to the server when requesting a new access token.&lt;/p&gt;

&lt;h3&gt;
  
  
  How they work!
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When a user logs in, the server generates a JWT token and sends it back to the client. This token is then included in subsequent requests to authenticate the user. The server can verify the token's authenticity and extract the necessary information from the payload to grant access to protected resources.&lt;/li&gt;
&lt;li&gt;When the access token expires, the client can use the refresh token to obtain a new access token without requiring the user to log in again. The server receives the refresh token, verifies its authenticity, and issues a new access token if the refresh token is valid. This process helps maintain a seamless user experience while ensuring security by regularly rotating access tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, both JWT tokens (access tokens &amp;amp; refresh tokens) can implement robust authentication mechanisms that protect user data while providing a seamless user experience.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Implementation with React and Express.js
&lt;/h1&gt;

&lt;p&gt;In our implementation, we'll use React with Redux Toolkit on the client-side and Express.js on the server-side. Our server will consist of two parts: an authentication server and a resource server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The authentication server&lt;/strong&gt;: running on port 8800, will handle login, logout, and refreshing access tokens. We'll secure the login and refresh routes using express-rate-limit to prevent brute force attacks and limit the number of requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The resource server&lt;/strong&gt;: running on port 8080, will expose a protected resource accessible only to authenticated users.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Code Walkthrough
&lt;/h1&gt;

&lt;p&gt;Let's dive into the code to see how it all comes together. We'll start with the client-side implementation in React, where we'll manage authentication state using Redux Toolkit. Then, we'll explore the server-side implementation in Express.js, where we'll define routes for login, logout, and refresh-access-token.&lt;br&gt;
You can find the complete code repository &lt;a href="https://github.com/DEVLOKER/JWT-Practice" rel="noopener noreferrer"&gt;JWT-Practice&lt;/a&gt;, which includes detailed comments to guide you through each step.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

&lt;p&gt;Feel free to adjust the content as needed to fit your style and the specific details of your implementation!&lt;/p&gt;

&lt;h1&gt;
  
  
  Future Perspectives
&lt;/h1&gt;

&lt;p&gt;As we wrap up, it's essential to consider future perspectives for our authentication system. One such perspective is enabling users to logging in from different devices securely. This can be achieved by associating each JWT token with a unique device identifier and implementing session management to revoke tokens when necessary.&lt;/p&gt;

&lt;p&gt;In conclusion, JWT tokens provide a robust and scalable solution for authentication in modern web applications. By understanding their inner workings and implementing them in our projects, we can ensure secure access to resources while providing a seamless user experience.&lt;/p&gt;

&lt;p&gt;I hope this post provides valuable insights into authentication using JWT tokens with React and Express.js. Feel free to leave any questions or feedback in the comments below!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Deploying React Projects Located in Subdirectories to GitHub Pages Using GitHub Actions (CI/CD)</title>
      <dc:creator>DEVLOKER</dc:creator>
      <pubDate>Thu, 11 Apr 2024 06:58:37 +0000</pubDate>
      <link>https://dev.to/devloker/deploy-a-react-projects-that-are-inside-a-subdirectories-to-github-pages-using-github-actions-cicd-3n9l</link>
      <guid>https://dev.to/devloker/deploy-a-react-projects-that-are-inside-a-subdirectories-to-github-pages-using-github-actions-cicd-3n9l</guid>
      <description>&lt;p&gt;Hello developers!&lt;/p&gt;

&lt;p&gt;Let's suppose that you have multiple React projects within the same GitHub repository, and you're looking to deploy them all to GitHub Pages while automating the deployment process for each commit, you've come to the right place!&lt;/p&gt;

&lt;p&gt;Today, I'd like to share some of the challenges I encountered while setting up a CI/CD pipeline via GitHub Actions for recent react projects I've been working on. Specifically, I'll be focusing on a scenario where I have a GitHub repository named &lt;a href="https://github.com/DEVLOKER/react-challenges"&gt;&lt;code&gt;react-challenges&lt;/code&gt;&lt;/a&gt;, which contains multiple React projects, each residing in a subdirectory (&lt;code&gt;accordion&lt;/code&gt;, &lt;code&gt;guess-word&lt;/code&gt;, &lt;code&gt;landing-page&lt;/code&gt;, &lt;code&gt;tic-tac-toe&lt;/code&gt;, and &lt;code&gt;tree&lt;/code&gt;).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Are you ready? Let's dive in!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Customize &lt;code&gt;vite.config.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;First you have to know that all those react projects are created using &lt;a href="https://vitejs.dev"&gt;Vite&lt;/a&gt;, and for each of them, you need change the &lt;code&gt;vite.config.ts&lt;/code&gt; file by adding the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8r4itgx5dobynynancw3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8r4itgx5dobynynancw3.jpg" alt="vite.config.ts after changes" width="747" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The default build folder for a Vite project is &lt;code&gt;dist&lt;/code&gt;, however in my projects I used &lt;code&gt;build&lt;/code&gt; folder. So, If you prefer to use the default, make sure to adjust the paths accordingly in the YAML file (step 2).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Create &lt;code&gt;deploy.yml&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Create a deployment file named &lt;code&gt;deploy.yml&lt;/code&gt; inside the &lt;code&gt;.github/workflows&lt;/code&gt; directory and paste the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy static content to Pages&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pages"&lt;/span&gt;
  &lt;span class="na"&gt;cancel-in-progress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Node&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;

      &lt;span class="c1"&gt;# landing-page project&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build landing-page&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cd landing-page&lt;/span&gt;
          &lt;span class="s"&gt;npm install &amp;amp;&amp;amp; npm run build&lt;/span&gt;
          &lt;span class="s"&gt;cd ..&lt;/span&gt;
          &lt;span class="s"&gt;mkdir -p deploy/landing-page&lt;/span&gt;
          &lt;span class="s"&gt;cp -r landing-page/build/* deploy/landing-page/&lt;/span&gt;
      &lt;span class="c1"&gt;# tic-tac-toe project&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build tic-tac-toe&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cd tic-tac-toe&lt;/span&gt;
          &lt;span class="s"&gt;npm install &amp;amp;&amp;amp; npm run build&lt;/span&gt;
          &lt;span class="s"&gt;cd ..&lt;/span&gt;
          &lt;span class="s"&gt;mkdir -p deploy/tic-tac-toe&lt;/span&gt;
          &lt;span class="s"&gt;cp -r tic-tac-toe/build/* deploy/tic-tac-toe/&lt;/span&gt;
      &lt;span class="c1"&gt;# guess-word project&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build guess-word&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cd guess-word&lt;/span&gt;
          &lt;span class="s"&gt;npm install &amp;amp;&amp;amp; npm run build&lt;/span&gt;
          &lt;span class="s"&gt;cd ..&lt;/span&gt;
          &lt;span class="s"&gt;mkdir -p deploy/guess-word&lt;/span&gt;
          &lt;span class="s"&gt;cp -r guess-word/build/* deploy/guess-word/&lt;/span&gt;
      &lt;span class="c1"&gt;# accordion project&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build accordion&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cd accordion&lt;/span&gt;
          &lt;span class="s"&gt;npm install &amp;amp;&amp;amp; npm run build&lt;/span&gt;
          &lt;span class="s"&gt;cd ..&lt;/span&gt;
          &lt;span class="s"&gt;mkdir -p deploy/accordion&lt;/span&gt;
          &lt;span class="s"&gt;cp -r accordion/build/* deploy/accordion/&lt;/span&gt;
      &lt;span class="c1"&gt;# tree project&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build tree&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cd tree&lt;/span&gt;
          &lt;span class="s"&gt;npm install &amp;amp;&amp;amp; npm run build&lt;/span&gt;
          &lt;span class="s"&gt;cd ..&lt;/span&gt;
          &lt;span class="s"&gt;mkdir -p deploy/tree&lt;/span&gt;
          &lt;span class="s"&gt;cp -r tree/build/* deploy/tree/&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Pages&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/configure-pages@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload artifact&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-pages-artifact@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./deploy"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to GitHub Pages&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deployment&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/deploy-pages@v4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this YAML file do? after building the projects, will copy the &lt;code&gt;build&lt;/code&gt; output of each project to a root folder named &lt;code&gt;./deploy&lt;/code&gt;, while the root folder will be served at the following link: &lt;code&gt;https://{username}.github.io/react-challenges/&lt;/code&gt;.&lt;br&gt;
And each project will be accessible by adding its subdirectory name to the end of the root link: &lt;code&gt;https://{username}.github.io/react-challenges/{react-sub-directory}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In my case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://DEVLOKER.github.io/react-challenges/guess-word"&gt;https://DEVLOKER.github.io/react-challenges/guess-word&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://DEVLOKER.github.io/react-challenges/tic-tac-toe"&gt;https://DEVLOKER.github.io/react-challenges/tic-tac-toe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://DEVLOKER.github.io/react-challenges/landing-page"&gt;https://DEVLOKER.github.io/react-challenges/landing-page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://DEVLOKER.github.io/react-challenges/accordion"&gt;https://DEVLOKER.github.io/react-challenges/accordion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devloker.github.io/react-challenges/tree"&gt;https://devloker.github.io/react-challenges/tree&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. GitHub Repository Settings
&lt;/h3&gt;

&lt;p&gt;Ensure that the build and deployment source are set to &lt;code&gt;GitHub Actions&lt;/code&gt; from &lt;code&gt;Settings/Pages/Build and deployment&lt;/code&gt;. &lt;/p&gt;

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

&lt;p&gt;Also, grant read and write permissions for Workflow permissions by checking &lt;code&gt;Read and write permissions&lt;/code&gt; from &lt;code&gt;Settings/Actions/General/Workflow permissions&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Finally, with these configurations in place, your deployment process should end successfully!&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Thats all!&lt;/strong&gt; &lt;br&gt;
I really hope this post was beneficial to you and saved you some research/debug time. If you find any thing incorrect or lacking in explanation, please leave a comment and I will edit accordingly.&lt;/p&gt;

&lt;p&gt;Feel free to fork the &lt;a href="https://github.com/DEVLOKER/react-challenges"&gt;Github repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the deployed GitHub Pages for each project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://DEVLOKER.github.io/react-challenges/guess-word"&gt;Guess-Word&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://DEVLOKER.github.io/react-challenges/tic-tac-toe"&gt;Tic-Tac-Toe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://DEVLOKER.github.io/react-challenges/landing-page"&gt;Landing Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://DEVLOKER.github.io/react-challenges/accordion"&gt;Accordion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devloker.github.io/react-challenges/tree"&gt;Tree&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy coding and deploying!&lt;/p&gt;

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