<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Karan Rathod</title>
    <description>The latest articles on Forem by Karan Rathod (@karanrathod316).</description>
    <link>https://forem.com/karanrathod316</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%2F1132212%2F0fd4f15c-8c4d-4f19-bedc-3a3a903f35d6.jpg</url>
      <title>Forem: Karan Rathod</title>
      <link>https://forem.com/karanrathod316</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/karanrathod316"/>
    <language>en</language>
    <item>
      <title>[This is a great read!]</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Wed, 18 Feb 2026 11:37:07 +0000</pubDate>
      <link>https://forem.com/karanrathod316/-1om5</link>
      <guid>https://forem.com/karanrathod316/-1om5</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/nigel_t" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1913196%2F81b71ba0-ac42-4063-8868-6d342a2591f7.png" alt="nigel_t"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/nigel_t/speed-vs-control-the-structural-conflict-inside-enterprise-application-development-304b" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Speed vs Control: The Structural Conflict Inside Enterprise Application Development&lt;/h2&gt;
      &lt;h3&gt;Nigel Tape ・ Feb 4&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#enterprise&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#compliance&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#internal&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#architecture&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>enterprise</category>
      <category>compliance</category>
      <category>internal</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Build An Audio Transcriber and Analyzer using ToolJet and OpenAI🎙️</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Thu, 29 Aug 2024 12:00:00 +0000</pubDate>
      <link>https://forem.com/tooljet/build-an-audio-transcriber-and-analyzer-using-tooljet-and-openai-1109</link>
      <guid>https://forem.com/tooljet/build-an-audio-transcriber-and-analyzer-using-tooljet-and-openai-1109</guid>
      <description>&lt;p&gt;In this hands-on tutorial, we’ll learn how to build a powerful audio transcriber and analyzer using ToolJet and Open AI. We'll quickly design an intuitive UI using ToolJet's pre-built &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-components/" rel="noopener noreferrer"&gt;components&lt;/a&gt;, and then use the platform's &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries" rel="noopener noreferrer"&gt;query builder&lt;/a&gt; to interact with Open AI for audio transcription and analysis.&lt;/p&gt;

&lt;p&gt;By the end of this tutorial, we'll have a fundamental structure to build more sophisticated transcription and audio analysis applications.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ToolJet&lt;/strong&gt; (&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source, low-code platform designed for quickly building and deploying internal tools. Sign up for a free ToolJet cloud account &lt;a href="https://app.tooljet.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open AI Account&lt;/strong&gt; : Register for an Open AI account to utilize AI-powered features in your ToolJet applications. Sign up &lt;a href="https://openai.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Here's a quick preview of what we are going to build:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ffvahkytka6o04f3d76g7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffvahkytka6o04f3d76g7.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before you begin, go to the &lt;a href="https://platform.openai.com/api-keys" rel="noopener noreferrer"&gt;Open AI Console&lt;/a&gt;, and copy your secret key. Next, login to your &lt;a href="https://app.tooljet.com/" rel="noopener noreferrer"&gt;ToolJet account&lt;/a&gt;, locate the &lt;strong&gt;Data Sources&lt;/strong&gt; section on the left sidebar, and configure Open AI as a data source using the secret key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fnu5xh4zzjm076lsonfdn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fnu5xh4zzjm076lsonfdn.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the data source is configured, create a new app called "Speech Insight" from the dashboard. And with that, we are ready to start building our application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Building the UI for the Audio Transcriber
&lt;/h2&gt;

