<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Roy Derks</title>
    <description>The latest articles on DEV Community by Roy Derks (@gethackteam).</description>
    <link>https://dev.to/gethackteam</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%2F140804%2F8a3103ad-29d4-4ce1-b00b-d6e279664065.jpg</url>
      <title>DEV Community: Roy Derks</title>
      <link>https://dev.to/gethackteam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gethackteam"/>
    <language>en</language>
    <item>
      <title>Build Tool Calling Agents with LangGraph and IBM watsonx.ai Flows Engine</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Tue, 03 Dec 2024 17:20:53 +0000</pubDate>
      <link>https://dev.to/gethackteam/build-tool-calling-agents-with-langgraph-and-watsonxai-flows-engine-230c</link>
      <guid>https://dev.to/gethackteam/build-tool-calling-agents-with-langgraph-and-watsonxai-flows-engine-230c</guid>
      <description>&lt;p&gt;Generative AI is evolving quickly, and in the past couple of years, we’ve seen a few clear patterns developer can implement — starting with simple prompting, moving to &lt;a href="https://developer.ibm.com/tutorials/awb-build-rag-application-watsonx-ai-flows-engine/" rel="noopener noreferrer"&gt;Retrieval Augmented Generation (RAG)&lt;/a&gt;, and now Tool Calling and Agents. Building applications around Agents often involves connecting different tools, models, and APIs.&lt;/p&gt;

&lt;p&gt;In this tutorial, you’ll learn how to set up and run an AI agent using watsonx.ai Flows Engine and LangGraph, with help from models powered by IBM’s watsonx.ai platform. This guide will take you step by step through installing the tools you need, deploying your tools to Flows Engine, and running a chat application on your own machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool Calling &amp;amp; Agents
&lt;/h2&gt;

&lt;p&gt;Tool calling allows Large Language Models (LLMs) to work with external tools by following user-defined instructions. The model figures out the needed inputs for a tool, and the tool does the actual work. This is great for turning existing data into structured information or linking tools into workflows. Flows Engine makes this process easier by offering ways to turn your existing data sources such as databases and APIs into tools, and connect to these tools from different frameworks for building AI applications such as LangChain and LangGraph.&lt;/p&gt;

&lt;p&gt;Agents are like AI helpers built to handle specific tasks, and to complete these talks they rely on tool calling. This allows them to access external tools, process information, and expand the exsisting knowledge of the LLM to fit the user’s needs. There are several popular frameworks for building agents, either in JavaScript or Python. In this tuturial we'll be using LangGraph, which builds upon LangChain, to create an Agent that is able to call tools that can retrieve information from Google Books and Wikipedia. The tools will be defined in Flows Engine, and connected through the JavaScript SDK as you'll learn in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a Tool Calling Agent
&lt;/h2&gt;

&lt;p&gt;In this section you'll learn how to set up and run an AI agent using watsonx.ai Flows Engine (&lt;code&gt;wxflows&lt;/code&gt;) and LangGraph. The agent will be able to call several tools to answer questions about your favorite books or other popular media, using a set of prebuilt community tools. Of course, you can also convert your own data sources (such as databases and APIs) into tools. We'll cover everything you need to know, from installing the tools to deploying and running the app on your machine.&lt;/p&gt;

&lt;p&gt;This example includes the following technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LangGraph SDK (for the agent)&lt;/li&gt;
&lt;li&gt;LangChain SDK watsonx.ai extension (for the models)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wxflows&lt;/code&gt; SDK (for the tools)&lt;/li&gt;
&lt;li&gt;Carbon AI Chat (for the user interface)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;We'll be using the watsonx.ai Chat Model from LangChain, but you can use any of the &lt;a href="https://js.langchain.com/docs/integrations/chat/" rel="noopener noreferrer"&gt;supported chat models&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&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%2Fcf-courses-data.s3.us.cloud-object-storage.appdomain.cloud%2FksIOX4rVsxFMT74bM3tfbA%2Fwxflows-langgraph-carbon.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%2Fcf-courses-data.s3.us.cloud-object-storage.appdomain.cloud%2FksIOX4rVsxFMT74bM3tfbA%2Fwxflows-langgraph-carbon.png" title="wxflows with langgraph" alt="wxflows with langgraph" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Continue to the next section to start installing the &lt;code&gt;wxflows&lt;/code&gt; CLI, set up your Flows Engine project, and run the agent via a chat application. We’ll use &lt;code&gt;google_books&lt;/code&gt; and &lt;code&gt;wikipedia&lt;/code&gt; as examples of tools that the agent can call.&lt;/p&gt;

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

&lt;p&gt;Before you begin, you should create an account for &lt;a href="https://ibm.biz/wxflows" rel="noopener noreferrer"&gt;watsonx.ai Flows Engine&lt;/a&gt; for this tutorial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign up for a free &lt;a href="https://ibm.biz/wxflows" rel="noopener noreferrer"&gt;watsonx.ai Flows Engine&lt;/a&gt; account.&lt;/li&gt;
&lt;li&gt;Sign up for the &lt;a href="https://dataplatform.cloud.ibm.com/registration/stepone?context=wx" rel="noopener noreferrer"&gt;free watsonx.ai trial&lt;/a&gt; to access models. Alternatively, you can use &lt;a href="https://js.langchain.com/docs/integrations/chat/ollama/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; to run a LLM locally.&lt;/li&gt;
&lt;li&gt;You need to have Python (version 3.8 or higher) installed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Install the &lt;code&gt;wxflows&lt;/code&gt; CLI
&lt;/h3&gt;

&lt;p&gt;Start by installing the &lt;code&gt;wxflows&lt;/code&gt; CLI, which needs Python (version 3.8 or higher) to be installed on our machine. Follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Download the CLI from the &lt;a href="https://wxflows.ibm.stepzen.com/docs/installation" rel="noopener noreferrer"&gt;installation page&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a new folder on your computer.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;wxflows-project
&lt;span class="nb"&gt;cd &lt;/span&gt;wxflows-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Inside this folder, run:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;wxflows_cli-1.0.0rc192-py3-none-any.whl &lt;span class="nt"&gt;--force-reinstall&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Use the exact name of the &lt;code&gt;.whl&lt;/code&gt; file you downloaded.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Log in to the CLI by following the &lt;a href="https://wxflows.ibm.stepzen.com/docs/authentication" rel="noopener noreferrer"&gt;login instructions&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wxflows login
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;After setting up the CLI for watsonx.ai Flows Engine let's continue to the next section and create an endpoint with the Wikipedia and Google Books tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Set up a watsonx.ai Flows Engine project
&lt;/h3&gt;

&lt;p&gt;Now, set up a new &lt;code&gt;wxflows&lt;/code&gt; project. This will include two tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google_books&lt;/code&gt;&lt;/strong&gt;: Used to search and retrieve information from Google Books.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;wikipedia&lt;/code&gt;&lt;/strong&gt;: Used to query and retrieve information from Wikipedia.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the following command to initialize the project and import these tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wxflows init &lt;span class="nt"&gt;--endpoint-name&lt;/span&gt; api/wxflows-toolcalling &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--import-name&lt;/span&gt; google_books &lt;span class="nt"&gt;--import-package&lt;/span&gt; https://github.com/IBM/wxflows/raw/refs/heads/main/tools/google_books.zip &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--import-tool-name&lt;/span&gt; google_books &lt;span class="nt"&gt;--import-tool-description&lt;/span&gt; &lt;span class="s2"&gt;"Retrieve information from Google Books. Find books by search string, for example to search for Daniel Keyes 'Flowers for Algernon' use q: 'intitle:flowers+inauthor:keyes'"&lt;/span&gt; &lt;span class="nt"&gt;--import-tool-fields&lt;/span&gt; &lt;span class="s2"&gt;"books|book"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--import-name&lt;/span&gt; wikipedia &lt;span class="nt"&gt;--import-package&lt;/span&gt; https://github.com/IBM/wxflows/raw/refs/heads/main/tools/wikipedia.zip &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--import-tool-name&lt;/span&gt; wikipedia &lt;span class="nt"&gt;--import-tool-description&lt;/span&gt; &lt;span class="s2"&gt;"Retrieve information from Wikipedia."&lt;/span&gt; &lt;span class="nt"&gt;--import-tool-fields&lt;/span&gt; &lt;span class="s2"&gt;"search|page"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what this command does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creates an endpoint&lt;/strong&gt;: Defines an endpoint called &lt;code&gt;api/wxflows-toolcalling&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Imports &lt;code&gt;google_books&lt;/code&gt;&lt;/strong&gt;: Adds a tool for retrieving books from Google Books with a description and specific fields like &lt;code&gt;books|book&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Imports &lt;code&gt;wikipedia&lt;/code&gt;&lt;/strong&gt;: Adds a tool for searching Wikipedia with a description and fields like &lt;code&gt;search|page&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After running the command, you can see a &lt;code&gt;wxflows.toml&lt;/code&gt; file appear in the current directory. This file holds the configuration for your tools, which we'll deploy to an endpoint by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Deploying the endpoint should only take a couple of seconds, and the &lt;code&gt;wxflows&lt;/code&gt; SDK will use this endpoint to retrieve and call tools as you'll learn in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Use LangGraph to create an agent
&lt;/h3&gt;

&lt;p&gt;Now that we have a Flows Engine endpoint, we need to create an agent that can use this endpoint for tool calling. We'll be using LangGraph for this, together with the &lt;code&gt;wxflows&lt;/code&gt; SDK and the LangChain extension for watsonx.ai:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a new directory:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;langgraph
&lt;span class="nb"&gt;cd &lt;/span&gt;langgraph
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In this directory run the following command to set up a new TypeScript project and to install the needed dependencies:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm i @langchain/langgraph @langchain/core @langchain/community dotenv typescript @wxflows/sdk@beta
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This installs the following packages:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- `@langchain/langgraph`: Build agents, structured workflows and handle tool calling.
- `@langchain/core`: Provides core functionality for building and managing AI-driven workflows.
- `@langchain/community`: Provides access to experimental and community-contributed integrations and tools, such as models on the watsonx.ai platform.
- `dotenv`: Loads environment variables from a `.env` file, making it easier to manage API keys and configuration values.
- `typescript`: Sets up TypeScript, a superset of JavaScript, for type checking and better code quality.
- `@wxflows/sdk@beta`: Includes the SDK for working with watsonx.ai Flows Engine, which allows you to deploy and manage tools.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After running these commands, your project will be ready to start building an agent.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create an &lt;code&gt;.env&lt;/code&gt; file with the following values:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# You can get these credentials from https://dataplatform.cloud.ibm.com/developer-access?context=wx&lt;/span&gt;
&lt;span class="nv"&gt;WATSONX_AI_AUTH_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;iam
&lt;span class="nv"&gt;WATSONX_AI_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://us-south.ml.cloud.ibm.com
&lt;span class="nv"&gt;WATSONX_AI_IDENTITY_SERVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;iam.cloud.ibm.com
&lt;span class="nv"&gt;WATSONX_AI_APIKEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;WATSONX_AI_PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;

&lt;span class="c"&gt;# run the command 'wxflows whoami --apikey'&lt;/span&gt;
&lt;span class="nv"&gt;WXFLOWS_APIKEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;

&lt;span class="c"&gt;# endpoint shows in your terminal after running 'wxflows deploy'&lt;/span&gt;
&lt;span class="nv"&gt;WXFLOWS_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After creating the &lt;code&gt;.env&lt;/code&gt; file, create a new file called &lt;code&gt;index.ts&lt;/code&gt; and add the code for LangGraph:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AIMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BaseMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HumanMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SystemMessage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@langchain/core/messages&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;ChatWatsonx&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@langchain/community/chat_models/ibm&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;StateGraph&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@langchain/langgraph&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;MemorySaver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Annotation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@langchain/langgraph&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;ToolNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@langchain/langgraph/prebuilt&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;wxflows&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@wxflows/sdk/langchain&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv/config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Define the graph state&lt;/span&gt;
    &lt;span class="c1"&gt;// See here for more info: https://langchain-ai.github.io/langgraphjs/how-tos/define-state/&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;StateAnnotation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Annotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Annotation&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BaseMessage&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;reducer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&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;y&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;wxflows&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WXFLOWS_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;apikey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WXFLOWS_APIKEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;traceSession&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&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;toolClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lcTools&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;toolNode&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;ToolNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Connect to the LLM provider &lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&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;ChatWatsonx&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mistralai/mistral-large&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WATSONX_AI_PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;serviceUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WATSONX_AI_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2024-05-31&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;bindTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This first part of the code will import the needed dependencies, retrieves the tools from watsonx.ai Flows Engine and sets up the connection to Mistral Large running on the watsonx.ai platform. Let's add the second part of the code for the &lt;code&gt;index.ts&lt;/code&gt; file which will handle the creation of the agent:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Define the function that determines whether to continue or not&lt;/span&gt;
    &lt;span class="c1"&gt;// We can extract the state typing via `StateAnnotation.State`&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shouldContinue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;StateAnnotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;State&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;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&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;lastMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;messages&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;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;AIMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// If the LLM makes a tool call, then we route to the "tools" node&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;lastMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&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="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;TOOL CALL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tools&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="c1"&gt;// Otherwise, we stop (reply to the user)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__end__&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="c1"&gt;// Define the function that calls the model&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;callModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;StateAnnotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;State&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;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&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;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// We return a list, because this will get added to the existing list&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;messages&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Define a new graph&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;workflow&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;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;StateAnnotation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callModel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tools&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toolNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__start__&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent&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;addConditionalEdges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shouldContinue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEdge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tools&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize memory to persist state between graph runs&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkpointer&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;MemorySaver&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Finally, we compile it!&lt;/span&gt;
    &lt;span class="c1"&gt;// This compiles it into a LangChain Runnable.&lt;/span&gt;
    &lt;span class="c1"&gt;// Note that we're (optionally) passing the memory when compiling the graph&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;checkpointer&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Use the Runnable&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finalState&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SystemMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Only use the tools available, don't answer the question based on pre-trained data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HumanMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search information about the book escape from james patterson&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;configurable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;42&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="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;finalState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;finalState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&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;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// You can use the `thread_id` to ask follow up questions, the conversation context is retained via the saved state (i.e. stored list of messages):&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In this second part of the code, the agent is created and we pass a message to the agent: "Search information about the book escape from james patterson". This will kick off a series of interactions between the tools running in Flows Engine and the LLM in watsonx.ai to provide you with an answer.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To run the above code, you need to add a &lt;code&gt;start&lt;/code&gt; script to the &lt;code&gt;package.json&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&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;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx tsx ./index.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&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;ol&gt;
&lt;li&gt;To send the message to the agent you can now run &lt;code&gt;npm start&lt;/code&gt; from the terminal, which should return more information about the book "Escape" by "James Patterson". Next to the information, the used tool calls will also be printed in your terminal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The tool call will look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;TOOL CALL &lt;span class="o"&gt;[&lt;/span&gt;
  &lt;span class="o"&gt;{&lt;/span&gt;
    name: &lt;span class="s1"&gt;'google_books'&lt;/span&gt;,
    args: &lt;span class="o"&gt;{&lt;/span&gt;
      query: &lt;span class="s1"&gt;'{\n'&lt;/span&gt; +
        &lt;span class="s1"&gt;'  books(q: "intitle:escape+inauthor:patterson") {\n'&lt;/span&gt; +
        &lt;span class="s1"&gt;'    authors\n'&lt;/span&gt; +
        &lt;span class="s1"&gt;'    title\n'&lt;/span&gt; +
        &lt;span class="s1"&gt;'    volumeId\n'&lt;/span&gt; +
        &lt;span class="s1"&gt;'  }\n'&lt;/span&gt; +
        &lt;span class="s1"&gt;'}'&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="nb"&gt;type&lt;/span&gt;: &lt;span class="s1"&gt;'tool_call'&lt;/span&gt;,
    &lt;span class="nb"&gt;id&lt;/span&gt;: &lt;span class="s1"&gt;'Zg9jXPOR2'&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;blockquote&gt;
&lt;p&gt;watsonx.ai Flows Engine is using GraphQL as the underlying technology to define and call tools.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the final response something like this:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;### Information about the book "Escape" by James Patterson&lt;/span&gt;

Here is the information about the book &lt;span class="s2"&gt;"Escape"&lt;/span&gt; by James Patterson:

- &lt;span class="k"&gt;**&lt;/span&gt;Authors:&lt;span class="k"&gt;**&lt;/span&gt; James Patterson, David Ellis
- &lt;span class="k"&gt;**&lt;/span&gt;Title:&lt;span class="k"&gt;**&lt;/span&gt; Escape
- &lt;span class="k"&gt;**&lt;/span&gt;Volume ID:&lt;span class="k"&gt;**&lt;/span&gt; EFtHEAAAQBAJ
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The next step would be to implement a chat application that's using the Flows Engine endpoint and the LangGraph agent, as you'll learn in the next section.&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4: Use the agent in a chat application
&lt;/h3&gt;

&lt;p&gt;The final step is to use the agent and the tools endpoint in a chat application, which you can find in this repository.&lt;/p&gt;

&lt;p&gt;You can run this application in the browser using the free service StackBlitz:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackblitz.com/github/IBM/wxflows/tree/main/examples/chat-app" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.stackblitz.com%2Fimg%2Fopen_in_stackblitz.svg" alt="Open in StackBlitz" width="162" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can either run the chat application in the browser via StackBlitz or use the "Download" button to download the source code for the application and run it locally.&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%2Fcf-courses-data.s3.us.cloud-object-storage.appdomain.cloud%2FQn644YyV-DiTEj7hOsce-Q%2FUntitled.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%2Fcf-courses-data.s3.us.cloud-object-storage.appdomain.cloud%2FQn644YyV-DiTEj7hOsce-Q%2FUntitled.png" title="langgraph wxflows stackblitz" alt="langgraph wxflows stackblitz" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This application will need the same credentials as in step 3.3, which you can store in a new &lt;code&gt;.env&lt;/code&gt; file. Either directly in StackBlitz or locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# You can get these credentials from https://dataplatform.cloud.ibm.com/developer-access?context=wx&lt;/span&gt;
&lt;span class="nv"&gt;WATSONX_AI_AUTH_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;iam
&lt;span class="nv"&gt;WATSONX_AI_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://us-south.ml.cloud.ibm.com
&lt;span class="nv"&gt;WATSONX_AI_IDENTITY_SERVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;iam.cloud.ibm.com
&lt;span class="nv"&gt;WATSONX_AI_APIKEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;WATSONX_AI_PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;

&lt;span class="c"&gt;# run the command 'wxflows whoami --apikey'&lt;/span&gt;
&lt;span class="nv"&gt;WXFLOWS_APIKEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;

&lt;span class="c"&gt;# endpoint shows in your terminal after running 'wxflows deploy'&lt;/span&gt;
&lt;span class="nv"&gt;WXFLOWS_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to run the application locally, don't forget to run &lt;code&gt;npm i&lt;/code&gt; in the application's directory to install the dependencies. After installing these, you can run &lt;code&gt;npm start&lt;/code&gt; to boot up the application.&lt;/p&gt;

&lt;p&gt;The chat application is using IBM's Carbon Chat AI component library, and looks like this:&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%2Fcf-courses-data.s3.us.cloud-object-storage.appdomain.cloud%2FhjNP90zk5kO0FcIiVabDNg%2Fstackblitz-com-github-IBM-wxflows-tree-main-examples-chat-app-file--env.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%2Fcf-courses-data.s3.us.cloud-object-storage.appdomain.cloud%2FhjNP90zk5kO0FcIiVabDNg%2Fstackblitz-com-github-IBM-wxflows-tree-main-examples-chat-app-file--env.png" title="carbon ai chat app with langgraph" alt="carbon ai chat app with langgraph" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now ask any sort of question related to books or other popular media. The agent will use the Google Books or Wikipedia tool from watsonx.ai Flows Engine to answer your questions, as LangGraph keeps memory state you can also ask follow up questions. The next step would be turn your own (enterprise) data into a tool, for which you can have a look at &lt;a href="https://github.com/IBM/wxflows/tree/main/tools" rel="noopener noreferrer"&gt;these instructions&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary and Next Steps
&lt;/h3&gt;

&lt;p&gt;This tutorial showed you how to set up and run an AI agent using IBM watsonx.ai Flows Engine and LangGraph. You learned how to configure tools for &lt;code&gt;google_books&lt;/code&gt; and &lt;code&gt;wikipedia&lt;/code&gt;, deploy a Flows Engine project, and run the application locally or in a browser. These tools enable your agent to retrieve real-time data and interact with external APIs.&lt;/p&gt;

&lt;p&gt;With these new skills, you now have a strong foundation for building AI-powered applications using &lt;a href="https://ibm.biz/wxflows" rel="noopener noreferrer"&gt;&lt;code&gt;wxflows&lt;/code&gt;&lt;/a&gt; and watsonx.ai. Whether you’re creating simple workflows or more complex integrations, the CLI and SDK make it easy to bring your projects to life.&lt;/p&gt;

&lt;p&gt;We’re excited to see what you create! Join our &lt;a href="https://ibm.biz/wxflows-discord" rel="noopener noreferrer"&gt;Discord community&lt;/a&gt; and share your projects with us!&lt;/p&gt;

</description>
      <category>genai</category>
      <category>langchain</category>
      <category>langgraph</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Build AI Applications With LangChain, JavaScript, and React</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Tue, 20 Feb 2024 13:24:00 +0000</pubDate>
      <link>https://dev.to/gethackteam/build-ai-applications-with-langchain-javascript-and-react-2gnf</link>
      <guid>https://dev.to/gethackteam/build-ai-applications-with-langchain-javascript-and-react-2gnf</guid>
      <description>&lt;p&gt;As a software developer seeking to accelerate development and incorporate AI into products, integrating tools like LangChain into your workflow is an exciting prospect. This post will provide a guide for developers on leveraging LangChain to execute prompting with OpenAI models.&lt;/p&gt;

&lt;p&gt;We will walk through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up a React app with Vite&lt;/li&gt;
&lt;li&gt;Installing and configuring LangChain&lt;/li&gt;
&lt;li&gt;Connecting to the OpenAI API&lt;/li&gt;
&lt;li&gt;Building a query function with LangChain&lt;/li&gt;
&lt;li&gt;Handling form submission to interface with the AI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click the image below to watch the &lt;a href="http://www.youtube.com/watch?v=_jIXRkGVQOo" rel="noopener noreferrer"&gt;YouTube video version&lt;/a&gt; of this blog post:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=_jIXRkGVQOo" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ytimg.com%2Fvi%2F_jIXRkGVQOo%2Fhqdefault.jpg" alt="Build AI Applications With LangChain, JavaScript, and React"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a React app with Vite
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hackteam.io/blog/vite-better-create-react-app-alternative" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; is a rapid frontend build tool for modern web development. For this tutorial, we use a basic Vite app styled similarly to ChatGPT - with a query box against an empty background ready to display questions and answers.&lt;/p&gt;

&lt;p&gt;I've already created a boilerplate for this tutorial, which you can find &lt;a href="https://github.com/royderks/ai-frontend-workshop/tree/main/my-gpt" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;You can check out the repository by running the following command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/royderks/ai-frontend-workshop.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After cloning the repository, you'll need to move into the new directory and install the dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;ai-frontend-workshop/my-gpt
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you've got everything installed, open your project in whatever IDE you use – we're gonna go with Visual Studio Code here. The project folder is gonna look pretty familiar if you've ever dabbled with Create React App. You'll find static assets such as images in &lt;code&gt;public&lt;/code&gt; and your React code in &lt;code&gt;src&lt;/code&gt;. Plus, all the must-haves like &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;vite.config.js&lt;/code&gt; are there. Oh, and TypeScript users, you haven’t been forgotten – there’s a &lt;code&gt;tsconfig.json&lt;/code&gt; in there for you.&lt;/p&gt;

&lt;p&gt;Ready to see your project live? Start your local development server with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And just like that, your Vite app is up and running in your browser. Which will look something like the screenshot you can see below.&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%2Fhackteam.io%2Fimages%2Flangchain-vite-initial-chat-app.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%2Fhackteam.io%2Fimages%2Flangchain-vite-initial-chat-app.png" alt="Initial chat app with Vite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You get hot-reloading and all the modern features that make coding less of a chore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing and configuring LangChain
&lt;/h2&gt;

&lt;p&gt;LangChainJS is a JavaScript library designed to integrate language AI capabilities into web and Node.js applications. LangChain began as a Python SDK but now has JavaScript and TypeScript support. By offering developers an easy-to-use interface to leverage Large Language Models (LLMs) like GPT-4, &lt;a href="https://js.langchain.com/docs/get_started/introduction" rel="noopener noreferrer"&gt;LangChainJS&lt;/a&gt; simplifies the process of incorporating advanced natural language understanding and generation into projects. &lt;/p&gt;

&lt;p&gt;Popular use cases for LangChainJS are chatbots, automating content creation, enhancing search functionalities, or crafting personalized user experiences. You can do all of this with a limited amount of knowledge about LLMs as LangChain offers a set of abstractions on top of popular LLM providers such as OpenAI and IBM Watson.&lt;/p&gt;

&lt;p&gt;Before installing LangChain, let's stop the dev server and run:&lt;br&gt;
&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;langchain @langchain/openai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install both the general LangChain library and the library needed to connect to OpenAI. In the next section, we'll be connecting to OpenAI for which we need to generate an API Key first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to OpenAI API
&lt;/h2&gt;

&lt;p&gt;OpenAI isn't only the creator of ChatGPT; it also has a platform where you can access the models used by ChatGPT. Developers can sign up for free, and often, will get a small credit of $5 to try out their APIs. On&lt;/p&gt;

&lt;p&gt;the &lt;a href="https://platform.openai.com/" rel="noopener noreferrer"&gt;OpenAI dashboard&lt;/a&gt;, we will generate a new secret key to authenticate our app.&lt;/p&gt;

&lt;p&gt;With our key secured, we create an environment file called &lt;code&gt;.env&lt;/code&gt; to store it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_OPENAI_API_KEY=&amp;lt;your_key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;We're using &lt;code&gt;VITE_&lt;/code&gt; as a prefix so the environment variable gets picked up by Vite.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we can initialize the connection in a new file called &lt;code&gt;langchain.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@langchain/openai&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;llm&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;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;openAIApiKey&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_OPENAI_API_KEY&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;After creating the connection to OpenAI, we can create a function to call the LLM and pass our question to retrieve the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a query function with LangChain
&lt;/h2&gt;

&lt;p&gt;There are multiple methods to query an LLM using LangChain, each of these methods will behave slightly differently. For this tutorial, we'll use the &lt;code&gt;invoke&lt;/code&gt; method, one of the simplest and quickest available in LangChainJS.&lt;/p&gt;

&lt;p&gt;With our connection configured, we can build out the query function in the same &lt;code&gt;langchain.ts&lt;/code&gt; file:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@langchain/openai&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;llm&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;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;openAIApiKey&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_OPENAI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&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;getAnswer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&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;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;answer&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;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;question&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;e&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;e&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;answer&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;This async function takes the question, queries the API using LangChain's &lt;code&gt;invoke&lt;/code&gt; method, and returns the answer. There's a try/catch block around the function so we can catch errors, for example, when we run out of tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling form submission to interface with the AI
&lt;/h2&gt;

&lt;p&gt;The final step to completing this tutorial is to use the &lt;code&gt;getAnswer&lt;/code&gt; function in the user interface that we built in the first section. As we're using client-side React, we need to create a few state variables in &lt;code&gt;src/App.tsx&lt;/code&gt; and import the &lt;code&gt;getAnswer&lt;/code&gt; function from &lt;code&gt;langchain.ts&lt;/code&gt;. Also, the &lt;code&gt;getAnswer&lt;/code&gt; function needs to be wrapped in a function that we can connect to the &lt;code&gt;onSubmit&lt;/code&gt; function of the text input for typing the question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getAnswer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./langchain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuestion&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLFormElement&lt;/span&gt;&lt;span class="o"&gt;&amp;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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&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;result&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;getAnswer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;question&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;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now handle the submission of the question by adding this function to the &lt;code&gt;onSubmit&lt;/code&gt; in the &lt;code&gt;form&lt;/code&gt; element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt;
    &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;"stretch mx-2 flex flex-row gap-3 last:mb-2 md:mx-4 md:last:mb-6 lg:mx-auto lg:max-w-2xl xl:max-w-3xl"&lt;/span&gt;
    &lt;span class="na"&gt;onSubmit=&lt;/span&gt;&lt;span class="s"&gt;{handleSubmit}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, our app can now interface with the AI! We can ask questions and see it return answers that are logged to the console. If you want to display the result in the user interface, you can create another state variable for the answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getAnswer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./langchain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuestion&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAnswer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLFormElement&lt;/span&gt;&lt;span class="o"&gt;&amp;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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&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;result&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;getAnswer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;setAnswer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value for &lt;code&gt;answer&lt;/code&gt; can be rendered anywhere in the user interface, for example, in a text balloon.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Integrating LangChain opens up lots of possibilities for automating workflows, analyzing data, providing search functionality, and more. The contents of this tutorial should give you a good start in building your own AI integrations. Feel free to leave any questions below!&lt;/p&gt;

&lt;p&gt;If you found this article useful, let me know on Twitter at &lt;a href="https://twitter.com/gethackteam" rel="noopener noreferrer"&gt;@gethackteam&lt;/a&gt;. Please share it around the web or subscribe to my &lt;a href="https://www.youtube.com/@gethackteam?sub_confirmation=1" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt; for more exciting content on web technologies.&lt;/p&gt;

</description>
      <category>react</category>
      <category>langchain</category>
      <category>openai</category>
      <category>genai</category>
    </item>
    <item>
      <title>GraphQL IDEs: GraphiQL vs Altair</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Wed, 21 Jun 2023 12:46:48 +0000</pubDate>
      <link>https://dev.to/gethackteam/graphql-ides-graphiql-vs-altair-ij4</link>
      <guid>https://dev.to/gethackteam/graphql-ides-graphiql-vs-altair-ij4</guid>
      <description>&lt;p&gt;In the world of web development, GraphQL has revolutionized how we think about APIs. GraphQL enables developers to query data in a much more flexible and efficient way compared to traditional RESTful APIs. However, as with any technology, you need the right tools to make the most of it. Today, we will compare two GraphQL Integrated Development Environments (IDEs): GraphiQL and Altair.&lt;/p&gt;

&lt;p&gt;Click the image below to watch the &lt;a href="https://www.youtube.com/watch?v=q3lDfKECGbU"&gt;YouTube video version&lt;/a&gt; of this blog post:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=q3lDfKECGbU"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pbx1wtrZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/q3lDfKECGbU/hqdefault.jpg" alt="GraphiQL vs. Altair - What's the best GraphQL IDE?" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to GraphQL IDEs
&lt;/h2&gt;

&lt;p&gt;Before diving into our comparison, let's quickly understand what a GraphQL IDE is. A GraphQL IDE is a tool that helps developers interact with GraphQL APIs, very similar to how your text-editor (like VSCode or IntelliJ) helps you write code.&lt;/p&gt;

&lt;p&gt;These IDEs provide several functionalities, such as auto-completion, error highlighting, and interactive documentation. They help developers to construct and test GraphQL queries and mutations, visualize the returned data, and understand the structure of the GraphQL schema.&lt;/p&gt;

&lt;p&gt;Two popular GraphQL IDEs are GraphiQL and Altair. Let's take a closer look at each.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphiQL
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cUn8-OEW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://hackteam.io/images/graphiql-graphql-ide.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cUn8-OEW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://hackteam.io/images/graphiql-graphql-ide.png" alt="GraphiQL GraphQL IDE" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/graphql/graphiql"&gt;GraphiQL&lt;/a&gt; is one of the most well-known GraphQL IDEs. Originally developed by Facebook, it is an in-browser tool that enables developers to write, validate, and test GraphQL queries. It is open-source and can be integrated into any project that uses GraphQL. Recently, GraphiQL has been revamped with a new UI and several new features as you can read in ths &lt;a href="https://medium.com/blog/exploring-graphiql-2-updates-and-new-features.md"&gt;blog post&lt;/a&gt; I wrote earlier.&lt;/p&gt;

&lt;p&gt;The most important features of GraphiQL are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Schema introspection:&lt;/strong&gt; GraphiQL offers a robust view of the schema, letting you examine types, fields, and overall structure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Autocompletion:&lt;/strong&gt; Based on the schema, GraphiQL provides autocompletion, making it easier to construct complex queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Syntax highlighting:&lt;/strong&gt; This feature makes it easier to understand and navigate through the GraphQL queries and mutations. This includes errors. If you make a syntax mistake, GraphiQL will underline it immediately.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interactive Documentation:&lt;/strong&gt; GraphiQL builds an interactive GraphQL API documentation on-the-fly, making it easy to understand the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Query history:&lt;/strong&gt; This feature lets you access your previous queries, so you don't have to rewrite them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As mentioned, if you want to learn more about GraphiQL then check out this &lt;a href="https://medium.com/blog/exploring-graphiql-2-updates-and-new-features.md"&gt;blog post&lt;/a&gt; I wrote earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Altair
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---q1-cv6H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://hackteam.io/images/altair-graphql-ide.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---q1-cv6H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://hackteam.io/images/altair-graphql-ide.png" alt="Altair GraphQL IDE" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://altairgraphql.dev/"&gt;Altair GraphQL Client&lt;/a&gt; is another impressive GraphQL IDE. It is open-source and available as a desktop app for all major operating systems, as well as a web extension for Chrome and Firefox.&lt;/p&gt;

&lt;p&gt;There's a lot of features that Altair offers that you can also find in GraphiQL, but here are some of the most important ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple Windows:&lt;/strong&gt; Altair allows you to open multiple windows at the same time, enabling you to work with different queries (and GraphQL APIs) simultaneously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Autocompletion &amp;amp; Error Highlighting:&lt;/strong&gt; Like GraphiQL, Altair also offers autocompletion and error highlighting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Subscriptions:&lt;/strong&gt; Altair supports GraphQL subscriptions, enabling real-time updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Uploads:&lt;/strong&gt; Altair supports GraphQL multipart request specification (Multipart request), allowing you to test file uploads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pre-request scripting:&lt;/strong&gt; You can write scripts that run before the request is sent. This is useful for handling complex authentication flows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collections:&lt;/strong&gt;: Perhaps the most powerful feature of Altair is the ability to create collections of queries and mutations. This allows you to organize your queries and mutations across multiple GraphQL APIs in a logical way.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, there are many more features that Altair offers. If you want to learn more about Altair, then check out the &lt;a href="https://altair.sirmuel.design/docs/"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So how do GraphiQL and Altair compare? Let's find out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing GraphiQL and Altair
&lt;/h2&gt;

&lt;p&gt;GraphiQL and Altair share a common set of features like schema introspection, syntax highlighting, error highlighting, and auto-completion. However, they have some distinctive attributes as well.&lt;/p&gt;

&lt;p&gt;While GraphiQL's interactive documentation and query history make API exploration and reiteration of queries more comfortable, it lacks some advanced features like pre-request scripting, file uploads, and subscriptions, which are provided by Altair.&lt;/p&gt;

&lt;p&gt;On the other hand, Altair shines with its extensive feature set, providing advanced functionalities that make it more versatile for complex use-cases. The ability to handle file uploads and work with multiple GraphQL APIs simultaneously is a huge plus.&lt;/p&gt;

&lt;p&gt;To see a side-by-side comparison of GraphiQL and Altair, check out &lt;a href="https://www.youtube.com/watch?v=q3lDfKECGbU"&gt;the video&lt;/a&gt; on my &lt;a href="https://www.youtube.com/@gethackteam?sub_confirmation=1"&gt;YouTube channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Or find me on Twitter at &lt;a href="https://twitter.com/gethackteam"&gt;@gethackteam&lt;/a&gt;. I'd love to hear from you!&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://hackteam.io/blog/graphql-ide-graphiql-vs-altair"&gt;hackteam.io&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter"&gt;Reposted.io&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>graphql</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Build Angular Search Functionality with GraphQL?</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Mon, 27 Mar 2023 12:46:11 +0000</pubDate>
      <link>https://dev.to/stepzen/how-to-build-angular-search-functionality-with-graphql-31kb</link>
      <guid>https://dev.to/stepzen/how-to-build-angular-search-functionality-with-graphql-31kb</guid>
      <description>&lt;p&gt;In this tutorial, you will learn how to build a fullstack Angular application that uses GraphQL to fetch data from a server. The application we'll build together will display a list of blog posts fetched from a GraphQL API using Apollo Client, including search functionality. To create the GraphQL API, we will use StepZen, a GraphQL API platform that allows you to build and deploy a GraphQL API in minutes.&lt;/p&gt;

&lt;p&gt;Do you prefer watching a video walkthrough instead? Check out the link below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/Cuh79sEvWqI"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hqIodK_q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/Cuh79sEvWqI/hqdefault.jpg" alt="Watch a video walkthrough of Getting Started With GraphQL in Angular using StepZen" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Google has developed Angular, an open-source web application framework based on TypeScript. The initial release of Angular from angular.js involved a complete rewrite, enabling the creation of large-scale, cross-platform applications.&lt;/p&gt;

&lt;p&gt;Angular has gained a reputation for its exceptional developer tooling, which includes built-in features such as TypeScript support, routing, and a command-line interface. Additionally, Angular's component-based architecture, remarkable speed and performance, and other powerful features make it a popular choice among developers.&lt;/p&gt;

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

&lt;p&gt;To follow this tutorial, you will need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://nodejs.org/en/download/"&gt;Node.js&lt;/a&gt; installed on your machine&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://cli.angular.io/"&gt;Angular CLI&lt;/a&gt; installed on your machine (you can install it globally by running the following command using npm: &lt;code&gt;npm install -g @angular/cli&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://stepzen.com/docs/quickstart"&gt;StepZen CLI&lt;/a&gt; installed on your machine (you can install it globally by running the following command using npm: &lt;code&gt;npm install -g stepzen&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You can find the source code for this tutorial on &lt;a href="https://github.com/stepzen-dev/examples/tree/main/with-angular"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setting up a new Angular project
&lt;/h2&gt;

&lt;p&gt;To build an Angular application, we will use the Angular CLI. The Angular CLI is a command-line interface that allows you to create, build, and test Angular applications.&lt;/p&gt;

&lt;p&gt;If you don't have the Angular CLI already on your machine, you can install it globally by running the following command using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @angular/cli&lt;span class="sb"&gt;`&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: The Angular CLI requires a minimum Node.js version of either v14.20, v16.13, or v18.10. With the Angular CLI installed, we can now create a new Angular application by running the following command:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;ng new with-angular &lt;span class="nt"&gt;--directory&lt;/span&gt; ./with-angular&lt;span class="sb"&gt;`&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This command will create a new Angular application named &lt;code&gt;with-angular&lt;/code&gt;, and we specified the directory where the application will be created with the'-- directory' flag. The Angular CLI will create a new directory named &lt;code&gt;with-angular&lt;/code&gt; if it doesn't exist and will create the application inside the directory.&lt;/p&gt;

&lt;p&gt;After the Angular CLI has finished creating the application, we can now navigate to the application directory and start the development server by running the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;with-angular
ng serve &lt;span class="nt"&gt;--open&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ng serve&lt;/code&gt; command will start the development server, and the &lt;code&gt;--open&lt;/code&gt; flag will open the application in the default browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7xxkUSCK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/starter-angular-application.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7xxkUSCK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/starter-angular-application.png" alt="The starter Angular application" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the starter application running, we can now start building our application. But before we can start building the application, we need to create a GraphQL API that we can use to fetch data. In the next section, we'll create a GraphQL API using StepZen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a GraphQL API with StepZen
&lt;/h2&gt;

&lt;p&gt;The Angular application we build in this blog post will fetch data from a GraphQL API. To create a GraphQL API, we will use StepZen, a GraphQL API platform that allows you to build and deploy a GraphQL API in minutes. One of the capabilities of StepZen is transforming REST APIs into GraphQL APIs, which will be demonstrated in this tutorial.&lt;/p&gt;

&lt;p&gt;Before creating a GraphQL API, we need to create a StepZen account. You can create a free account by visiting the &lt;a href="https://stepzen.com/signup"&gt;StepZen website&lt;/a&gt;. And once you've created an account, you can install the StepZen CLI (if you haven't already) by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; stepzen&lt;span class="sb"&gt;`&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;With the StepZen CLI installed, we can now create a new StepZen project in the &lt;code&gt;with-angular&lt;/code&gt; directory by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;stepzen
stepzen init &lt;span class="nt"&gt;--endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;api/with-angular
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The blog posts we want to show in our application are fetched from the &lt;a href="https://dev.to/"&gt;DEV.to&lt;/a&gt; API. More specifically, we will fetch the posts from the DEV.to API's &lt;code&gt;articles&lt;/code&gt; endpoint: &lt;code&gt;https://dev.to/api/articles?username=gethackteam&lt;/code&gt;. The &lt;code&gt;articles&lt;/code&gt; endpoint returns a list of articles, and you could provide a different username to fetch articles from another user.&lt;/p&gt;

&lt;p&gt;To create a GraphQL API that fetches data from the DEV.to API, we can use the &lt;code&gt;import&lt;/code&gt; command from the StepZen CLI. This command will create a GraphQL schema for this REST API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;stepzen import curl &lt;span class="s1"&gt;'https://dev.to/api/articles?username=gethackteam'&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;posts &lt;span class="nt"&gt;--query-type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Posts &lt;span class="nt"&gt;--query-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;posts&lt;span class="sb"&gt;`&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Which generates a new GraphQL schema in a directory named &lt;code&gt;posts&lt;/code&gt;, which has a query called &lt;code&gt;posts&lt;/code&gt; that returns a list of posts. The &lt;code&gt;--query-type&lt;/code&gt; flag specifies the name of the type that the query will return, and the &lt;code&gt;--query-name&lt;/code&gt; flag specifies the query's name.&lt;/p&gt;

&lt;p&gt;From a different DEV.to endpoint, we want to retrieve a single post by its ID to retrieve a list of posts. To do this, we can use the &lt;code&gt;import&lt;/code&gt; command again, but this time we'll use the &lt;code&gt;--query-type&lt;/code&gt; and &lt;code&gt;--query-name&lt;/code&gt; flags with different values to specify the name of the type and query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;stepzen import curl &lt;span class="s1"&gt;'https://dev.to/api/articles/1366695'&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;post &lt;span class="nt"&gt;--query-type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Post &lt;span class="nt"&gt;--query-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;post&lt;span class="sb"&gt;`&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;There might be some overlap between type names when importing multiple REST APIs using &lt;code&gt;stepzen import curl&lt;/code&gt;. The StepZen CLI will notify you of this, and you can manually delete the duplicated types from the GraphQL schemas. For this project, we can delete the &lt;code&gt;User&lt;/code&gt;, and &lt;code&gt;Organization&lt;/code&gt; types from the file &lt;code&gt;post/index.graphql&lt;/code&gt; as these were already specified in the schema for the first import.&lt;/p&gt;

&lt;p&gt;To deploy the GraphQL API, we can run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;stepzen start&lt;span class="sb"&gt;`&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This command will deploy the GraphQL API to the StepZen cloud. Once the GraphQL API is deployed, you explore the GraphQL API from the Explorer in the StepZen dashboard by visiting the following URL: &lt;a href="https://dashboard.stepzen.com/explorer?endpoint=api%2Fwith-angular%2F__graphql"&gt;https://dashboard.stepzen.com/explorer?endpoint=api%2Fwith-angular%2F__graphql&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From the Explorer, you can run queries and mutations against the GraphQL API. For example, you can run the following query to retrieve a list of posts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetPosts&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="n"&gt;posts&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&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;You can also search for articles from a specific user by changing the &lt;code&gt;username&lt;/code&gt; parameter in the query, as shown in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GPwGKbFG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/angular-application-graphql-explorer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GPwGKbFG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/angular-application-graphql-explorer.png" alt="The StepZen Explorer" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the GraphQL API deployed, we can now start building our Angular application. In the next section, we'll add Apollo Client to our Angular application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Apollo Client to our Angular application
&lt;/h2&gt;

&lt;p&gt;Install Apollo Client for Angular&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;ng add apollo-angular&lt;span class="sb"&gt;`&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;We're using the Angular CLI to add the library &lt;code&gt;apollo-angular&lt;/code&gt; rather than npm, as this will autogenerate some of the boilerplate code to set up Apollo Client. The Angular CLI will prompt you for the endpoint of your GraphQL API, which you can answer with the endpoint of your GraphQL API that you deployed in the previous step. The endpoint of your GraphQL API is printed in the terminal after running &lt;code&gt;stepzen start&lt;/code&gt;, and will look something like this: &lt;code&gt;https://YOUR_USERNAME.stepzen.com/with-angular/__graphql&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once entering your GraphQL API endpoint and the GraphQL version (you can use the suggested one), the Angular CLI will generate the setup files for Apollo Client and reference it in the entry point of your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;CREATE src/app/graphql.module.ts &lt;span class="o"&gt;(&lt;/span&gt;713 bytes&lt;span class="o"&gt;)&lt;/span&gt;
UPDATE package.json &lt;span class="o"&gt;(&lt;/span&gt;1128 bytes&lt;span class="o"&gt;)&lt;/span&gt;
UPDATE tsconfig.json &lt;span class="o"&gt;(&lt;/span&gt;895 bytes&lt;span class="o"&gt;)&lt;/span&gt;
UPDATE src/app/app.module.ts &lt;span class="o"&gt;(&lt;/span&gt;462 bytes&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These steps complete the installation of Apollo Client but don't handle the data fetching part yet. The next section will add a new Angular component and fetch data from the GraphQL API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching data with Apollo Client
&lt;/h2&gt;

&lt;p&gt;The query we'll use to display the blog posts is the same one we created in the first part of this blog post. You need to create a new file called &lt;code&gt;graphql.operations.ts&lt;/code&gt; in the &lt;code&gt;app&lt;/code&gt; directory and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gql&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;apollo-angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GET_POSTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
    query GetPosts {
        posts {
        id
        title
        description
        }
    }
`&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GET_POSTS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And use the Angular CLI to generate the boilerplate files for a new component called &lt;code&gt;posts&lt;/code&gt; in the &lt;code&gt;app&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;ng generate component posts &lt;span class="nt"&gt;--module&lt;/span&gt; app&lt;span class="sb"&gt;`&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The Angular CLI will create a new directory called &lt;code&gt;posts&lt;/code&gt; with the files for the business logic (&lt;code&gt;*.ts&lt;/code&gt;), styling (&lt;code&gt;*.css&lt;/code&gt;), markup (&lt;code&gt;*.html&lt;/code&gt;), and testing (&lt;code&gt;*.spec.ts&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;To add the logic to fetch the data from the GraphQL API, you can replace the code in &lt;code&gt;posts/posts.component.ts&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&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;@angular/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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Apollo&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;apollo-angular&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;GET_POSTS&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;../graphql.operations&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="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./posts.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./posts.component.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostsComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;apollo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Apollo&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;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apollo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watchQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GET_POSTS&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;valueChanges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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;error&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="kr"&gt;any&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&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;posts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;this&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;=&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="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we also need to add the styling and markup to render the posts in the application. In &lt;code&gt;posts.component.html&lt;/code&gt; and &lt;code&gt;posts.component.css&lt;/code&gt;, let's add the following HTML and CSS:&lt;/p&gt;

&lt;p&gt;Add the following HTML code in &lt;code&gt;posts.component.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Error: {{ error }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"posts-container"&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"posts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;*ngFor= &lt;/span&gt;&lt;span class="s"&gt;"let post of posts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"post-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ post.title }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"post-description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ post.description }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the following CSS in &lt;code&gt;posts.component.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.posts-container&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;list-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;grid-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.posts-container&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#e0e0e0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.post-title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.post-description&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14px&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;ol&gt;
&lt;li&gt; To render the posts in the application, we need to add &lt;code&gt;app-posts&lt;/code&gt; (the selector from &lt;code&gt;PostsComponent&lt;/code&gt;) to the &lt;code&gt;app.component.html&lt;/code&gt; file. In this file, replace the content with the following:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"banner"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://stepzen.comdata:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;My posts&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;app-posts&amp;gt;&amp;lt;/app-posts&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; Finally, add styling to the &lt;code&gt;app.component.css&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1976d2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;16px&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;The application should now look like this; make sure to run &lt;code&gt;npm start&lt;/code&gt; to start the development server:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M7VqL-qY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/graphql-angular-application.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M7VqL-qY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/graphql-angular-application.png" alt="Fetching GraphQL in an Angular application" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But that's not all. You can also search posts by username. In the next section, we'll extend the functionality of this application by adding a search bar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding search functionality
&lt;/h2&gt;

&lt;p&gt;In this section, we'll add a search bar to the application to search for posts by username. With this functionality, we can search for posts by a specific user.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; For starters, we will add a new query to the &lt;code&gt;graphql.operations.ts&lt;/code&gt; file. This query will take a username as an argument and return the same fields as the &lt;code&gt;GET_POSTS&lt;/code&gt; query:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GET_POSTS_BY_USERNAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
    query GetPostsByUsername($username: String!) {
        posts(username: $username) {
            id
            title
            description
        }
  }
`&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GET_POSTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GET_POSTS_BY_USERNAME&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; From the file &lt;code&gt;posts/posts.component.ts&lt;/code&gt;, we first need to import the built-in forms library &lt;code&gt;@angular/forms&lt;/code&gt; and the &lt;code&gt;GET_POSTS_BY_USERNAME&lt;/code&gt; query:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&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;@angular/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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&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;@angular/forms&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;Apollo&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;apollo-angular&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;GET_POSTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GET_POSTS_BY_USERNAME&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;../graphql.operations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; In the same file, we will add a new method called &lt;code&gt;searchPosts&lt;/code&gt; that will be called when the user submits the search form. This method will take the &lt;code&gt;GET_POSTS_BY_USERNAME&lt;/code&gt; query and pass the username as an argument. The data for &lt;code&gt;posts&lt;/code&gt; will be overwritten with the new data:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostsComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;searchForm&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;FormGroup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gethackteam&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;searchPosts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apollo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GET_POSTS_BY_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchForm&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="nx"&gt;username&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;subscribe&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="kr"&gt;any&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&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;posts&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;ol&gt;
&lt;li&gt; To add the search bar, we will add a &lt;code&gt;form&lt;/code&gt; element to the markup file &lt;code&gt;posts.component.html&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Error: {{ error }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form"&lt;/span&gt; &lt;span class="na"&gt;[formGroup]=&lt;/span&gt;&lt;span class="s"&gt;"searchForm"&lt;/span&gt; &lt;span class="na"&gt;(ngSubmit)=&lt;/span&gt;&lt;span class="s"&gt;"searchPosts()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Enter username"&lt;/span&gt; &lt;span class="na"&gt;formControlName=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"submit-button"&lt;/span&gt; &lt;span class="na"&gt;[disabled]=&lt;/span&gt;&lt;span class="s"&gt;"searchForm.invalid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;SUBMIT&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; And to complete the search functionality, you can add the following styling rules to the bottom of the file &lt;code&gt;posts.component.css&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"text"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#E23237&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#FFF&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;If you go to the Angular application running in your browser on &lt;code&gt;localhost&lt;/code&gt; you can now search by username. A placeholder username is already present, and you can press the "submit" button to search for posts written by this username. Or, replace this value with your own username.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CMoYccgC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/graphql-angular-application-with-search.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CMoYccgC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/graphql-angular-application-with-search.png" alt="Search for posts with an username" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congrats on building a fullstack Angular application! The final application should look something like the screenshot above. You can add features like error and loading status or routing to display an individual post to continue learning.&lt;/p&gt;

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

&lt;p&gt;This tutorial taught you to use GraphQL in an Angular application using Apollo Client. With Angular, you can build scalable frontend applications with native TypeScript support. On the other hand, Apollo Client is a library to help you fetish data from a GraphQL API. For example, the GraphQL API you created in this tutorial by transforming the DEV.to REST API into GraphQL using StepZen.&lt;/p&gt;

&lt;p&gt;Head over to our &lt;a href="https://github.com/stepzen-dev/examples"&gt;examples repository&lt;/a&gt; for more examples of using GraphQL and frontend libraries. Or the &lt;a href="https://stepzen.com/docs/quick-start"&gt;StepZen docs&lt;/a&gt; to learn more about building GraphQL APIs? If you have questions about this tutorial, you can ask for help on our &lt;a href="https://discord.com/invite/9k2VdPn2FR"&gt;Discord channel&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://stepzen.com/blog/getting-started-with-graphql-in-angular"&gt;stepzen.com&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter"&gt;Reposted.io&lt;/a&gt;. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a JWT Login Flow with Auth0, Next.js, and StepZen</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Wed, 15 Feb 2023 13:34:42 +0000</pubDate>
      <link>https://dev.to/stepzen/building-a-jwt-login-flow-with-auth0-nextjs-and-stepzen-2j62</link>
      <guid>https://dev.to/stepzen/building-a-jwt-login-flow-with-auth0-nextjs-and-stepzen-2j62</guid>
      <description>&lt;p&gt;Almost every frontend application needs some form of authentication. This post will build a JWT login flow with Auth0, Next.js, and StepZen. Auth0 Next.js authentication library &lt;code&gt;nextjs-auth0&lt;/code&gt;, a library maintained by Auth0 to make integrating with Next.js flawless, will handle the authentication flow. Auth0 is a popular authentication provider that supports many different authentication methods, including social login, passwordless login, and more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TLDR; You can find the complete source code for this blog post on &lt;a href="https://github.com/stepzen-dev/examples/tree/main/with-auth0/authorization-jwt"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What does the login flow look like?
&lt;/h2&gt;

&lt;p&gt;For this login flow, we will rely on OAuth 2.0 and more specifically the &lt;a href="https://stepzen.com/blog/authenticating-graphql-apis-with-oauth2"&gt;Authorization Code Grant flow&lt;/a&gt;. This flow involves both a frontend and a backend. The frontend application will handle the login flow and redirect the user to the backend. The backend will exchange the authorization code for a JSON Web Token (JWT) and return it to the frontend application. The frontend application will then use the JWT to make requests to the backend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UXWPmqKU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/validating-jwt-tokens/flow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UXWPmqKU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/validating-jwt-tokens/flow.png" alt="Authorization Code Grant flow with Auth0 and StepZen" width="582" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The frontend application will be a Next.js application that uses the &lt;code&gt;nextjs-auth0&lt;/code&gt; library to handle the login flow. In this application, users click a button that brings them to the Auth0 Universal Login page. From this page, they can log in using a combination of email address and password, or one of the many social providers that are available in Auth0. After logging in, the user is asked to grant access to their profile information to the authorization server. The backend StepZen GraphQL API references an &lt;a href="https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-key-sets"&gt;Auth0 JSON Web Key Set&lt;/a&gt; to verify the JWT before returning sensitive data to the frontend application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Auth0
&lt;/h2&gt;

&lt;p&gt;​In this section, we will configure our Auth0 account to integrate it into our application later. This involves creating an Auth0 account, creating an API in the Auth0 dashboard, and an application that will be used to generate access tokens for our StepZen GraphQL API.&lt;/p&gt;

&lt;p&gt;First, you need to have an Auth0 account. If you don't have one yet, you can create one for free by following the instructions on the &lt;a href="https://auth0.com/"&gt;Auth0 website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Second, we need to create an API in Auth0. This API will represent our StepZen GraphQL API and give it access to the Auth0 authorization server. To do this, we need to go to the Auth0 dashboard and:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Click the &lt;strong&gt;Applications&lt;/strong&gt; link in the left navigation pane.&lt;/li&gt;
&lt;li&gt;  Click the &lt;strong&gt;APIs`&lt;/strong&gt; link in the left navigation pane.&lt;/li&gt;
&lt;li&gt;  Click the &lt;strong&gt;+ Create API&lt;/strong&gt; button.&lt;/li&gt;
&lt;li&gt;  On this page you need to fill out the following fields:​

&lt;ul&gt;
&lt;li&gt;  Enter a name in the &lt;em&gt;Name&lt;/em&gt; field to help you identify this client. For example: "My StepZen API".&lt;/li&gt;
&lt;li&gt;  For the &lt;em&gt;Identifier&lt;/em&gt; field, enter a unique value. For example: "&lt;a href="https://my-stepzen-api.com"&gt;https://my-stepzen-api.com&lt;/a&gt;".&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;  And click the &lt;strong&gt;Create&lt;/strong&gt; button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g9eWKWfg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-auth0-login-setup-api.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g9eWKWfg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-auth0-login-setup-api.png" alt="Create an API in Auth0" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should now see a page that contains the Identifier and Audience fields. The &lt;code&gt;Identifier&lt;/code&gt; is the URL that will be used to identify your API; this is the value that will be used to identify your API when requesting an access token. We will need these values later on, so copy them somewhere.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Not setting up an API in this stage will lead to Auth0 creating an &lt;em&gt;opaque&lt;/em&gt; access token. This token will not be able to be validated by StepZen, but only by Auth0. This is not what we want, so make sure to create an API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, we need to create an application in Auth0. This application is the authorization server that will be used to generate access tokens for our StepZen GraphQL API.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Go Back to the &lt;strong&gt;Applications&lt;/strong&gt; page.&lt;/li&gt;
&lt;li&gt;  Click the &lt;strong&gt;+ Create Application&lt;/strong&gt; button.&lt;/li&gt;
&lt;li&gt;  Fill out the following fields:​

&lt;ul&gt;
&lt;li&gt;  Enter a name in the &lt;em&gt;Name&lt;/em&gt; field to help you identify this client. For example: "My StepZen App".&lt;/li&gt;
&lt;li&gt;  For application type, select &lt;em&gt;Single Page Web Applications&lt;/em&gt; (or &lt;em&gt;Regular Web Applications&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;  Click the &lt;strong&gt;Create&lt;/strong&gt; button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go the &lt;strong&gt;Settings&lt;/strong&gt; tab to find the configuration needed to integrate with StepZen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Domain​&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Client ID​&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Client Secret​&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oviyk-d4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-auth0-login-setup-application.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oviyk-d4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-auth0-login-setup-application.png" alt="Create an Application in Auth0" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the values for the &lt;em&gt;Domain&lt;/em&gt;, &lt;em&gt;Client ID&lt;/em&gt;, and &lt;em&gt;Client Secret&lt;/em&gt; fields. We will need these values in our frontend application later on.&lt;/p&gt;

&lt;p&gt;We also need to configure the application to allow it to redirect to our frontend application. Scroll down to the &lt;strong&gt;Allowed Callback URLs&lt;/strong&gt; field and add the following URL: "&lt;a href="http://localhost:3000/api/auth/callback"&gt;http://localhost:3000/api/auth/callback&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SSgQM7Wc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-auth0-login-setup-application-callback.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SSgQM7Wc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-auth0-login-setup-application-callback.png" alt="Create the allowed callbacks in Auth0" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! We have now configured our Auth0 account and can move on to the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Next.js application
&lt;/h2&gt;

&lt;p&gt;In this section, we will create a Nextjs frontend application to handle the login flow with &lt;code&gt;nextjs-auth0&lt;/code&gt;. This application will use the &lt;code&gt;nextjs-auth0&lt;/code&gt; library to handle the login flow. This library will take the redirect to the Auth0 Universal Login page and handle the callback from the Auth0 authorization server. It will also handle storing the JWT in the browser and, optionally, refreshing the JWT when it expires.&lt;/p&gt;

&lt;p&gt;You can create a new Nextjs application by running the following command:​&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
&lt;/code&gt;npx create-next-app`&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The Next.js setup will prompt you with a few questions, such as the name you want to give to the application, if you want to use TypeScript, and if you want to use experimental features. We will use the default settings for this post, so you can press enter to accept the default values.&lt;/p&gt;

&lt;p&gt;Once you've finished the setup of the Next.js application, let's install the following dependency that is needed for authentication:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`bash&lt;br&gt;
npm install @auth0/nextjs-auth0&lt;/p&gt;

&lt;h1&gt;
  
  
  or if you're using yarn
&lt;/h1&gt;

&lt;p&gt;yarn add @auth0/nextjs-auth0&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And add your Auth0 API and Application configuration to the &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
AUTH0_SECRET='LONG_RANDOM_VALUE' # A long, secret value used to encrypt the session cookie&lt;br&gt;
AUTH0_BASE_URL='http://localhost:3000'&lt;br&gt;
AUTH0_ISSUER_BASE_URL='https://YOUR_AUTH0_DOMAIN.auth0.com'&lt;br&gt;
AUTH0_CLIENT_ID='YOUR_AUTH0_CLIENT_ID'&lt;br&gt;
AUTH0_CLIENT_SECRET='YOUR_AUTH0_CLIENT_ID'&lt;br&gt;
AUTH0_AUDIENCE='YOUR_AUTH0_API_IDENTIFIER'&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can execute the following command to generate a suitable string for the &lt;code&gt;AUTH0_SECRET&lt;/code&gt; value: &lt;code&gt;node -e "console.log(crypto.randomBytes(32).toString('hex'))"&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the configuration in place, we can now add the code to the Next.js application to use the &lt;code&gt;nextjs-auth0&lt;/code&gt; library to handle the login flow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a new file called &lt;code&gt;pages/api/auth/[...auth0].ts&lt;/code&gt; (or create the file as &lt;code&gt;.js&lt;/code&gt; if you prefer not to use TypeScript). The &lt;code&gt;nextjs-auth0&lt;/code&gt; library will use this file to handle the login flow and as the callback URL for the Auth0 authorization server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following code to the new &lt;code&gt;pages/api/auth/[...auth0].ts&lt;/code&gt; file:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
import { handleAuth, handleLogin } from '@auth0/nextjs-auth0';&lt;/p&gt;

&lt;p&gt;export default handleAuth({&lt;br&gt;
  login: handleLogin({&lt;br&gt;
    authorizationParams: {&lt;br&gt;
      audience: process.env.AUTH0_AUDIENCE, // or AUTH0_IDENTIFIER&lt;br&gt;
      // Add the &lt;code&gt;offline_access&lt;/code&gt; scope to also get a Refresh Token&lt;br&gt;
      scope: 'openid profile email', // or AUTH0_SCOPE&lt;br&gt;
    },&lt;br&gt;
  }),&lt;br&gt;
});&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We also need to wrap the application with the &lt;code&gt;UserProvider&lt;/code&gt; component. This component will be used to store the user information in the React context. This will allow us to access the user information in any component in the application. For example, by using any of the Hooks provided by &lt;code&gt;nextjs-auth0&lt;/code&gt;. To do this, we need to add the following code to the &lt;code&gt;pages/_app.tsx&lt;/code&gt; file:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
// pages/_app.tsx&lt;br&gt;
import '@/styles/globals.css';&lt;br&gt;
import type { AppProps } from 'next/app';&lt;br&gt;
import { UserProvider } from '@auth0/nextjs-auth0/client';&lt;/p&gt;

&lt;p&gt;export default function App({ Component, pageProps }: AppProps) {&lt;br&gt;
  return (&lt;br&gt;
    &lt;br&gt;
      &lt;br&gt;
    &lt;br&gt;
  );&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The last step is to add a login button to the application. To do this, we need to add the replace the contents in the &lt;code&gt;pages/index.tsx&lt;/code&gt; file with the following code:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`tsx&lt;br&gt;
// pages/index.tsx&lt;br&gt;
import Head from 'next/head';&lt;br&gt;
import Link from 'next/link';&lt;br&gt;
import styles from '@/styles/Home.module.css';&lt;/p&gt;

&lt;p&gt;export default function Home() {&lt;br&gt;
  return (&lt;br&gt;
    &amp;lt;&amp;gt;&lt;br&gt;
      &lt;/p&gt;
&lt;br&gt;
        My StepZen App&lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
      
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;main className={styles.main}&amp;gt;
    &amp;lt;Link href='/api/auth/login' className={styles.loginButton}&amp;gt;
      &amp;lt;span className={styles.auth0Logo} /&amp;gt;Login with Auth0
    &amp;lt;/Link&amp;gt;
  &amp;lt;/main&amp;gt;
&amp;lt;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;);&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  And finally, we need to add some styles to the application. Open the file called &lt;code&gt;styles/Home.module.css&lt;/code&gt; and add the following code to the bottom of it:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`css&lt;br&gt;
.loginButton {&lt;br&gt;
  display: flex;&lt;br&gt;
  align-items: center;&lt;br&gt;
  background: #eb5424;&lt;br&gt;
  padding: 10px 20px;&lt;br&gt;
  border-radius: 10px;&lt;br&gt;
  font-size: larger;&lt;br&gt;
  color: white;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.auth0Logo {&lt;br&gt;
  width: 32px;&lt;br&gt;
  height: 32px;&lt;br&gt;
  margin-right: 10px;&lt;br&gt;
  background: url('/auth0_icon.svg');&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Now run the application by executing the following command:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`bash&lt;br&gt;
npm run dev&lt;/p&gt;

&lt;h1&gt;
  
  
  or if you're using yarn
&lt;/h1&gt;

&lt;p&gt;yarn dev&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Open the application in your browser by navigating to &lt;code&gt;http://localhost:3000&lt;/code&gt;. You should see a login button:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OPJk1BSU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-login-flow-auth0-login-button.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OPJk1BSU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-login-flow-auth0-login-button.png" alt="Login button for Auth0 in a Next.js app" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Once you press the login button, you should be redirected to the Auth0 Universal Login page. Sign up here for a new account that will be added to the linked Auth0 account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dkxxUJtb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-login-flow-auth0-login-screen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dkxxUJtb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-login-flow-auth0-login-screen.png" alt="Auth0 Universal Login page" width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  After clicking the &lt;strong&gt;Continue&lt;/strong&gt; button, you should be redirected back to the application. If you open the browser's developer tools and look at the cookies, you should see a new cookie added that includes your JWT. This cookie is used to authenticate you in the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We now have the first part of the login flow that uses Auth0 to get a JWT. Next, we want to use this JWT to authenticate the user in the StepZen GraphQL API, so we can fetch the user's profile information from the Auth0 API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a StepZen GraphQL API
&lt;/h2&gt;

&lt;p&gt;With StepZen, you can create a GraphQL API for every data source, including REST APIs, databases, and more. In this section, we will create a GraphQL API that uses the Auth0 JWT to authenticate the user. The GraphQL API will fetch the user's profile information from the Auth0 API.&lt;/p&gt;

&lt;p&gt;First, we need to create a new StepZen project. To do this, create a new directory called &lt;code&gt;stepzen&lt;/code&gt; in the root of your project and run the following command in your terminal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
&lt;/code&gt;stepzen init api/jwt-login-flow`&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will create a new StepZen configuration file and set the endpoint name to &lt;code&gt;api/jwt-login-flow&lt;/code&gt;. You can also choose to use a different name if you prefer.&lt;/p&gt;

&lt;p&gt;To set up the StepZen GraphQL API, we need to complete the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create a new schema file called &lt;code&gt;api.graphql&lt;/code&gt;. This file will contain the GraphQL schema for the API, including a query to get user information from the Auth0 API. Replace the value for &lt;code&gt;YOUR_AUTH0_DOMAIN&lt;/code&gt; with the domain of your Auth0 account:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`graphql&lt;br&gt;
type User {&lt;br&gt;
  email: String&lt;br&gt;
  email_verified: Boolean&lt;br&gt;
  name: String&lt;br&gt;
  nickname: String&lt;br&gt;
  picture: String&lt;br&gt;
  sub: String&lt;br&gt;
  updated_at: DateTime&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;type Query {&lt;br&gt;
  me: User&lt;br&gt;
    @rest(&lt;br&gt;
      endpoint: "&lt;a href="https://YOUR_AUTH0_DOMAIN/userinfo"&gt;https://YOUR_AUTH0_DOMAIN/userinfo&lt;/a&gt;"&lt;br&gt;
      forwardheaders: ["Authorization"]&lt;br&gt;
    )&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  StepZen needs to have an &lt;code&gt;index.graphql&lt;/code&gt; that references the &lt;code&gt;api.graphql&lt;/code&gt; file. Create a new file called &lt;code&gt;index.graphql&lt;/code&gt; and add the following code to it:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;graphql&lt;br&gt;
schema @sdl(files: ["api.graphql"]) {&lt;br&gt;
  query: Query&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  To verify the Auth0 JWT, we need to create a new file called &lt;code&gt;config.yaml&lt;/code&gt;. In this file, we'll add the configuration to valide the JWT using the JSON Web Key Set (JWKS) endpoint from Auth0 and the configuration to protect the GraphQL query &lt;code&gt;me&lt;/code&gt; so authenticated users can only access it. Replace the value for &lt;code&gt;YOUR_AUTH0_DOMAIN&lt;/code&gt; with the domain of your Auth0 account:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`yaml&lt;/p&gt;

&lt;h1&gt;
  
  
  Add the JWKS endpoint
&lt;/h1&gt;

&lt;p&gt;deployment:&lt;br&gt;
  identity:&lt;br&gt;
    jwksendpoint: '&lt;a href="https://YOUR_AUTH0_DOMAIN/.well-known/jwks.json"&gt;https://YOUR_AUTH0_DOMAIN/.well-known/jwks.json&lt;/a&gt;'&lt;/p&gt;

&lt;h1&gt;
  
  
  Set the policies
&lt;/h1&gt;

&lt;p&gt;access:&lt;br&gt;
  policies:&lt;br&gt;
    - type: Query&lt;br&gt;
      policyDefault:&lt;br&gt;
        condition: true&lt;br&gt;
      rules:&lt;br&gt;
        - condition: '?$jwt' # Require JWT&lt;br&gt;
          fields: [me] # Define fields that require JWT&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Now run the following command to deploy and run your StepZen project:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
&lt;/code&gt;stepzen start`&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In your terminal, you should see a message that includes the URL of your GraphQL API. Copy the URL (which starts with &lt;code&gt;https://YOUR_USERNAME.stepzen.net/api/******&lt;/code&gt; and paste it into the &lt;code&gt;.env&lt;/code&gt; file:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`bash&lt;/p&gt;

&lt;h1&gt;
  
  
  Your StepZen endpoint
&lt;/h1&gt;

&lt;p&gt;STEPZEN_ENDPOINT='YOUR_STEPZEN_ENDPOINT'&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's it! We now have a working GraphQL API that can be used to validate the Auth0 JWT and fetch user information from the Auth0 API.&lt;/p&gt;

&lt;p&gt;In the next section, we'll use this GraphQL API to fetch the user's profile information in the Next.js application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching user information in the Next.js application
&lt;/h2&gt;

&lt;p&gt;In this section, we will use the GraphQL API that we created in the previous section to fetch the user's profile information in the Next.js application. We'll take the token from Auth0 using the library &lt;code&gt;nextjs-auth0&lt;/code&gt; to authenticate the user in the GraphQL API.&lt;/p&gt;

&lt;p&gt;To do this, we need to complete the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create a new file called &lt;code&gt;pages/api/graphql/index.ts&lt;/code&gt;. This file will be the API route to send requests to the StepZen GraphQL API. It uses the &lt;code&gt;withApiAuthRequired&lt;/code&gt; function from the &lt;code&gt;nextjs-auth0&lt;/code&gt; library, so the JWT will be available in the request, which we can extract using the &lt;code&gt;getAccessToken&lt;/code&gt; function. We're using an API route here as exectuting the data fetching server side is the recommended way to fetch data in Next.js. This JWT will then be forwarded to the GraphQL API together with the GraphQL query. You can add the following code to this file:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
import type { NextApiRequest, NextApiResponse } from 'next';&lt;br&gt;
import { withApiAuthRequired, getAccessToken } from '@auth0/nextjs-auth0';&lt;/p&gt;

&lt;p&gt;export default withApiAuthRequired(async function handler(&lt;br&gt;
  req: NextApiRequest,&lt;br&gt;
  res: NextApiResponse,&lt;br&gt;
) {&lt;br&gt;
  const { accessToken } = await getAccessToken(req, res);&lt;/p&gt;

&lt;p&gt;const headers = {&lt;br&gt;
    Authorization: &lt;code&gt;Bearer ${accessToken}&lt;/code&gt;,&lt;br&gt;
    'Content-Type': 'application/json',&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;const body = req.body;&lt;/p&gt;

&lt;p&gt;try {&lt;br&gt;
    const response = await fetch(process.env?.STEPZEN_ENDPOINT || '', {&lt;br&gt;
      method: 'POST',&lt;br&gt;
      headers,&lt;br&gt;
      body,&lt;br&gt;
    });&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const json = await response.json();

res.status(200).json(json);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;} catch (e: unknown) {&lt;br&gt;
    const message = (e as Error).message;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;res.status(500).json({ error: message });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
});&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can also generate a code snippet to connect to a StepZen GraphQL API from the &lt;a href="https://dashboard.stepzen.com/"&gt;StepZen dashboard&lt;/a&gt;. You can find this under the &lt;strong&gt;Explorer&lt;/strong&gt; tab in the left pane of the dashboard by clicking on the &lt;strong&gt;Connect&lt;/strong&gt; button in the top navigation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;  In the &lt;code&gt;pages/index.tsx&lt;/code&gt; file, we're using the new API route to fetch the user's profile information. When sending a request to this API route, we need to pass along the GraphQL query to get the user's name and picture. You can add the following code to this file:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`tsx&lt;br&gt;
export default function Home() {&lt;br&gt;
  const [userData, setUserData] = useState
    name: string;&lt;br&gt;
    picture: string;&lt;br&gt;
  }&amp;gt;(null);&lt;/p&gt;

&lt;p&gt;useEffect(() =&amp;gt; {&lt;br&gt;
    async function fetchData() {&lt;br&gt;
      const res = await fetch('/api/graphql', {&lt;br&gt;
        method: 'POST',&lt;br&gt;
        body: JSON.stringify({&lt;br&gt;
          query: &lt;code&gt;&lt;br&gt;
            query {&lt;br&gt;
              me {&lt;br&gt;
                name&lt;br&gt;
                picture&lt;br&gt;
              }&lt;br&gt;
            }&lt;br&gt;
&lt;/code&gt;,&lt;br&gt;
        }),&lt;br&gt;
      });&lt;br&gt;
      const json = await res.json();&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  if (json?.data?.me) setUserData(json.data.me);
}

fetchData();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}, [setUserData]);&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    // ...&lt;br&gt;
  );&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  After retrieving the user's profile information, we can display it in the UI. You can add the following code to the &lt;code&gt;pages/index.tsx&lt;/code&gt; file:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;tsx&lt;br&gt;
return (&lt;br&gt;
  &amp;lt;main className={styles.main}&amp;gt;&lt;br&gt;
    &amp;lt;div className={styles.center}&amp;gt;&lt;br&gt;
      {userData ? (&lt;br&gt;
        &amp;lt;div className={styles.profile}&amp;gt;&lt;br&gt;
          &amp;lt;img&lt;br&gt;
            src={userData.picture}&lt;br&gt;
            alt={&lt;/code&gt;${userData.name}'s profile picture&lt;code&gt;}&lt;br&gt;
            width={200}&lt;br&gt;
            height={200}&lt;br&gt;
          /&amp;gt;&lt;br&gt;
          &amp;lt;p&amp;gt;&lt;br&gt;
            &amp;lt;strong&amp;gt;Welcome {userData?.name}!&amp;lt;/strong&amp;gt;{' '}&lt;br&gt;
            &amp;lt;a href='/api/auth/logout'&amp;gt;Logout&amp;lt;/a&amp;gt;&lt;br&gt;
          &amp;lt;/p&amp;gt;&lt;br&gt;
        &amp;lt;/div&amp;gt;&lt;br&gt;
      ) : (&lt;br&gt;
        &amp;lt;Link href='/api/auth/login' className={styles.loginButton}&amp;gt;&lt;br&gt;
          &amp;lt;span className={styles.auth0Logo} /&amp;gt;&lt;br&gt;
          Login with Auth0&lt;br&gt;
        &amp;lt;/Link&amp;gt;&lt;br&gt;
      )}&lt;br&gt;
    &amp;lt;/div&amp;gt;&lt;br&gt;
  &amp;lt;/main&amp;gt;&lt;br&gt;
)&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Next.js recommends using the &lt;code&gt;Image&lt;/code&gt; component from &lt;code&gt;next/image&lt;/code&gt; to render images. However, when rendering remote sources, you need to allow access to the remote URLs of these sources. Therefore, we're using the &lt;code&gt;img&lt;/code&gt; tag instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;  Finally, we need to add the styling for the profile information. You can add the following code to the &lt;code&gt;Home.module.css&lt;/code&gt; file:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`css&lt;br&gt;
.profile {&lt;br&gt;
  display: flex;&lt;br&gt;
  justify-content: center;&lt;br&gt;
  align-items: center;&lt;br&gt;
  flex-direction: column;&lt;br&gt;
  margin-top: 20px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.profile img {&lt;br&gt;
  border-radius: 50%;&lt;br&gt;
  margin-bottom: 20px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.profile a {&lt;br&gt;
  color: #eb5424;&lt;br&gt;
  text-decoration: underline;&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Now, if you open the application in the browser again and click on the &lt;strong&gt;Login with Auth0&lt;/strong&gt; button, you should be redirected to the Auth0 login page. After logging in, you should see the user's profile information in the UI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vs76VaCH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-login-flow-auth0-login-profile-page.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vs76VaCH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://stepzen.com/images/blog/jwt-login-flow-auth0-login-profile-page.png" alt="Application after logging in" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  As a finishing touch, we can show a loading indicator while the application checks if the user is authenticated and fetches the user's profile information. Therefore the &lt;code&gt;useUser&lt;/code&gt; hook should be imported from &lt;code&gt;@auth0/nextjs-auth0/client&lt;/code&gt; and the &lt;code&gt;isLoading&lt;/code&gt; property should be used to check if the user is authenticated. You can add the following code to the &lt;code&gt;pages/index.tsx&lt;/code&gt; file:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`tsx&lt;br&gt;
import { useEffect, useState } from 'react';&lt;br&gt;
import Head from 'next/head';&lt;br&gt;
import Link from 'next/link';&lt;br&gt;
import { useUser } from '@auth0/nextjs-auth0/client';&lt;br&gt;
import styles from '@/styles/Home.module.css';&lt;/p&gt;

&lt;p&gt;export default function Home() {&lt;br&gt;
  const { isLoading } = useUser();&lt;/p&gt;

&lt;p&gt;// ...&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &lt;br&gt;
      {isLoading ? (&lt;br&gt;
        Loading...&lt;br&gt;
      ) : (&lt;br&gt;
        &lt;br&gt;
        {&lt;br&gt;
          // ...&lt;br&gt;
        } &lt;br&gt;
        &lt;br&gt;
      )}&lt;br&gt;
      &lt;br&gt;
  );&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Great! With this, we've implemented the login flow using Auth0 and StepZen. You can find the complete source code for this blog post on &lt;a href="https://github.com/stepzen-dev/examples/tree/main/with-auth0/authorization-jwt"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps?
&lt;/h2&gt;

&lt;p&gt;The flow we've implemented in this blog post is a typical pattern for frontend applications that want to provide a secure way to authenticate users. The application uses the &lt;code&gt;@auth0/nextjs-auth0&lt;/code&gt; package to handle the authentication flow and a StepZen GraphQL API to verify the JWT on the server side. This way, the application can use the user's profile information on both the client side and in requests to the GraphQL API.&lt;/p&gt;

&lt;p&gt;Follow us on &lt;a href="https://twitter.com/stepzen_dev"&gt;Twitter&lt;/a&gt; or &lt;a href="https://discord.gg/9k2VdPn2FR"&gt;join our Discord community&lt;/a&gt; to stay updated about our latest developments.&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://stepzen.com/blog/building-jwt-login-flow-auth0-nextjs-stepzen"&gt;stepzen.com&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter"&gt;Reposted.io&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Comparing GraphQL Directives: Type System Vs. Executable Directive Locations</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Wed, 01 Feb 2023 16:12:17 +0000</pubDate>
      <link>https://dev.to/stepzen/comparing-graphql-directives-type-system-vs-executable-directive-locations-2ab1</link>
      <guid>https://dev.to/stepzen/comparing-graphql-directives-type-system-vs-executable-directive-locations-2ab1</guid>
      <description>&lt;p&gt;Have you ever wondered why some directives have to be added to your GraphQL schemas while others you can only use in runtime? That's because there are two types of directive locations: type system directive locations and executable directive locations.&lt;/p&gt;

&lt;p&gt;Earlier, we wrote about the &lt;a href="https://stepzen.com/blog/graphql-directives" rel="noopener noreferrer"&gt;different directives&lt;/a&gt; there are in GraphQL. This post will recapture what directives are and examine the difference between the different locations directives can be applied to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remind me, what is a GraphQL Directive?
&lt;/h2&gt;

&lt;p&gt;Directives in GraphQL offer a means to change runtime execution and type validation in a GraphQL document. You can apply directives to many different locations in a GraphQL document, such as fields, fragments, and operations. They allow you to modify the behavior of GraphQL's execution by providing options that are not available through field arguments. For instance, you can conditionally include or exclude a field using directives, as you'll learn in this post.&lt;/p&gt;

&lt;p&gt;You can use built-in or custom directives when building or consuming a GraphQL API. Built-in directives are defined by the GraphQL specification, while custom directives are defined by the GraphQL service or tool you use. Let's look at some of the built-in directives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built-in Directives
&lt;/h3&gt;

&lt;p&gt;The GraphQL specification defines a set of built-in directives. Directives have a specific name and can accept values of any input type as arguments. They can be applied to, for example, types, fields, fragments, and operations.&lt;/p&gt;

&lt;p&gt;The following list has all the built-in directives that are defined by the GraphQL specification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;@skip&lt;/code&gt;: This directive can be used to exclude fields from a query operation conditionally.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;@include&lt;/code&gt;: Does the opposite of &lt;code&gt;@skip&lt;/code&gt; and can be used to include fields in a query operation conditionally.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;@deprecated&lt;/code&gt;: This directive can mark a field or an enum value as deprecated and can provide a reason for deprecation to the client.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;@specifiedBy&lt;/code&gt;: This directive can be used to provide a URL for the specification of a custom scalar.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: As GraphQL evolves, new execution capabilities may be introduced and exposed through directives. The directives &lt;code&gt;@defer&lt;/code&gt; and &lt;code&gt;@stream&lt;/code&gt; have been announced by the GraphQL Working Group but aren't listed in the latest draft of the GraphQL specification.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;GraphQL services and tools can also provide custom directives beyond those already mentioned. We'll learn more about custom directives in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Directives
&lt;/h3&gt;

&lt;p&gt;Custom directives can be used to extend the functionality of GraphQL and are the preferred way to add custom behavior to a GraphQL API. Different GraphQL server and client implementations are already using custom directives to add additional functionality to GraphQL.&lt;/p&gt;

&lt;p&gt;For example, at StepZen, we have defined custom directives to connect with your data sources, such as the &lt;code&gt;@rest&lt;/code&gt;, &lt;code&gt;@dbquery&lt;/code&gt;, and &lt;code&gt;@graphql&lt;/code&gt; directives. When using StepZen to develop your GraphQL API, you can use these directives to connect to REST APIs, databases, and other GraphQL APIs. Additionally, we have defined the &lt;code&gt;@materializer&lt;/code&gt; and &lt;code&gt;@sequence&lt;/code&gt; directives to mix and match data from multiple data sources in a single type.&lt;/p&gt;

&lt;p&gt;But next to built-in and custom directives, there is another distinction to be made between directives: the location they are used in. In the next section, we'll examine the difference between directives applied to type system and executable locations in GraphQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type System Directive Locations vs. Executable Directive Locations
&lt;/h2&gt;

&lt;p&gt;Directives in GraphQL can be applied to different locations, where the GraphQL Specification makes a distinction between type system directive locations and executable directive locations. Directives applied to either of these locations have the same syntax; therefore, their location determines how a GraphQL implementation handles them. However, a directive may support both type system and executable locations, though typically, a single directive supports only one location. For example, &lt;code&gt;@skip&lt;/code&gt; only supports executable directive locations.&lt;/p&gt;

&lt;p&gt;Let's look at the locations where directives can be applied and see examples for both types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directives that apply to the type system
&lt;/h3&gt;

&lt;p&gt;Directives that apply to the type system are used to annotate a schema, object type, or field definition written in GraphQL SDL (schema definition language) when building a GraphQL server. Both built-in and custom directives can be used in type system directive locations, and GraphQL server implementations can then use these annotations to take additional actions. Therefore, type system directive locations are also called "schema directives" as they only exist on the GraphQL schema itself.&lt;/p&gt;

&lt;p&gt;The following locations in a GraphQL schema are valid type system directive locations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;SCHEMA&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;SCALAR&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;OBJECT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;FIELD_DEFINITION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;ARGUMENT_DEFINITION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;INTERFACE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;UNION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;ENUM&lt;/code&gt; &amp;amp; &lt;code&gt;ENUM_VALUE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;INPUT_OBJECT&lt;/code&gt; &amp;amp; &lt;code&gt;INPUT_FIELD_DEFINITION&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples of directives that apply to the type system include &lt;code&gt;@deprecated&lt;/code&gt;, a built-in directive that can mark a field as deprecated. Let's see what it looks like in a schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&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="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;instead&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&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;In the example above, the &lt;code&gt;@deprecated&lt;/code&gt; directive marks the &lt;code&gt;name&lt;/code&gt; field as deprecated. The &lt;code&gt;reason&lt;/code&gt; argument provides a reason for deprecation available to services that introspect the schema. The client could then, for example, warn the user that the field &lt;code&gt;name&lt;/code&gt; is deprecated and shouldn't be used anymore.&lt;/p&gt;

&lt;p&gt;When you would look up the &lt;code&gt;User&lt;/code&gt; type in the documentation generated by GraphiQL, you should see warnings about using the field &lt;code&gt;name&lt;/code&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%2Fo05zaqyq3hgdaf0eufom.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%2Fo05zaqyq3hgdaf0eufom.png" alt="Deprecated field in GraphiQL" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another example of a directive that can be applied to the type system is &lt;code&gt;@rest&lt;/code&gt;, a custom directive only available in StepZen GraphQL implementations. The data for the &lt;code&gt;User&lt;/code&gt; type in the example above is fetched from a REST API using the &lt;code&gt;@rest&lt;/code&gt; directive, which is defined in the following way on a query field in a GraphQL schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&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="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&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="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&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="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;rest&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="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="n"&gt;jsonplaceholder&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="n"&gt;typicode&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="err"&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;When you run an operation that includes the &lt;code&gt;user&lt;/code&gt; field, the StepZen GraphQL API fetches the data from the REST API and returns it to the client. The &lt;code&gt;@rest&lt;/code&gt; directive is applied to a type system location because it annotates the &lt;code&gt;user&lt;/code&gt; field in the schema. It lets you declaratively define how the data for the &lt;code&gt;user&lt;/code&gt; field should be fetched, rather than having to write a resolver function, as you might expect from other GraphQL server implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directives that apply to execution
&lt;/h3&gt;

&lt;p&gt;You can use directives that apply to execution to modify the behavior of an operation, field, or fragment in runtime execution. For example, directives that apply to execution can include or exclude fields or perform additional data processing before the response is returned.&lt;/p&gt;

&lt;p&gt;Executable directive locations in GraphQL are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;QUERY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;MUTATION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;SUBSCRIPTION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;FIELD&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;FRAGMENT_DEFINITION&lt;/code&gt; &amp;amp; &lt;code&gt;FRAGMENT_SPREAD&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;INLINE_FRAGMENT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;VARIABLE_DEFINITION&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Similar to directives that apply to the type system directives, both built-in and custom directives can be applied to executable locations. Most built-in directives are executable, such as &lt;code&gt;@skip&lt;/code&gt; and &lt;code&gt;@include&lt;/code&gt;, which you can use to include or exclude fields in an operation conditionally.&lt;/p&gt;

&lt;p&gt;Let's see what the &lt;code&gt;@include&lt;/code&gt; directive looks like in a query operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$showName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Boolean&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="n"&gt;me&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;@include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$showName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;@include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$showName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;email&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;The &lt;code&gt;@include&lt;/code&gt; directive conditionally includes the &lt;code&gt;firstName&lt;/code&gt; and &lt;code&gt;lastName&lt;/code&gt; fields in the response. The &lt;code&gt;if&lt;/code&gt; argument specifies a boolean value determining whether to include the field in the response. In the example above, the &lt;code&gt;if&lt;/code&gt; argument is set to a variable &lt;code&gt;$showName&lt;/code&gt;, which is defined in the operation variables. The variable's value can be set to &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; to include or exclude the fields in the response.&lt;/p&gt;

&lt;p&gt;When you'd pass this operation to a GraphQL API, the response should include the fields &lt;code&gt;firstName&lt;/code&gt; and &lt;code&gt;lastName&lt;/code&gt; in the response if the value of the variable &lt;code&gt;$showName&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt; as you can see in the screenshot below:&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%2Fo2cg46qnigyhsix5aivz.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%2Fo2cg46qnigyhsix5aivz.png" alt="Include fields with directives in GraphiQL" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another example of an executable directive is &lt;code&gt;@sort&lt;/code&gt;, a custom directive only available in StepZen GraphQL implementations.&lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;@sort&lt;/code&gt; directive, you can sort the data returned by a field in a GraphQL operation. You can use the &lt;code&gt;@sort&lt;/code&gt; directive on a field that returns either a list of leaf fields or a list of objects.&lt;/p&gt;

&lt;p&gt;For example, let's say you have a &lt;code&gt;products&lt;/code&gt; field that returns a list of &lt;code&gt;tags&lt;/code&gt;. You can use the &lt;code&gt;@sort&lt;/code&gt; directive to sort the tags by alphabetical order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&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="n"&gt;products&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="n"&gt;tags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ['c', 'b', 'a', null]&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;Will be transformed to this when the &lt;code&gt;@sort&lt;/code&gt; directive is used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&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="n"&gt;products&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="n"&gt;tags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;@sort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# [null, 'a', 'b', 'c']&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;Next to a list of leaf fields, the same &lt;code&gt;@sort&lt;/code&gt; directive can be applied to a field that returns a list of objects. You can find more information on using the &lt;code&gt;@sort&lt;/code&gt; directive in the &lt;a href="https://stepzen.com/docs/custom-graphql-directives/directives" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;In this blog post, you learned about built-in and custom directives and how they can be applied to different locations in GraphQL. These locations are either type system or executable locations. Directives applied to the type system directives are used in GraphQL Schema Definition Language (SDL) only. At the same time, directives applied to executable locations are used to modify the response of GraphQL in runtime execution.&lt;/p&gt;

&lt;p&gt;Want to learn more about building and consuming GraphQL APIs? Follow StepZen on &lt;a href="https://twitter.com/stepzen_dev" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://discord.gg/9k2VdPn2FR" rel="noopener noreferrer"&gt;join our Discord community&lt;/a&gt; to stay updated about our latest developments.&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://stepzen.com/blog/type-system-directives-versus-executable-directives" rel="noopener noreferrer"&gt;stepzen.com&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter" rel="noopener noreferrer"&gt;Reposted.io&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>web3</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>Authenticating GraphQL APIs with OAuth 2.0</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Wed, 25 Jan 2023 17:33:58 +0000</pubDate>
      <link>https://dev.to/stepzen/authenticating-graphql-apis-with-oauth-20-1gl9</link>
      <guid>https://dev.to/stepzen/authenticating-graphql-apis-with-oauth-20-1gl9</guid>
      <description>&lt;p&gt;There are many different ways to handle authentication in GraphQL, but one of the most common is to use OAuth 2.0 - and, more specifically, JSON Web Tokens (JWT) or Client Credentials.&lt;/p&gt;

&lt;p&gt;In this blog post, we'll look at how to use OAuth 2.0 to authenticate GraphQL APIs using two different flows: the Authorization Code flow and the Client Credentials flow. We'll also look at how to use StepZen to manage authentication.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is OAuth 2.0?
&lt;/h2&gt;

&lt;p&gt;But first, what is OAuth 2.0? OAuth 2.0 is an open standard for authorization that allows one application to let another application access certain parts of a user's account without giving away the user's password. There are different ways to set up this type of authorization, called "flows", and it depends on the type of application you are building.&lt;/p&gt;

&lt;p&gt;For example, if you're building a mobile app, you will use the "Authorization Code" flow. This flow will ask the user to permit the app to access their account, and then the app will receive a code to use to get an access token (JWT). The access token will allow the app to access the user's information on the website. You might have seen this flow when you log in to a website using a social media account, such as Facebook or Twitter.&lt;/p&gt;

&lt;p&gt;Another example is if you're building a server-to-server application, you will use the "Client Credentials" flow. This flow involves sending the website's unique information, like a client ID and secret, to get an access token (JWT). The access token will allow the server to access the user's information on the website. This flow is quite common for APIs that need to access a user's data, such as a CRM or a marketing automation tool.&lt;/p&gt;

&lt;p&gt;Let's have a look at these two flows in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization Code Flow (using JWT)
&lt;/h2&gt;

&lt;p&gt;The most common way to use OAuth 2.0 is with the Authorization Code flow, which involves using JSON Web Tokens (JWT). As mentioned above, this flow is used when you want to build a mobile or web application that needs to access a user's data from a different application.&lt;/p&gt;

&lt;p&gt;For example, if you have a GraphQL API that allows users to access their data, you can use a JWT to verify that the user is authorized to access the data. The JWT could contain information about the user, such as the user's ID, and the server can use this ID to query the database and return the user's data.&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%2Fhsg0bx3f33p2qgu9if3w.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%2Fhsg0bx3f33p2qgu9if3w.png" alt="Flow to get JWT" width="582" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You would need a frontend application that can redirect the user to the authorization server and then redirect the user back to the frontend application with the authorization code. The frontend application can then exchange the authorization code for an access token (JWT) and then use the JWT to make requests to the GraphQL API.&lt;/p&gt;

&lt;p&gt;The JWT can be sent to the GraphQL API in the &lt;code&gt;Authorization&lt;/code&gt; header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="err"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;https://USERNAME.stepzen.net/api/hello-world/__graphql&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;--header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"Authorization:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Bearer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;JWT_TOKEN"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;--header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"Content-Type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;application/json"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;--data-raw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="err"&gt;":&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;query&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="n"&gt;me&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&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="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
   &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;And the server can use the JWT to verify that the user is authorized to access the data.&lt;/p&gt;

&lt;p&gt;The JWT can also contain information about the user's permissions, such as whether they can access a specific field or mutation. This is useful if you want to restrict access to specific fields or mutations or if you want to limit the number of requests a user can make. But we'll look at this in more detail after discussing the Client Credentials flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Client Credentials Flow
&lt;/h2&gt;

&lt;p&gt;The Client Credentials flow is used when you want to build a server-to-server application, like an API, that needs to access information from a different application. It also relies on JWT.&lt;/p&gt;

&lt;p&gt;As mentioned above, this flow involves sending the website's unique information, like a client ID and secret, to get an access token. The access token will allow the server to access the user's information on the website. Unlike the Authorization Code flow, the Client Credentials flow doesn't involve a (frontend) client. Instead, the authorization server will directly communicate with the server that needs to access the user's information.&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%2Fvtsswjn5j6svs3sg06e4.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%2Fvtsswjn5j6svs3sg06e4.png" alt="Client Credentials Flow" width="800" height="476"&gt;&lt;/a&gt;&lt;em&gt;Image from &lt;a href="https://auth0.com/docs/flows/concepts/client-credentials" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The JWT can be sent to the GraphQL API in the &lt;code&gt;Authorization&lt;/code&gt; header, in the same way as for the Authorization Code flow.&lt;/p&gt;

&lt;p&gt;In the next section, we'll look at how to implement both the Authorization Code flow and the Client Credentials flow using StepZen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using StepZen to Manage Authentication
&lt;/h2&gt;

&lt;p&gt;By default, StepZen uses API Keys to authenticate requests. This is a developer-friendly way to authenticate requests that don't require an external authorization server. But if you want to use OAuth 2.0 to authenticate requests, you can use StepZen to manage authentication. Similar to how you can use StepZen to build a GraphQL schema for all your data in a declarative way, you can also manage authentication declaratively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement Authorization Code Flow (using JWT)
&lt;/h3&gt;

&lt;p&gt;To implement the Authorization Code flow, you must set up both a (frontend) client and an authorization server. You can use an existing authorization server, such as Auth0, or build your own.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can find a complete example of using StepZen to implement the Authorization Code flow in the &lt;a href="https://github.com/stepzen-dev/examples/tree/main/with-auth0/" rel="noopener noreferrer"&gt;StepZen GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;StepZen can validate the JWTs generated by the authorization server and send them to the GraphQL API. You only need the authorization server to validate the user's credentials to generate a JWT and StepZen to validate the JWT.&lt;/p&gt;

&lt;p&gt;Let's have another look at the flow we discussed above:&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%2Fhsg0bx3f33p2qgu9if3w.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%2Fhsg0bx3f33p2qgu9if3w.png" alt="Flow to get JWT" width="582" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this flow diagram, you can see that the frontend application redirects the user to the authorization server (from Auth0) and then turns the user back to the frontend application with the authorization code. The frontend application can then exchange the authorization code for a JWT and then use that JWT to make requests to the GraphQL API.&lt;/p&gt;

&lt;p&gt;StepZen will validate the JWT that is sent to the GraphQL API in the &lt;code&gt;Authorization&lt;/code&gt; header by configuring the JSON Web Key Set (JWKS) endpoint in the StepZen configuration in the &lt;code&gt;config.yaml&lt;/code&gt; file in your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;identity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jwksendpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YOUR_JWKS_ENDPOINT'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JWKS endpoint is a read-only endpoint that contains the public keys to verify a JWT. The public keys can only be used to validate the tokens, as you would need the private keys to sign the tokens, which is why you need to set up an authorization server to generate the JWTs.&lt;/p&gt;

&lt;p&gt;You can then limit the fields and mutations a user can access by adding &lt;a href="https://stepzen.com/docs/access-control/access-control-rules" rel="noopener noreferrer"&gt;Access Control rules&lt;/a&gt; to the GraphQL schema. For example, you can add a rule to the &lt;code&gt;me&lt;/code&gt; query to only allow access when a valid JWT is sent to the GraphQL API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;identity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jwksendpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YOUR_JWKS_ENDPOINT'&lt;/span&gt;
&lt;span class="na"&gt;access&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Query&lt;/span&gt;
      &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;?$jwt'&lt;/span&gt; &lt;span class="c1"&gt;# Require JWT&lt;/span&gt;
          &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;me&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# Define fields that require JWT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This rule only allows access to the &lt;code&gt;me&lt;/code&gt; query when a valid JWT is sent to the GraphQL API. If the JWT is invalid, or if no JWT is sent, the &lt;code&gt;me&lt;/code&gt; query will return an error.&lt;/p&gt;

&lt;p&gt;Earlier, we mentioned that the JWT could contain information about the user's permissions, such as whether they can access a specific field or mutation. This is useful if you want to restrict access to specific fields or mutations or if you want to limit the number of requests a user can make.&lt;/p&gt;

&lt;p&gt;You can add a rule to the &lt;code&gt;me&lt;/code&gt; query to only allow access when a user has the &lt;code&gt;admin&lt;/code&gt; role:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;identity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jwksendpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YOUR_JWKS_ENDPOINT'&lt;/span&gt;
&lt;span class="na"&gt;access&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Query&lt;/span&gt;
      &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$jwt.roles:String&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;has&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"admin"'&lt;/span&gt; &lt;span class="c1"&gt;# Require JWT&lt;/span&gt;
          &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;me&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# Define fields that require JWT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To learn more about implementing the Authorization Code Flow with StepZen, look at the &lt;a href="https://stepzen.com/blog/simple-abac-for-graphql" rel="noopener noreferrer"&gt;Easy Attribute-based Access Control for any GraphQL API article&lt;/a&gt; on the StepZen blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement Client Credentials Flow
&lt;/h3&gt;

&lt;p&gt;You will also need to set up an authorization server to implement the Client Credentials flow. But instead of redirecting the user to the authorization server, the server will directly communicate with the authorization server to get an access token (JWT).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can find a complete example for implementing the Client Credentials flow in the &lt;a href="https://github.com/stepzen-dev/examples/tree/main/with-auth0/" rel="noopener noreferrer"&gt;StepZen GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, you must set up the authorization server to generate the access token. You can use an existing authorization server, such as Auth0, or build your own.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;config.yaml&lt;/code&gt; file in your StepZen project, you can configure the authorization server to generate the access token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add the JWKS endpoint&lt;/span&gt;
&lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;identity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jwksendpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://YOUR_AUTH0_DOMAIN/.well-known/jwks.json'&lt;/span&gt;

&lt;span class="c1"&gt;# Add the authorization server configuration&lt;/span&gt;
&lt;span class="na"&gt;configurationset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;configuration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;auth&lt;/span&gt;
      &lt;span class="na"&gt;client_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;YOUR_CLIENT_ID&lt;/span&gt;
      &lt;span class="na"&gt;client_secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;YOUR_CLIENT_SECRET&lt;/span&gt;
      &lt;span class="na"&gt;audience&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;YOUR_AUDIENCE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;client_id&lt;/code&gt;, &lt;code&gt;client_secret&lt;/code&gt; and &lt;code&gt;audience&lt;/code&gt; are required parameters for the authorization server to generate the access token (JWT). The &lt;code&gt;audience&lt;/code&gt; is the API's identifier for the JWT. The &lt;code&gt;jwksendpoint&lt;/code&gt; is the same as the one we used for the Authorization Code flow.&lt;/p&gt;

&lt;p&gt;In a &lt;code&gt;.graphql&lt;/code&gt; file in your StepZen project, you can define a query to get the access token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&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="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;YOUR_AUTHORIZATION_SERVER&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="n"&gt;oauth&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;postbody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"""&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;audience&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;audience&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;grant_type&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;client_credentials&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;"""&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;The &lt;code&gt;token&lt;/code&gt; mutation will request the authorization server to get the JWT. The &lt;code&gt;postbody&lt;/code&gt; contains the parameters that are required by the authorization server to generate the access token.&lt;/p&gt;

&lt;p&gt;You can then use the JWT from the response on the &lt;code&gt;token&lt;/code&gt; mutation to request the GraphQL API, by sending the JWT in the &lt;code&gt;Authorization&lt;/code&gt; header.&lt;/p&gt;

&lt;p&gt;But we can do better than that. We can use the &lt;code&gt;@sequence&lt;/code&gt; custom directive to pass the response of the &lt;code&gt;token&lt;/code&gt; mutation to the query that needs authorization. This way, we don't need to send the JWT manually in the &lt;code&gt;Authorization&lt;/code&gt; header on every request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&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="n"&gt;me&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;YOUR_API_ENDPOINT&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;headers&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="err"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;Authorization&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;Bearer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;steps&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="err"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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;The &lt;code&gt;profile&lt;/code&gt; query will first request the &lt;code&gt;token&lt;/code&gt; query to get the JWT. Then, it will send a request to the &lt;code&gt;me&lt;/code&gt; query, passing along the JWT from the response of the &lt;code&gt;token&lt;/code&gt; query as the &lt;code&gt;access_token&lt;/code&gt; argument.&lt;/p&gt;

&lt;p&gt;As you can see, all configuration is set up in a single file, and you can use the same configuration for both the Authorization Code flow and the Client Credentials flow. Both are written declarative, and both use the same JWKS endpoint to request the authorization server to verify the tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;In this blog post, you learned about common OAuth 2.0 flows and how to implement them with StepZen. It's important to note that, as with any authentication mechanism, the details of the implementation will depend on the application's specific requirements and the security measures that need to be in place.&lt;/p&gt;

&lt;p&gt;StepZen GraphQL APIs are default protected with an API key but can be configured to use any authentication mechanism. We'd love to hear what authentication mechanisms you use with StepZen and how you use them. Ping us on &lt;a href="https://twitter.com/stepzen_dev" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or join our &lt;a href="https://discord.gg/9k2VdPn2FR" rel="noopener noreferrer"&gt;Discord community&lt;/a&gt; to let us know.&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://stepzen.com/blog/authenticating-graphql-apis-with-oauth2" rel="noopener noreferrer"&gt;stepzen.com&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter" rel="noopener noreferrer"&gt;Reposted.io&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>Learn React in 5 minutes</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Mon, 23 Jan 2023 09:24:22 +0000</pubDate>
      <link>https://dev.to/gethackteam/learn-react-in-5-minutes-3e7k</link>
      <guid>https://dev.to/gethackteam/learn-react-in-5-minutes-3e7k</guid>
      <description>&lt;p&gt;Can you learn React in five minutes? Well, it depends on what you mean by "learn React". In this blog post you will "learn the basics of React" in five minutes, by going over a few of the core concepts of React.&lt;/p&gt;

&lt;p&gt;Click the image below to watch the &lt;a href="https://www.youtube.com/watch?v=JKtLRDfTYTU" rel="noopener noreferrer"&gt;YouTube video version&lt;/a&gt; of this blog post:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=JKtLRDfTYTU" rel="noopener noreferrer"&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%2F100xnmxrrdkz7ecoi084.jpg" alt="Learn React in 5 minutes" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is React?
&lt;/h2&gt;

&lt;p&gt;React is a JavaScript library that is widely used for building user interfaces, particularly for single-page applications. It allows you to create reusable components that can be rendered on the web, mobile, or desktop. Today, it is one of the most popular tools for front-end web development.&lt;/p&gt;

&lt;p&gt;So, if you're interested in learning React, where do you start?&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript
&lt;/h2&gt;

&lt;p&gt;First, it's important to have a solid understanding of JavaScript. React is built with JavaScript, so you'll need to be comfortable with the basics of the language before you dive into React.&lt;/p&gt;

&lt;p&gt;Once you've got a handle on JavaScript, the next step is to familiarize yourself with the React syntax and concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Components
&lt;/h2&gt;

&lt;p&gt;One of the core principles of React is that a component should be a self-contained piece of code that is easy to understand and maintain.&lt;/p&gt;

&lt;p&gt;This is what a component looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My Component&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;A component is a JavaScript function that returns a React element. It can be a simple function that returns a single element, or it can be a more complex component that returns multiple elements or has state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data flows
&lt;/h2&gt;

&lt;p&gt;In React, data flows in a single direction from the parent component to the child component, following the unidirectional data flow principle. This helps make applications easier to reason about and debug.&lt;/p&gt;

&lt;p&gt;Parent components can pass data to child components using props, below is an example of a child compoinent that receives data from a parent component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'My Component'&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;function&lt;/span&gt; &lt;span class="nf"&gt;Title&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Props are used to keep track of data that is passed from a parent component to a child component. They are immutable, which means that they cannot be changed once they are passed to a child component.&lt;/p&gt;

&lt;h2&gt;
  
  
  State
&lt;/h2&gt;

&lt;p&gt;State is a special type of data that is managed by a component. It is used to store data that is specific to a component and it can be passed on to other components lower in the tree. State is often used to store data that is used to render the UI, such as a list of items or a user's name.&lt;/p&gt;

&lt;p&gt;State can be managed using the useState hook, which is a function that returns an array with two values: the current state and a function that can be used to update the state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyComponent&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&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;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increment&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Virtual DOM
&lt;/h2&gt;

&lt;p&gt;React uses a virtual DOM (Document Object Model) to optimize updates and minimize the number of DOM mutations. This makes applications built with React faster and more efficient.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://reactjs.org/docs/faq-internals.html" rel="noopener noreferrer"&gt;Virtual DOM&lt;/a&gt; is a virtual representation of a user interface, which is kept in memory and synchronized with the "real" DOM by for example ReactDOM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ecosystem
&lt;/h2&gt;

&lt;p&gt;React also has a large ecosystem of tools and libraries that can be leveraged to build amazing applications. Some popular ones include &lt;a href="https://tanstack.com/query/latest/docs/react/examples/react/basic" rel="noopener noreferrer"&gt;Tanstack Query&lt;/a&gt; for data fetching, Tailwind for styling and &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; or &lt;a href="https://remix.run/" rel="noopener noreferrer"&gt;Remix&lt;/a&gt; for server-rendered React applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Projects
&lt;/h2&gt;

&lt;p&gt;It's also a good idea to start building some small projects with React to get a feel for how it works in practice. There are plenty of resources available online that can help you get started with your first React project, including templates and starter kits.&lt;/p&gt;

&lt;p&gt;Need inspiration for a project?&lt;/p&gt;

&lt;p&gt;you might want to have a look at my book React Projects. Which walks you through all the React concepts in 10 chapters. You'll build 10 unique projects. These are a "movie list" (like IMDB), a developer portfolio website using Github, a mobile game application and much more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep learning
&lt;/h2&gt;

&lt;p&gt;Finally, keep in mind that learning React is an ongoing process. As you build more complex projects and encounter new challenges, you'll continue to learn and improve your skills.&lt;/p&gt;

&lt;p&gt;The comings months I'll livestreams on building these projects - and the first ones are already uploaded. So if you're interested in learning React, make sure to subscribe to my YouTube channel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@gethackteam?sub_confirmation=1" rel="noopener noreferrer"&gt;&amp;gt; Subscribe to my YouTube channel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or find me on Twitter at &lt;a href="https://twitter.com/gethackteam" rel="noopener noreferrer"&gt;@gethackteam&lt;/a&gt;. I'd love to hear from you!&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://hackteam.io/blog/learn-react-in-five-minutes" rel="noopener noreferrer"&gt;hackteam.io&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter" rel="noopener noreferrer"&gt;Reposted.io&lt;/a&gt;. A free tool to repost your content across all blogging platforms.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Bootstrap Is The Easiest Way To Style React Apps in 2023</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Sun, 15 Jan 2023 20:05:21 +0000</pubDate>
      <link>https://dev.to/gethackteam/bootstrap-is-the-easiest-way-to-style-react-apps-in-2023-2gjm</link>
      <guid>https://dev.to/gethackteam/bootstrap-is-the-easiest-way-to-style-react-apps-in-2023-2gjm</guid>
      <description>&lt;p&gt;This blog post will teach you how to use Bootstrap 5 to style a React application. With Bootstrap, you don't have to write any stying rules yourself; instead, you can use class names to apply styles to HTML elements.&lt;/p&gt;

&lt;p&gt;Click the image below to watch the &lt;a href="http://www.youtube.com/watch?v=I-DzvL6yvGI" rel="noopener noreferrer"&gt;YouTube video version&lt;/a&gt; of this blog post:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=I-DzvL6yvGI" rel="noopener noreferrer"&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%2Fi0u48xvdf1tnxxfus2s6.jpg" alt="Create a React Project From Scratch Without any Framework" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This blog post is extracted from my book React Projects, available on &lt;a href="https://packt.link/ReactProjects" rel="noopener noreferrer"&gt;Packt&lt;/a&gt; and &lt;a href="https://amzn.to/3vq4FQP" rel="noopener noreferrer"&gt;Amazon&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why use Bootstrap?
&lt;/h2&gt;

&lt;p&gt;IMO, Bootstrap is still the easiest way to style a React application. Bootstrap has been around for a long time and is widely used across web applications of all sorts and sizes. And build with different frameworks or tools, ranging from WordPress to React. There are a few reasons why you might want to use Bootstrap to style a React app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Ease of use: Bootstrap is a well-documented and widely-used CSS framework, making it easy to start and learn.&lt;/li&gt;
&lt;li&gt;  Responsive design: Bootstrap includes a responsive grid system and predefined styles for common UI elements, which makes it easier to build a responsive app that looks good on multiple devices.&lt;/li&gt;
&lt;li&gt;  Time savings: Using a CSS framework like Bootstrap can save you time by providing a set of pre-styled UI components that you can use out-of-the-box, rather than style everything from scratch.&lt;/li&gt;
&lt;li&gt;  Consistency: By using a common CSS framework, you can ensure that your app has a consistent look and feel, which can improve the user experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, Bootstrap (or any other CSS framework) can be useful for building a well-designed and responsive React app more efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Bootstrap
&lt;/h2&gt;

&lt;p&gt;You can install Bootstrap using npm or yarn. For this blog post, we will use npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`npm install --save-dev bootstrap`

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

&lt;/div&gt;



&lt;p&gt;This will install Bootstrap as a &lt;code&gt;devDependency&lt;/code&gt; in your project, and it will only be used during development and will not be included in the production build. By installing Bootstrap you can now include the CSS in your project by importing it in the root of your React project, for example, your &lt;code&gt;index.js&lt;/code&gt; file that contains the root component of your app:&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;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;react-dom/client&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;List&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;./containers/List&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bootstrap/dist/css/bootstrap.min.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&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;container&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&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;root&lt;/span&gt; &lt;span class="o"&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;createRoot&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="nx"&gt;root&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;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part in the code block above is the line &lt;code&gt;import 'bootstrap/dist/css/bootstrap.min.css'&lt;/code&gt;, which will import the Bootstrap CSS file from the &lt;code&gt;node_modules&lt;/code&gt; directory. This will make the Bootstrap styles available to your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Bootstrap components
&lt;/h2&gt;

&lt;p&gt;Bootstrap includes several pre-styled components that you can use in your React app. For example, you can use the &lt;a href="https://getbootstrap.com/docs/5.3/components/navbar/" rel="noopener noreferrer"&gt;&lt;code&gt;NavBar&lt;/code&gt; component&lt;/a&gt; to add a header element to your application.&lt;/p&gt;

&lt;p&gt;To use this component, you can copy-paste the following code block and use it in your app:&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;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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bootstrap/dist/css/bootstrap.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Header&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="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;nav&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;navbar bg-body-tertiary&lt;/span&gt;&lt;span class="dl"&gt;"&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;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;container-fluid&lt;/span&gt;&lt;span class="dl"&gt;"&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;a&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;navbar-brand&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&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="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&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="s2"&gt;https://hackteam.iohttps://getbootstrap.com/docs/5.3/assets/brand/bootstrap-logo.svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Logo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;30&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d-inline-block align-text-top&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;Bootstrap&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&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;/div&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;/nav&lt;/span&gt;&lt;span class="err"&gt;&amp;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;Which will render the following header:&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%2Fll096as7gscmgvdq3r4i.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%2Fll096as7gscmgvdq3r4i.png" alt="Bootstrap NavBar component" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By adding the correct class names to HTML elements, you will get a modern-looking header that you don't need to style.&lt;/p&gt;

&lt;p&gt;Of course, there are much more Bootstrap components that you can use in your React app. For example, you can use the &lt;a href="https://getbootstrap.com/docs/5.3/components/card/" rel="noopener noreferrer"&gt;&lt;code&gt;Card&lt;/code&gt; component&lt;/a&gt; to render a card with a title, image, and text:&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;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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bootstrap/dist/css/bootstrap.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Card&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="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width: 18rem;&lt;/span&gt;&lt;span class="dl"&gt;'&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;img&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;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card-img-top&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&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="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card-body&lt;/span&gt;&lt;span class="dl"&gt;'&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;h5&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card-title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Card&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h5&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="nx"&gt;p&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card-text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;Some&lt;/span&gt; &lt;span class="nx"&gt;quick&lt;/span&gt; &lt;span class="nx"&gt;example&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;build&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;card&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;make&lt;/span&gt; &lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt;
          &lt;span class="nx"&gt;bulk&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;card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s content.
        &amp;lt;/p&amp;gt;
        &amp;lt;a href=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; class=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;btn&lt;/span&gt; &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;
          Go somewhere
        &amp;lt;/a&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which will render the following card:&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%2Fij70iosyk9smabnp9o7f.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%2Fij70iosyk9smabnp9o7f.png" alt="Bootstrap Card component" width="800" height="990"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With just a few lines of HTML you can render a card with a title, image, and text. And you can extend this further by using Bootstrap utilities or custom CSS to style the card even more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrap utilities
&lt;/h2&gt;

&lt;p&gt;Bootstrap includes a set of utility classes that can be used to apply common styles quickly and easily. These utility classes are designed to be used in conjunction with other Bootstrap styles and can be used to override or extend the default styles of certain elements.&lt;/p&gt;

&lt;p&gt;Some of the Bootstrap utilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;.text-*:&lt;/code&gt; These classes can be used to apply different colors to text, depending on the context (e.g. .text-primary, .text-secondary, etc.).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;.bg-*:&lt;/code&gt; These classes can be used to apply different background colors to elements (e.g. .bg-primary, .bg-secondary, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at an example:&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;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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bootstrap/dist/css/bootstrap.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;container mt-5&lt;/span&gt;&lt;span class="dl"&gt;"&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;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;row&lt;/span&gt;&lt;span class="dl"&gt;"&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;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;col-md-6&lt;/span&gt;&lt;span class="dl"&gt;"&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;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;card bg-primary text-white&lt;/span&gt;&lt;span class="dl"&gt;"&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;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;card-body&lt;/span&gt;&lt;span class="dl"&gt;"&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;h5&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;card-title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Primary&lt;/span&gt; &lt;span class="nx"&gt;Card&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h5&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="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;card-text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Some&lt;/span&gt; &lt;span class="nx"&gt;quick&lt;/span&gt; &lt;span class="nx"&gt;example&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;build&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;card&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;make&lt;/span&gt; &lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;bulk&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;card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s content.&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="col-md-6"&amp;gt;
          &amp;lt;div className="card bg-secondary text-white"&amp;gt;
            &amp;lt;div className="card-body"&amp;gt;
              &amp;lt;h5 className="card-title"&amp;gt;Secondary Card&amp;lt;/h5&amp;gt;
              &amp;lt;p className="card-text"&amp;gt;Some quick example text to build on the card title and make up the bulk of the card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="nx"&gt;content&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;/p&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;/div&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;/div&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;/div&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;/div&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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we use Bootstrap's grid system to create a layout with two equal-width columns, and we use the &lt;code&gt;.bg-primary&lt;/code&gt; and &lt;code&gt;.bg-secondary&lt;/code&gt; classes to give the cards different background colors. We are also using the &lt;code&gt;.text-white&lt;/code&gt; class to make the text white to be visible against the colored backgrounds.&lt;/p&gt;

&lt;p&gt;These are just a few examples of Bootstrap utilities. Many others are available, and you can find more information in the &lt;a href="https://getbootstrap.com/docs/5.3/utilities/" rel="noopener noreferrer"&gt;Bootstrap documentation&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;This blog post has shown how to use Bootstrap 5 to style a React application. With Bootstrap you don't have to write any stying rules yourself. Instead, you can use class names to apply styles to HTML elements. Of course, you can also use Bootstrap utilities to apply common styles quickly and easily.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This blog post is extracted from my book React Projects, available on &lt;a href="https://packt.link/ReactProjects" rel="noopener noreferrer"&gt;Packt&lt;/a&gt; and &lt;a href="https://amzn.to/3vq4FQP" rel="noopener noreferrer"&gt;Amazon&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I hope you learned some new things about styling in React! Any feedback? Let me know by &lt;a href="https://www.twitter.com/gethackteam" rel="noopener noreferrer"&gt;connecting to me on Twitter&lt;/a&gt;. Or leave a comment on my &lt;a href="https://www.youtube.com/@gethackteam?sub_confirmation=1" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://hackteam.io/blog/bootstrap-easiest-way-to-style-react-apps-2023" rel="noopener noreferrer"&gt;hackteam.io&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter" rel="noopener noreferrer"&gt;Reposted.io&lt;/a&gt;. A free tool to repost your content across all blogging platforms.&lt;/p&gt;

</description>
      <category>welcome</category>
    </item>
    <item>
      <title>Create a React Project From Scratch Without any Framework</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Fri, 06 Jan 2023 15:15:54 +0000</pubDate>
      <link>https://dev.to/gethackteam/create-a-react-project-from-scratch-without-any-framework-1n6o</link>
      <guid>https://dev.to/gethackteam/create-a-react-project-from-scratch-without-any-framework-1n6o</guid>
      <description>&lt;p&gt;This blog post will guide you through the process of creating a new single-page React application from the ground up. We will begin by setting up a new project using Webpack and Babel. Building a React project from scratch will give you a strong foundation and understanding of the fundamental requirements of a project, which is essential for any project you may undertake before jumping into a framework like Next.js or Remix.&lt;/p&gt;

&lt;p&gt;Click the image below to watch the &lt;a href="http://www.youtube.com/watch?v=X48Kt8rSByQ"&gt;YouTube video version&lt;/a&gt; of this blog post:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=X48Kt8rSByQ"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BoK482KY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/X48Kt8rSByQ/hqdefault.jpg" alt="Create a React Project From Scratch Without any Framework" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This blog post is extracted from my book React Projects, available on &lt;a href="https://packt.link/ReactProjects"&gt;Packt&lt;/a&gt; and &lt;a href="https://amzn.to/3vq4FQP"&gt;Amazon&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setting up a new project
&lt;/h2&gt;

&lt;p&gt;Before you can start building your new React project, you will need to create a new directory on your local machine. For this blog (which is based upon the book React Projects), you can name this directory 'chapter-1'.&lt;/p&gt;

&lt;p&gt;To initiate the project, navigate to the directory you just created and enter the following command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`npm init -y`

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

&lt;/div&gt;



&lt;p&gt;This will create a &lt;code&gt;package.json&lt;/code&gt; file with the minimum information required to run a JavaScript/React project. The &lt;code&gt;-y&lt;/code&gt; flag allows you to bypass the prompts for setting project details such as the name, version, and description.&lt;/p&gt;

&lt;p&gt;After running this command, you should see a &lt;code&gt;package.json&lt;/code&gt; file created for your project similar to the following:&lt;br&gt;
&lt;/p&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chapter-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&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.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&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;"keywords"&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;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&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;Now that you have created the &lt;code&gt;package.json&lt;/code&gt; file, the next step is to add Webpack to the project. This will be covered in the following section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Webpack to the project
&lt;/h2&gt;

&lt;p&gt;In order to run the React application, we need to install Webpack 5 (the current stable version at the time of writing) and the Webpack CLI as &lt;code&gt;devDependencies&lt;/code&gt;. Webpack is a tool that allows us to create a bundle of JavaScript/React code that can be used in a browser. Follow these steps to set up Webpack:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Install the necessary packages from npm using the following command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`npm install --save-dev webpack webpack-cli`

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; After installation, these packages will be listed in the package.json file and can be run in our start and build scripts. But first, we need to add some files to the project:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chapter-1
|- node_modules
|- package.json
   |- src
      |- index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add an &lt;code&gt;index.js&lt;/code&gt; file to a new directory called &lt;code&gt;src&lt;/code&gt;. Later, we will configure Webpack so that this file is the starting point for our application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Add the following code block to this file:
&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="s2"&gt;`console.log('Rick and Morty');`&lt;/span&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; To run the code above, we will add start and build scripts to our application using Webpack. The test script is not needed in this case, so it can be removed. Also, the main field can be changed to private with the value of true, as the code we are building is a local project:
&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chapter-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&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.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode=development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode=production"&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;"keywords"&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;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&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;The npm start command will run Webpack in development mode, while npm run build will create a production bundle using Webpack. The main difference is that running Webpack in production mode will minimize our code and reduce the size of the project bundle.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Run the &lt;code&gt;start&lt;/code&gt; or &lt;code&gt;build&lt;/code&gt; command from the command line; Webpack will start up and create a new directory called &lt;code&gt;dist&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chapter-1
|- node_modules
|- package.json
   |- dist
      |- main.js
   |- src
      |- index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; Inside this directory, there will be a file called &lt;code&gt;main.js&lt;/code&gt; that includes our project code and is also known as our bundle. If successful, you should see the following output:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asset main.js 794 bytes [compared for emit] (name: main)
./src/index.js 31 bytes [built] [code generated]
webpack compiled successfully in 67 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code in this file will be minimized if you run Webpack in production mode.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; To test if your code is working, run the main.js file in your bundle from the command line:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`node dist/main.js`

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

&lt;/div&gt;



&lt;p&gt;This command runs the bundled version of our application and should return the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; node dist/main.js
Rick and Morty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we're able to run JavaScript code from the command line. In the next part of this blog post, we will learn how to configure Webpack so that it works with React.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Webpack for React
&lt;/h2&gt;

&lt;p&gt;Now that we have set up a basic development environment with Webpack for a JavaScript application, we can begin installing the packages necessary to run a React application. These packages are &lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt;, where the former is the core package for React and the latter provides access to the browser's DOM and allows for rendering of React. To install these packages, enter the following command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`npm install react react-dom`

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

&lt;/div&gt;



&lt;p&gt;However, simply installing the dependencies for React is not enough to run it, since by default, not all browsers can understand the format (such as ES2015+ or React) in which your JavaScript code is written. Therefore, we need to compile the JavaScript code into a format that can be read by all browsers.&lt;/p&gt;

&lt;p&gt;To do this, we will use Babel and its related packages to create a toolchain that allows us to use React in the browser with Webpack. These packages can be installed as &lt;code&gt;devDependencies&lt;/code&gt; by running the following command:&lt;/p&gt;

&lt;p&gt;In addition to the Babel core package, we will also install &lt;code&gt;babel-loader&lt;/code&gt;, which is a helper that allows Babel to run with Webpack, and two preset packages. These preset packages help determine which plugins will be used to compile our JavaScript code into a readable format for the browser (&lt;code&gt;@babel/preset-env&lt;/code&gt;) and to compile React-specific code (&lt;code&gt;@babel/preset-react&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Now that we have the packages for React and the necessary compilers installed, the next step is to configure them to work with Webpack so that they are used when we run our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`npm install --save-dev @babel/core babel-loader @babel/preset-env @babel/preset-react`

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

&lt;/div&gt;



&lt;p&gt;To do this, configuration files for both Webpack and Babel need to be created in the src directory of the project: &lt;code&gt;webpack.config.js&lt;/code&gt; and &lt;code&gt;babel.config.json&lt;/code&gt;, respectively. The &lt;code&gt;webpack.config.js&lt;/code&gt; file is a JavaScript file that exports an object with the configuration for Webpack. The &lt;code&gt;babel.config.json&lt;/code&gt; file is a JSON file that contains the configuration for Babel.&lt;/p&gt;

&lt;p&gt;The configuration for Webpack is added to the &lt;code&gt;webpack.config.js&lt;/code&gt; file to use &lt;code&gt;babel-loader&lt;/code&gt;:&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&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;test&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;js$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/node_modules/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration file tells Webpack to use &lt;code&gt;babel-loader&lt;/code&gt; for every file with the &lt;code&gt;.js&lt;/code&gt; extension and excludes files in the &lt;code&gt;node_modules&lt;/code&gt; directory from the Babel compiler.&lt;/p&gt;

&lt;p&gt;To utilize the Babel presets, the following configuration must be added to &lt;code&gt;babel.config.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&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;"presets"&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="s2"&gt;"@babel/preset-env"&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;"targets"&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;"esmodules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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="s2"&gt;"@babel/preset-react"&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;"runtime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"automatic"&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;In the above &lt;code&gt;@babel/preset-env&lt;/code&gt; must be set to target &lt;code&gt;esmodules&lt;/code&gt; in order to use the latest Node modules. Additionally, defining the JSX runtime to automatic is necessary since React 18 has adopted the &lt;a href="https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html"&gt;new JSX Transform functionality&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that we have set up Webpack and Babel, we can run JavaScript and React from the command line. In the next section, we will write our first React code and run it in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering React components
&lt;/h2&gt;

&lt;p&gt;Now that we have installed and configured the packages necessary to set up Babel and Webpack in the previous sections, we need to create a real React component that can be compiled and run. This process involves adding some new files to the project and making changes to the Webpack configuration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Let's edit the &lt;code&gt;index.js&lt;/code&gt; file that already exists in our &lt;code&gt;src&lt;/code&gt; directory so that we can use &lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt;. Replace the contents of this file with the following:
&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="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;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Rick&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;Morty&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&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;container&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&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;root&lt;/span&gt; &lt;span class="o"&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;createRoot&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="nx"&gt;root&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;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this file imports the &lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt; packages, defines a simple component that returns an &lt;code&gt;h1&lt;/code&gt; element containing the name of your application, and has this component rendered in the browser with &lt;code&gt;react-dom&lt;/code&gt;. The last line of code mounts the &lt;code&gt;App&lt;/code&gt; component to an element with the &lt;code&gt;root&lt;/code&gt; ID selector in your document, which is the entry point of the application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; We can create a file that has this element in a new directory called &lt;code&gt;public&lt;/code&gt; and name that file &lt;code&gt;index.html&lt;/code&gt;. The document structure of this project should look like the following:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chapter-1
  |- node_modules
  |- package.json
  |- babel.config.json
  |- webpack.config.js
  |- dist
    |- main.js
  |- public
    |- index.html
  |- src
    |- index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; After adding a new file called &lt;code&gt;index.html&lt;/code&gt; to the new &lt;code&gt;public&lt;/code&gt; directory, we add the following code inside it:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt;
      &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt;
      &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width,
initial-scale=1.0"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"X-UA-Compatible"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"ie=edge"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Rick and Morty&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds an HTML heading and body. Within the &lt;code&gt;head&lt;/code&gt; tag is the title of our application, and inside the &lt;code&gt;body&lt;/code&gt; tag is a section with the "root" ID selector. This matches the element we have mounted the &lt;code&gt;App&lt;/code&gt; component to in the &lt;code&gt;src/index.js&lt;/code&gt; file.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; The final step in rendering our React component is extending Webpack so that it adds the minified bundle code to the body tags as scripts when running. To do this, we should install the &lt;code&gt;html-webpack-plugin&lt;/code&gt; package as a &lt;code&gt;devDependency&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`npm install --save-dev html-webpack-plugin`

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

&lt;/div&gt;



&lt;p&gt;To use this new package to render our files with React, the Webpack configuration in the &lt;code&gt;webpack.config.js&lt;/code&gt; file must be updated:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HtmlWebpackPlugin&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;html-webpack-plugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&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;test&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;js$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/node_modules/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./public/index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we run &lt;code&gt;npm start&lt;/code&gt; again, Webpack will start in development mode and add the &lt;code&gt;index.html&lt;/code&gt; file to the &lt;code&gt;dist&lt;/code&gt; directory. Inside this file, we'll see that a new &lt;code&gt;scripts&lt;/code&gt; tag has been inserted inside the body tag that points to our application bundle – that is, the &lt;code&gt;dist/main.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;If we open this file in the browser or run &lt;code&gt;open dist/index.html&lt;/code&gt; from the command line, it will display the result directly in the browser. The same is true when running the npm run build command to start Webpack in production mode; the only difference is that our code will be minified:.&lt;/p&gt;

&lt;p&gt;This process can be sped up by setting up a development server with Webpack. We'll do this in the final part of this blog post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a Webpack development server
&lt;/h2&gt;

&lt;p&gt;While working in development mode, every time we make changes to the files in our application, we need to rerun the &lt;code&gt;npm start&lt;/code&gt; command. This can be tedious, so we will install another package called &lt;code&gt;webpack-dev-server&lt;/code&gt;. This package allows us to force Webpack to restart every time we make changes to our project files and manages our application files in memory instead of building the &lt;code&gt;dist&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;webpack-dev-server&lt;/code&gt; package can be installed with npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`npm install --save-dev webpack-dev-server`

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

&lt;/div&gt;



&lt;p&gt;Also, we need to edit the dev script in the &lt;code&gt;package.json&lt;/code&gt; file so that it uses &lt;code&gt;webpack- dev-server&lt;/code&gt; instead of Webpack. This way, you don't have to recompile and reopen the bundle in the browser after every code change:&lt;br&gt;
&lt;/p&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chapter-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&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.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack serve --mode=development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode=production"&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;"keywords"&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;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&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;The preceding configuration replaces Webpack in the start scripts with &lt;code&gt;webpack-dev-server&lt;/code&gt;, which runs Webpack in development mode. This will create a local development server that runs the application and ensures that Webpack is restarted every time an update is made to any of your project files.&lt;/p&gt;

&lt;p&gt;To start the local development server, just enter the following command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`npm start`

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

&lt;/div&gt;



&lt;p&gt;This will cause the local development server to be active at &lt;code&gt;http://localhost:8080/&lt;/code&gt; and refresh every time we make an update to any file in our project.&lt;/p&gt;

&lt;p&gt;Now, we have created the basic development environment for our React application, which you can further develop and structure when you start building your application.&lt;/p&gt;

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

&lt;p&gt;In this blog post, we learned how to set up a React project with Webpack and Babel. We also learned how to render a React component in the browser. I always like to learn a technology by building something with it from scratch before jumping into a framework like Next.js or Remix. This helps me understand the fundamentals of the technology and how it works.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This blog post is extracted from my book React Projects, available on &lt;a href="https://packt.link/ReactProjects"&gt;Packt&lt;/a&gt; and &lt;a href="https://amzn.to/3vq4FQP"&gt;Amazon&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I hope you learned some new things about React! Any feedback? Let me know by &lt;a href="https://www.twitter.com/gethackteam"&gt;connecting to me on Twitter&lt;/a&gt;. Or leave a comment on my &lt;a href="https://www.youtube.com/@gethackteam?sub_confirmation=1"&gt;YouTube channel&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://hackteam.io/blog/create-react-project-from-scratch-without-framework"&gt;hackteam.io&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter"&gt;Reposted.io&lt;/a&gt;. A free tool to repost your content across all blogging platforms.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webpack</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Why Do Developers Love GraphQL?</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Wed, 21 Dec 2022 10:25:02 +0000</pubDate>
      <link>https://dev.to/gethackteam/why-do-developers-love-graphql-lpm</link>
      <guid>https://dev.to/gethackteam/why-do-developers-love-graphql-lpm</guid>
      <description>&lt;p&gt;GraphQL has changed how developers interact with data in their applications and has often been called the successor to REST. REST APIs have been the standard for a long time but lack certain features to make consuming them easy. GraphQL on the other is hand was created to make the lifes of developers easy. So why do developers love GraphQL so much? In this blog post, I'll give you three reasons why!&lt;/p&gt;

&lt;p&gt;Click the image below to watch the &lt;a href="http://www.youtube.com/watch?v=huqR946Y5is" rel="noopener noreferrer"&gt;YouTube video version&lt;/a&gt; of this blog post:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=huqR946Y5is" rel="noopener noreferrer"&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%2Fus1sprjpwu5140whsfwe.jpg" alt="Can you compare GraphQL and tRPC?" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is GraphQL?
&lt;/h2&gt;

&lt;p&gt;If you haven't heard of GraphQL, it's a query language for APIs. It was created by Facebook in 2012 and open-sourced in 2015. GraphQL allows you to query data from an API in a structured way. It's a great alternative to REST, the most popular way to create APIs today.&lt;/p&gt;

&lt;p&gt;I started using GraphQL in 2016 during a hackathon in Berlin and have been using it ever since. I'm using GraphQL in all my projects where I need access to an API, and I have been creating content about GraphQL for years. I've created a GraphQL book, &lt;a href="https://www.newline.co/books/fullstack-graphql/welcome" rel="noopener noreferrer"&gt;Fullstack GraphQL&lt;/a&gt;, and multiple GraphQL tutorials on my &lt;a href="https://www.youtube.com/@gethackteam?sub_confirmation=1" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do developers love GraphQL?
&lt;/h2&gt;

&lt;h2&gt;
  
  
  One single endpoint for all your data
&lt;/h2&gt;

&lt;p&gt;One of the biggest advantages of GraphQL is that you only need one single endpoint to query all your data. In REST, you need multiple endpoints to query different data. Generally speaking, every data entity (like a database table) in REST API will have its own endpoint. For example, if you want to get a list of posts and a specific from a CMS API, you need to send requests to two endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://jsonplaceholder.typicode.com/posts" rel="noopener noreferrer"&gt;GET /posts&lt;/a&gt; (list of posts)&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://jsonplaceholder.typicode.com/posts/1" rel="noopener noreferrer"&gt;GET /posts/1&lt;/a&gt; (specific post)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In GraphQL, you can request both the list of posts and the specific post in one single query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&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="n"&gt;posts&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&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="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&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;GraphQL would execute this query against a single endpoint, which is much easier to manage. You don't need to worry about creating multiple endpoints, and you don't need to worry about versioning them.&lt;/p&gt;

&lt;h2&gt;
  
  
  No more over- and under-fetching
&lt;/h2&gt;

&lt;p&gt;In REST, you sometimes fetch more than the data you actually need, and this is called over-fetching. In the example from the previous section, you're fetching the list of posts from a REST API, and let's say we want to display them on an overview page. Therefore we need the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt; of each post, but this REST API is returning a lot more data than you need. Not only is it returning the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt; of the post, but also the &lt;code&gt;body&lt;/code&gt; and &lt;code&gt;userId&lt;/code&gt;. Getting more data than you need wastes bandwidth and processing power.&lt;br&gt;
&lt;/p&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sunt aut facere repellat provident occaecati excepturi optio reprehenderit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"quia et suscipit&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;suscipit recusandae consequuntur expedita et cum&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;reprehenderit molestiae ut ut quas totam&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;nostrum rerum est autem sunt rem eveniet architecto"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"qui est esse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"est rerum tempore vitae&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;sequi sint nihil reprehenderit dolor beatae ea dolores neque&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;fugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;qui aperiam non debitis possimus qui neque nisi nulla"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;posts...&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;In GraphQL, you can request exactly the data you need by specifying the fields you want to get in your query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&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="n"&gt;posts&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&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;Opposite to over-fetching, there's also under-fetching. Sometimes need to make multiple requests to REST API endpoints to get all the data you need. This is called under-fetching because you're not getting all the data you need at once. Let's have another look at the example from the previous section. Instead of just getting a specific post on a detail page, we also want the comments for this post. In REST, you need to make two requests as a different endpoint than the post returns the comments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://jsonplaceholder.typicode.com/posts/1" rel="noopener noreferrer"&gt;GET /posts/1&lt;/a&gt; (specific post)&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://jsonplaceholder.typicode.com/posts/1/comments" rel="noopener noreferrer"&gt;GET /posts/1/comments&lt;/a&gt; (comments for specific post)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In GraphQL, you can request exactly the data you need even when the data is spread across multiple entities. You can request the post and the comments in one single query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;comments&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;name&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 query would return the post and comments in one single response, which is much easier to manage in your application and takes fewer data to transfer. Especially as you prevent over-fetching in this example and only receive the data you're using on your detail page.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL is self-documenting
&lt;/h2&gt;

&lt;p&gt;Well, at least partially...&lt;/p&gt;

&lt;p&gt;In REST, you need to document your API. This is a lot of work, and it's easy to forget to update the documentation when you make changes to your API. In GraphQL, you don't need to document your API, as the documentation is generated automatically. You can use the GraphiQL tool to explore your GraphQL API and see all the available queries and mutations. You can also see the fields you can request for each query and mutation. This is much easier to manage than documenting your API manually.&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%2F26ek6rf40w7pdl8byu3a.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%2F26ek6rf40w7pdl8byu3a.png" alt="Using GraphiQL" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GraphQL APIs have built-in documentation, which can be generated from its GraphQL schema. Every GraphQL API has a schema for defining all the operations and data types. The schema is used to validate the queries and mutations you send to the API. You can use the GraphiQL tool (read more in this &lt;a href="https://hackteam.io/blog/exploring-graphiql-2-updates-and-new-features" rel="noopener noreferrer"&gt;blog post&lt;/a&gt;) to explore your GraphQL API and see all the available queries and mutations. You can also see the fields you can request for each query and mutation. But also to generate the documentation, making using a GraphQL API a lot easier to manage than having to document your REST API manually.&lt;/p&gt;

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

&lt;p&gt;There are many reasons developers love GraphQL, especially frontend developers. GraphQL is easier to manage than REST and is much easier to use in your application. You can use GraphQL in your frontend application to fetch all the data you need in one single request. It prevents over- and under-fetching, plus it's self-documenting.&lt;/p&gt;

&lt;p&gt;I'd love to hear your thoughts on this topic. Do you love GraphQL? Why? Let me know by &lt;a href="https://www.twitter.com/gethackteam" rel="noopener noreferrer"&gt;connecting to me on Twitter&lt;/a&gt;. Or leave a comment on my &lt;a href="https://www.youtube.com/@gethackteam?sub_confirmation=1" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://hackteam.io/blog/why-developers-love-graphql" rel="noopener noreferrer"&gt;hackteam.io&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter" rel="noopener noreferrer"&gt;Reposted.io&lt;/a&gt;. A free tool to repost your content across all blogging platforms.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Exploring GraphiQL 2 Updates and New Features</title>
      <dc:creator>Roy Derks</dc:creator>
      <pubDate>Mon, 12 Dec 2022 14:03:53 +0000</pubDate>
      <link>https://dev.to/gethackteam/exploring-graphiql-2-updates-and-new-features-52a6</link>
      <guid>https://dev.to/gethackteam/exploring-graphiql-2-updates-and-new-features-52a6</guid>
      <description>&lt;p&gt;GraphiQL is a popular tool for GraphQL developers. It is a web-based IDE for GraphQL that lets you explore a GraphQL API. It's a great tool for developers to test their GraphQL queries and mutations, and find out what the schema of a GraphQL API looks like. For many developers it's the first tool they use to learn GraphQL.&lt;/p&gt;

&lt;p&gt;But for many years, GraphiQL hasn't had a UI update. And it's been a while since it's been updated. But now since few months, GraphiQL 2 is here. It's a complete new version of GraphiQL with a new UI and a lot of new features. In this blog post, I'll explore the new features of GraphiQL 2 and show you how to use them.&lt;/p&gt;

&lt;p&gt;Click the image below to watch the &lt;a href="http://www.youtube.com/watch?v=IFoMMoXezJg" rel="noopener noreferrer"&gt;YouTube video version&lt;/a&gt; of this blog post:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=IFoMMoXezJg" rel="noopener noreferrer"&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%2Fnt8ossy1vg2stjer1v9b.jpg" alt="Can you compare GraphQL and tRPC?" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Little bit of history
&lt;/h2&gt;

&lt;p&gt;GraphiQL is a tool that was created to help developers explore GraphQL APIs, maintained by the GraphQL Foundation. But when GraphiQL became more and more popular, developers started to create additional GraphQL IDEs. A good example of this was &lt;a href="https://github.com/graphql/graphql-playground" rel="noopener noreferrer"&gt;GraphQL Playground&lt;/a&gt;, which quickly became the most popular GraphQL IDE. It was loosely based on GraphiQL, but had more features and a better UI.&lt;/p&gt;

&lt;p&gt;After GraphQL Playground became part of the GraphQL Foundation, the need for having just one GraphQL IDE became more important. So the GraphQL Foundation decided to merge GraphiQL and GraphQL Playground into one tool. GraphiQL 1 relied on major tech debt and multiple dependencies that were outdated and hard to maintain. With the merge of GraphiQL and GraphQL Playground, the GraphQL Foundation decided to create a new version of GraphiQL, which is now called GraphiQL 2. The design and creation of GraphiQL 2 was &lt;a href="https://github.com/graphql/graphiql/discussions/2216" rel="noopener noreferrer"&gt;all documented in Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  First look at GraphiQL 2
&lt;/h2&gt;

&lt;p&gt;For me personally, this is one of the biggest releases in GraphQL world this year. As for too many years we had to work with GraphiQL 1, which is looking like it's coming from the Stone Age. With GraphiQL 2, the theme behind GraphiQL has really outdone themselves as they've created a better version of GraphiQL that looks like it's actually from modern day.&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%2F26ek6rf40w7pdl8byu3a.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%2F26ek6rf40w7pdl8byu3a.png" alt="Exploring GraphiQL 2 updates" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the above screenshot of GraphiQL 2, it looks way more modern than GraphiQL 1. It has a dark mode, a light mode, and a system mode. It has a new UI, and a lot of new features. Compared to GraphiQL 1, it's looks like a complete new version of GraphiQL with the same feel.&lt;/p&gt;

&lt;p&gt;Let's look at the same page in GraphiQL 1:&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%2Fl7h4txmobk1v7nzasi22.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%2Fl7h4txmobk1v7nzasi22.png" alt="Comparison with GraphiQL 1" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This screenshot is from GraphiQL 1 and as you can see it just feels outdated, from the color scheme to the used font. As oppposed to GraphiQL 2 there's no way to change the theme from the UI itself.&lt;/p&gt;

&lt;p&gt;Most features from GraphiQL 1 are also available in GraphiQL 2, such as the docs page, history, and the ability to pass variables and headers. But GraphiQL 2 has a lot of new features as well, which I'll explore in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  New features in GraphiQL 2
&lt;/h2&gt;

&lt;p&gt;I already mentioned GraphiQL 2 has a dark mode, which is a great addition and something most modern developer tools have today. OFcourse, you cna also switch to system mode, which will use the system theme so it changes to dark when sun sets.&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%2Fqy6rpsubre36s4ac9hjf.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%2Fqy6rpsubre36s4ac9hjf.png" alt="Dark mode in GraphiQL 2" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But next to dark mode the biggest feature update is the tabs to switch between multiple queries. This is a great addition as it allows you to have multiple queries open at the same time. This is something I've been missing in GraphiQL 1 for a long time.&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%2F1ymab65ot4r28igf4ou3.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%2F1ymab65ot4r28igf4ou3.png" alt="Tabs GraphiQL 2" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having tabs is especially useful when you have a query to get a list of results and a query to get a specific item. You can now have both open at the same time and switch between them.&lt;/p&gt;

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

&lt;p&gt;GraphiQL 2 is a great update to GraphiQL 1. It has a new UI, a lot of new features, and a dark mode. It's still the easiest tool to use for GraphQL developers to explore a GraphQL API. I'm really excited to see what the future of GraphiQL 2 will bring, especially as GraphiQL 2 is now maintained more activley than GraphiQL 1 used to be.&lt;/p&gt;

&lt;p&gt;P.S. Follow &lt;a href="https://www.twitter.com/gethackteam" rel="noopener noreferrer"&gt;Roy Derks on Twitter&lt;/a&gt; for more React, GraphQL and TypeScript tips &amp;amp; tricks. And subscribe to my &lt;a href="https://www.youtube.com/@gethackteam" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt; for React, GraphQL and TypeScript tutorials.&lt;/p&gt;




&lt;p&gt;This post was originally published on &lt;a href="https://hackteam.io/blog/exploring-graphiql-2-updates-and-new-features" rel="noopener noreferrer"&gt;hackteam.io&lt;/a&gt;. Reposted automatically with &lt;a href="https://reposted.io?utm_source=postFooter" rel="noopener noreferrer"&gt;Reposted.io&lt;/a&gt;. A free tool to repost your content across all blogging platforms.&lt;/p&gt;

</description>
      <category>gratitude</category>
    </item>
  </channel>
</rss>