&lt;p&gt;Let's use ToolJet's visual app builder to design our UI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the app header, drag and drop an &lt;strong&gt;Icon&lt;/strong&gt; component on the canvas. Navigate to its properties panel on the right, and select the &lt;code&gt;IconBrandDingtalk&lt;/code&gt; icon.&lt;/li&gt;
&lt;li&gt;Drop a &lt;strong&gt;Text&lt;/strong&gt; component next to it, and enter "Speech Insight" under its Data property.&lt;/li&gt;
&lt;li&gt;Change the color of both components to blue (&lt;code&gt;#3E63DD&lt;/code&gt;). This will be the primary color scheme of our app, update the color scheme of the remaining components accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ftft7as3w2n2hydid22ll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftft7as3w2n2hydid22ll.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Place a &lt;strong&gt;Container&lt;/strong&gt; component below the header. We will organize the upcoming components inside the Container component.&lt;/li&gt;
&lt;li&gt;Rename it to &lt;code&gt;mainContainer&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fpxfzmcowcuthl26rgz0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fpxfzmcowcuthl26rgz0w.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the top left of the Container component, place a &lt;strong&gt;Text&lt;/strong&gt; component with the label "Output".&lt;/li&gt;
&lt;li&gt;Below it, add another &lt;strong&gt;Container&lt;/strong&gt; and place two &lt;strong&gt;Text&lt;/strong&gt; components inside it. We will use these components to display the transcribed text and feedback. Name them &lt;code&gt;transcribedText&lt;/code&gt; and &lt;code&gt;feedback&lt;/code&gt; respectively.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;File Picker&lt;/strong&gt; component below it and rename it to &lt;code&gt;uploader&lt;/code&gt;. Change its &lt;code&gt;Accept file types&lt;/code&gt; property to &lt;code&gt;"audio/*"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Place a &lt;strong&gt;Button&lt;/strong&gt; component below it and rename it to &lt;code&gt;analyzeButton&lt;/code&gt; and add an "Analyze Button" label to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F1hn33z3rpcx6v5omuchx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F1hn33z3rpcx6v5omuchx.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; We are renaming key components to make them easier to reference in other parts of our application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finally, place four &lt;strong&gt;Statistics&lt;/strong&gt; components on the right for Fluency, Pronunciation, Intonation, and Vocabulary scores.&lt;/li&gt;
&lt;li&gt;Drop a &lt;strong&gt;Button&lt;/strong&gt; component below it labeled "Copy Output" and rename it to &lt;code&gt;copyButton&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fbl7w02dtioa3ibwqga8t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fbl7w02dtioa3ibwqga8t.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The UI is now ready! Time to configure the interactions with Open AI.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Interact With Open AI
&lt;/h2&gt;

&lt;p&gt;In the below steps, we will go through the configuration to interact with Open AI using both REST API and ToolJet's native integration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expand the query panel at the bottom and click on the &lt;strong&gt;Add&lt;/strong&gt; button to create a new REST API query. Rename the query to &lt;code&gt;transcribe&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Enter the Open AI URL under the &lt;code&gt;URL&lt;/code&gt; property: &lt;code&gt;https://api.openai.com/v1/audio/transcriptions&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a new row under &lt;strong&gt;Header&lt;/strong&gt;, enter &lt;code&gt;Content-Type&lt;/code&gt; as the key and &lt;code&gt;multipart/form-data&lt;/code&gt; as the value.&lt;/li&gt;
&lt;li&gt;Add another key for &lt;code&gt;Authorization&lt;/code&gt;. Enter &lt;code&gt;Bearer &amp;lt;OPEN_AI_KEY&amp;gt;&lt;/code&gt; in the value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fg1wpbxyluwy29otqhipr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fg1wpbxyluwy29otqhipr.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under &lt;strong&gt;Body&lt;/strong&gt;, add &lt;code&gt;file&lt;/code&gt; as the key and value as &lt;code&gt;{{ components.uploader.file[0] }}&lt;/code&gt;. This will ensure the audio file selected in our uploader/File Picker component is sent.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;model&lt;/code&gt; as the key and enter &lt;code&gt;whisper-1&lt;/code&gt; as the value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fd4pgec9dp0htbqp0jfbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fd4pgec9dp0htbqp0jfbw.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now if we select an audio file in the uploader/File Picker component and click on the &lt;strong&gt;Run&lt;/strong&gt; button, we will see the transcribed audio as the output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fuwgdw0sq52bsbixc1wfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fuwgdw0sq52bsbixc1wfs.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the audio is transcribed, we need to analyze it to provide a score. Let's use the native Open AI integration for this query.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the &lt;strong&gt;Add&lt;/strong&gt; button and add a new query. Select &lt;strong&gt;Open AI&lt;/strong&gt; as the data source for this query. This is the same data source that we had set up at the beginning. Rename it to &lt;code&gt;analyze&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Chat&lt;/strong&gt; as the operation and &lt;strong&gt;Message&lt;/strong&gt; as input, and enter the below prompt:
&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="nx"&gt;Based&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;transcribed&lt;/span&gt; &lt;span class="nx"&gt;audio&lt;/span&gt; &lt;span class="nx"&gt;below&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;provide&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; 
&lt;span class="nx"&gt;JSON&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

   &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Fluency &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Pronunciation &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Vocabulary &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Intonation &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;paragraph&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;gives&lt;/span&gt; &lt;span class="nx"&gt;general&lt;/span&gt; &lt;span class="nx"&gt;feedback&lt;/span&gt; 
&lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;transcribed&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s quality and overall improvement suggestions.

   Return the object in the following format:

   {fluency: "...", pronunciation: "...", 
vocabulary: "...", intonation: "...", feedback: "..."}

   Transcribed text:
   {{queries.transcribe.data.text}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fe2qacepaqbz6z5jozaaj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fe2qacepaqbz6z5jozaaj.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this prompt, we are using Open AI to perform a detailed analysis of the audio transcription. We are referencing the data returned by the &lt;code&gt;transcribe&lt;/code&gt; query in the prompt along with other scoring criteria. &lt;/p&gt;

&lt;p&gt;Running this query will result in the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcfkw4y3qw3gmgrvmh6y1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcfkw4y3qw3gmgrvmh6y1.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both the queries are ready. As a final step, let's automate the process of triggering the &lt;code&gt;analyze&lt;/code&gt; query every time the &lt;code&gt;transcribe&lt;/code&gt; query is successfully executed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go back to the &lt;code&gt;transcribe&lt;/code&gt; query, navigate to &lt;strong&gt;Events&lt;/strong&gt; and add a new &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-events/" rel="noopener noreferrer"&gt;event&lt;/a&gt; handler.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Query Success&lt;/strong&gt; as the Event, &lt;strong&gt;Run Query&lt;/strong&gt; as the Action, and &lt;code&gt;analyze&lt;/code&gt; as the Query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fdcbwgj5whjp2u3lzkeso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fdcbwgj5whjp2u3lzkeso.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By using events, we have set up the process of triggering the &lt;code&gt;analyze&lt;/code&gt; query after the &lt;code&gt;transcribe&lt;/code&gt; query is triggered and is ready with the output for analysis.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Binding the Transcripts and Analysis to Components
&lt;/h2&gt;

&lt;p&gt;Onto the final step. We have built our UI and also built queries to interact with Open AI. Now we can connect it all together and see the app in action.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the &lt;strong&gt;Analyze Audio&lt;/strong&gt; button, navigate to its properties panel on the right and add a new event.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;On click&lt;/strong&gt; as the Event, &lt;strong&gt;Run Query&lt;/strong&gt; as the Action, and &lt;code&gt;transcribe&lt;/code&gt; as the Query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now every time the Analyze Audio button is clicked, it will trigger the &lt;code&gt;transcribe&lt;/code&gt; query.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the &lt;strong&gt;Copy Output&lt;/strong&gt; button and add a new event to it.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;On click&lt;/strong&gt; as the Event, &lt;strong&gt;Copy to clipboard&lt;/strong&gt; as the Action, and &lt;code&gt;{{queries.analyze.data}}&lt;/code&gt; as the Text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This configuration will ensure that the analyzed output gets copied when you click on the Copy Output button.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;Text&lt;/strong&gt; component that we had placed to display the transcript. Enter the following value under its Data property:&lt;br&gt;
&lt;strong&gt;Transcript:&lt;/strong&gt; &lt;code&gt;{{queries.transcribe.data.text}}&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;Text&lt;/strong&gt; component to display the feedback. Enter the following value under its Data property:&lt;br&gt;
&lt;strong&gt;Feedback:&lt;/strong&gt; &lt;code&gt;{{JSON.parse(queries.analyze.data).feedback}}&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; We received a JSON string in response to our &lt;code&gt;analyze&lt;/code&gt; query. Therefore, we need to parse it to construct a JavaScript object before displaying it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;Statistics&lt;/strong&gt; component for "Fluency" and enter the below value under its &lt;code&gt;Primary value&lt;/code&gt; property:&lt;br&gt;
&lt;code&gt;{{JSON.parse(queries.analyze.data).fluency}}&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the rest of the Statistics components using the same logic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our audio transcriber and analyzer is now fully complete. Upload an audio file and click on the Analyze Audio button to see the transcription, feedback, and scores getting populated in the UI. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fh4qq0bzys8izun9tvfng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fh4qq0bzys8izun9tvfng.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;In this tutorial, we learned how to create a complete audio transcription and analysis tool using ToolJet and OpenAI. We walked through designing an intuitive user interface, setting up API queries to interact with OpenAI, and binding the results to display transcriptions, feedback, and speech analysis scores.&lt;/p&gt;

&lt;p&gt;To further customize the application, experiment with different UI components to enhance the user experience or integrate additional APIs to analyze other aspects of the audio, such as emotion detection or language translation.&lt;/p&gt;

&lt;p&gt;To learn more, check out ToolJet's official &lt;a href="https://docs.tooljet.com/docs/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; or connect on &lt;a href="https://tooljet.slack.com" rel="noopener noreferrer"&gt;Slack&lt;/a&gt; for questions or queries.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>Build an Advanced Web Scraping Tool Using ToolJet and Scraper API! 🚀 🛠️</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Thu, 15 Aug 2024 12:35:05 +0000</pubDate>
      <link>https://forem.com/tooljet/build-an-advanced-web-scraping-tool-using-tooljet-and-scraper-api-fp7</link>
      <guid>https://forem.com/tooljet/build-an-advanced-web-scraping-tool-using-tooljet-and-scraper-api-fp7</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Scraping data can be tedious, especially when dealing with dynamic content. However, it becomes a lot more convenient if you can instantly preview the data scraped in the UI. ToolJet, combined with &lt;a href="https://www.scraperapi.com/" rel="noopener noreferrer"&gt;Scraper API&lt;/a&gt;, enables exactly that. This tutorial shows how to set up a script to scrape data using ToolJet and display the results in real time.&lt;/p&gt;

&lt;p&gt;If you've worked with web scraping using &lt;a href="https://colab.research.google.com/" rel="noopener noreferrer"&gt;Google Colab&lt;/a&gt; or tools like &lt;a href="https://www.selenium.dev/" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;, you know the challenges. Here, we'll take a different approach using JavaScript web scraping, utilizing ToolJet’s visual app builder to manage the data flow.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ToolJet&lt;/strong&gt; (&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source, low-code platform designed for quickly building and deploying internal tools. Sign up for a free ToolJet cloud account &lt;a href="https://app.tooljet.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Basic knowledge of &lt;strong&gt;JavaScript&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Begin by creating an application named &lt;strong&gt;TJ Web Scraper&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Designing the UI to Display the Scraped Data
&lt;/h2&gt;

&lt;p&gt;Let's use ToolJet's &lt;a href="https://docs.tooljet.com/docs/#visual-app-builder" rel="noopener noreferrer"&gt;visual app builder&lt;/a&gt; to quickly design the UI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drag and drop a &lt;strong&gt;Container&lt;/strong&gt; &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-components" rel="noopener noreferrer"&gt;component&lt;/a&gt; onto the canvas.&lt;/li&gt;
&lt;li&gt;Inside the container, place an &lt;strong&gt;Icon&lt;/strong&gt; component on the left for the logo.&lt;/li&gt;
&lt;li&gt;Place a &lt;strong&gt;Text&lt;/strong&gt; component next to it and enter "TJ Web Scraper" under its Data property.&lt;/li&gt;
&lt;li&gt;Place another &lt;strong&gt;Text&lt;/strong&gt; component on the right to display the total count of scraped products.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fv0x4w850i94wfxdb2owt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fv0x4w850i94wfxdb2owt.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We are using blue (hex code: &lt;code&gt;#075ab9&lt;/code&gt;) as the primary color for this application; change the color scheme of all the components accordingly.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;strong&gt;Table&lt;/strong&gt; component below the header and a &lt;strong&gt;Button&lt;/strong&gt; component on the bottom-right of the canvas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fp163czpzroo6q8f7iqh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fp163czpzroo6q8f7iqh3.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With that, our UI is ready in just a couple of minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Writing the JavaScript Code to Scrape Data
&lt;/h2&gt;

&lt;p&gt;In this step, we will utilize the Scraper API to scrape the data from a sample eCommerce website. Here's a preview of the website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcm9hgeo0ylg94vli8nze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcm9hgeo0ylg94vli8nze.png" alt=" " width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The website has a few products with their images, titles, and prices. Additionally, it has a load more button to dynamically load more content.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To start, expand the &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries" rel="noopener noreferrer"&gt;Query Panel&lt;/a&gt; at the bottom, and click on the &lt;strong&gt;Add&lt;/strong&gt; button to create a new Run JavaScript code query. Rename the query to &lt;strong&gt;scrapeData&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set up the main scraping function&lt;/strong&gt;: Create the &lt;code&gt;runMainScript()&lt;/code&gt; function that will coordinate all the logic needed for scraping products.&lt;br&gt;
&lt;/p&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runMainScript&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;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SCRAPER_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="c1"&gt;// Main logic goes here&lt;/span&gt;
    &lt;span class="c1"&gt;// .....&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;strong&gt;Create a request helper&lt;/strong&gt;: Build a helper function &lt;code&gt;makeRequest()&lt;/code&gt; using axios to handle API requests, manage responses, and deal with errors efficiently.
&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeRequest&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.scraperapi.com/&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;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&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="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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="k"&gt;if &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="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;404NotFound&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;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="s2"&gt;`Error making request to &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;: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extract product details&lt;/strong&gt;: Define the &lt;code&gt;parseProducts()&lt;/code&gt; function to gather relevant information (like title, price, and image) from the HTML content, filtering out incomplete data. This function uses the HTML selectors tailored to the target website.
&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parseProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&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;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DOMParser&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;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseFromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/html&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;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&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="s1"&gt;.product-item&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="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;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="o"&gt;=&amp;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;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="s1"&gt;.product-name&lt;/span&gt;&lt;span class="dl"&gt;'&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;price&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.product-price&lt;/span&gt;&lt;span class="dl"&gt;'&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;image&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;N/A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;url&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handle dynamic loading&lt;/strong&gt;: The fetchProducts() function manages the initial page load and any additional AJAX requests, collecting all available products. It saves the total count in a ToolJet &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/variables/#variables-and-page-variables" rel="noopener noreferrer"&gt;variable&lt;/a&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ajaxUrl&lt;/span&gt;&lt;span class="p"&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;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;let&lt;/span&gt; &lt;span class="nx"&gt;offset&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialPageHtml&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;makeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;initialPageHtml&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;products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&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;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parseProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialPageHtml&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;while &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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ajaxHtml&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;makeRequest&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;ajaxUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?offset=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;offset&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ajaxHtml&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&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;newProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ajaxHtml&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;newProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&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;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newProducts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Scraped &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; products so far...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Save the length of the total products fetched in a ToolJet variable&lt;/span&gt;
        &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;totalProductsScraped&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Launch the scraping process&lt;/strong&gt;: Implement the &lt;code&gt;scrapeProducts()&lt;/code&gt; function to trigger the scraping and output the final count of products collected.
&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;scrapeProducts&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;pageUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.scrapingcourse.com/button-click&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;ajaxUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.scrapingcourse.com/ajax/products&lt;/span&gt;&lt;span class="dl"&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;products&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;fetchProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ajaxUrl&lt;/span&gt;&lt;span class="p"&gt;);&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`\nTotal products scraped: &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="k"&gt;return&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Run the script and handle results&lt;/strong&gt;: Execute the scraping process, save the data, and log a sample of the products for review and handles potential errors by setting an error variable.
&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="nf"&gt;scrapeProducts&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&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;// Save all the products fetched from the eCommerce website&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scrapedProducts&lt;/span&gt;&lt;span class="dl"&gt;'&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;console&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="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Scraped products stored in 'scrapedProducts' variable.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Total 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="nx"&gt;console&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="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Sample of scraped products:&lt;/span&gt;&lt;span class="dl"&gt;"&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;slice&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&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;console&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;`Title: &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="nx"&gt;title&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;console&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;`Price: &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="nx"&gt;price&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;console&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;`Image: &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="nx"&gt;image&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;console&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;`URL: &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="nx"&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="nx"&gt;console&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="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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scrapingError&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="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&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;An error occurred:&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time to see the code in action&lt;/strong&gt; : Invoke the &lt;code&gt;runMainScript()&lt;/code&gt; function to start the entire 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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;runMainScript&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Main logic&lt;/span&gt;
    &lt;span class="c1"&gt;// .....&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;runMainScript&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The code to scrape the data is ready. The above code for web scraping will have to be adjusted based on each target website.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;strong&gt;Run&lt;/strong&gt; button on the Query Panel and check all the logs that will appear in the browser console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fxty9ufcbhgtpxadvpc3z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fxty9ufcbhgtpxadvpc3z.png" alt=" " width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 3: Displaying the Scraped Data
&lt;/h1&gt;

&lt;p&gt;With the UI and code set up, we can now focus on displaying the data on the Table component and triggering the code based on Button click.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the &lt;strong&gt;Button&lt;/strong&gt; component, navigate to its properties and create a new &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-events" rel="noopener noreferrer"&gt;event&lt;/a&gt; handler.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;On click&lt;/strong&gt; as the event, &lt;strong&gt;Run Query&lt;/strong&gt; as the action, and &lt;strong&gt;scrapeData&lt;/strong&gt; as the query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjr5m2csnvbphdbmn3wzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjr5m2csnvbphdbmn3wzt.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the &lt;strong&gt;Table&lt;/strong&gt; component, and under its Data property, enter &lt;code&gt;{{variables.scrapedProducts}}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;Text&lt;/strong&gt; component in the header that is created to display the total count of the products that are scraped. Enter the &lt;code&gt;{{"Total Products Scraped: " + variables.totalProductsScraped || 0 }}&lt;/code&gt; code under its Data property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We've successfully linked the components with the query. Now, just click the Button component and watch as the data is scraped and displayed in the Table component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fsf64qvo6tzumizp1qcfc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fsf64qvo6tzumizp1qcfc.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Scraping data effectively requires overcoming challenges like dynamic content and pagination, especially when dealing with AJAX-loaded pages. Using ToolJet combined with Scraper API, you can simplify this process and gain the ability to instantly preview and manage your scraped data through a clean UI.&lt;/p&gt;

&lt;p&gt;Unlike traditional approaches like Selenium web scraping or using Google Colab, this method integrates JavaScript web scraping seamlessly into your workflow with real-time visibility of your data. Building on this foundation, you can scale the tool to handle more complex scraping needs while maintaining an intuitive interface.&lt;/p&gt;

&lt;p&gt;To learn more, check out &lt;a href="https://docs.tooljet.com/docs/" rel="noopener noreferrer"&gt;ToolJet's official documentation&lt;/a&gt; or connect on &lt;a href="https://tooljet.slack.com/" rel="noopener noreferrer"&gt;Slack&lt;/a&gt; with any questions.💡&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webscraping</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Scrape Data From a Page With Infinite Scroll! ♾️</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Sun, 11 Aug 2024 08:07:18 +0000</pubDate>
      <link>https://forem.com/karanrathod316/how-to-scrape-data-from-a-page-with-infinite-scroll-2enk</link>
      <guid>https://forem.com/karanrathod316/how-to-scrape-data-from-a-page-with-infinite-scroll-2enk</guid>
      <description>&lt;p&gt;Web scraping can get challenging when dealing with dynamically loaded content. Modern websites often use infinite scroll or “Load more” buttons to load additional content as you scroll. While this enhances user experience, it complicates data extraction using conventional methods.&lt;/p&gt;

&lt;p&gt;In this tutorial, you’ll learn how to scrape data from a website that employs an infinite scroll mechanism. We’ll go step-by-step to fetch, parse, and save the data, eventually exporting it to a CSV file.&lt;/p&gt;

&lt;p&gt;By the end of this tutorial, you will have learned how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch HTML content from a web page.&lt;/li&gt;
&lt;li&gt;Simulate clicking the “Load more” button to load additional content.&lt;/li&gt;
&lt;li&gt;Parse and extract specific data from the HTML.&lt;/li&gt;
&lt;li&gt;Save the extracted data to a CSV file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s get started!&lt;/p&gt;




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

&lt;p&gt;To develop this web scraper, we'll use Node.js along with a few open-source libraries and the ZenRows API to handle anti-scraping mechanisms. Below is a list of tools and libraries that will be used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt;: A runtime environment for executing JavaScript code on the server side. You can download it from &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;nodejs.org&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Axios&lt;/strong&gt;: A library for making HTTP requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cheerio&lt;/strong&gt;: A library for parsing HTML.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;csv-writer&lt;/strong&gt;: A library for writing data to a CSV file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ZenRows API&lt;/strong&gt;: A service to bypass anti-scraping mechanisms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, create a new Node.js project named &lt;code&gt;web-scraper-tool&lt;/code&gt;. Then, install the required libraries by running the following command in your terminal:&lt;/p&gt;

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

npm &lt;span class="nb"&gt;install &lt;/span&gt;axios cheerio csv-writer


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

&lt;/div&gt;

&lt;p&gt;With the basic setup in place, you are ready to start building your web scraper.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Fetch HTML Content
&lt;/h2&gt;

&lt;p&gt;The first task is to fetch the HTML content of the page. This involves sending a request to the target URL using the ZenRows API. The response will contain the raw HTML of the page, initially displaying 12 products.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;fetchHtml&lt;/code&gt; function that retrieves the HTML content from a target URL using the ZenRows API. This function should handle HTTP requests and errors, returning the HTML data for further processing.&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&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;cheerio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cheerio&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;csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;csv-writer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;createObjectCsvWriter&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;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ZENROWS_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Replace with your ZenRows API key&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.scrapingcourse.com/button-click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Page to be scraped&lt;/span&gt;

&lt;span class="c1"&gt;// Function to fetch HTML content from a URL&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchHtml&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="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.zenrows.com/v1/&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;params&lt;/span&gt;&lt;span class="p"&gt;:&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="nx"&gt;apiKey&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="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Return the HTML content&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="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="s2"&gt;`Error fetching &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;: &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="nx"&gt;message&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;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Return null if an error occurs&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;To test the &lt;code&gt;fetchHtml&lt;/code&gt; function, create a &lt;code&gt;main&lt;/code&gt; function to execute the logic and print the fetched HTML.&lt;/p&gt;

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

&lt;span class="c1"&gt;// Main function to test and execute all the logic&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&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;html&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;fetchHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Fetch HTML content of the initial 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;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&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="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Run the code using the command node index.js. The output in your terminal should display the entire raw HTML for the page. This HTML will be the foundation for the data extraction process.&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%2Fkiohc0k8p89jyo11slh7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkiohc0k8p89jyo11slh7.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Load More Products
&lt;/h2&gt;

&lt;p&gt;Once you have fetched the initial set of products, the next step is to simulate clicking the “Load more” button multiple times to load all the remaining pages. This step ensures that all products beyond the initial set displayed on the home page are fetched.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;fetchAllProducts&lt;/code&gt; function that simulates clicking the “Load more” button by sending requests to the AJAX endpoint. This function should continue to load more products until a specified number of products have been fetched.&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ajaxUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.scrapingcourse.com/ajax/products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// AJAX URL to load more products&lt;/span&gt;

&lt;span class="c1"&gt;// Function to fetch all products by simulating the "Load more" button&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchAllProducts&lt;/span&gt;&lt;span class="p"&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;productsHtml&lt;/span&gt; &lt;span class="o"&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;offset&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;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsHtml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;48&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;newHtml&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;fetchHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ajaxUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;newHtml&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Stop if no HTML is returned&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cheerio&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="nx"&gt;newHtml&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;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div.product-item&lt;/span&gt;&lt;span class="dl"&gt;'&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&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;return&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="nx"&gt;productsHtml&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;products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Collect the HTML content of the products&lt;/span&gt;
      &lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Increment offset to load the next set of products&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Fetched &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productsHtml&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; products so far...`&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="nx"&gt;productsHtml&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="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Join the HTML snippets into a single, cleaner string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Update the &lt;code&gt;main&lt;/code&gt; function to test the &lt;code&gt;fetchAllProducts&lt;/code&gt; function.&lt;/p&gt;

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

&lt;span class="c1"&gt;// Main function to test and execute all the logic&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&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;productsHtml&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;fetchAllProducts&lt;/span&gt;&lt;span class="p"&gt;();&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsHtml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Log the fetched products&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;When you run the code, your terminal should display the message *&lt;em&gt;Fetched X products so far… *&lt;/em&gt; followed by the raw HTML of the products.&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%2Ftqdqmac22yyuc21y6dvv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqdqmac22yyuc21y6dvv.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Parse Product Information
&lt;/h2&gt;

&lt;p&gt;With the raw HTML content of at least 48 products fetched, the next step is to parse this HTML to extract specific product information like title, price, image URL, and product URL.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;parseProducts&lt;/code&gt; function that extracts specific product information like title, price, image URL, and product URL from the fetched HTML. Use the Cheerio library to navigate and parse the HTML content.&lt;/p&gt;

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

&lt;span class="c1"&gt;// Function to parse product information from HTML&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parseProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&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;$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cheerio&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="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a[href*="/ecommerce/product/"]&lt;/span&gt;&lt;span class="dl"&gt;'&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;_&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;span.product-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&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="nf"&gt;$&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;span.product-price&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&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;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;'&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="s1"&gt;N/A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$&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;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;href&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="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Update the &lt;code&gt;main&lt;/code&gt; function to run the &lt;code&gt;parseProducts&lt;/code&gt; function and log the output.&lt;/p&gt;

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

&lt;span class="c1"&gt;// Main function to test and execute all the logic&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&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;productsHtml&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;fetchAllProducts&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;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsHtml&lt;/span&gt;&lt;span class="p"&gt;);&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;log&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;// Log the parsed product information to the console&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Run the code to see the parsed product information in an array of objects instead of the raw HTML seen in the previous step. The output in your terminal should look like an array of objects, each representing a product with its title, price, image URL, and product URL.&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%2Fkv03sy9sjefnwv3vvjvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkv03sy9sjefnwv3vvjvw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Export Product Information to CSV
&lt;/h2&gt;

&lt;p&gt;After successfully parsing the data, the next task is to save it in a structured format for further analysis. In this step, the parsed data will be written to a CSV file, which is a popular choice for storing tabular data due to its simplicity and wide support.&lt;/p&gt;

&lt;p&gt;Create an &lt;code&gt;exportProductsToCSV&lt;/code&gt; function that writes the parsed product data to a CSV file. Use the csv-writer library to define the file structure and save the data.&lt;/p&gt;

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

&lt;span class="c1"&gt;// Function to export products to a CSV file&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;exportProductsToCSV&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;csvWriter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products.csv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;header&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;price&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Price&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Image URL&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Product URL&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;csvWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeRecords&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;console&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CSV file has been created.&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;p&gt;Update the &lt;code&gt;main&lt;/code&gt; function to run the &lt;code&gt;exportProductsToCSV&lt;/code&gt; function.&lt;/p&gt;

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

&lt;span class="c1"&gt;// Main function to test and execute all the logic&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&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;productsHtml&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;fetchAllProducts&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;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsHtml&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;exportProductsToCSV&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;// Export products to CSV&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;After running the code, you should see a &lt;code&gt;products.csv&lt;/code&gt; file in your working directory with the parsed product information. You will also see a message in the terminal confirming that the CSV file has been created.&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%2Fqicbkc4qjsby9gv2efl3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqicbkc4qjsby9gv2efl3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Get Extra Data for Top Products
&lt;/h2&gt;

&lt;p&gt;In the final step, the focus will be on refining the scraping process by fetching additional details for the top five highest-priced products. This involves visiting each product’s page to extract the needed information, such as product descriptions and SKU codes.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;getProductDetails&lt;/code&gt; function that fetches additional details like product descriptions and SKU codes from each product's individual page.&lt;/p&gt;

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

&lt;span class="c1"&gt;// Function to fetch additional product details from the product page&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getProductDetails&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="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&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;fetchHtml&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;html&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;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;N/A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;N/A&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;$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cheerio&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="nx"&gt;html&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;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&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;div.woocommerce-Tabs-panel--description p&lt;/span&gt;&lt;span class="dl"&gt;"&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&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="nf"&gt;get&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&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="s1"&gt;N/A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&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;.product_meta .sku&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&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="s1"&gt;N/A&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;p&gt;Finally, update the &lt;code&gt;exportProductsToCSV&lt;/code&gt; function to include the new data for the top 5 highest-priced products.&lt;/p&gt;

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

&lt;span class="c1"&gt;// Function to export products to a CSV file&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;exportProductsToCSV&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;csvWriter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products.csv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;header&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;price&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Price&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Image URL&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Product URL&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Description&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sku&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SKU&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;csvWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeRecords&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;console&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CSV file with additional product details has been created.&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;p&gt;Finally, update the &lt;code&gt;main&lt;/code&gt; function to fetch the additional details and export the enriched product data to the CSV file.&lt;/p&gt;

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

&lt;span class="c1"&gt;// Main function to test and execute all the logic&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&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;productsHtml&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;fetchAllProducts&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;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productsHtml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// Sort products by price in descending order&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;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;0-9.-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+/g&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;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;0-9.-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+/g&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;span class="c1"&gt;// Fetch additional details for the top 5 highest-priced products&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;0&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="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="mi"&gt;5&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="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;details&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;getProductDetails&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;i&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="nx"&gt;products&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="o"&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;products&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="nx"&gt;details&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;exportProductsToCSV&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;// Export products to CSV&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CSV file with additional product details has been created.&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;p&gt;Once you run the code, you will see a CSV file with the top five highest-priced products, each containing additional details like product descriptions and SKU codes.&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%2Flpuabf5fc89mzj9t0uky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpuabf5fc89mzj9t0uky.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: The number of products fetched (48) is based on the earlier limit set in the &lt;code&gt;fetchAllProducts&lt;/code&gt; function. You can adjust this limit if you want to scrape more products before identifying the top five.&lt;/p&gt;




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

&lt;p&gt;By following these steps, you’ve successfully built a web scraper capable of handling dynamic web pages with an infinite scroll or “Load more” button. The key to effective web scraping lies in understanding the structure of the target website and using tools to navigate and bypass anti-scraping measures.&lt;/p&gt;

&lt;p&gt;To further enhance your web scraping skills, consider implementing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use rotating proxies to avoid IP bans.&lt;/li&gt;
&lt;li&gt;Explore techniques for handling CAPTCHA challenges.&lt;/li&gt;
&lt;li&gt;Scrape more complex sites with additional AJAX calls or nested "Load more" buttons.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tutorial provided a strong foundation for scraping dynamic content, and you can now apply these principles to other web scraping projects.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Build a Grammarly Alternative Using ToolJet and OpenAI in 10 Minutes📝</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Wed, 07 Aug 2024 13:42:21 +0000</pubDate>
      <link>https://forem.com/tooljet/build-a-grammarly-alternative-using-tooljet-and-openai-in-10-minutes-ai9</link>
      <guid>https://forem.com/tooljet/build-a-grammarly-alternative-using-tooljet-and-openai-in-10-minutes-ai9</guid>
      <description>&lt;p&gt;This tutorial will walk you through the process of creating a Grammarly alternative using ToolJet and OpenAI. We will use ToolJet's visual app builder to design an elegant user interface for our application. Then we will use the platform's low-code query builder to connect with OpenAI to perform detailed text analysis. The completed application will allow you to perform four operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;List all grammatical errors in your text&lt;/li&gt;
&lt;li&gt;Fix all grammatical errors and return the revised text&lt;/li&gt;
&lt;li&gt;Provide a score for the text based on specific parameters: clarity, coherence, grammar, and engagement&lt;/li&gt;
&lt;li&gt;Make the content sound more natural (ideal for transforming generic AI-generated content with a more organic tone)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Feel free to adjust the structure and functionality of the application to match your exact content-enhancement needs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Check out &lt;a href="https://dev.to/tooljet/creating-a-csv-to-graph-generator-app-using-tooljet-and-python-libraries-18nb"&gt;this tutorial&lt;/a&gt; to learn how to build a QR Code generator using ToolJet and Python.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's a final preview of the application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fa7bujbzi20werwcrfnug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fa7bujbzi20werwcrfnug.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;ToolJet&lt;/strong&gt; (&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source, low-code platform designed for quickly building and deploying internal tools. Sign up for a free ToolJet cloud account &lt;a href="https://app.tooljet.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenAI Account&lt;/strong&gt; : Register for an OpenAI account to utilize AI-powered features in your applications by accessing APIs such as GPT for advanced natural language processing. Sign up &lt;a href="https://openai.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Since integration in ToolJet is &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-datasources#adding-a-data-source" rel="noopener noreferrer"&gt;very straightforward&lt;/a&gt;, you can use any other service instead of OpenAI to build the same application.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1. Set up Your First ToolJet Data Source
&lt;/h2&gt;

&lt;p&gt;In the steps below, we will set up the data source and create a new app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access the &lt;a href="https://platform.openai.com/api-keys" rel="noopener noreferrer"&gt;OpenAI Console&lt;/a&gt; and generate a new secret key. Remember to copy this key for later use.&lt;/li&gt;
&lt;li&gt;Sign up for a free &lt;a href="https://app.tooljet.com/" rel="noopener noreferrer"&gt;ToolJet cloud account&lt;/a&gt; if you haven't already and log in.&lt;/li&gt;
&lt;li&gt;On the ToolJet dashboard, locate the Data Sources section on the left sidebar. Here, click on the &lt;strong&gt;Add&lt;/strong&gt; button under the OpenAI plugin.&lt;/li&gt;
&lt;li&gt;In the API Key field, paste the API key you copied from OpenAI Console and click on the Save button&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ffcdlsy7ew3wlkey546s3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffcdlsy7ew3wlkey546s3.png" alt=" " width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;strong&gt;Test Connection&lt;/strong&gt; button to ensure the OpenAI plugin is correctly connected to your ToolJet account.&lt;/li&gt;
&lt;li&gt;Finally, click on the "Apps" icon in the left sidebar to navigate to the applications section. &lt;/li&gt;
&lt;li&gt;Select "Create new app" and name your application "Wordly" (or anything else based on your use case), and click on "Create app" to finalize the app creation.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Step 2. Building the User Interface
&lt;/h2&gt;

&lt;p&gt;We will start by creating a minimal UI for the application. The UI will take around five minutes to build. First, we will build the header section, then the input section, and finally, the output section, where we will display the results of the text analysis.&lt;/p&gt;
&lt;h3&gt;
  
  
  Header
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For the Header, drop an &lt;strong&gt;Icon&lt;/strong&gt; &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-components" rel="noopener noreferrer"&gt;component&lt;/a&gt; on the empty canvas and place a &lt;strong&gt;Text&lt;/strong&gt; component next to it. Set its Icon property to "IconTextWrap" and change its font size to 28.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fi49tirxxj0hv4b8nce3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fi49tirxxj0hv4b8nce3s.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We are using light blue ("#d9e2fc") as the primary color in this application. Update the color scheme of all the components accordingly.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Input Section
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Drag and drop a &lt;strong&gt;Container&lt;/strong&gt; component below the header and rename it to &lt;em&gt;mainContainer&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fza7li6ydzbo72d1s8426.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fza7li6ydzbo72d1s8426.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We will rename important components like containers and input fields to ensure that we can easily refer and access component-related data inside the app builder.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;strong&gt;Text&lt;/strong&gt; component at the top left of the container with the label 'Enter Text'. &lt;/li&gt;
&lt;li&gt;Place a &lt;strong&gt;Dropdown&lt;/strong&gt; component next to it with the label 'Operation'. Rename it to &lt;em&gt;operationDropdown&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;Set the dropdown's Option labels to: &lt;code&gt;{{['List Grammatical Errors', 'Fix Grammatical Errors', 'Humanize Content', 'Provide Content Score']}}&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Set the Option values to: &lt;code&gt;{{['listGrammaticalErrors', 'fixGrammaticalErrors', 'humanizeContent', 'provideAScore']}}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Textarea&lt;/strong&gt; component below and rename it to &lt;em&gt;textInput&lt;/em&gt;.  - Add a &lt;strong&gt;Button&lt;/strong&gt; component labeled 'GENERATE OUTPUT ⚡' and rename it to &lt;em&gt;generateButton&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;Add another &lt;strong&gt;Button&lt;/strong&gt; component next to it labeled 'COPY 🗒️' and rename it to &lt;em&gt;copyButton&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fh991ltcpbllhbe5qd6pl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fh991ltcpbllhbe5qd6pl.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Output Section
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;strong&gt;Text&lt;/strong&gt; component labeled 'Output'. &lt;/li&gt;
&lt;li&gt;Place another &lt;strong&gt;Text&lt;/strong&gt; component below it to display the output. This component will display the data returned by the OpenAI queries.&lt;/li&gt;
&lt;li&gt;Rename the &lt;strong&gt;Text&lt;/strong&gt; component to &lt;em&gt;output&lt;/em&gt;, and under its Data property, set Markdown as the type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fok06gbzjw19btyh44r0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fok06gbzjw19btyh44r0i.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 3. Creating Queries to Interact With OpenAI
&lt;/h2&gt;

&lt;p&gt;Next, we’ll create four OpenAI &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries" rel="noopener noreferrer"&gt;queries&lt;/a&gt; and a JavaScript query that will conditionally trigger one of the OpenAI queries based on the selected operation.&lt;/p&gt;
&lt;h3&gt;
  
  
  List Grammatical Errors:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Expand the Query Panel at the bottom of the screen and click on the &lt;strong&gt;Add&lt;/strong&gt; button to create a new query &lt;/li&gt;
&lt;li&gt;Rename this query to &lt;em&gt;listGrammaticalErrors&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;Select OpenAI as the Data Source and select Chat as the Operation. In the Message input field, enter the following prompt:
&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="nx"&gt;Find&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;grammatical&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;heading&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="nx"&gt;using&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Include&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;bold&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;appropriate&lt;/span&gt; &lt;span class="nx"&gt;emoji&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;mention&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;Sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Provide&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;sentence&lt;/span&gt; &lt;span class="nx"&gt;which&lt;/span&gt; &lt;span class="nx"&gt;contains&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Provide&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;brief&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;two&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="nx"&gt;breaks&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="nx"&gt;these&lt;/span&gt; &lt;span class="nx"&gt;emojis&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;different&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Verb&lt;/span&gt; &lt;span class="nx"&gt;Agreement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;🧑‍🏫&lt;/span&gt;
&lt;span class="nx"&gt;Verb&lt;/span&gt; &lt;span class="nx"&gt;Tense&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;⏳&lt;/span&gt;
&lt;span class="nx"&gt;Punctuation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;📝&lt;/span&gt;
&lt;span class="nx"&gt;Spelling&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;🔠&lt;/span&gt;
&lt;span class="nx"&gt;Sentence&lt;/span&gt; &lt;span class="nx"&gt;Structure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;🏗️&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;please&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;other&lt;/span&gt; &lt;span class="nx"&gt;more&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;related&lt;/span&gt; &lt;span class="nx"&gt;emojis&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;needed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;Ensure&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;section&lt;/span&gt; &lt;span class="nx"&gt;clearly&lt;/span&gt; &lt;span class="nx"&gt;identifies&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;provides&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;description&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://media2.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%2Foc1v1shypccxjwx7krdu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Foc1v1shypccxjwx7krdu.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create Three More OpenAI Queries:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create three more OpenAI queries - &lt;em&gt;fixGrammaticalErrors&lt;/em&gt;, &lt;em&gt;humanizeContent&lt;/em&gt;, and &lt;em&gt;provideAScore&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Prompt for &lt;em&gt;fixGrammaticalErrors&lt;/em&gt; query:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Review&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;identify&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;grammatical&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;provide&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;corrected&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; 

&lt;span class="nx"&gt;Provide&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Prompt for &lt;em&gt;humanizeContent&lt;/em&gt; query:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Rewrite&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;make&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="nx"&gt;sound&lt;/span&gt; &lt;span class="nx"&gt;more&lt;/span&gt; &lt;span class="nx"&gt;natural&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;human&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;written&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; 

&lt;span class="nx"&gt;Ensure&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;revised&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;engaging&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;maintains&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="nx"&gt;meaning&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; 
&lt;span class="nx"&gt;Provide&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Prompt for &lt;em&gt;provideAScore&lt;/em&gt; query:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Analyze&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;provide&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; 
&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
&lt;span class="nx"&gt;clarity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;coherence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;grammar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;engagement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;overall&lt;/span&gt; &lt;span class="nx"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; 

&lt;span class="nx"&gt;Present&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="nx"&gt;format&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;structure&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;Overall&lt;/span&gt; &lt;span class="nx"&gt;Quality&lt;/span&gt;&lt;span class="err"&gt;🌟&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="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;Show&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="nx"&gt;four&lt;/span&gt; &lt;span class="nx"&gt;paremeters&lt;/span&gt; &lt;span class="nx"&gt;inside&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt;
&lt;span class="nx"&gt;Clarity&lt;/span&gt;&lt;span class="err"&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;score&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;Coherence&lt;/span&gt;&lt;span class="err"&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;score&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;Grammar&lt;/span&gt;&lt;span class="err"&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;score&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;Engagement&lt;/span&gt;&lt;span class="err"&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;score&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;-------------------------------------------------------------------&lt;/span&gt;

&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;Comments&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="nx"&gt;below&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; 

&lt;span class="nx"&gt;Ensure&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;include&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="nx"&gt;before&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; 

&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Create a Query to Conditionally Trigger the OpenAI Queries
&lt;/h3&gt;

&lt;p&gt;Create a JavaScript query named &lt;em&gt;triggerQuery&lt;/em&gt; with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;operationDropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;listGrammaticalErrors&lt;/span&gt;&lt;span class="dl"&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;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listGrammaticalErrors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fixGrammaticalErrors&lt;/span&gt;&lt;span class="dl"&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;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fixGrammaticalErrors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;humanizeContent&lt;/span&gt;&lt;span class="dl"&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;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;humanizeContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;provideAScore&lt;/span&gt;&lt;span class="dl"&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;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provideAScore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&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;&lt;a href="https://media2.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%2Fpp908mipqcljdhytew93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fpp908mipqcljdhytew93.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This JavaScript query will check the selected operation from the operationDropdown component and run the relevant OpenAI query.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4. Configuring Events and Other Functionalities
&lt;/h2&gt;

&lt;p&gt;In the final step, we will configure the events and bind queries with components and see how it all comes together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update the Output on Query Success:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a new Query Success &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries" rel="noopener noreferrer"&gt;event handler&lt;/a&gt; to the &lt;em&gt;listGrammaticalErrors&lt;/em&gt; query and select Action as Control Component. &lt;/li&gt;
&lt;li&gt;Under Action Options, set the Component as &lt;em&gt;output&lt;/em&gt;, Action as Set text, and Text as &lt;code&gt;{{queries.listGrammaticalErrors.data}}&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Follow the same steps for the remaining three OpenAI queries; this will populate the &lt;code&gt;output&lt;/code&gt; component with the returned data from the query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmcvq6ipxi2t1ymqiytne.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmcvq6ipxi2t1ymqiytne.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate Button:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Select the Generate Output button, navigate to its properties panel on the right and create a new event under Events. &lt;/li&gt;
&lt;li&gt;For the event configuration, select Action as Control Component. - Under Action Options, set the Component as &lt;em&gt;output&lt;/em&gt;, Action as Clear. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fu2kt6xgma7o61kiuiqj2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fu2kt6xgma7o61kiuiqj2.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This event will clear the output component every time the button is clicked.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add another event to the Generate Output button to run the JavaScript query when it is clicked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fhhdl871na53eg5pyq2xa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fhhdl871na53eg5pyq2xa.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This event will trigger the JavaScript query. The JavaScript query will then trigger one of the OpenAI queries based on the selected operation from the dropdown, and the output component will be populated with the latest data.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Copy Button
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a new event for the Copy button, select &lt;code&gt;Copy to clipboard&lt;/code&gt; as the event, and enter &lt;code&gt;{{components.output.text}}&lt;/code&gt; under its Text property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F6asx7pjeey5qcu7esi9z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F6asx7pjeey5qcu7esi9z.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With this setting, every time you click on the Copy button, the text inside the output component will be copied to the clipboard.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The functionality of our application is now fully configured. Enter some text in the input field, click on the Generate Output button and test the output for the available operations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fh51801z0k2c5we3e16k4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fh51801z0k2c5we3e16k4.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Congratulations! You've built a Grammarly alternative in less than 10 minutes. Using ToolJet's Continue adjusting the application's functionality to meet your specific text analysis needs. You can create new OpenAI queries for a variety of content enhancement scenarios such as changing the tone of the content, improving SEO, changing the language of the output content, improving clarity, etc.&lt;/p&gt;

&lt;p&gt;To learn more, check out the &lt;a href="https://docs.tooljet.com/docs/" rel="noopener noreferrer"&gt;ToolJet documentation&lt;/a&gt; or connect with us on &lt;a href="https://tooljet.slack.com/" rel="noopener noreferrer"&gt;Slack&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>openai</category>
    </item>
    <item>
      <title>Creating a CSV to Graph Generator App Using ToolJet and Python Libraries 🚀</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Thu, 25 Jul 2024 12:53:21 +0000</pubDate>
      <link>https://forem.com/tooljet/creating-a-csv-to-graph-generator-app-using-tooljet-and-python-libraries-18nb</link>
      <guid>https://forem.com/tooljet/creating-a-csv-to-graph-generator-app-using-tooljet-and-python-libraries-18nb</guid>
      <description>&lt;p&gt;In this tutorial, we'll create a CSV to Graph Generator app using ToolJet and Python code. This app enables users to upload a CSV file and generate various types of graphs, including line, scatter, bar, histogram, and box plots. Since ToolJet supports Python (and JavaScript) code out of the box, we'll incorporate Python code and the &lt;a href="https://matplotlib.org/" rel="noopener noreferrer"&gt;matplotlib&lt;/a&gt; library to handle the graph generation. Additionally, we'll use ToolJet's customizable pre-built components to design an intuitive user interface in minutes.&lt;/p&gt;

&lt;p&gt;Here's a quick preview of the complete application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fsmwtomyqbpcg31pyg53y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fsmwtomyqbpcg31pyg53y.png" alt=" " width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Check out &lt;a href="https://blog.tooljet.com/create-a-qr-code-generator-using-tooljet-in-5-minutes/" rel="noopener noreferrer"&gt;this&lt;/a&gt; tutorial to learn how to develop a QR code generator using ToolJet.&lt;/em&gt;&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ToolJet&lt;/strong&gt;(&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source, low-code business application builder. &lt;a href="https://www.tooljet.com/signup" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; for a free ToolJet cloud account or &lt;a href="https://docs.tooljet.com/docs/setup/try-tooljet/" rel="noopener noreferrer"&gt;run ToolJet on your local machine&lt;/a&gt; using Docker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic knowledge of &lt;strong&gt;Python&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Begin by creating an application named &lt;strong&gt;CSV To Graph Generator&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Designing the User Interface
&lt;/h2&gt;

&lt;p&gt;Let's use ToolJet's &lt;a href="https://blog.tooljet.com/build-graphs-using-csv-files-with-tooljet-and-python-libraries/" rel="noopener noreferrer"&gt;visual app builder&lt;/a&gt; to quickly design the UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Designing the Header
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Drag and drop a &lt;strong&gt;Text&lt;/strong&gt; &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-components" rel="noopener noreferrer"&gt;component&lt;/a&gt; onto the canvas for the header. Rename this component to &lt;code&gt;headerText&lt;/code&gt; and set its text to "CSV TO GRAPH GENERATOR."&lt;/li&gt;
&lt;li&gt;Customize its styling properties to have:

&lt;ul&gt;
&lt;li&gt;Text size: 25&lt;/li&gt;
&lt;li&gt;Font weight: bolder&lt;/li&gt;
&lt;li&gt;Text color: #375fcfff&lt;/li&gt;
&lt;li&gt;Text alignment: right&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This will serve as the header text of your app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add an &lt;strong&gt;Icon&lt;/strong&gt; component, naming it &lt;code&gt;logo&lt;/code&gt;. Set the icon to &lt;code&gt;IconChartAreaFilled&lt;/code&gt; and the icon color to #375fcfff. Position it appropriately on the canvas to complement the header text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9sgdf6ag2pd2ioe042m1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9sgdf6ag2pd2ioe042m1.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the CSV Upload Section
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Drag a &lt;strong&gt;Container&lt;/strong&gt; component onto the canvas. Style this container with:

&lt;ul&gt;
&lt;li&gt;Border radius: 7&lt;/li&gt;
&lt;li&gt;Background color: #fff&lt;/li&gt;
&lt;li&gt;Box shadow: 2px 2px 1px 1px #aec0f5ff&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This container will hold all the input fields and output preview.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Inside the container, add a &lt;strong&gt;File Picker&lt;/strong&gt; component and rename it to &lt;code&gt;fileUploader&lt;/code&gt;. Set its &lt;strong&gt;Accept file types&lt;/strong&gt; property to &lt;code&gt;{"csv/*"}&lt;/code&gt; to accept CSV files. Enable the &lt;strong&gt;Parse content&lt;/strong&gt; toggle, and select &lt;strong&gt;File type&lt;/strong&gt; as CSV.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, add a &lt;strong&gt;Dropdown&lt;/strong&gt; component next to the File Picker, rename it to &lt;code&gt;graphSelectionDropdown&lt;/code&gt;. Set the component's &lt;strong&gt;Option values&lt;/strong&gt; to &lt;code&gt;["line", "scatter", "bar", "histogram", "box"]&lt;/code&gt; and &lt;strong&gt;Option labels&lt;/strong&gt; to &lt;code&gt;["Line", "Scatter", "Bar", "Histogram", "Box"]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Below the dropdown, add a &lt;strong&gt;Button&lt;/strong&gt; component and rename it to &lt;code&gt;generateGraphButton&lt;/code&gt;. Set its text to "Generate Graph".&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F0qbwuxnouuvweuakridt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0qbwuxnouuvweuakridt.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/how-to-access-values" rel="noopener noreferrer"&gt;Double curly braces&lt;/a&gt; in ToolJet are used to pass custom code and refer or access values.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the Image Preview
&lt;/h3&gt;

&lt;p&gt;To display the generated graph, add an &lt;strong&gt;Image&lt;/strong&gt; component below the File Picker and Button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F3ad9s1lhax4czbdvyubc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3ad9s1lhax4czbdvyubc.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The UI is now ready! &lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Using Python Libraries through Queries
&lt;/h2&gt;

&lt;p&gt;ToolJet's &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries" rel="noopener noreferrer"&gt;query&lt;/a&gt; builder offers a convenient way to use custom code or connect with external data sources, services, and libraries. We will use it to create a Python query that uses the CSV data and interacts with the matplotlib library to generate graphs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expand the query panel at the bottom, create a new query named &lt;code&gt;generateGraph&lt;/code&gt;, and choose &lt;strong&gt;Python&lt;/strong&gt; as the data source.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter the below code in your Python query: &lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&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;io&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BytesIO&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_plot&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;csv_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fileUploader&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
        &lt;span class="n"&gt;graph_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graphSelectionDropdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Debug info:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;csv_string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;graph_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StringIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv_string&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CSV must contain at least two columns&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;x_column&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;columns&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;y_columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;columns&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;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;graph_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;line&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x_column&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&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;Line Plot: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x_column&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;)&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;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xticks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;right&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;graph_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;scatter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y_columns&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;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y_columns&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;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&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;Scatter Plot: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;y_columns&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="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;y_columns&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="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_columns&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;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_columns&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="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x_column&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y_columns&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;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&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;Scatter Plot: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x_column&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;y_columns&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="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_column&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_columns&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="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;graph_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bar&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x_column&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
            &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;xi&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;xi&lt;/span&gt; &lt;span class="ow"&gt;in&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;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_column&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&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;Bar Plot: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;)&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;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xticks&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;xi&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_columns&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="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;xi&lt;/span&gt; &lt;span class="ow"&gt;in&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;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x_column&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;right&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;graph_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;histogram&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;bins&lt;/span&gt;&lt;span class="o"&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;alpha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&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;Histogram: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;)&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;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Frequency&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;graph_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;box&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;boxplot&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&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;Box Plot: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;)&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;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xticks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_columns&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="n"&gt;y_columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;right&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Value&lt;/span&gt;&lt;span class="sh"&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="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&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;Invalid graph type: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;graph_type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. Choose &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;line&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;scatter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bar&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;histogram&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, or &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;box&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tight_layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="nb"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;savefig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seek&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;img_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getvalue&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;plt&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;img_str&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&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;Error in create_plot: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="nf"&gt;create_plot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

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



&lt;p&gt;&lt;a href="https://media2.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%2Fspopgg01n6h5tjbznt29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fspopgg01n6h5tjbznt29.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this is configured, you can select a CSV file in the File Picker, select the graph type, and click on the &lt;strong&gt;Run&lt;/strong&gt; button in the query panel. You can see the output generated by the query under preview.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Connecting the UI Components with the Query
&lt;/h2&gt;

&lt;p&gt;Time to bind the query to the components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring the Image Preview
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In the &lt;strong&gt;Data&lt;/strong&gt; property of the &lt;strong&gt;Image&lt;/strong&gt; component, enter the following code to bind the query's result: &lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data:image;base64,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateGraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

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



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For the &lt;strong&gt;Loading state&lt;/strong&gt; property of the Image component, click on the fx button to enter custom code and enter the below code: &lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateGraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

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



&lt;h3&gt;
  
  
  Triggering the Query Based on Button Click
&lt;/h3&gt;

&lt;p&gt;Bind the query to the &lt;strong&gt;generateGraphButton&lt;/strong&gt; by adding an &lt;strong&gt;on Click&lt;/strong&gt; &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-events" rel="noopener noreferrer"&gt;event&lt;/a&gt; that triggers the &lt;strong&gt;generateGraph&lt;/strong&gt; query. This setup ensures that the script runs and generates the graph when the button is clicked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fihus5ca5efk5gg60tz6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fihus5ca5efk5gg60tz6s.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After this setup, every time you upload a CSV file, select a graph type, and click on the &lt;strong&gt;generateGraphButton&lt;/strong&gt;, the graph will be created and a preview will be visible in the Image component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fa0cemhi6h8kz9i6ag0b2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fa0cemhi6h8kz9i6ag0b2.png" alt=" " width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;By following these steps, we've successfully built a dynamic and user-friendly CSV to Graph Generator app with ToolJet. We utilized ToolJet's visual app builder to craft an elegant and intuitive UI, used the query builder to integrate a Python library for graph generation, and demonstrated how to customize ToolJet applications to deliver a smooth user experience.&lt;/p&gt;

&lt;p&gt;To learn and explore more about ToolJet, check out the &lt;a href="https://docs.tooljet.io" rel="noopener noreferrer"&gt;ToolJet docs&lt;/a&gt; or connect with us and post your queries on our &lt;a href="https://tooljet.slack.com/" rel="noopener noreferrer"&gt;Slack channel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Build an HTML To Markdown Converter using ToolJet📋</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Thu, 04 Jul 2024 13:05:46 +0000</pubDate>
      <link>https://forem.com/tooljet/build-an-html-to-markdown-converter-using-tooljet-4p7h</link>
      <guid>https://forem.com/tooljet/build-an-html-to-markdown-converter-using-tooljet-4p7h</guid>
      <description>&lt;p&gt;In this tutorial, we will walk through the steps to build an HTML to Markdown Converter using ToolJet. This application allows users to input HTML code and get the corresponding Markdown output which can be copied with a button click. Using ToolJet's intuitive pre-built components, we'll design an elegant UI in just 5 minutes. The HTML to markdown conversion will be managed by the &lt;a href="https://github.com/mixmark-io/turndown?utm_source=cdnjs&amp;amp;utm_medium=cdnjs_link&amp;amp;utm_campaign=cdnjs_library" rel="noopener noreferrer"&gt;Turndown JavaScript library&lt;/a&gt;, while the Markdown preview will be rendered using the &lt;a href="https://www.npmjs.com/package/react-markdown" rel="noopener noreferrer"&gt;react-markdown&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ToolJet's Run JavaScript query and Text component can be utilized to convert HTML to Markdown and preview the content without using external libraries. However, in this tutorial, we are looking to demonstrate the process of using 3rd party libraries in ToolJet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's a preview of the complete application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fnldb333nq4ytyhsfpcyf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fnldb333nq4ytyhsfpcyf.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Prerequisites:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ToolJet&lt;/strong&gt;(&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source, low-code business application builder. &lt;a href="https://www.tooljet.com/signup" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; for a free ToolJet cloud account or &lt;a href="https://docs.tooljet.com/docs/setup/try-tooljet/" rel="noopener noreferrer"&gt;run ToolJet on your local machine&lt;/a&gt; using Docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basics of JavaScript&lt;/strong&gt;: A basic understanding of JavaScript is essential for this tutorial since we will use JavaScript and React libraries to handle the logic for converting HTML to Markdown and previewing the markdown content.&lt;/p&gt;

&lt;p&gt;To begin, create a new application named &lt;strong&gt;HTML To Markdown Converter&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Creating the UI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Header
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a Container &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-components" rel="noopener noreferrer"&gt;component&lt;/a&gt; at the top of the canvas and rename it to &lt;code&gt;headerContainer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add an Icon and a Text component inside the Container. Rename them to &lt;code&gt;logo&lt;/code&gt; and &lt;code&gt;headerText&lt;/code&gt; respectively.&lt;/li&gt;
&lt;li&gt;Set the text to &lt;strong&gt;"HTML to Markdown Converter"&lt;/strong&gt; and select an appropriate icon for the app in the Icon component.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F71o2pr63y20cgtv0uyp5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F71o2pr63y20cgtv0uyp5.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Input Section
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add another Container component on the left and rename it to &lt;code&gt;inputContainer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inside the container, add a Text component labeled &lt;strong&gt;"Enter HTML Code:"&lt;/strong&gt;. Rename it to &lt;code&gt;enterHTMLLabel&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Below the label, add a Textarea component for the HTML input and rename it to &lt;code&gt;htmlInput&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Output Section
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a container next to the input section and rename it to &lt;code&gt;outputContainer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a Text component labeled &lt;strong&gt;"Markdown Preview:"&lt;/strong&gt; below the input section. Rename it to &lt;code&gt;markdownLabel&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a Custom Component to display the Markdown output and rename it to &lt;code&gt;markdownOutput&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Buttons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a Button component labeled &lt;strong&gt;"Convert"&lt;/strong&gt; below the Textarea component. Rename the button to &lt;code&gt;convertButton&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add another Button component labeled &lt;strong&gt;"Copy Markdown"&lt;/strong&gt; besides the Convert button and rename it to &lt;code&gt;copyButton&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fkhmc06dd6h8c0xas7wgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkhmc06dd6h8c0xas7wgn.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The UI of the application is done. Time to focus on the functionality.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Adding Queries and Events
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Import Turndown Library
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a Run JavaScript code &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries" rel="noopener noreferrer"&gt;query&lt;/a&gt; named &lt;code&gt;importTurndownLibrary&lt;/code&gt; to import the Turndown library.&lt;/li&gt;
&lt;li&gt;Use the following code in the query to import the library:
&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="c1"&gt;// Function to add script dynamically&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;src&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="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;scriptTag&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;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;scriptTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;scriptTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;load&lt;/span&gt;&lt;span class="dl"&gt;'&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;scriptTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&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="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="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scriptTag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Importing turndown&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;addScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdnjs.cloudflare.com/ajax/libs/turndown/7.0.0/turndown.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Showing a success alert&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&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="s1"&gt;Turndown JS is imported&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;turndownService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turndown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textarea1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enable the &lt;strong&gt;Run this query on application load?&lt;/strong&gt; toggle to automatically run this query every time the app loads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fl99vh8a3m6uwjx92filx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fl99vh8a3m6uwjx92filx.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Convert HTML to Markdown
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create another Run JavaScript code query named &lt;code&gt;convertToMarkdown&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use the following code in the query to convert the text entered in the &lt;code&gt;htmlInput&lt;/code&gt; component to markdown:
&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;turndownService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TurndownService&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;markdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;turndownService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turndown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;htmlInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;markdown&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://media2.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%2Fe60btw0gozshpmnsyagj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fe60btw0gozshpmnsyagj.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Button Actions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For the &lt;strong&gt;Convert&lt;/strong&gt; button, create a new &lt;strong&gt;On click&lt;/strong&gt; &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-events" rel="noopener noreferrer"&gt;event&lt;/a&gt;, set the Action as &lt;strong&gt;Run Query&lt;/strong&gt;, and select &lt;code&gt;convertToMarkdown&lt;/code&gt; as the Query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F4yl5ig5foh5nen0z8b2r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F4yl5ig5foh5nen0z8b2r.png" alt=" " width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the &lt;strong&gt;Copy Markdown&lt;/strong&gt; button, create a new &lt;strong&gt;On click&lt;/strong&gt; event, set the Action as &lt;strong&gt;Copy to clipboard&lt;/strong&gt; the &lt;code&gt;{{queries.convertToMarkdown.data}}&lt;/code&gt; as the Text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fyw3ooa0b9461f6kiri88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fyw3ooa0b9461f6kiri88.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most of the key functionality is now configured. In the next step, we will use a Custom Component to import a React library to preview the markdown content.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Creating Markdown Preview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Add Custom Component
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;In the Custom Component, add the data that will be returned by the &lt;code&gt;convertToMarkdown&lt;/code&gt; query:
&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="p"&gt;{{&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;convertToMarkdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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;ul&gt;
&lt;li&gt;Use the following code to render the Markdown preview:
&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="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="s1"&gt;https://cdn.skypack.dev/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="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/react-dom&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;Container&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="s1"&gt;https://cdn.skypack.dev/@material-ui/core&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;Markdown&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://esm.sh/react-markdown@9&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;MyCustomComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Container&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Markdown&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Markdown&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Container&lt;/span&gt;&lt;span class="err"&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;ConnectedComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Tooljet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connectComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyCustomComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ConnectedComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fz2a6l46zc7mkbivkij35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fz2a6l46zc7mkbivkij35.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this, the HTML to Markdown converter is ready. Time to see it in action!&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Preview and Testing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Test the application by entering various HTML snippets and checking the Markdown output.&lt;/li&gt;
&lt;li&gt;Ensure that the &lt;strong&gt;Copy Markdown&lt;/strong&gt; button works correctly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fx52gtfv8b8ntysalaeb5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fx52gtfv8b8ntysalaeb5.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;We have successfully built an HTML to Markdown Converter using ToolJet in just minutes! This application is designed to simplify your content formatting process, and you can easily expand its functionality based on your specific requirements. Explore the capabilities of ToolJet to create similar projects and enhance your workflow.&lt;/p&gt;

&lt;p&gt;You can check out &lt;a href="https://docs.tooljet.com" rel="noopener noreferrer"&gt;ToolJet docs&lt;/a&gt; for further learning or join the ToolJet Slack community for doubts and queries.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Build an AI BPMN Diagram Analyzer using ToolJet 🛠️</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Thu, 27 Jun 2024 13:12:06 +0000</pubDate>
      <link>https://forem.com/tooljet/build-an-ai-bpmn-diagram-analyzer-using-tooljet-2b00</link>
      <guid>https://forem.com/tooljet/build-an-ai-bpmn-diagram-analyzer-using-tooljet-2b00</guid>
      <description>&lt;p&gt;In this tutorial, we'll create a BPMN Diagram Analyzer application using ToolJet. This app allows users to generate detailed explanations of BPMN processes by uploading them in image format. We'll use &lt;strong&gt;ToolJet's&lt;/strong&gt; &lt;strong&gt;low-code app-builder&lt;/strong&gt; for the user interface and its &lt;strong&gt;query builder&lt;/strong&gt; to connect to the Gemini API to generate an in depth analysis of uploaded BPMN processes.&lt;/p&gt;

&lt;p&gt;Here's a quick preview of our application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F20b0iaftmp1hpm9bbae0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F20b0iaftmp1hpm9bbae0.gif" alt=" " width="760" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Gemini API Key&lt;/strong&gt; : The Gemini API is an advanced AI service provided by &lt;a href="https://aistudio.google.com/app/apikey" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt;. It enables developers to integrate powerful content generation capabilities into their applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ToolJet&lt;/strong&gt;(&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source, low-code business application builder. &lt;a href="https://www.tooljet.com/signup" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; for a free ToolJet cloud account or &lt;a href="https://docs.tooljet.com/docs/setup/try-tooljet/" rel="noopener noreferrer"&gt;run ToolJet on your local machine&lt;/a&gt; using Docker.&lt;/p&gt;

&lt;p&gt;To begin, create a new application named &lt;em&gt;BPMN Diagram Analyzer&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Adding UI Elements 🖼️
&lt;/h2&gt;

&lt;p&gt;The first step in the app-building process is to utilize ToolJet's customizable pre-built components to build a UI in minutes. We will start with the header.&lt;/p&gt;

&lt;h3&gt;
  
  
  App Header
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;For the logo, add an &lt;strong&gt;Icon&lt;/strong&gt; component at the top of the canvas and name it &lt;code&gt;logo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Choose an appropriate icon (e.g., &lt;code&gt;IconAnalyzeFilled&lt;/code&gt;) and set its color to &lt;code&gt;#3e63ddff&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Text&lt;/strong&gt; component next to the Icon component.&lt;/li&gt;
&lt;li&gt;Set its Data property to "BPMN Diagram Analyzer".&lt;/li&gt;
&lt;li&gt;Style it with &lt;code&gt;#3e63ddff&lt;/code&gt; as the color, &lt;code&gt;24px&lt;/code&gt; as the font size, and font weight as bold.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F1r4qz4lxsqiu65o61fae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F1r4qz4lxsqiu65o61fae.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We are using blue (hex code: #3e63ddff) as the primary color, style the upcoming components accordingly.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Input Section
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;strong&gt;Container&lt;/strong&gt; on the left to hold the input elements, and name it &lt;code&gt;inputContainer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inside this container, add a &lt;strong&gt;Text&lt;/strong&gt; component as the header, and name it &lt;code&gt;inputLabel&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the Text component's Data property to "Input".&lt;/li&gt;
&lt;li&gt;Below it, place an &lt;strong&gt;Image&lt;/strong&gt; component to display the uploaded BPMN diagram. Name it &lt;code&gt;imagePreview&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;File Picker&lt;/strong&gt; component and name it &lt;code&gt;fileUploader&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Button&lt;/strong&gt; component labeled "Generate". Name it &lt;code&gt;generateButton&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add another &lt;strong&gt;Button&lt;/strong&gt; labeled "Copy Output", and name it &lt;code&gt;copyButton&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Position the buttons appropriately next to the File Picker.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjskct4n24vbg07jmv2oz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjskct4n24vbg07jmv2oz.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Output Section
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add another &lt;strong&gt;Container&lt;/strong&gt; for the output section, and name it &lt;code&gt;outputContainer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Text&lt;/strong&gt; component inside this container as the header, and name it &lt;code&gt;outputLabel&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the Text component's Data property to "Output".&lt;/li&gt;
&lt;li&gt;Add another &lt;strong&gt;Text&lt;/strong&gt; component for the generated explanation. Name it &lt;code&gt;generatedOutput&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the data format to HTML since the generated explanation will be formatted in HTML format.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmjvytfj5sfdzsp8g7cdx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmjvytfj5sfdzsp8g7cdx.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Configuring Queries 🔗
&lt;/h2&gt;

&lt;p&gt;With the UI ready, we can now connect to Gemini API and format the image preview using queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate Image Preview Query
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a new &lt;strong&gt;Run JavaScript code&lt;/strong&gt; query named &lt;code&gt;generateImagePreview&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add the code below in the query:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;`data:image;base&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="err"&gt;,$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;components.fileUploader.file&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="err"&gt;.base&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="err"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above query will restructure the image data and return it. The returned value will be used as a URL to display the image as a preview in the Image component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analyze Diagram Query
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a new &lt;strong&gt;REST API&lt;/strong&gt; query named &lt;code&gt;analyseDiagram&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the method to POST and enter the below URL under the URL property:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;https://generativelanguage.googleapis.com/v&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;beta/models/gemini&lt;/span&gt;&lt;span class="mf"&gt;-1.5&lt;/span&gt;&lt;span class="err"&gt;-pro:generateContent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Under &lt;strong&gt;Headers&lt;/strong&gt;, add a new header and set the key to &lt;code&gt;Content-Type&lt;/code&gt; and value to &lt;code&gt;application/json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a new workspace constant named &lt;code&gt;GEMINI_API_KEY&lt;/code&gt; and add your Gemini API Key to it.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Parameters&lt;/strong&gt;, add a new row with the key as &lt;code&gt;key&lt;/code&gt; and value as &lt;code&gt;{{constants.GEMINI_API_KEY}}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Configure the Body property of the query using the code below:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"contents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Explain in depth the content and overall of the uploaded BPMN (Business Process Model and Notation) diagram in HTML formatting only. Respond with only the explanation, and nothing else. Return the following information, with clear bullet points and headers (under 18 px) for each section: 1. **Title**: The title or main heading of the BPMN diagram. 2. **Description**: A brief description or summary of the BPMN diagram. 3. **Elements**: Explain all the processes identified in the diagram in the correct flow. If there are multiple sequences, explain them individually. 4. **Flows**: Describe the sequence flows, message flows, and associations between elements. 5. **Data Objects**: Identify and describe any data objects present in the diagram. 6. **Swimlanes**: If present, list the swimlanes (e.g., pools, lanes) and their roles or participants. Ensure the returned HTML is well-structured, with appropriate tags for headers, lists, and any other necessary elements for readability and organization."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"inline_data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"mime_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"image/jpeg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{components.fileUploader.file[0].base64Data}}"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&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;p&gt;This JSON request sends an uploaded BPMN diagram image for analysis, asking for a detailed HTML explanation of its contents, including the title, description, elements, flows, data objects, and swimlanes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Using Events For Dynamic Interaction 🔘
&lt;/h2&gt;

&lt;p&gt;Events in ToolJet allow you to easily create dynamic app interactions based on triggers such as button clicks or query completion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate Button Click
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add a new event to the &lt;strong&gt;Generate&lt;/strong&gt; button.&lt;/li&gt;
&lt;li&gt;Leave the Event as &lt;strong&gt;On click&lt;/strong&gt;, select &lt;strong&gt;Run Query&lt;/strong&gt; as the Action and Query as &lt;code&gt;analyseDiagram&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjuagcv10qmhon1i8i8ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjuagcv10qmhon1i8i8ac.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now every time the Generate button is clicked, the &lt;code&gt;analyseDiagram&lt;/code&gt; query will run and the output will be generated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copy Button Click
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add an &lt;strong&gt;On click&lt;/strong&gt; event on the &lt;strong&gt;Copy Output&lt;/strong&gt; button to copy the generated output to the clipboard.&lt;/li&gt;
&lt;li&gt;Set the action as &lt;strong&gt;Copy to Clipboard&lt;/strong&gt; and under the Text property, enter the code below:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generatedOutput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&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://media2.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%2Fjqovfgxi4tt882feg4oo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjqovfgxi4tt882feg4oo.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above setting will copy the output text from the related component every time we click on the Copy Output button.&lt;/p&gt;

&lt;h3&gt;
  
  
  File Picker Load:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add an &lt;strong&gt;On File Loaded&lt;/strong&gt; event on the File Picker component to run the generateImagePreview query.&lt;/li&gt;
&lt;li&gt;This configuration will ensure that the &lt;code&gt;generateImagePreview&lt;/code&gt; query runs each time a file gets uploaded to the File Picker component.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F84funu16nihb1wkh9xww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F84funu16nihb1wkh9xww.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This configuration will ensure that the generateImagePreview query runs each time a file gets uploaded to the File Picker component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Image Preview
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Under the URL property of the &lt;strong&gt;Image&lt;/strong&gt; component, enter the code below:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateImagePreview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the Image component will display the BPMN diagram image once it is uploaded using the File Picker.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Testing ✅
&lt;/h2&gt;

&lt;p&gt;Time to test all the functionalities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;strong&gt;File Picker&lt;/strong&gt; to upload an image - a preview should be visible on the Image component.&lt;/li&gt;
&lt;li&gt;Click on the &lt;strong&gt;Generate Button&lt;/strong&gt; - the Text component in output should display the explanation of the BPMN diagram in-depth through HTML formatting.&lt;/li&gt;
&lt;li&gt;Click on the &lt;strong&gt;Copy Output Button&lt;/strong&gt; - the generated explanation should get copied and you should get a notification saying "Copied to clipboard!"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F092pwp4qug1auw560d1q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F092pwp4qug1auw560d1q.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;By following this tutorial, you have successfully created a BPMN Diagram Analyzer using ToolJet. This app allows users to upload BPMN diagrams in image format and receive detailed explanations, enhancing their workflow analysis capabilities. Feel free to expand and customize the app further based on your specific requirements. Happy building!&lt;/p&gt;

&lt;p&gt;To learn and explore more about ToolJet, check out the &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-components" rel="noopener noreferrer"&gt;ToolJet docs&lt;/a&gt; or connect with us and post your queries on &lt;a href="https://tooljet.slack.com/" rel="noopener noreferrer"&gt;Slack&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>coding</category>
    </item>
    <item>
      <title>Create a QR Code Generator Using ToolJet and Python in 5 Minutes! 🛠️</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Thu, 20 Jun 2024 13:04:57 +0000</pubDate>
      <link>https://forem.com/tooljet/create-a-qr-code-generator-using-tooljet-and-python-in-5-minutes-19m6</link>
      <guid>https://forem.com/tooljet/create-a-qr-code-generator-using-tooljet-and-python-in-5-minutes-19m6</guid>
      <description>&lt;p&gt;This quick tutorial will guide you through the steps to create a QR Code Generator application using ToolJet. The app will allow users to select a URL and generate a corresponding QR code. We will utilize ToolJet's visual app-builder to rapidly build a user interface and then connect to a Python module to generate QR codes from URLs.&lt;/p&gt;

&lt;p&gt;Here's the preview of the application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Flbo8w8oj79llquvfuazh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Flbo8w8oj79llquvfuazh.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ToolJet&lt;/strong&gt;(&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source, low-code business application builder. &lt;a href="https://www.tooljet.com/signup" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; for a free ToolJet cloud account or &lt;a href="https://docs.tooljet.com/docs/setup/try-tooljet/" rel="noopener noreferrer"&gt;run ToolJet on your local machine&lt;/a&gt; using Docker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic knowledge of &lt;strong&gt;Python&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Begin by creating an application named &lt;em&gt;QR Code Generator&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Design the User Interface
&lt;/h2&gt;

&lt;h4&gt;
  
  
  - Add a Container for the Header
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Drag and drop a &lt;code&gt;Container&lt;/code&gt; component onto the canvas.&lt;/li&gt;
&lt;li&gt;Name it &lt;code&gt;headerContainer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set its background color to &lt;code&gt;#0a60c6ff&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  - Add a Text Component for the App Name
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Inside the &lt;code&gt;headerContainer&lt;/code&gt;, add a &lt;code&gt;Text&lt;/code&gt; component.&lt;/li&gt;
&lt;li&gt;Set the text to "QR Code Generator."&lt;/li&gt;
&lt;li&gt;Style it with:

&lt;ul&gt;
&lt;li&gt;Text Color: &lt;code&gt;#ffffffff&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Text Size: &lt;code&gt;24&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Font Weight: &lt;code&gt;bold&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Border Radius: &lt;code&gt;6&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  - Add an Icon for the App Logo
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Inside the &lt;code&gt;headerContainer&lt;/code&gt;, add an &lt;code&gt;Icon&lt;/code&gt; component.&lt;/li&gt;
&lt;li&gt;Set the icon to &lt;code&gt;IconQrcode&lt;/code&gt; and color to &lt;code&gt;#ffffffff&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  - Add a Table with URLs and Other Information
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Drag and drop a &lt;code&gt;Table&lt;/code&gt; component onto the canvas.&lt;/li&gt;
&lt;li&gt;Name it &lt;code&gt;linksTable&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Below is the database table structure that we are using for this application:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;: Auto-generated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt;: String&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;url&lt;/code&gt;: String&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt;: String&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Populate the &lt;code&gt;Table&lt;/code&gt; component with data, based on the provided structure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  - Add a Text Component for the Table Header
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Above the table, add a &lt;code&gt;Text&lt;/code&gt; component.&lt;/li&gt;
&lt;li&gt;Set the text to "URL Information."&lt;/li&gt;
&lt;li&gt;Style it with:

&lt;ul&gt;
&lt;li&gt;Text Color: &lt;code&gt;#0a60c6ff&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Text Size: &lt;code&gt;24&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Font Weight: &lt;code&gt;bold&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  - Add a Modal for QR Code Generation
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Drag and drop a &lt;code&gt;Modal&lt;/code&gt; component onto the canvas.&lt;/li&gt;
&lt;li&gt;Name it &lt;code&gt;generateButton&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the Trigger button label to "Generate QR" and the Background color to &lt;code&gt;#0a60c6ff&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  - Add an Image Component to Display the QR Code
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Inside the modal, add an &lt;code&gt;Image&lt;/code&gt; component.&lt;/li&gt;
&lt;li&gt;Name it &lt;code&gt;qrOutput&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the below code for the Image component's URL property:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;png&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;,{{&lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QRGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Similarly, use the below code for the Loading state property of the Image component:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QRGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;The above configuration will display the generated QR code in the Image component after we craft and run the related query(named &lt;code&gt;QRGenerator&lt;/code&gt;).&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Implement Functionality
&lt;/h2&gt;

&lt;h4&gt;
  
  
  - Add a Python Script for QR Code Generation
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Add a query named &lt;code&gt;QRGenerator&lt;/code&gt; using the Run Python code data source.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the following Python code to generate the QR code:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;micropip&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;micropip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;install&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qrcode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;qrcode&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BytesIO&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;QR_Generator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;qr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qrcode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;QRCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;version&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;error_correction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;qrcode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ERROR_CORRECT_L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;box_size&lt;/span&gt;&lt;span class="o"&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;border&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;qr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linksTable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectedRow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;qr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fit&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="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;make_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fill_color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;black&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;back_color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;white&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;buffered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PNG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Specify the format as a string
&lt;/span&gt;    &lt;span class="n"&gt;img_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getvalue&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;img_str&lt;/span&gt;
&lt;span class="nc"&gt;QR_Generator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ffde7kmb9xs2i4ocx8ido.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffde7kmb9xs2i4ocx8ido.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This code uses the &lt;code&gt;qrcode&lt;/code&gt; library to generate a QR code from a selected URL in a ToolJet table component. The generated QR code is converted to a base64-encoded PNG image and returned as a string.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  - Link the QR Generator to the Generate Button
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Select the &lt;code&gt;generateButton&lt;/code&gt; modal and add a new event handler to it.&lt;/li&gt;
&lt;li&gt;Set up an &lt;code&gt;On open&lt;/code&gt; event to run the &lt;code&gt;QRGenerator&lt;/code&gt; query.&lt;/li&gt;
&lt;li&gt;After the above configuration, the output of the &lt;code&gt;QRGenerator&lt;/code&gt; query will be displayed in the &lt;code&gt;qrOutput&lt;/code&gt; Image component based on the earlier configuration.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 3: Test the Application
&lt;/h2&gt;

&lt;p&gt;Select a row on the &lt;code&gt;Table&lt;/code&gt; component and click on the &lt;code&gt;generateButton&lt;/code&gt; modal to generate and view the QR code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fvzwezsz8969iqes9gvv6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fvzwezsz8969iqes9gvv6.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can save the QR code by right-clicking on the image and selecting &lt;code&gt;Save image as&lt;/code&gt;. Alternatively, you can set up a Button component to download the image directly.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Congratulations
&lt;/h2&gt;

&lt;p&gt;Congratulations! You've successfully built a production-ready QR code generator. This application demonstrates ToolJet's capability to rapidly design clean user interfaces and extend functionality with custom code. While we used Python code in this tutorial, ToolJet also supports JavaScript code and Custom Components for users who want to extend the platform's functionality for very specific use-cases.&lt;/p&gt;

&lt;p&gt;For any questions or support, join the &lt;a href="https://tooljet.slack.com/" rel="noopener noreferrer"&gt;ToolJet Slack community&lt;/a&gt;. You can also check out the &lt;a href="https://docs.tooljet.com/docs/" rel="noopener noreferrer"&gt;ToolJet docs&lt;/a&gt; to learn more!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Build an AI Business Proposal Writer Using Gemini API and ToolJet in 10 minutes 🚀</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Thu, 13 Jun 2024 13:03:15 +0000</pubDate>
      <link>https://forem.com/tooljet/build-an-ai-business-proposal-writer-using-gemini-api-and-tooljet-in-10-minutes-4j3j</link>
      <guid>https://forem.com/tooljet/build-an-ai-business-proposal-writer-using-gemini-api-and-tooljet-in-10-minutes-4j3j</guid>
      <description>&lt;p&gt;In this tutorial, we'll guide you through the process of creating an AI Business Proposal Writer using ToolJet and Gemini API. We will utilize ToolJet's pre-built components and simple integration process to quickly create an application that can interact with the Gemini API. This application will allow users to input business details and generate professional business proposals.&lt;/p&gt;

&lt;p&gt;Here's a preview of the final application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Frghughfkz183bzjtqpou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Frghughfkz183bzjtqpou.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fewcpalt0obyfkvdh68xr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fewcpalt0obyfkvdh68xr.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Gemini API Key&lt;/strong&gt; : The Gemini API is an advanced AI service provided by &lt;a href="https://aistudio.google.com/app/apikey" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt;. It enables developers to integrate powerful content generation capabilities into their applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ToolJet&lt;/strong&gt;(&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source, low-code business application builder. &lt;a href="https://www.tooljet.com/signup" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; for a free ToolJet cloud account or &lt;a href="https://docs.tooljet.com/docs/setup/try-tooljet/" rel="noopener noreferrer"&gt;run ToolJet on your local machine&lt;/a&gt; using Docker.&lt;/p&gt;

&lt;p&gt;Begin by creating an application named &lt;em&gt;Business Proposal Writer&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Create a New Application
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open ToolJet and click on &lt;strong&gt;Create new application&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Name your application "Business Proposal Writer."&lt;/li&gt;
&lt;li&gt;Once you create a new application, you will see an empty canvas with a component library on the right and a query panel at the bottom.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fuox8timx0s6gmmhjbty9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fuox8timx0s6gmmhjbty9.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Design the UI
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Drag and drop the following components onto your canvas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Containers&lt;/strong&gt;: To organize the header, input fields, and output section.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text and Text Inputs&lt;/strong&gt;: For company name, service description, budget, deadline, and company expertise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Button&lt;/strong&gt;: For generating the proposal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text&lt;/strong&gt;: To display the generated proposal in HTML format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Icons&lt;/strong&gt;: For logos and making the UI more appealing.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Rename the input fields for clarity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;companyNameInput&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;serviceDescriptionInput&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;budgetInput&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deadlineInput&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;companyExpertiseInput&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Name the button &lt;code&gt;createButton&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Name the text component that will display the generated proposal as &lt;code&gt;output&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fd268ymnakkc0xzrhm09o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fd268ymnakkc0xzrhm09o.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ToolJet's pre-built &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-components" rel="noopener noreferrer"&gt;components&lt;/a&gt; offer complete flexibility in functionality and styling customization.&lt;/em&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  3. Integrating with Gemini API through Queries
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Create a &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/workspace-constants/" rel="noopener noreferrer"&gt;workspace constant&lt;/a&gt; to save your Gemini API key. Name it &lt;code&gt;GEMINI_API_KEY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Expand the query panel, create a new query, and name it &lt;code&gt;generateProposal&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Change the Request Method to &lt;code&gt;POST&lt;/code&gt; and paste the following URL under the URL input:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;https://generativelanguage.googleapis.com/v&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;beta/models/gemini&lt;/span&gt;&lt;span class="mf"&gt;-1.5&lt;/span&gt;&lt;span class="err"&gt;-pro:generateContent?key=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="err"&gt;constants.GEMINI_API_KEY&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;ul&gt;
&lt;li&gt;Navigate to the &lt;strong&gt;Body&lt;/strong&gt; section of the &lt;code&gt;generateProposal&lt;/code&gt; query. Toggle on &lt;strong&gt;Raw JSON&lt;/strong&gt; and enter the following code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"contents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"
1. **Client/Company Name:** {{components.companyNameInput.value}}
2. **Project/Service Description:** {{components.serviceDescriptionInput.value}}
3. **Budget Range (if applicable):** {{components.budgetInput.value}}
4. **Deadline:** {{components.deadlineInput.value}}
5. **Company Expertise:** {{components.companyExpertiseInput.value}}

Based on these inputs, generate a well-structured and comprehensive business proposal document in HTML format. The generated proposal should include the following sections, each with ample padding and spacing:

1. **Executive Summary**
2. **Company Overview and Qualifications**
3. **Project Understanding and Approach**
4. **Proposed Solution and Methodology**
5. **Timeline and Deliverables**
6. **Team Structure and Bios**
7. **Cost Breakdown and Budget** (Include charts as needed)
8. **Terms and Conditions**
9. **Conclusion and Call to Action**

Ensure that the HTML output is properly formatted and visually appealing."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&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;p&gt;&lt;a href="https://media2.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%2Fkx6u1z4w3go5whk6ednk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkx6u1z4w3go5whk6ednk.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries" rel="noopener noreferrer"&gt;Queries&lt;/a&gt; in ToolJet offer a simple and easy way to connect with &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-datasources" rel="noopener noreferrer"&gt;databases, APIs, and cloud storage services&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  4. Connecting the UI Components with Queries
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Select the &lt;code&gt;createButton&lt;/code&gt; component.&lt;/li&gt;
&lt;li&gt;Add an event handler to trigger the &lt;code&gt;generateProposal&lt;/code&gt; query when the button is clicked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fi66iykhynllvavuvuvub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fi66iykhynllvavuvuvub.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-events" rel="noopener noreferrer"&gt;Events&lt;/a&gt; are used to run queries, show alerts, and other functionalities based on triggers such as button clicks or query completion.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the &lt;code&gt;output&lt;/code&gt; component that was added to display the generated business proposal.&lt;/li&gt;
&lt;li&gt;Under its &lt;strong&gt;Data&lt;/strong&gt; property, enter the following code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="err"&gt;queries.generateProposal.data.candidates&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="err"&gt;.content.parts&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="err"&gt;.text&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;ul&gt;
&lt;li&gt;Now, enter the required details in the input fields and click on the button. You should see the generated business proposal in the output component.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fi2hkc9s5duzoqm7s4uud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fi2hkc9s5duzoqm7s4uud.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fxed4o0pkc92cywh7vj1e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fxed4o0pkc92cywh7vj1e.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;You have successfully built a business proposal writer using the Gemini API and ToolJet in just 10 minutes. This tool will streamline the creation of professional business proposals, saving you time and effort. &lt;/p&gt;

&lt;p&gt;For any questions or support, join the &lt;a href="https://join.slack.com/t/tooljet/shared_invite/zt-2l2i9tuls-NNCZPBlPAi2flYIhrjBqHA" rel="noopener noreferrer"&gt;ToolJet Slack community&lt;/a&gt;. You can also check out the &lt;a href="https://docs.tooljet.com" rel="noopener noreferrer"&gt;ToolJet documentation&lt;/a&gt; to learn more!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Build an AI Content Generator Using Gemini API and ToolJet in 10 Minutes 🛠️</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Tue, 04 Jun 2024 13:18:51 +0000</pubDate>
      <link>https://forem.com/tooljet/build-an-ai-content-generator-using-gemini-api-and-tooljet-in-10-minutes-2d0m</link>
      <guid>https://forem.com/tooljet/build-an-ai-content-generator-using-gemini-api-and-tooljet-in-10-minutes-2d0m</guid>
      <description>&lt;p&gt;In this quick tutorial, we'll build an AI-powered content generator using the Gemini API and ToolJet, all within just 10 minutes. This app will generate content based on the uploaded images, selected content type, and additional info entered by the user. Whether you need titles, short descriptions, long descriptions, creative stories, blog post outlines, full blog posts, social media captions, or advertising copies, this app will have you covered. Follow along to use ToolJet's rapid development process and Gemini's advanced AI capabilities to seamlessly integrate content creation into your workflow.&lt;/p&gt;

&lt;p&gt;Here is a preview of our final application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F4jktjjr8hox6c4y38ndq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F4jktjjr8hox6c4y38ndq.png" alt=" " width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ToolJet (&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source , low-code business application builder. &lt;a href="https://www.tooljet.com/signup" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; for a free ToolJet cloud account or &lt;a href="https://docs.tooljet.com/docs/setup/try-tooljet/" rel="noopener noreferrer"&gt;run ToolJet on your local machine&lt;/a&gt; using Docker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gemini API Key : Gemini API is an advanced AI service provided by &lt;a href="https://aistudio.google.com/app/apikey" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt;. It enables developers to integrate powerful content generation capabilities into their applications. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step One - Designing the UI 🎨
&lt;/h2&gt;

&lt;p&gt;Begin by creating an application named &lt;em&gt;AI Content Generator&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Once the app is created, we can start designing the UI with ToolJet's pre-built components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Drag and drop a &lt;strong&gt;Container&lt;/strong&gt; component from the &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-components" rel="noopener noreferrer"&gt;components library&lt;/a&gt; on the right and adjust its size so that it covers most of the canvas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drop an &lt;strong&gt;Icon&lt;/strong&gt; component and &lt;strong&gt;Text&lt;/strong&gt; component on the container. Then, rename the Icon component to &lt;em&gt;logo&lt;/em&gt; and the Text component to &lt;em&gt;logoText&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the Icon component to see a properties panel on the right. Select &lt;strong&gt;IconListSearch&lt;/strong&gt; as the icon.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the Text component, enter &lt;em&gt;AI Content Generator&lt;/em&gt; under its &lt;strong&gt;Text&lt;/strong&gt; property, and adjust its font weight and text size. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the color of the Icon and Text components to dark blue (Hex code - #354094). &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fkf3k3orw0yckdn786unl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkf3k3orw0yckdn786unl.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;This tutorial uses dark blue(#354094) as the primary color. Update the colors of your components accordingly in the upcoming steps. Feel free to use a different color scheme.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add an &lt;strong&gt;Image&lt;/strong&gt; component and a &lt;strong&gt;Text&lt;/strong&gt; component below the header that we just created. Rename them to &lt;em&gt;imagePreview&lt;/em&gt; and &lt;em&gt;output&lt;/em&gt; respectively. &lt;em&gt;imagePreview&lt;/em&gt; will display a preview of the uploaded image and &lt;em&gt;output&lt;/em&gt; will display the generated text based on the image and selected options.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;File Picker&lt;/strong&gt; component below the image and rename it to &lt;em&gt;imageUploader&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Place a &lt;strong&gt;Dropdown&lt;/strong&gt; component and &lt;strong&gt;Text Input&lt;/strong&gt; component next to it. Rename them to &lt;em&gt;typeOfContentInput&lt;/em&gt; and &lt;em&gt;additionalInfoInput&lt;/em&gt; respectively.&lt;/li&gt;
&lt;li&gt;For the Text Input component, enter the below value under &lt;strong&gt;Placeholder&lt;/strong&gt; property:
&lt;code&gt;Enter additional information&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;For the Dropdown component, paste the below array under &lt;strong&gt;Option values&lt;/strong&gt; and &lt;strong&gt;Option labels&lt;/strong&gt; properties using double curly braces:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{["Title", "Short Description (1-2 sentences)", "Long Description (paragraph)", "Creative Story", "Blog Post Outline", "Blog Post", "Social Media Caption", "Advertisement Copy"]}}

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enter the below value under the Dropdown component's Placeholder property:
&lt;code&gt;Select type of content&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmqnp25tphss8np3to3fc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmqnp25tphss8np3to3fc.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Renaming components can be useful when the application has a large number of components and we need to refer to component-related values inside the app.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;strong&gt;Button&lt;/strong&gt; component at the bottom as the last step in the UI building process. Rename the component to &lt;em&gt;generateContentButton&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fu25jhdxw86aeqkr5yx2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fu25jhdxw86aeqkr5yx2k.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;br&gt;
We've designed a simple UI for this application, which you can fully customize to meet your specific requirements. ToolJet offers extensive flexibility, allowing you to define and arrange components exactly as you envision.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step Two - Integrating AI Capabilities 🛠️
&lt;/h2&gt;

&lt;p&gt;With the UI complete, we can use ToolJet's &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries" rel="noopener noreferrer"&gt;queries&lt;/a&gt; to connect with Gemini API and get a response based on the uploaded image, content type, and additional information that we enter in the components.&lt;/p&gt;

&lt;p&gt;To protect your Gemini API key, we'll leverage ToolJet's &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/workspace-constants" rel="noopener noreferrer"&gt;Workspace Constants&lt;/a&gt;. This way, your key remains hidden and secure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the ToolJet logo in the top left corner. From the dropdown, select Workspace constants.&lt;/li&gt;
&lt;li&gt;Click on the &lt;strong&gt;Create new constant&lt;/strong&gt; button. Set the name as &lt;em&gt;GEMINI_API_KEY&lt;/em&gt; and enter your Gemini API key in the value input.
Click on the &lt;strong&gt;Add constant&lt;/strong&gt; button. This constant will now be available across our workspace and can be accessed using &lt;code&gt;{{constants.GEMINI_API_KEY}}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fog7gvo56vva0t2ziu25j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fog7gvo56vva0t2ziu25j.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;You can log into &lt;a href="https://aistudio.google.com/app/apikey" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt; using your existing Google credentials. In the AI Studio interface, you'll be able to locate and copy your API key.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate back to your app and expand the &lt;strong&gt;Query Panel&lt;/strong&gt; at the bottom.&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;+ Add&lt;/strong&gt; button and choose the &lt;strong&gt;REST API&lt;/strong&gt; option. Rename the query as &lt;em&gt;getContent&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Change the Request Method as &lt;strong&gt;POST&lt;/strong&gt; and paste the following URL under the URL input:
&lt;code&gt;https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent?key={{constants.GEMINI_API_KEY}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;strong&gt;Body&lt;/strong&gt; section of the &lt;em&gt;getContent&lt;/em&gt; query. Toggle on &lt;strong&gt;Raw JSON&lt;/strong&gt; and enter the following code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{
    `{
     "contents": [{
       "parts": [{
         "text": "Generate the following content for this image in markdown format:
         content type: ${components.typeOfContentInput.value},
         additional info: ${components.additionalInfoInput.value}"
        },
        {
            "inline_data": {
              "mime_type":"image/jpeg",
              "data": "${components.imageUploader.file[0].base64Data}"
            }
          },],
      },],
    }`
  }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fqnelq2jt9zmbjxa4k3tw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqnelq2jt9zmbjxa4k3tw.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;In the above configuration, we are creating a structured JSON payload that combines user-input text and image data. The JSON object is then sent to the Gemini API endpoint to process the provided content and image.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step Three - Binding Data to Components 🔗
&lt;/h2&gt;

&lt;p&gt;With the query ready, we can setup a way to trigger it every time the Button component is clicked.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the Button component, and navigate its properties panel on the right.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Events&lt;/strong&gt;, click on &lt;strong&gt;&lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-events" rel="noopener noreferrer"&gt;New Event Handler&lt;/a&gt;&lt;/strong&gt; to create a new event.&lt;/li&gt;
&lt;li&gt;For the new event, select &lt;strong&gt;On click&lt;/strong&gt; as the Event and &lt;strong&gt;Run Query&lt;/strong&gt; as the Action.&lt;/li&gt;
&lt;li&gt;Select &lt;em&gt;getContent&lt;/em&gt; as the Query (the query created in the previous step).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fouhohqt8tartis014yv3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fouhohqt8tartis014yv3.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, every time the Button component is clicked, the &lt;em&gt;getContent&lt;/em&gt; query will be triggered, and it will return the AI-generated content based on the uploaded image and user input.&lt;/p&gt;

&lt;p&gt;Next, we will populate the Text(&lt;em&gt;output&lt;/em&gt;) component with the value returned by the &lt;em&gt;getContent&lt;/em&gt; query using the below steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the Text (&lt;em&gt;output&lt;/em&gt;) component that was created for the output of the query.&lt;/li&gt;
&lt;li&gt;Under its &lt;strong&gt;Data&lt;/strong&gt; property, enter the below code:
&lt;code&gt;{{queries.getContent.data.candidates[0].content.parts[0].text}}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Similarly, populate the Image component with the uploaded image from the File Picker component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the Image component.&lt;/li&gt;
&lt;li&gt;Under its &lt;strong&gt;URL&lt;/strong&gt; property, enter the below code:
&lt;code&gt;{{'data:image;base64,' + components.imageUploader.file[0].base64Data}}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our application is now ready. Let's give it a spin and see the results. Select an image, choose a content type, enter some additional info, and click on the generate button. We should now be able to see the preview of the image and AI-generated text output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fb85w892qss30h3smueij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fb85w892qss30h3smueij.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;We've now built a fully functional AI-powered content generator using the Gemini API and ToolJet in just 10 minutes. This application demonstrates how seamlessly ToolJet's rapid development environment integrates with Gemini's advanced AI capabilities to automate content creation based on user inputs.&lt;/p&gt;

&lt;p&gt;To explore more, checkout &lt;a href="https://docs.tooljet.com/docs/" rel="noopener noreferrer"&gt;ToolJet docs&lt;/a&gt; or join us on &lt;a href="https://tooljet.slack.com/" rel="noopener noreferrer"&gt;slack&lt;/a&gt;. Happy coding!!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>geminiapi</category>
    </item>
    <item>
      <title>Building a Personal Finance Tracker Using ToolJet</title>
      <dc:creator>Karan Rathod</dc:creator>
      <pubDate>Thu, 16 May 2024 14:10:38 +0000</pubDate>
      <link>https://forem.com/tooljet/building-a-personal-finance-tracker-using-tooljet-41d9</link>
      <guid>https://forem.com/tooljet/building-a-personal-finance-tracker-using-tooljet-41d9</guid>
      <description>&lt;p&gt;Building apps on &lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;ToolJet&lt;/a&gt; is fast and convenient, but it gets even better when you couple it with ToolJetDB (ToolJet's Internal Database). In this tutorial, we will build a &lt;strong&gt;Personal Finance Tracker&lt;/strong&gt; application using ToolJet and ToolJetDB.&lt;/p&gt;

&lt;p&gt;Here's a preview of what we are going to build:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fla5ytn11q6zs2zrdj14i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fla5ytn11q6zs2zrdj14i.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ToolJet&lt;/strong&gt; (&lt;a href="https://github.com/ToolJet/ToolJet" rel="noopener noreferrer"&gt;https://github.com/ToolJet/ToolJet&lt;/a&gt;) : An open-source, low-code platform that streamlines the process of building and deploying internal tools. Sign up for a free ToolJet cloud account &lt;a href="https://app.tooljet.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic JavaScript&lt;/strong&gt;: Knowledge of basic JavaScript can be handy for implementing dynamic functionality in your ToolJet applications.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Creating the Database
&lt;/h2&gt;

&lt;p&gt;Let's jump right into the development process. Log in to your ToolJet account and click on the &lt;a href="https://docs.tooljet.com/docs/tooljet-db/tooljet-database" rel="noopener noreferrer"&gt;ToolJet Database&lt;/a&gt; icon in the left sidebar.&lt;/p&gt;

&lt;p&gt;Create a new database table with the following columns and rename it to &lt;em&gt;personalFinanceTracker&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;id (primary key/auto-generated)&lt;/li&gt;
&lt;li&gt;month(varchar)&lt;/li&gt;
&lt;li&gt;income (int)&lt;/li&gt;
&lt;li&gt;description (varchar)&lt;/li&gt;
&lt;li&gt;expense (int)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add some dummy data to the table so that we have something to work with when we begin the app-development process.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Developing the UI
&lt;/h2&gt;

&lt;p&gt;Once the database is ready, click on the &lt;strong&gt;Apps&lt;/strong&gt; icon to move to Applications section and create a new application named &lt;em&gt;Personal Finance Tracker&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Now we will utilize ToolJet's pre-built components to quickly spin-up the UI of the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcufnqvwz7nwj7j0cr06x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcufnqvwz7nwj7j0cr06x.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's begin with the header of the application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drag and drop a &lt;strong&gt;Text&lt;/strong&gt; component on the canvas from the &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-components" rel="noopener noreferrer"&gt;components library&lt;/a&gt; on the right and rename it to &lt;em&gt;header&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Click on the Text component to see its configuration options in the Properties Panel on the right.&lt;/li&gt;
&lt;li&gt;Enter &lt;strong&gt;Personal Finance Tracker&lt;/strong&gt; under its &lt;strong&gt;Data&lt;/strong&gt; property, change its color to dark blue (Hex code - #36405B) and font size to 20.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F3amp5v62lyw42o1btlh2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3amp5v62lyw42o1btlh2.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time to create the income and expense input sections.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drag and drop a &lt;strong&gt;Container&lt;/strong&gt; component. Containers are used to group related components in the App-Builder.&lt;/li&gt;
&lt;li&gt;Inside the Container component, add a Text component for the &lt;strong&gt;Income&lt;/strong&gt; header.&lt;/li&gt;
&lt;li&gt;Under the Text component, add a &lt;strong&gt;Text Input&lt;/strong&gt; component followed by a &lt;strong&gt;Number Input&lt;/strong&gt; component.&lt;/li&gt;
&lt;li&gt;Rename them to &lt;em&gt;incomeDescriptionInput&lt;/em&gt; and &lt;em&gt;incomeInput&lt;/em&gt; respectively. Set the default value of &lt;em&gt;incomeInput&lt;/em&gt; component to 0.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Button&lt;/strong&gt; component below the Number Input component and rename it to &lt;em&gt;addIncomeButton&lt;/em&gt;. Also change its &lt;strong&gt;Button Text&lt;/strong&gt; property to &lt;strong&gt;Add/Update Income&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fsalmcqppthnkez4pxkkj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fsalmcqppthnkez4pxkkj.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Renaming the components can be handy when you want to refer the values inside them in queries.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy the Text, Text Input, Number Input and Button components and paste them right below the Income section to create the &lt;strong&gt;Expense&lt;/strong&gt; section.&lt;/li&gt;
&lt;li&gt;Rename the Text Input, Number Input and Button components to &lt;em&gt;expenseDescriptionInput&lt;/em&gt;, &lt;em&gt;expenseInput&lt;/em&gt;, and &lt;em&gt;addExpenseButton&lt;/em&gt; respectively.&lt;/li&gt;
&lt;li&gt;Also add two &lt;strong&gt;Statistics&lt;/strong&gt; Components below the &lt;em&gt;addExpenseButton&lt;/em&gt; component.&lt;/li&gt;
&lt;li&gt;Rename the Statistics components to &lt;em&gt;monthlyIncome&lt;/em&gt; and &lt;em&gt;monthlyExpense&lt;/em&gt;. We will use them to display the monthly income and expenses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fqonhymq9dz09qf89rvn3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqonhymq9dz09qf89rvn3.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also need to list all the income and expense entries. We can handle that with the &lt;strong&gt;Table&lt;/strong&gt; component.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a Table component next to the Container component. Rename it to &lt;em&gt;entriesTable&lt;/em&gt; and remove the sample data under its &lt;strong&gt;Data&lt;/strong&gt; property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fdbb1xcdcttged9g2qfwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fdbb1xcdcttged9g2qfwb.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Fetching and Binding the Data
&lt;/h2&gt;

&lt;p&gt;We had created a database table named &lt;em&gt;personalFinanceTracker&lt;/em&gt; with some dummy data in the first step. Let's use the low-code query builder to create a query that fetches the data from the database. We will then use it to populate the Table component with it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expand the &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-queries" rel="noopener noreferrer"&gt;Query Panel&lt;/a&gt; at the bottom and click on the &lt;strong&gt;Add&lt;/strong&gt; button to create a query.&lt;/li&gt;
&lt;li&gt;Rename the query to &lt;em&gt;listEntries&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;em&gt;personalFinanceTracker&lt;/em&gt; as the &lt;strong&gt;Table name&lt;/strong&gt; and &lt;strong&gt;List rows&lt;/strong&gt; under &lt;strong&gt;Operations&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Run this query on application load?&lt;/strong&gt; to ensure the query runs every time the app is loaded.&lt;/li&gt;
&lt;li&gt;Click on the &lt;strong&gt;Run&lt;/strong&gt; button to run the query and check the response under &lt;strong&gt;Preview&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjqscku5tuw6x0drholas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjqscku5tuw6x0drholas.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To populate the &lt;em&gt;entriesTable&lt;/em&gt;(Table) component using the data returned by the &lt;em&gt;listEntries&lt;/em&gt; query, follow the below steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the &lt;em&gt;entriesTable&lt;/em&gt; component.&lt;/li&gt;
&lt;li&gt;Navigate to its properties and pass the below value under its Data property:
&lt;code&gt;{{queries.listEntries.data}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Delete the id column under the &lt;strong&gt;Columns&lt;/strong&gt; property and re-arrange the columns so that we have the columns in the following order:
&lt;em&gt;Month || Income || Expense || Description&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fm3ikvtouc6npbyqn2io8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fm3ikvtouc6npbyqn2io8.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In ToolJet, you can use &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/how-to-access-values" rel="noopener noreferrer"&gt;double curly braces&lt;/a&gt; to refer dynamic values or use custom code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's create two more queries to add income and expenses. We will bind them to the &lt;em&gt;addIncomeButton&lt;/em&gt; and &lt;em&gt;addExpenseButton&lt;/em&gt; respectively.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new query named &lt;em&gt;addIncome&lt;/em&gt; with the below configuration:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F842g6st2l7z2fsahb9sg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F842g6st2l7z2fsahb9sg.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have used the following mappings in the query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;month - &lt;code&gt;{{moment().format('MMMM')}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;income - &lt;code&gt;{{components.incomeInput.value}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;expense - 0&lt;/li&gt;
&lt;li&gt;description - &lt;code&gt;{{components.incomeDescriptionInput.value}}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create another query and name it &lt;em&gt;addExpense&lt;/em&gt; with the below configuration:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fk1rpmnz073j2ndm28isl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fk1rpmnz073j2ndm28isl.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below are the mappings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;month - &lt;code&gt;{{moment().format('MMMM')}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;income - 0&lt;/li&gt;
&lt;li&gt;expense - &lt;code&gt;{{components.expenseInput.value}}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;description - &lt;code&gt;{{components.expenseDescriptionInput.value}}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's bind these queries to the &lt;em&gt;addIncomeButton&lt;/em&gt; and &lt;em&gt;addExpenseButton&lt;/em&gt; components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the &lt;em&gt;addIncomeButton&lt;/em&gt;, navigate to its properties and create a new &lt;a href="https://docs.tooljet.com/docs/tooljet-concepts/what-are-events" rel="noopener noreferrer"&gt;event&lt;/a&gt; by clicking on New event handler.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;On click&lt;/strong&gt; as the &lt;strong&gt;Event&lt;/strong&gt;, &lt;strong&gt;Run Query&lt;/strong&gt; as the &lt;strong&gt;Action&lt;/strong&gt; and &lt;em&gt;addIncome&lt;/em&gt; as the &lt;strong&gt;Query&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fe3yn0kkxcwacu7mpi8hb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fe3yn0kkxcwacu7mpi8hb.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add another event to the &lt;em&gt;addIncomeButton&lt;/em&gt; that runs the &lt;em&gt;listEntries&lt;/em&gt; query on click.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ftk05mzpj7vphq9w2i25r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftk05mzpj7vphq9w2i25r.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Now clicking the addIncomeButton triggers the addIncome and listEntries queries. This setting adds a new income record to the database and refreshes the entriesTable with updated data.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Use the same logic for the &lt;em&gt;addExpenseButton&lt;/em&gt; and trigger the &lt;em&gt;addExpense&lt;/em&gt; and &lt;em&gt;listEntries&lt;/em&gt; queries when the &lt;em&gt;addExpenseButton&lt;/em&gt; component is clicked.&lt;/p&gt;

&lt;p&gt;Now every time you enter values and click on the related buttons, new entries will be added to the table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fzx6bprklqw3wnp2xl620.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzx6bprklqw3wnp2xl620.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main functionality of our application is ready. Let's update the &lt;strong&gt;Statistics&lt;/strong&gt; components so that they display the monthly overview.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new &lt;strong&gt;Run JavaScript code&lt;/strong&gt; query and rename it to &lt;em&gt;monthlyOverview&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Paste the below code in the code input field:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await queries.listEntries.run();

let allData = queries.listEntries.getData();

function calculateCurrentMonthTotals(data) {
    // Get the current month in 'MMMM' format, e.g., 'May'
    const currentMonth = moment().format('MMMM');

    // Initialize sums for income and expense
    let totalIncome = 0;
    let totalExpense = 0;

    // Iterate through each data entry
    data.forEach(entry =&amp;gt; {
        // Check if the entry's month matches the current month
        if (entry.month === currentMonth) {
            // Sum up income and expense
            totalIncome += entry.income;
            totalExpense += entry.expense;
        }
    });

    // Return the calculated totals in an object
    return {
        income: totalIncome,
        expense: totalExpense
    };
}

const currentMonthTotals = calculateCurrentMonthTotals(allData);
return currentMonthTotals
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This code retrieves all entries from a database, then calculates and returns the total income and expenses for the current month.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pass the returned data to the &lt;strong&gt;Primary value&lt;/strong&gt; property of the Statistics components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter &lt;code&gt;{{queries.monthlyOverview.data.income}}&lt;/code&gt; for the &lt;em&gt;monthlyIncome&lt;/em&gt; component and enter &lt;code&gt;{{queries.monthlyOverview.data.expense}}&lt;/code&gt; for the &lt;em&gt;monthlyExpense&lt;/em&gt; component.&lt;/li&gt;
&lt;li&gt;Adjust the color of the &lt;em&gt;monthlyIncome&lt;/em&gt; component's primary value to light green( hex code #36AF8B), and set the &lt;em&gt;monthlyExpense&lt;/em&gt; component's primary value to dark red (hex code - #D0021B).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fr79ue9q4ry97bl230lsk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fr79ue9q4ry97bl230lsk.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With that, our personal finance application is fully complete🎉.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;With the completion of this tutorial, we now have a functional Personal Finance Tracker application, built using &lt;a href="https://www.tooljet.com/" rel="noopener noreferrer"&gt;ToolJet&lt;/a&gt; and &lt;a href="https://docs.tooljet.com/docs/tooljet-db/tooljet-database" rel="noopener noreferrer"&gt;ToolJetDB&lt;/a&gt;. This application demonstrates how you can use ToolJet's visual app-builder and low-code query builder to create apps 10x faster. To explore more, checkout &lt;a href="https://docs.tooljet.com/docs/" rel="noopener noreferrer"&gt;ToolJet docs&lt;/a&gt; or join us on &lt;a href="https://tooljet.slack.com/" rel="noopener noreferrer"&gt;slack&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
