<?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: Temitope</title>
    <description>The latest articles on DEV Community by Temitope (@kingdavid).</description>
    <link>https://dev.to/kingdavid</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%2F111643%2F49aa0a5d-53bb-4e31-8519-df1b8f411e8e.png</url>
      <title>DEV Community: Temitope</title>
      <link>https://dev.to/kingdavid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kingdavid"/>
    <language>en</language>
    <item>
      <title>Build the Product. Let AI Launch It: Creating VividLaunch for the Gemini Live Agent Challenge</title>
      <dc:creator>Temitope</dc:creator>
      <pubDate>Mon, 16 Mar 2026 23:41:55 +0000</pubDate>
      <link>https://dev.to/kingdavid/build-the-product-let-ai-launch-it-creating-vividlaunch-for-the-gemini-live-agent-challenge-1dpm</link>
      <guid>https://dev.to/kingdavid/build-the-product-let-ai-launch-it-creating-vividlaunch-for-the-gemini-live-agent-challenge-1dpm</guid>
      <description>&lt;h2&gt;
  
  
  The Vibe Coding Era: Why Building Apps Is Easy but Launching Them Is Hard
&lt;/h2&gt;

&lt;p&gt;We live in the era of "vibe coding." With tools that enable us to turn a spark of an idea into a functional product in days, the barrier to entry for building has never been lower. But as indie hackers and small teams are discovering, &lt;strong&gt;building is no longer the bottleneck—distribution is.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most brilliant apps don’t fail because the code is bad; they fail because they are "ghosts." Modern marketing demands a relentless stream of high-impact content: TikToks, Reels, LinkedIn thought leadership, and constant activity on X. For a solo founder, this content treadmill is overwhelming. It steals time away from building a product users love. I built &lt;strong&gt;VividLaunch&lt;/strong&gt; to solve exactly this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing VividLaunch: The AI Creative Director for Product Launches
&lt;/h2&gt;

&lt;p&gt;VividLaunch is an autonomous orchestration platform that handles the entire lifecycle of a product launch. It acts as the "Creative Director" every founder needs but can't yet afford. By leveraging a multi-agent system, VividLaunch weaves together text, visuals, audio, and video into a single, fluid output stream. It doesn't just "chat"—it creates.&lt;/p&gt;

&lt;p&gt;VividLaunch is an autonomous growth engine that generates and distributes marketing assets from a single product prompt. It can automatically create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎬 &lt;strong&gt;Promotional videos&lt;/strong&gt; for YouTube, TikTok, and Reels&lt;/li&gt;
&lt;li&gt;✍️ &lt;strong&gt;Thought-leadership blogs&lt;/strong&gt; for Medium or Substack&lt;/li&gt;
&lt;li&gt;📱 &lt;strong&gt;Platform-optimized posts&lt;/strong&gt; for X, LinkedIn, and Instagram&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of creating each asset manually, Gemini acts as a Creative Director, generating a multimodal storyboard that combines narration, visuals, typography, and motion into a single creative flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built VividLaunch for the Gemini Live Agent Challenge
&lt;/h2&gt;

&lt;p&gt;I created this project specifically for the &lt;strong&gt;Gemini Live Agent Challenge&lt;/strong&gt; in the &lt;strong&gt;Creative Storyteller&lt;/strong&gt; category. My goal was to push the boundaries of what a "Creative Agent" can do by exploring Gemini’s native interleaved output capabilities and tool-calling prowess.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This piece of content was created for the purposes of entering the Gemini Live Agent Challenge.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing an AI Creative Director with Gemini
&lt;/h2&gt;

&lt;p&gt;At the heart of VividLaunch is a persona: the &lt;strong&gt;Creative Director&lt;/strong&gt;. Unlike traditional chatbots that operate in a turn-based text box, our agent acts as a multimodal brain. It "thinks" in scenes, cinematic motion, and emotional pacing. It uses Gemini to analyze your product's "Brand DNA" (Tone, Humor, Formality) and translates those intangible vibes into structured, production-ready assets.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Multi-Agent Architecture Behind VividLaunch
&lt;/h3&gt;

&lt;p&gt;VividLaunch is powered by a sophisticated hierarchy of agents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Researcher Agent (Gemini 3 Flash)&lt;/strong&gt;: Autonomously "surfs" your website or blog to gather product context. It uses tool-calling to query Firestore and scrape web data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creative Director Agent (Gemini 3.1 Pro)&lt;/strong&gt;: Interprets the research to choose a marketing angle and "vibe." This is the powerhouse model orchestrating the core creative strategy across all mediums.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cinematographer Agent&lt;/strong&gt;: Generates the multimodal storyboard, specifying camera moves, transitions, and audio pacing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Media Worker&lt;/strong&gt;: A backend system built with FFmpeg that interprets Gemini's instructions to produce the final media.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using Gemini's Interleaved Output to Generate Multimodal Storyboards
&lt;/h3&gt;

&lt;p&gt;The key innovation behind VividLaunch's Video Studio is using Gemini’s interleaved multimodal output to generate narration, visuals, and timing instructions in a single inference pass. &lt;/p&gt;

&lt;p&gt;Instead of generating a script first and visuals later, Gemini produces an &lt;strong&gt;interleaved JSON stream&lt;/strong&gt;. In a single inference pass, the agent generates:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Narration Script&lt;/strong&gt; (Text)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Prompts&lt;/strong&gt; (Directives for Imagen/Veo)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kinetic Typography&lt;/strong&gt; (Subtitles)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporal Instructions&lt;/strong&gt; (Exact timing and durations)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This allows the storyboard to exist as a single, cohesive creative artifact where all elements are aware of each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Google-Native Stack Powering VividLaunch
&lt;/h2&gt;

&lt;p&gt;I chose a fully Google-native stack for maximum synergy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google GenAI SDK (ADK)&lt;/strong&gt;: For orchestration and autonomous tool-calling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 3 Flash &amp;amp; Gemini 3.1 Pro&lt;/strong&gt;: The brains of the operation ensuring speed where needed and deep creative reasoning where it counts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud Firestore&lt;/strong&gt;: Managing our asset registry, project configurations, and event logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud Storage&lt;/strong&gt;: Hosting high-volume media and rendered outputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vertex AI&lt;/strong&gt;: Powering Imagen 3 and Veo for visual synthesis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud Text-to-Speech&lt;/strong&gt;: For professional-grade voiceovers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Vertex AI Imagen and Veo Power Cinematic Content Generation
&lt;/h3&gt;

&lt;p&gt;VividLaunch features a &lt;strong&gt;3-Tier Generation Engine&lt;/strong&gt; that adapts to the user's needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Classic Mode&lt;/strong&gt;: Uses Imagen 3 for high-fidelity static backgrounds with cinematic motion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid Mode&lt;/strong&gt;: Leverages &lt;strong&gt;Veo 2&lt;/strong&gt; for high-action scenes requiring dynamic AI video.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cinematic Mode&lt;/strong&gt;: Fully utilizes &lt;strong&gt;Veo 3.1&lt;/strong&gt; for the absolute latest in generative video quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Streaming AI Creativity: Turning Gemini JSON into Real Videos
&lt;/h3&gt;

&lt;p&gt;The technical pipeline is a marvel of coordination. As Gemini streams JSON blocks to the UI, our custom FFmpeg worker begins interpreting the instructions. It fetches assets from GCS, triggers Google TTS for audio, and composites everything in real-time. Watching a live stream of raw AI "thoughts" turn into a playable video with subtitles in under 60 seconds is truly magical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comprehensive Marketing Orchestration: The Studios
&lt;/h2&gt;

&lt;p&gt;VividLaunch is not just a video generator—it is a complete suite of studios designed to master every distribution channel.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Social Studio: Intelligent A/B Testing
&lt;/h3&gt;

&lt;p&gt;The Social Studio is designed for rapid iteration on platforms like X, LinkedIn, Instagram, and Facebook. I built an integrated &lt;strong&gt;A/B Variant Mode&lt;/strong&gt; into the Social Studio. Using Gemini 3.1 Pro, the agent generates two distinct strategies—for example, an educational thread vs. an engaging hook—and provides a rationale for each. Users can preview these side-by-side in real-time on live device mockups and select the winner instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Blog Studio: Distraction-Free Authority
&lt;/h3&gt;

&lt;p&gt;For long-form thought leadership, the Blog Studio generates high-authority pieces for Medium or Substack. It features a distraction-free, minimalist writing area that lets the founder edit Gemini's output before dispatching. It integrates seamlessly with the global connectors system to publish directly with one click.&lt;/p&gt;

&lt;h3&gt;
  
  
  Global Connectors: Secure Distribution
&lt;/h3&gt;

&lt;p&gt;To distribute content autonomously, I built a robust &lt;strong&gt;Global Connectors API&lt;/strong&gt;. This system manages encrypted credentials for all major platforms (Dev.to, Hashnode, Medium, X, YouTube, etc.) at the owner level. A founder connects their accounts once, and VividLaunch can seamlessly dispatch content across all their projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Autopilot Command Center
&lt;/h3&gt;

&lt;p&gt;The crown jewel of VividLaunch is the &lt;strong&gt;Autopilot Command Center&lt;/strong&gt;, a production-ready dashboard providing real-time operational visibility. Inspired by modern SaaS platforms like Vercel and Linear, it features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smart Scheduling&lt;/strong&gt;: Gemini analyzes engagement and dynamically sets the optimal posting times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pulse Settings&lt;/strong&gt;: Fine-grained sliders to control the volume of Video, Blog, and Social generations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Activity Feed&lt;/strong&gt;: Powered by real-time Firestore events, providing a transparent view of every generation, queue, and publish action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brand Voice Directives&lt;/strong&gt;: Advanced sliders for Tone, Humor, and Formality, plus a custom directive prompt to ensure the AI personality is strictly maintained.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Autopilot enabled, a founder can literally launch a product by configuring the command center and letting the agents execute the strategy week over week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering Challenges
&lt;/h2&gt;

&lt;p&gt;Synchronizing diverse AI outputs isn't easy. Here are the major hurdles I cleared:&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing the “Breathless Narrator” Problem
&lt;/h3&gt;

&lt;p&gt;AI voiceovers are often too efficient, finishing sentences before a visual scene ends. I implemented dynamic &lt;strong&gt;SSML (Speech Synthesis Markup Language)&lt;/strong&gt; where Gemini inserts &lt;code&gt;&amp;lt;break/&amp;gt;&lt;/code&gt; tags to add natural pauses. My timing engine then stretches the visual scene to perfectly match the resulting audio duration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teaching AI Cinematic Motion: The Ken Burns Effect
&lt;/h3&gt;

&lt;p&gt;Getting an LLM to output raw X/Y coordinates for camera moves was unstable. I solved this by building a &lt;strong&gt;Motion Preset Library&lt;/strong&gt;. Gemini now selects an "Intent" (e.g., &lt;code&gt;ZOOM_IN_SLOW&lt;/code&gt;), which my worker maps to smooth, mathematically stable FFmpeg filters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solving the Multimodal Identity Crisis
&lt;/h3&gt;

&lt;p&gt;Background music often drowned out narration. I built an &lt;strong&gt;Audio Mixer&lt;/strong&gt; with a "Ducking" filter that automatically lowers music volume by 15dB whenever the narrator's audio stream is active.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Subtitle Intelligence for Vertical Video
&lt;/h3&gt;

&lt;p&gt;To prevent text overflow in TikTok-style frames, I developed &lt;strong&gt;Text-Wrapping Logic&lt;/strong&gt;. If a subtitle card is too long, the system automatically segments it into multiple cards synced to the vocal timestamps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Stability vs. Creativity Tradeoff
&lt;/h3&gt;

&lt;p&gt;I discovered that one model doesn't fit all tasks. I architected a &lt;strong&gt;Dual-Tier Agency&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 3 Flash&lt;/strong&gt;: Handles the "Research" where tool-calling stability and speed are critical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 3.1 Pro&lt;/strong&gt;: Takes on the "Director" role, where state-of-the-art creative nuance, deep reasoning, and strategic thinking are paramount.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Designing an AI Interface That Feels Like a Creative Director
&lt;/h3&gt;

&lt;p&gt;The VividLaunch UI breaks the "text box" paradigm. Users watch a &lt;strong&gt;live timeline construction&lt;/strong&gt; where scene blocks appear in real-time. You can interact with the AI-extracted "Brand DNA" sliders to tweak the vibe before the final render begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next for VividLaunch?
&lt;/h2&gt;

&lt;p&gt;The foundation is built, but the future of VividLaunch involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VividAnalytics&lt;/strong&gt;: An agent that scans your engagement metrics from connected platforms and suggests "Regenerations" to optimize your content performance, closing the loop between generation and results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborative Storyboarding&lt;/strong&gt;: A multi-user "War Room" where teams can tweak Gemini's creative decisions in real-time before finalizing the generation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Build the Product. Let AI Launch It.
&lt;/h2&gt;

&lt;p&gt;VividLaunch isn't just about making content; it's about reclaiming a founder's most precious resource: time. By letting Gemini act as our Creative Director, we can finally bridge the gap between building a great product and making sure the world sees it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Submission Details:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hackathon&lt;/strong&gt;: Gemini Live Agent Challenge&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Category&lt;/strong&gt;: Creative Storyteller&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Models&lt;/strong&gt;: Gemini 3 Flash, Gemini 3.1 Pro&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tech&lt;/strong&gt;: Google Cloud, Vertex AI, GenAI SDK&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>geminiliveagentchallenge</category>
      <category>ai</category>
      <category>gemini</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Unbiased Intelligence in a Biased Game: Building Elite Sports Intelligence Engine with Elastic Agent Builder</title>
      <dc:creator>Temitope</dc:creator>
      <pubDate>Fri, 27 Feb 2026 16:39:41 +0000</pubDate>
      <link>https://dev.to/kingdavid/unbiased-intelligence-in-a-biased-game-building-elite-sports-intelligence-engine-with-elastic-252o</link>
      <guid>https://dev.to/kingdavid/unbiased-intelligence-in-a-biased-game-building-elite-sports-intelligence-engine-with-elastic-252o</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Football is a global language spoken by over &lt;strong&gt;5 billion people&lt;/strong&gt;. But it's also a game defined by extreme unpredictability. As humans, we can’t help but be biased. When we see a club like &lt;strong&gt;Liverpool&lt;/strong&gt; spending over &lt;strong&gt;$400 million&lt;/strong&gt; in a transfer window, our brains tell us they &lt;em&gt;should&lt;/em&gt; beat a smaller squad like &lt;strong&gt;Brentford&lt;/strong&gt; or &lt;strong&gt;AFC Bournemouth&lt;/strong&gt;. We factor in money, trophies, history, fanbase, and the "weight of the jersey".&lt;/p&gt;

&lt;p&gt;These biases cloud judgment. I was inspired by the idea of removing this emotional cloud. I wanted to build an agent that ignores the hype and looks only at the raw, unbiased data provided by leagues across the world—from the Premier League to the Bundesliga. My goal was to create an &lt;strong&gt;"Elite Sports Intelligence Engine"&lt;/strong&gt; that gives fans and journalists the objective truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Brain of the Operation: What the Agent Actually Does
&lt;/h2&gt;

&lt;p&gt;In most AI applications, you ask a question and the model predicts the next word based on its training. But football changes every day—yesterday's stats are today's history. To solve this, I didn't just build a chatbot; I built an &lt;strong&gt;Autonomous Orchestrator&lt;/strong&gt; using the &lt;strong&gt;Elastic Agent Builder&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond RAG: From Search to Reasoning
&lt;/h3&gt;

&lt;p&gt;While standard Retrieval-Augmented Generation (RAG) simply finds documents, my agent performs &lt;strong&gt;Agentic RAG&lt;/strong&gt;. When you select a match like &lt;em&gt;Arsenal vs. Man City&lt;/em&gt;, the agent doesn't just "look up" the teams. It initiates a multi-step reasoning loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deconstruction:&lt;/strong&gt; It breaks your request into specific data requirements (e.g., "I need home form for Team A and away form for Team B").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Selection:&lt;/strong&gt; It scans its "utility belt" of &lt;strong&gt;14+ custom ES|QL tools&lt;/strong&gt; to decide which ones will provide the most accurate tactical narrative.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Synthesis:&lt;/strong&gt; It executes complex ES|QL queries against my Elasticsearch indices, retrieving structured stats on expected goals (xG), referee behavior, and player fatigue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Final Verdict:&lt;/strong&gt; It synthesizes these disparate data points into a cohesive, professional-grade match report.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The "Innovation" Protocol
&lt;/h3&gt;

&lt;p&gt;What makes this agent unique is its ability to uncover &lt;strong&gt;hidden variables&lt;/strong&gt;. For example, if my &lt;strong&gt;Fatigue Analysis Tool&lt;/strong&gt; reports that a team has had only three days of rest, and my &lt;strong&gt;Official Conduct Tool&lt;/strong&gt; shows the assigned referee has a high yellow-card frequency, the agent is smart enough to flag this as a "High-Risk Discipline Scenario." It connects dots that a human analyst might spend hours trying to find.&lt;/p&gt;

&lt;p&gt;By using the &lt;strong&gt;Elastic Agent Builder&lt;/strong&gt;, I was able to give the LLM "hands" (the ability to query data) and "eyes" (the ability to see real-time trends), turning a simple language model into a high-fidelity &lt;strong&gt;Sports Intelligence Engine&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Ingestion – Keeping the Engine Fresh
&lt;/h3&gt;

&lt;p&gt;One of the core strengths of the &lt;strong&gt;Elastic Agent Builder&lt;/strong&gt; is its ability to connect an LLM to private, high-velocity data. But an agent is only as smart as the data it can access. Since football matches are played almost every hour across the globe, a static database simply wouldn't cut it.&lt;/p&gt;

&lt;p&gt;I needed a "Live Memory" for my agent.&lt;/p&gt;

&lt;p&gt;That’s why I built an automated daily ingestion pipeline using &lt;strong&gt;Next.js&lt;/strong&gt; and &lt;strong&gt;Vercel’s cron jobs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;All match data (results, goals, corners, cards, shots, etc.) is sourced from &lt;a href="http://football-data.co.uk" rel="noopener noreferrer"&gt;http://football-data.co.uk&lt;/a&gt; — one of the most comprehensive free football databases available. It covers an impressive range of leagues, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;England (Premier League E0, Championship E1, League One E2, League Two E3, National League EC, and more)&lt;/li&gt;
&lt;li&gt;Spain (La Liga SP1, Segunda SP2)&lt;/li&gt;
&lt;li&gt;Germany (Bundesliga D1, 2. Bundesliga D2)&lt;/li&gt;
&lt;li&gt;Italy (Serie A I1, Serie B I2)&lt;/li&gt;
&lt;li&gt;France (Ligue 1 F1, Ligue 2 F2)&lt;/li&gt;
&lt;li&gt;Netherlands (Eredivisie N1)&lt;/li&gt;
&lt;li&gt;Belgium (Pro League B1)&lt;/li&gt;
&lt;li&gt;Portugal (Primeira Liga P1)&lt;/li&gt;
&lt;li&gt;Turkey (Süper Lig T1)&lt;/li&gt;
&lt;li&gt;Greece (Super League G1)&lt;/li&gt;
&lt;li&gt;And many others: Argentina (ARG), Austria (AUT), Brazil (BRA), Denmark (DNK), Finland (FIN), Ireland (IRL), Japan (JPN), Mexico (MEX), Norway (NOR), Poland (POL), Romania (ROU), Russia (RUS), Sweden (SWE), Switzerland (SUI), USA (MLS/USA), and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This wide coverage means the engine isn’t limited to just one league — it can analyze matches from most major global competitions.&lt;/p&gt;

&lt;p&gt;The magic happens in a single Next.js API route: &lt;code&gt;/api/update-leagues&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fetch&lt;/strong&gt; — Every day, the route downloads the latest CSV files from football-data.co.uk (main leagues use the &lt;code&gt;mmz4281/2526/&lt;/code&gt; path, others use &lt;code&gt;/new/&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parse&lt;/strong&gt; — Using &lt;code&gt;csv-parse/sync&lt;/code&gt;, I read the CSV into records, standardize dates (DD/MM/YY → ISO YYYY-MM-DD), and add &lt;code&gt;leagueCode&lt;/code&gt; for easy filtering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incremental sync&lt;/strong&gt; — Before uploading, I query Elasticsearch for the latest date in that league. If the CSV has newer data (or it’s the first run), I proceed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upsert safely&lt;/strong&gt; — I create a unique &lt;code&gt;_id&lt;/code&gt; for each match (&lt;code&gt;YYYY-MM-DD_HomeTeam_AwayTeam&lt;/code&gt;) so duplicates are automatically overwritten or skipped — no manual cleanup needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bulk upload&lt;/strong&gt; — Using the Elasticsearch JavaScript client, I send batches via &lt;code&gt;client.bulk({ refresh: true })&lt;/code&gt; — fast, atomic, and efficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To run this daily without any manual intervention, I added a simple &lt;code&gt;vercel.json&lt;/code&gt; file:&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;"crons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/update-leagues"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"schedule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0 0 * * *"&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;Every&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;day&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;midnight&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;UTC&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;h3&gt;
  
  
  The Tools That Power the Engine
&lt;/h3&gt;

&lt;p&gt;At the heart of &lt;strong&gt;Elite Sports Intelligence Engine&lt;/strong&gt; are &lt;strong&gt;19 custom ES|QL tools&lt;/strong&gt; I built directly in &lt;strong&gt;Elastic Agent Builder&lt;/strong&gt;. These tools are not just simple queries — they are specialized intelligence modules that extract, aggregate, and interpret historical match data from the Elasticsearch index.&lt;/p&gt;

&lt;p&gt;Each tool is tailored to a specific angle of football analysis, and the agent intelligently decides which ones to call and how to combine them.&lt;/p&gt;

&lt;p&gt;Here’s a summary of the key tools and what they do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;get_corner_dynamics_insights&lt;/strong&gt; — Analyzes set-piece pressure and territorial dominance through average corners per match, team splits, and high-volume corner events (9.5+). Helps identify matches likely to be defined by heavy wing play.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_defensive_integrity_metrics&lt;/strong&gt; — Calculates clean sheet frequency and shutout probability for both teams. Reveals elite defensive units or goalkeepers in form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_disciplinary_trend_insights&lt;/strong&gt; — Tracks yellow/red card averages, foul patterns, and likelihood of high-caution games (3.5+ yellows). Flags tension and potential suspension risks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_double_chance_insights&lt;/strong&gt; — Quantifies tactical resilience: probability of avoiding defeat (win or draw) or decisive outcomes. Highlights unbeaten streaks or high-stakes fixtures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_full_time_result_insights&lt;/strong&gt; — Analyzes recent form and head-to-head to estimate win/draw/loss percentages. Includes sample-size warnings for reliability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_goal_density_insights&lt;/strong&gt; — Categorizes match intensity (0-1, 2-3, 4+ goals). Reveals if a fixture tends toward tactical stalemates or open, high-scoring affairs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_league_context_benchmarks&lt;/strong&gt; — Provides division-wide averages (goals, cards, corners) to show if a team is above or below league norms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_mutual_scoring_insights&lt;/strong&gt; — Measures BTTS frequency. Identifies balanced attacks or games likely to feature both sides scoring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_offensive_penetration_metrics&lt;/strong&gt; — Evaluates shot volume, high-attack games (15+ shots), and conversion efficiency. Differentiates dominant but wasteful teams from clinical finishers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_official_conduct_analysis&lt;/strong&gt; — Analyzes referee tendencies (fouls called, yellow/red averages). Spots strict or lenient officials that could influence match flow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_over_under_goals_insights&lt;/strong&gt; — Calculates over/under likelihood across 0.5 to 4.5 lines. Predicts whether the game will be low-scoring or explosive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_recent_form_trajectory&lt;/strong&gt; — Tracks momentum via weighted points from the last 5 results. Identifies teams on upward or downward spirals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_schedule_density_analysis&lt;/strong&gt; — Measures rest days since last fixture. Flags fatigue or rotation risks that could impact performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_scoreline_distribution_analysis&lt;/strong&gt; — Finds the most frequent final scorelines. Reveals "typical" outcomes between teams.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_strategic_performance_indicators&lt;/strong&gt; — Computes xG proxy (shots/SoT-based), form momentum, and H2H dominance. Spots teams over/under-performing their stats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_team_scoring_profile_insights&lt;/strong&gt; — Analyzes individual team scoring averages and multi-goal consistency. Highlights scoring threats or droughts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_venue_performance_splits&lt;/strong&gt; — Breaks down home/away win rates and goal differentials. Identifies "fortress" homes or "road warrior" away sides.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_victory_margin_analysis&lt;/strong&gt; — Measures average goal margin and win-to-nil frequency. Reveals dominant winners or tight contests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent doesn’t just run one tool — it chains several in multi-step reasoning. For example, it might start with recent form and head-to-head, then pull goal and corner trends, then check referee and schedule density to flag fatigue + discipline risks. This creates a &lt;strong&gt;"Strategic Narrative"&lt;/strong&gt; — connecting dots that would take a human analyst hours to find manually.&lt;/p&gt;

&lt;p&gt;All the ES|QL source code for these tools is available in the attached GitHub repositor.&lt;/p&gt;

&lt;p&gt;These tools are what make the agent feel truly intelligent — not just retrieving data, but synthesizing it into meaningful, actionable football intelligence — exactly what &lt;strong&gt;Elastic Agent Builder&lt;/strong&gt; was designed for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Sample Frontend Apps (Review, News, Prediction, Chat)
&lt;/h2&gt;

&lt;p&gt;To showcase the full power of &lt;strong&gt;Elite Sports Intelligence Engine&lt;/strong&gt;, I built a clean, multi-page Next.js application with four distinct experiences — each powered by the same agent but using a specialized prompt and API route to deliver exactly what different users need.&lt;/p&gt;

&lt;p&gt;All pages share a consistent cascading selector (country → league → home team → away team) for easy match input, and each calls a dedicated Next.js proxy route that crafts a tailored prompt and forwards it to the Agent Builder endpoint.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Match Review (Homepage – /)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The core experience. This page delivers a quick, high-level tactical snapshot of the fixture.&lt;br&gt;&lt;br&gt;
Route: &lt;code&gt;/api/match-review&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Prompt style: Focused on data-driven analysis (form, trends, key patterns).&lt;br&gt;&lt;br&gt;
Output: Structured Markdown with sections and tables — ideal for analysts or fans who want stats fast.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Match News / Preview (/news)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Journalistic storytelling mode.&lt;br&gt;&lt;br&gt;
Route: &lt;code&gt;/api/news&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Prompt style: Adopts a neutral "sports reporter" persona — generates engaging articles with headlines, storylines, key battles, and balanced conclusions.&lt;br&gt;&lt;br&gt;
Output: Readable, narrative preview — perfect for casual fans or content creators.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Match Stats &amp;amp; Predictions (/stats)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The "quant" deep-dive.&lt;br&gt;&lt;br&gt;
Route: &lt;code&gt;/api/stats&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Prompt style: Forces structured tables covering probabilities (1X2, over/under, BTTS, corners, cards, shots).&lt;br&gt;&lt;br&gt;
Output: Clean Markdown tables + a built-in risk disclaimer emphasizing that predictions are data-derived, not certainties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Chat (/chat)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Conversational exploration for power users.&lt;br&gt;&lt;br&gt;
Route: &lt;code&gt;/api/chat&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Prompt style: Open-ended — the agent can answer follow-ups, dive deeper into stats, compare players, or analyze league-wide trends.&lt;br&gt;&lt;br&gt;
Output: Full chat history with Markdown support — great for research or custom questions like "Why is Arsenal weak away?" or "Compare corner conversion rates."&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These four experiences show how Elastic Agent Builder enables one backend agent to power multiple frontends with different personas and formats — all through prompt engineering and custom tool chaining. The agent stays consistent while adapting perfectly to each use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "War Stories": Overcoming Technical Hurdles
&lt;/h2&gt;

&lt;p&gt;Every innovative project comes with its own set of "Final Boss" challenges. For &lt;strong&gt;Elite Sports Intelligence Engine&lt;/strong&gt;, the primary battle wasn't just building the intelligence—it was making that intelligence fast enough for the modern web.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Timeout Battle: 19 Tools vs. 60 Seconds
&lt;/h3&gt;

&lt;p&gt;When I first deployed the agent with its full suite of &lt;strong&gt;19 ES|QL tools&lt;/strong&gt;, I hit a wall: the &lt;strong&gt;504 Gateway Timeout&lt;/strong&gt;. Orchestrating nearly 20 specialized data-fetching tasks within a standard 60-second web window proved nearly impossible, as the agent’s "Chain of Thought" loop took longer than the browser was willing to wait.&lt;/p&gt;

&lt;p&gt;To win this battle, I implemented a three-pronged strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure Tuning:&lt;/strong&gt; I extended the execution limit in my Next.js route handler to &lt;code&gt;maxDuration = 120&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js Resilience:&lt;/strong&gt; I implemented &lt;strong&gt;AbortControllers&lt;/strong&gt; and &lt;code&gt;AbortSignal.timeout(110000)&lt;/code&gt; to manage these long-running AI tasks without crashing the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lean Tooling:&lt;/strong&gt; I discovered that the agent was significantly faster when interacting directly within the Elasticsearch UI compared to the API. To bridge this speed gap, I strategically &lt;strong&gt;unchecked the least-critical tools&lt;/strong&gt;, narrowing the engine's focus to the highest-impact metrics for the best performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Prompt Refinement: From "Ambiguity" to "Direct Command"
&lt;/h3&gt;

&lt;p&gt;Originally, my system prompt was a massive, complex document that governed every possible behavior. However, I realized that a long prompt actually slowed the agent down by increasing the "Thinking" overhead.&lt;/p&gt;

&lt;p&gt;I pivoted to a &lt;strong&gt;"Parallel-Reasoning" Instruction&lt;/strong&gt; strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minimalist Agent Base:&lt;/strong&gt; I simplified the default agent instructions in the Elastic UI to be as lean as possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend Orchestration:&lt;/strong&gt; I moved the heavy lifting—the specific formatting and tactical requirements—to the &lt;strong&gt;Next.js frontend prompt&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The "Delegation" Fix:&lt;/strong&gt; Instead of trying to be everything at once, the agent is now simply told to: &lt;em&gt;"Focus on the specific request from the frontend and choose only the most relevant tools for that specific task"&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This refinement turned the agent from an "Over-thinker" into a "Decisive Analyst," dramatically reducing latency while maintaining the "Elite" quality of the insights.&lt;/p&gt;

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

&lt;p&gt;Building &lt;strong&gt;Elite Sports Intelligence Engine&lt;/strong&gt; started as a simple idea: what if we could remove human bias from football analysis and let pure data tell the story? What began as a frustration with manual spreadsheets turned into a fully autonomous, tool-driven agent that delivers deep, neutral insights in seconds.&lt;/p&gt;

&lt;p&gt;Elastic Agent Builder was the perfect platform for this vision. It let me rapidly create 19 custom ES|QL tools, chain them intelligently, connect everything to my private Elasticsearch index, and expose powerful capabilities through clean APIs — exactly what the framework is designed to enable. The result is an engine that serves millions of football fans worldwide: casual viewers who want quick previews, analysts who need stats, fantasy players who crave probabilities, and journalists who want compelling narratives.&lt;/p&gt;

&lt;p&gt;The project taught me that real intelligence comes from thoughtful tool design, safe data pipelines, and letting the agent reason over results — not from forcing an LLM to guess. It also proved that even a solo builder can create something impactful with the right tools.&lt;/p&gt;

&lt;p&gt;This is just the beginning.&lt;br&gt;&lt;br&gt;
I’m excited to keep evolving Elite Sports Intelligence Engine — adding live match-day data, injury/weather context, player-level depth, and support for other sports — until it becomes the go-to unbiased intelligence layer for global football.&lt;/p&gt;

&lt;p&gt;If you're reading this, thank you for following along.&lt;br&gt;&lt;br&gt;
The repo is open (link below) — fork it, extend it, or build your own version.&lt;br&gt;&lt;br&gt;
The future of sports analysis is data-driven, neutral, and agent-powered — and I’m just getting started.&lt;/p&gt;

&lt;p&gt;Thanks again to the Elastic team for an incredible Agent Builder framework. To everyone who took the time to read through this journey: thank you for your curiosity.&lt;/p&gt;

&lt;p&gt;Let’s keep pushing the boundaries.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/tope-olajide/match-intel/" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Demo App:&lt;/strong&gt; &lt;a href="https://match-intel.vercel.app/" rel="noopener noreferrer"&gt;MatchScout AI Live Demo&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>elasticsearch</category>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>LucideCrawl: AI-Powered Web Ingestion and Phishing Detection API Built on Xano</title>
      <dc:creator>Temitope</dc:creator>
      <pubDate>Mon, 15 Dec 2025 07:56:49 +0000</pubDate>
      <link>https://dev.to/kingdavid/lucidecrawl-ai-powered-web-ingestion-and-phishing-detection-api-built-on-xano-3ee4</link>
      <guid>https://dev.to/kingdavid/lucidecrawl-ai-powered-web-ingestion-and-phishing-detection-api-built-on-xano-3ee4</guid>
      <description>&lt;p&gt;&lt;strong&gt;This is a submission for the &lt;a href="https://dev.to/challenges/xano-2025-11-20"&gt;Xano AI-Powered Backend Challenge&lt;/a&gt;: Production-Ready Public API&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;LucideCrawl&lt;/strong&gt; — a production-ready public API that allows developers to safely ingest and analyze web content at scale while protecting users from phishing, scams, and malicious sites.&lt;/p&gt;

&lt;p&gt;LucideCrawl provides four core capabilities, all implemented entirely in Xano with robust authentication, per-user rate limiting, usage tracking, and audit logging:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Phishing &amp;amp; Safety Detection&lt;/strong&gt; – AI-powered, real-time evaluation of URLs to detect scams, impersonation, urgent threats, and security risks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask Questions About Web Pages&lt;/strong&gt; – Extract clean content and answer natural language questions grounded in the page content. Perfect for RAG, summarization, or compliance checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sitemap-Based Bulk Ingestion&lt;/strong&gt; – Crawl all pages from a sitemap.xml with include/exclude path filtering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full Website Crawl&lt;/strong&gt; – Depth-controlled crawling of entire websites with domain/path rules, delivering structured, clean data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LucideCrawl is ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser extensions and email tools needing instant phishing detection&lt;/li&gt;
&lt;li&gt;AI agents requiring safe, grounded web data&lt;/li&gt;
&lt;li&gt;Knowledge platforms building search indexes or SEO audits&lt;/li&gt;
&lt;li&gt;Security teams monitoring brand impersonation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All core logic, authentication, API key management, and rate limiting are built natively in Xano.&lt;/p&gt;




&lt;h2&gt;
  
  
  API Documentation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Base URL:&lt;/strong&gt; &lt;code&gt;https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx&lt;/code&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;All endpoints require an &lt;code&gt;x-api-key&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;API keys are generated upon signup and displayed only once. Users can manage them in their account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Rate Limits (monthly requests per user – applies to all protected endpoints):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Monthly Limit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;3,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;This unified monthly quota applies to &lt;strong&gt;all endpoints that require an API key&lt;/strong&gt; (i.e., every endpoint except &lt;code&gt;/auth/signup&lt;/code&gt;, &lt;code&gt;/auth/login&lt;/code&gt; etc).&lt;br&gt;&lt;br&gt;
Usage is tracked globally across all protected calls — once the limit is reached, further requests will be blocked with a clear error until the next calendar month.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Core Endpoints
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;/auth/signup API&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Create a new user account and instantly generate a &lt;strong&gt;secure API key&lt;/strong&gt; and &lt;strong&gt;auth token&lt;/strong&gt;.&lt;br&gt;
This endpoint is designed for &lt;strong&gt;developer onboarding&lt;/strong&gt; and &lt;strong&gt;quick start integration&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ The API key is returned &lt;strong&gt;once&lt;/strong&gt;. Clients must store it securely.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h4&gt;
  
  
  Request Body
&lt;/h4&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;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"secure_password"&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;h4&gt;
  
  
  Example: Create a new account
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/auth/signup &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "name": "user004",
    "email": "user004@email.com",
    "password": "strong_password_here"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Response
&lt;/h4&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;"success"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Account created successfully. Save your API key — it will not be shown again!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"auth_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiemlwIjoiREVGIn0..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user"&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;5&lt;/span&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;"user004"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user004@email.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"free"&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;"api_key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sk_ad79826169d2f7e7c0736d649fd1a3feacb45919"&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;h3&gt;
  
  
  🔐 What this endpoint does
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Validates email uniqueness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Creates a new user (&lt;code&gt;role: member&lt;/code&gt;, &lt;code&gt;plan: free&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Generates a cryptographically secure API key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Stores the API key server-side&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Returns an auth token for immediate access&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h3&gt;
  
  
  🧠 How &lt;code&gt;/auth/signup&lt;/code&gt; fits into the platform
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;auth/signup → receive API key → call crawl_webpage / trust_scan / ask_the_page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This makes onboarding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;One request&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No manual key creation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production-ready from first call&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;/auth/login&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Authenticate an existing user and retrieve a &lt;strong&gt;new auth token&lt;/strong&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Example: Log in to an existing account
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/auth/login &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "email": "user004@email.com",
    "password": "strongpassword123"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Response (simplified)
&lt;/h4&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;"authToken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiemlwIjoiREVGIn0..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user_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;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;📌 &lt;strong&gt;Notes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used for authenticated dashboard or account-level actions&lt;/li&gt;
&lt;li&gt;Does &lt;strong&gt;not&lt;/strong&gt; return the API key (by design)&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  🧠 How Authentication Fits Into the Platform
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;login  → manage account → rotate keys → monitor usage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This keeps your platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secure&lt;/strong&gt; (keys + auth tokens)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable&lt;/strong&gt; (plan-based limits)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer-friendly&lt;/strong&gt; (simple onboarding)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔐 Authentication APIs&lt;br&gt;
/auth/me&lt;/p&gt;

&lt;p&gt;Retrieve the current user’s record using the authentication token.&lt;/p&gt;

&lt;p&gt;Example: Get authenticated user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/auth/me &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &amp;lt;YOUR_AUTH_TOKEN&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response (simplified)&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;"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;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12-20T08:15:30Z"&lt;/span&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;"user004"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user004@email.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"account_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;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"member"&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;📌 Notes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires a valid auth token in the &lt;code&gt;Authorization&lt;/code&gt; header&lt;/li&gt;
&lt;li&gt;Returns user info associated with the token&lt;/li&gt;
&lt;li&gt;Useful for verifying the logged-in user or fetching profile details&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;/reset/magic-link-login&lt;/p&gt;

&lt;p&gt;Exchange a one-time magic token for an authentication token. Logs in the user via a passwordless magic link.&lt;/p&gt;

&lt;p&gt;Example: Log in with a magic link&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/reset/magic-link-login &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "email": "user004@email.com",
    "magic_token": "8a9b7c6d-1234-5678-90ab-cdef12345678"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response (simplified)&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;"authToken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiemlwIjoiREVGIn0..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user_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;5&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;📌 Notes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;magic_token&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt; are &lt;strong&gt;required&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Tokens expire after a set time and &lt;strong&gt;can only be used once&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Generates a standard auth token for the user on successful validation&lt;/li&gt;
&lt;li&gt;Use this for passwordless login flows or “magic link” login emails&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;/trust_scan API&lt;/strong&gt;
&lt;/h3&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%2F0dfntba4vjmiq49yrax9.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%2F0dfntba4vjmiq49yrax9.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/trust_scan &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url": "https://paypal-security-update-2025.com/login"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response (simplified):&lt;/strong&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;"success"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"safety_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"safety_label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Danger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidence_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"phishing_category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"financial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"impersonated_brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PayPal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"detected_threats"&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;"URGENT_ACTION_REQUIRED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"FAKE_LOGIN_FORM"&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;"details"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This page mimics PayPal's login interface and uses urgency tactics to steal credentials."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user_action_recommendation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Do not enter any information. Close immediately."&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;"usage"&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;"month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;88&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;h3&gt;
  
  
  &lt;strong&gt;/ask_the_page API&lt;/strong&gt;
&lt;/h3&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%2Fcxjphly292b07qncbo2k.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%2Fcxjphly292b07qncbo2k.png" alt=" " width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ask a direct question about a webpage and receive an AI-generated explanation based on the page’s content and domain signals.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example: Verify a banking login page
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/ask_the_page &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://bankofamerica-secure-login-2025.com",
    "question": "Is this the real Bank of America login page?"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response (simplified):&lt;/strong&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;"success"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://bankofamerica-secure-login-2025.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"question"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Is this the real Bank of America login page?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"answer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"No, this is not a legitimate Bank of America page. The domain is not owned by Bank of America and uses urgency-driven login prompts commonly associated with phishing attacks."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"page_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;"Bank of America Secure Login"&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;"usage"&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;"month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;87&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;h3&gt;
  
  
  &lt;strong&gt;/crawl_webpage API&lt;/strong&gt;
&lt;/h3&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%2Fntdhiwtme9d4zlhzkdfr.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%2Fntdhiwtme9d4zlhzkdfr.png" alt=" " width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fetch and extract structured data from any public webpage.&lt;br&gt;
This endpoint is useful for &lt;strong&gt;content analysis, AI training, indexing, or downstream security scans&lt;/strong&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Example: Crawl a webpage
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/crawl_webpage &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://example.com"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Response (simplified):&lt;/strong&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;"success"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"raw_html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;!doctype html&amp;gt;...&amp;lt;/html&amp;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;"clean_text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This domain is for use in documentation examples without needing permission. Avoid use in operations. Learn more"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&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;"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;"Example Domain"&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="kc"&gt;null&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"canonical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&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;"headings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"h1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Domain"&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;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://iana.org/domains/example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn more"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"is_external"&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="nl"&gt;"structured_page_json"&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;"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;"Example Domain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"clean_text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This domain is for use in documentation examples without needing permission. Avoid use in operations. Learn more"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&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;"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;"Example Domain"&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="kc"&gt;null&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"canonical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&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;"headings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"h1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Domain"&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;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://iana.org/domains/example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn more"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"is_external"&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="nl"&gt;"usage"&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;"month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;76&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;h3&gt;
  
  
  &lt;strong&gt;/site_crawl API&lt;/strong&gt;
&lt;/h3&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%2Fnl65fkg7llgzdoxh35i8.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%2Fnl65fkg7llgzdoxh35i8.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Crawl an entire website (or section of it) and return structured content from multiple pages in a single request.&lt;br&gt;
Ideal for &lt;strong&gt;bulk analysis, AI training, indexing, and large-scale security scans&lt;/strong&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Input Parameters
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;url&lt;/code&gt; – Starting URL for the crawl&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pageLimit&lt;/code&gt; – Maximum number of pages to crawl&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;crawlDepth&lt;/code&gt; – How deep the crawler should follow internal links&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;includeSubdomains&lt;/code&gt; – Whether to include subdomains&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;followExternalLinks&lt;/code&gt; – Whether to crawl external domains&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;includePaths&lt;/code&gt; – Optional allowlist of URL paths&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;excludePaths&lt;/code&gt; – Optional blocklist of URL paths&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Example: Crawl a small website
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/site_crawl &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://example.com",
    "pageLimit": 3,
    "crawlDepth": 1,
    "includeSubdomains": false,
    "followExternalLinks": false,
    "includePaths": [],
    "excludePaths": []
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Response (simplified):&lt;/strong&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;"success"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Crawl completed successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"crawl_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;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pages_crawled"&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;"formattedData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://httpbin.org/forms/post"&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Customer name: Telephone: E-mail address: Pizza Size Small Medium Large..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&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;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&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="kc"&gt;null&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"canonical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;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="nl"&gt;"headings"&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="nl"&gt;"crawledData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://httpbin.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"raw_html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;!DOCTYPE html&amp;gt;...&amp;lt;/html&amp;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;"clean_text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A simple HTTP Request &amp;amp; Response Service."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&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;"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;"httpbin.org"&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="kc"&gt;null&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"canonical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&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;"headings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"h2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"httpbin.org"&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;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/requests/httpbin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"is_external"&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="nl"&gt;"usage"&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;"current"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&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;h3&gt;
  
  
  &lt;strong&gt;/load_sitemap API&lt;/strong&gt;
&lt;/h3&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%2Fdv1hz8hdv2k2qqirfxbd.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%2Fdv1hz8hdv2k2qqirfxbd.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Load and process an XML sitemap, extract valid URLs, and crawl only the pages you care about using path filters.&lt;br&gt;
Ideal for &lt;strong&gt;bulk ingestion, SEO analysis, AI training, and large-scale monitoring&lt;/strong&gt; without full site crawling.&lt;/p&gt;

&lt;h4&gt;
  
  
  Input Parameters
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sitemap_url&lt;/code&gt; – Full URL to the sitemap XML&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;include_paths&lt;/code&gt; – Optional list of URL path prefixes to allow&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exclude_paths&lt;/code&gt; – Optional list of URL path prefixes to block&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;include_paths&lt;/code&gt; and &lt;code&gt;exclude_paths&lt;/code&gt; work together to precisely control which sitemap URLs are processed.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  Example: Load and filter a sitemap
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/load_sitemap &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "sitemap_url": "https://octopus.do/sitemap.xml",
    "include_paths": [
      "/sitemap/changelog/"
    ],
    "exclude_paths": []
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Response (simplified)
&lt;/h4&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;"success"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sitemap processed successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sitemap_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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sitemap processed. Found 1 valid pages."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"formattedData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://octopus.do/sitemap/changelog"&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;"Check out our Updates and Roadmap | Octopus.do"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"November 28, 2025 Feature Export to Excel... Octopus core refactoring..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&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;"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;"Check out our Updates and Roadmap | Octopus.do"&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;"Our changelog includes new product features and development updates."&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"canonical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&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;"headings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"h1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Changelog"&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;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"h2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Export to Excel"&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;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"h2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Introducing Sitemap AI assistant BETA"&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="nl"&gt;"raw"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://octopus.do/sitemap/changelog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"raw_html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;!DOCTYPE html&amp;gt;...&amp;lt;/html&amp;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;"clean_text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"November 28, 2025 Feature Export to Excel..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&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;"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;"Check out our Updates and Roadmap | Octopus.do"&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;"Our changelog includes new product features and development updates."&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"canonical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&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;"headings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"h1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Changelog"&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;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://x.com/octopusdoHQ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Follow for updates"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"is_external"&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="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"usage"&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;"current"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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;h3&gt;
  
  
  &lt;strong&gt;/generate_pdf_from_page API&lt;/strong&gt;
&lt;/h3&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%2F9kjwwansprxbo6tikc50.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kjwwansprxbo6tikc50.gif" alt=" " width="480" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Generate a high-quality, fully rendered PDF of any webpage (A4 format, with images, CSS, and JavaScript support).&lt;/p&gt;

&lt;p&gt;Perfect for &lt;strong&gt;archiving&lt;/strong&gt;, &lt;strong&gt;legal snapshots&lt;/strong&gt;, &lt;strong&gt;report generation&lt;/strong&gt;, or &lt;strong&gt;offline sharing&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Returns raw PDF binary — browsers will automatically prompt download or display inline.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  Request Body
&lt;/h4&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://react.dev"&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;h4&gt;
  
  
  Example: Generate PDF
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/generate_pdf_from_page &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_secure_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://react.dev"
  }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; react-dev.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Response
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Binary PDF file&lt;/strong&gt; of the fully rendered page&lt;br&gt;&lt;br&gt;
Content-Type: &lt;code&gt;application/pdf&lt;/code&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;/capture_screenshot API&lt;/strong&gt;
&lt;/h3&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%2F2lo9ajhwvz0bzy6mb17u.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%2F2lo9ajhwvz0bzy6mb17u.png" alt=" " width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Capture a screenshot of any webpage — full page or viewport — in PNG or JPEG format.&lt;/p&gt;

&lt;p&gt;Ideal for &lt;strong&gt;thumbnails&lt;/strong&gt;, &lt;strong&gt;visual monitoring&lt;/strong&gt;, &lt;strong&gt;social cards&lt;/strong&gt;, or &lt;strong&gt;debugging layout issues&lt;/strong&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  Request Body
&lt;/h4&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://react.dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fullPage"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"png"&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;blockquote&gt;
&lt;p&gt;&lt;code&gt;fullPage&lt;/code&gt;: &lt;code&gt;true&lt;/code&gt; (default) = capture entire scrollable page&lt;br&gt;&lt;br&gt;
&lt;code&gt;format&lt;/code&gt;: &lt;code&gt;"png"&lt;/code&gt; (default) or &lt;code&gt;"jpeg"&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  Example: Full-page PNG screenshot
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/capture_screenshot &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_secure_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://react.dev",
    "fullPage": true,
    "format": "png"
  }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; react-dev-screenshot.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Response
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Binary image file&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Content-Type: &lt;code&gt;image/png&lt;/code&gt; or &lt;code&gt;image/jpeg&lt;/code&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;/generate_markdown_from_page API&lt;/strong&gt;
&lt;/h3&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%2Fymj0iswlgvyp9qg0t1l6.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%2Fymj0iswlgvyp9qg0t1l6.png" alt=" " width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Convert any fully rendered webpage into clean, structured Markdown.&lt;/p&gt;

&lt;p&gt;Great for &lt;strong&gt;content import&lt;/strong&gt;, &lt;strong&gt;documentation&lt;/strong&gt;, &lt;strong&gt;blog migration&lt;/strong&gt;, or &lt;strong&gt;preparing data for AI&lt;/strong&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  Request Body
&lt;/h4&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com"&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;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/generate_markdown_from_page &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_secure_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://example.com"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Response
&lt;/h4&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;"success"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"markdown"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"# Example Domain&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;[More information...](https://www.iana.org/domains/example)"&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;"usage"&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;"month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;29&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;h3&gt;
  
  
  &lt;strong&gt;/extract_metadata_from_page API&lt;/strong&gt; 🔍
&lt;/h3&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%2Fuxcifnawq96wyf34mo4q.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%2Fuxcifnawq96wyf34mo4q.png" alt=" " width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Extract SEO and Open Graph metadata (title, description, image, keywords, canonical) from any webpage.&lt;/p&gt;

&lt;p&gt;Essential for &lt;strong&gt;link previews&lt;/strong&gt;, &lt;strong&gt;content curation&lt;/strong&gt;, &lt;strong&gt;social sharing&lt;/strong&gt;, and &lt;strong&gt;crawler intelligence&lt;/strong&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  Request Body
&lt;/h4&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://react.dev"&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;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/extract_metadata_from_page &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_secure_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://react.dev"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Response
&lt;/h4&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;"success"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://react.dev"&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;"React"&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;"React is the library for web and native user interfaces. Build user interfaces out of individual pieces called components written in JavaScript..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ogImage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://react.dev/images/og-home.png"&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;"canonical"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://react.dev/"&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;"usage"&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;"month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;23&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;h3&gt;
  
  
  &lt;strong&gt;/summarize_webpage API&lt;/strong&gt; 🧠
&lt;/h3&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%2F8v4q70i6intoktzfjrks.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%2F8v4q70i6intoktzfjrks.png" alt=" " width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Generate a rich, structured AI summary of any webpage using &lt;strong&gt;Gemini 2.5 Flash&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Includes short summary, TL;DR, key bullets, quotes, topics, and estimated reading time.&lt;/p&gt;

&lt;p&gt;Perfect for &lt;strong&gt;research&lt;/strong&gt;, &lt;strong&gt;news aggregation&lt;/strong&gt;, &lt;strong&gt;content digestion&lt;/strong&gt;, or &lt;strong&gt;knowledge base building&lt;/strong&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  Request Body
&lt;/h4&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://react.dev"&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;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://xmmh-djbw-xefx.n7e.xano.io/api:x9tl6bvx/summarize_webpage &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: sk_your_secure_key_here"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://react.dev"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Response
&lt;/h4&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;"success"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://react.dev"&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;"React"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"short"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React is a JavaScript library for building web and native user interfaces from reusable components, emphasizing interactivity, scalability, and a robust community."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tldr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React enables component-based UI development using JSX... supports full-stack frameworks and is maintained by a global developer community."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bullets"&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;"React enables building user interfaces from reusable components"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Uses JSX to combine markup and logic in JavaScript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Supports interactive UIs with efficient updates"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Integrates with full-stack frameworks like Next.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Works for both web and native apps"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Backed by a massive global developer community"&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;"keyQuotes"&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;"React lets you build user interfaces out of individual pieces called components."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"This is why React is more than a library... React is a community."&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;"topics"&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;"Component-Based UI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"JSX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Interactivity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Full-Stack Integration"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Web &amp;amp; Native"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Developer Community"&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;"readingTimeMinutes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gemini-2.5-flash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"summaryGeneratedAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12-30T23:07:56.221Z"&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;"usage"&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;"month"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;21&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;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/auth/signup&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create a new account and issue a permanent API key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/auth/login&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Authenticate an existing user and return a session auth token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/crawl_webpage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Crawl and extract structured data from a single webpage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/site_crawl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Crawl multiple pages across a website with depth and path controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/load_sitemap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Load and process URLs from an XML sitemap with smart filtering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/trust_scan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Detect phishing, scam, and impersonation signals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/ask_the_page&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Extract clean content and answer natural language questions grounded in the page content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/generate_pdf_from_page&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate a fully rendered PDF (A4, with images &amp;amp; JS) of any webpage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/capture_screenshot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Capture a full-page or viewport screenshot (PNG or JPEG) of any webpage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/generate_markdown_from_page&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Convert a fully rendered webpage into clean, structured Markdown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/extract_metadata_from_page&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Extract SEO &amp;amp; Open Graph metadata (title, description, og:image, keywords, canonical)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/summarize_webpage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate a structured AI summary (short, TL;DR, bullets, quotes, topics)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Account &amp;amp; Key Management Endpoints
&lt;/h3&gt;

&lt;p&gt;These endpoints allow developers to programmatically manage their access keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. `GET /get_api_keys&lt;/strong&gt;` – &lt;strong&gt;List Active Keys&lt;/strong&gt;&lt;br&gt;
Retrieves a paginated list of API keys for the authenticated user.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input:&lt;/strong&gt; None (uses Auth Token).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Returns:&lt;/strong&gt; A list of keys with values masked (e.g., &lt;code&gt;sk_123...890&lt;/code&gt;), creation date, and plan type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. `POST /generate_api_key&lt;/strong&gt;` – &lt;strong&gt;Create New Key&lt;/strong&gt;&lt;br&gt;
Generates a new secure API key (24 random bytes, hex-encoded).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input:&lt;/strong&gt; &lt;code&gt;{ "name": "Production App" }&lt;/code&gt; (Optional label).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Returns:&lt;/strong&gt; The full API key string (shown only once), &lt;code&gt;id&lt;/code&gt;, and &lt;code&gt;name&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Note:&lt;/strong&gt; This action is logged in the &lt;code&gt;event_log&lt;/code&gt; table for security auditing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. `DELETE /delete_api_key&lt;/strong&gt;` – &lt;strong&gt;Revoke Key&lt;/strong&gt;&lt;br&gt;
Permanently deletes an API key.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input:&lt;/strong&gt; &lt;code&gt;{ "key_id": 15 }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Returns:&lt;/strong&gt; Success message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Validates that the key belongs to the authenticated user before deletion.&lt;/li&gt;
&lt;/ul&gt;







&lt;h2&gt;
  
  
  The AI Prompt I Used
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Build a production-ready backend for an application called LucideCrawl.&lt;br&gt;
LucideCrawl is a Web Crawling + Content Extraction API that allows developers to crawl websites, extract clean data, and optionally run AI analysis using Google Gemini.&lt;br&gt;
The backend must expose a secure public API with proper documentation, authentication, rate limiting, and usage logs.&lt;br&gt;
Focus on practicality and simplicity—avoid overly complex ML/RAG pipelines.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI produced strong foundations that I then refined for production readiness.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Refined the AI-Generated Code
&lt;/h2&gt;

&lt;p&gt;I used the AI-generated Xano backend as a &lt;strong&gt;strong starting point&lt;/strong&gt;, then refined and extended it to meet the needs of a production-ready, public API for website scanning and phishing detection. My goal was to align the generated structure with real-world usage patterns such as API access control, usage tracking, detailed scan results, and long-term data integrity.&lt;/p&gt;

&lt;p&gt;Below are the key transformations I made, with examples where applicable.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. API Key Management and Access Control
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Initial state (AI-generated):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic API key support tied to a user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Improvements made:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Introduced a dedicated &lt;code&gt;api_key&lt;/code&gt; table that supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple API keys per user&lt;/li&gt;
&lt;li&gt;A unique constraint on the &lt;code&gt;key&lt;/code&gt; field&lt;/li&gt;
&lt;li&gt;An optional &lt;code&gt;name&lt;/code&gt; field so users can label keys (e.g., “Production”, “Testing”)&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;plan_type&lt;/code&gt; field to support tiered access (free / pro)
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api_key
- id
- user_id
- key (unique)
- name (optional)
- plan_type
- created_at
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes API access more flexible, secure, and easier to manage for end users.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Monthly Usage Aggregation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Initial state:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request-level usage was logged, but not aggregated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Improvements made:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Added an &lt;code&gt;api_monthly_usage&lt;/code&gt; table to track request counts per user per month&lt;/li&gt;
&lt;li&gt;Enforced a unique constraint on &lt;code&gt;(user_id, month)&lt;/code&gt; to guarantee one row per user per billing cycle
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api_monthly_usage
- user_id
- month (YYYY-MM)
- call_count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure enables efficient rate limiting, analytics, and future billing logic without relying on expensive log scans.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Usage Log Enhancements
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Initial state:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core usage logging was already present&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Improvements made:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extended the existing &lt;code&gt;usage_log&lt;/code&gt; table by adding a &lt;code&gt;url&lt;/code&gt; field&lt;/li&gt;
&lt;li&gt;Preserved all existing fields and historical data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This provides better visibility into how each endpoint is used and which URLs are being analyzed, improving traceability and auditing.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Detailed Scan Result Storage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Initial state:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scan results were stored at a high level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Improvements made:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expanded the &lt;code&gt;scan_history&lt;/code&gt; table to store detailed analysis returned by the external scanning API&lt;/li&gt;
&lt;li&gt;Added only missing columns to ensure idempotent and non-destructive schema updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;New fields include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safety score and label&lt;/li&gt;
&lt;li&gt;Confidence level&lt;/li&gt;
&lt;li&gt;Phishing category&lt;/li&gt;
&lt;li&gt;Detected threats and risk factors (JSON)&lt;/li&gt;
&lt;li&gt;User-facing explanations and recommendations&lt;/li&gt;
&lt;li&gt;External verification results&lt;/li&gt;
&lt;li&gt;Scan timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows scan results to be both machine-readable and human-friendly.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Question &amp;amp; Answer History Tracking
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;New addition:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Created an &lt;code&gt;ask_history&lt;/code&gt; table to persist user questions, AI responses, and related metadata such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model used&lt;/li&gt;
&lt;li&gt;Scraped text length&lt;/li&gt;
&lt;li&gt;Timestamp of the request&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This provides a clear audit trail and supports analytics, debugging, and future model evaluation.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Crawl and Sitemap History Separation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Improvements made:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Added a &lt;code&gt;crawl_history&lt;/code&gt; table to store website crawl configurations and outcomes&lt;/li&gt;
&lt;li&gt;Added a &lt;code&gt;sitemap_history&lt;/code&gt; table to track sitemap processing independently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By separating crawl and sitemap data, the backend remains clean, easier to query, and more adaptable as crawling features expand.&lt;/p&gt;




&lt;h3&gt;
  
  
  7. Schema Evolution and Safety
&lt;/h3&gt;

&lt;p&gt;All schema changes were applied in a way that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds new capabilities without breaking existing functionality&lt;/li&gt;
&lt;li&gt;Avoids recreating tables or modifying existing columns&lt;/li&gt;
&lt;li&gt;Preserves historical data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach ensures smooth iteration while maintaining system stability.&lt;/p&gt;

&lt;p&gt;The AI-generated backend provided a solid foundation in Xano. By thoughtfully extending it with additional tables, constraints, and fields, I tailored the system to support real-world API usage, detailed scan analysis, and long-term scalability—while staying fully aligned with Xano best practices.&lt;/p&gt;

&lt;p&gt;Key improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Robust header handling:&lt;/strong&gt; Case-insensitive &lt;code&gt;x-api-key&lt;/code&gt; detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-endpoint rate limiting:&lt;/strong&gt; Separate usage tracking for each endpoint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atomic usage counting:&lt;/strong&gt; Prevents accidental overcharging on failed requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comprehensive history tables:&lt;/strong&gt; For auditing and dashboard support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan-based dynamic limits:&lt;/strong&gt; Free, Pro, Enterprise&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long operation timeouts:&lt;/strong&gt; Up to 600s for deep crawls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent response format:&lt;/strong&gt; Always &lt;code&gt;{ success, data, usage }&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These refinements ensure fairness, transparency, and a developer-friendly API.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Overall Experience Using Xano
&lt;/h2&gt;

&lt;p&gt;Xano made it possible to build a fully featured, secure, public-facing API in a relatively short amount of time.&lt;/p&gt;

&lt;p&gt;One of the most helpful aspects was the &lt;strong&gt;visual canvas and function stack&lt;/strong&gt;, which clearly shows how data flows through each API—from authentication, to rate limiting, processing, logging, and response handling. While I didn’t have enough time to explore the visual builder as deeply as I would have liked due to the deadline, it was still very useful for understanding and structuring complex logic.&lt;/p&gt;

&lt;p&gt;I relied mostly on &lt;strong&gt;XanoScript&lt;/strong&gt; for implementation. As someone still gaining experience with it, I encountered several syntax and structure errors along the way. However, the &lt;strong&gt;Logic Assistant&lt;/strong&gt; was extremely helpful in resolving these issues. It not only identified errors quickly but often suggested cleaner, more efficient ways to write the logic, which significantly improved the quality of my code and helped me learn faster.&lt;/p&gt;

&lt;p&gt;Overall, Xano struck a great balance between visual tooling and low-level control. Even when working primarily with XanoScript, the platform provided enough guidance and tooling to move quickly, fix mistakes, and ship with confidence.&lt;/p&gt;

&lt;p&gt;LucideCrawl is now live, helping developers build safer, smarter web-powered applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Example
&lt;/h2&gt;

&lt;p&gt;To showcase LucideCrawl in a real-world scenario, I built &lt;strong&gt;Trust Shield&lt;/strong&gt; — a lightweight Chrome extension that uses the &lt;code&gt;POST /trust_scan&lt;/code&gt; endpoint to protect users from phishing &lt;strong&gt;in real time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Trust Shield turns LucideCrawl from a backend API into &lt;strong&gt;always-on, user-facing protection&lt;/strong&gt; that runs quietly in the background while users browse.&lt;/p&gt;




&lt;h3&gt;
  
  
  What Trust Shield Does
&lt;/h3&gt;

&lt;p&gt;On every page visit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The current URL is &lt;strong&gt;automatically scanned&lt;/strong&gt; using LucideCrawl&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The extension badge updates instantly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🛡️ &lt;strong&gt;Green&lt;/strong&gt; — Safe&lt;/li&gt;
&lt;li&gt;⚠️ &lt;strong&gt;Red&lt;/strong&gt; — Potentially dangerous&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Risky sites trigger a &lt;strong&gt;Chrome notification&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safety label&lt;/li&gt;
&lt;li&gt;Risk score&lt;/li&gt;
&lt;li&gt;Clear next-step guidance&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Clicking the extension icon opens a popup with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safety score and confidence&lt;/li&gt;
&lt;li&gt;Detected threats and risk factors&lt;/li&gt;
&lt;li&gt;Impersonated brand (if applicable)&lt;/li&gt;
&lt;li&gt;Human-readable explanation of the risk&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The user never has to think about scanning, protection happens by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source Code
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Open source:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/tope-olajide/trust-shield" rel="noopener noreferrer"&gt;trust-shield&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Try It Yourself (≈ 2 Minutes)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Get an API key&lt;/strong&gt;&lt;br&gt;
Create a free LucideCrawl account via the &lt;code&gt;POST /auth/signup&lt;/code&gt; endpoint using any REST client (Postman, cURL, etc.).&lt;br&gt;
Copy the generated &lt;code&gt;sk_...&lt;/code&gt; API key (shown once).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Install the Chrome extension&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone or download: &lt;a href="https://github.com/tope-olajide/trust-shield" rel="noopener noreferrer"&gt;trust-shield&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;chrome://extensions/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Developer mode&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Load unpacked&lt;/strong&gt; and select the project folder&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;3. Connect your API key&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click the Trust Shield icon&lt;/li&gt;
&lt;li&gt;Paste your API key&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Test it&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visit a safe site → badge turns &lt;strong&gt;green 🛡️&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Visit a phishing test site → badge turns &lt;strong&gt;red ⚠️&lt;/strong&gt; and a warning appears&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No refreshes, no manual scans — protection is automatic.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>xanochallenge</category>
      <category>api</category>
      <category>backend</category>
    </item>
    <item>
      <title>Understanding Object Destructuring in JavaScript: A Beginner's Guide</title>
      <dc:creator>Temitope</dc:creator>
      <pubDate>Fri, 31 Mar 2023 13:35:27 +0000</pubDate>
      <link>https://dev.to/kingdavid/understanding-object-destructuring-in-javascript-a-beginners-guide-1c32</link>
      <guid>https://dev.to/kingdavid/understanding-object-destructuring-in-javascript-a-beginners-guide-1c32</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Object destructuring is an important technique in JavaScript that enables developers to easily extract specific properties from an object and assign them to variables with a single line of code. This not only simplifies the code but also improves its readability and maintainability.&lt;/p&gt;

&lt;p&gt;Introduced in ECMAScript 6 (ES6), object destructuring is one of several features aimed at enhancing the language's expressiveness and functionality. The use of curly braces (&lt;code&gt;{}&lt;/code&gt;) is employed in ES6 to extract properties from objects and assign them to variables with the same name. Before ES6, developers had to manually extract properties from objects by writing multiple lines of code. The syntax for object destructuring is clear and concise and can be used for both simple and nested objects, as well as for default values and aliasing.&lt;/p&gt;

&lt;p&gt;For beginners, comprehending the concept of object destructuring in JavaScript can be quite challenging and can also hinder their ability to understand code that uses this technique. In this tutorial, you will learn how to effectively destructure arrays and object literals in JavaScript.&lt;/p&gt;

&lt;p&gt;We will begin by first learning how to destructure arrays, before moving on to object literals.&lt;/p&gt;

&lt;h1&gt;
  
  
  Destructuring Array Literals
&lt;/h1&gt;

&lt;p&gt;By using the destructuring assignment syntax, we can efficiently extract the elements we want from an array and assign them to new variables in a readable and concise manner. This approach enables us to access relevant data swiftly and avoid the use of verbose and repetitive indexing code. In this section, we will examine different methods of destructuring array literals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assigning Values to Variables
&lt;/h2&gt;

&lt;p&gt;The process of assigning values to variables is pretty straightforward. We start by declaring a variable on the left-hand side of the assignment operator (&lt;code&gt;=&lt;/code&gt;), followed by an array on the right-hand side. Each variable on the left-hand side corresponds to an element of the array on the right-hand side. Consider the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const countries = ['Canada', 'Lesotho', 'Nigeria', 'USA', 'China', 'England', 'India']

const [first, second, third] = countries;
console.log(first) // Canada
console.log(second) // Lesotho
console.log(third) // Nigeria

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

&lt;/div&gt;



&lt;p&gt;In the above code, the pattern [first, second, third] matches the first three elements of the &lt;code&gt;countries&lt;/code&gt; array and assigns their values to the variables: &lt;code&gt;first&lt;/code&gt;, &lt;code&gt;second&lt;/code&gt;, and &lt;code&gt;third&lt;/code&gt;, respectively. The square brackets on the left side of the equal sign define the variables that will receive the values. The remaining elements of the array ('USA', 'China', 'England', and 'India') are not assigned to any variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skipping Elements
&lt;/h2&gt;

&lt;p&gt;In the example above, we skipped 'USA', 'China', 'England', and 'India' by omitting the corresponding variable name. You can also skip elements by using commas to indicate their position in the array. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const countries = ['Canada', 'Lesotho', 'Nigeria', 'USA', 'China', 'England','India']

const [northAmerica, , africa, , asia, europe] = countries;
console.log(northAmerica) // Canada
console.log(africa) // Nigeria
console.log(asia) // China
console.log(europe) // England

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

&lt;/div&gt;



&lt;p&gt;In this code, the first element of the &lt;code&gt;countries&lt;/code&gt; array is assigned to the variable &lt;code&gt;northAmerica&lt;/code&gt;, which means that &lt;code&gt;northAmerica&lt;/code&gt; now contains the string "Canada". The third element of the &lt;code&gt;countries&lt;/code&gt; array is assigned to the variable &lt;code&gt;Africa&lt;/code&gt;, which means that &lt;code&gt;Africa&lt;/code&gt; now contains the string "Nigeria". The second and fourth elements of the array are skipped due to the blank space in between the commas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Default Values
&lt;/h2&gt;

&lt;p&gt;When an array has undefined or missing elements, it is helpful to assign default values while destructuring it. This way, the default values can provide fallbacks if the array does not have the expected values or they are undefined. For example, consider the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const countries = ['Canada', 'Lesotho', , undefined, 'China', 'England', 'India']

const [first='Mexico', second = 'Ghana', third = 'Nigeria', fourth = 'Australia'] = countries;

console.log(first) // Canada
console.log(second) // Lesotho
console.log(third) // Nigeria
console.log(fourth) // Australia

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

&lt;/div&gt;



&lt;p&gt;In the code above, the default values are assigned to the variables when the corresponding value in the array is missing or undefined. The first variable &lt;code&gt;first&lt;/code&gt; will be assigned the value of the first element in the countries array, which is 'Canada'. Similarly, the &lt;code&gt;second&lt;/code&gt; variable will be assigned the value of the second element in the array, which is 'Lesotho'. Since the third element in the array is missing, the default value 'Nigeria' will be assigned to the &lt;code&gt;third&lt;/code&gt; variable. Finally, the &lt;code&gt;fourth&lt;/code&gt; variable will be assigned the default value which is 'Australia' because the fourth element in the array is &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Destructuring with &lt;code&gt;rest&lt;/code&gt; operator
&lt;/h2&gt;

&lt;p&gt;The rest operator is denoted by three dots (&lt;code&gt;...&lt;/code&gt;) and can only be used as the last element in an array destructuring statement. When used, it collects all the remaining elements of the array that were not assigned to individual variables and assigns them to the variable that follows the rest operator. The rest operator essentially allows developers to create a new array from the remaining elements of an existing array.&lt;/p&gt;

&lt;p&gt;Consider the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const countries = ['Canada', 'Lesotho', 'Nigeria', 'USA', 'China', 'England','India']

const [northAmerica, africa, ...remainings] = countries;
console.log(northAmerica) // Canada
console.log(africa) // Lesotho
console.log(remainings) // ['Nigeria', 'USA', 'China', 'England', 'India']

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

&lt;/div&gt;



&lt;p&gt;In this example, the first two elements of the &lt;code&gt;countries&lt;/code&gt; array are assigned to the &lt;code&gt;northAmerica&lt;/code&gt; and &lt;code&gt;Africa&lt;/code&gt; variables, respectively. The rest operator is then used to collect the remaining elements of the array &lt;code&gt;['Nigeria', 'USA', 'China', 'England', 'India']&lt;/code&gt; and assign them to the &lt;code&gt;remainings&lt;/code&gt; variable.&lt;/p&gt;

&lt;h1&gt;
  
  
  Destructuring Object Literals
&lt;/h1&gt;

&lt;p&gt;Destructuring array literals differs slightly from dealing with object literals. In an array, objects are indexed with a numerical value starting from 0, while object literals are indexed using keys. When destructuring an object in an array, the syntax involves using square brackets to access the index of the object you want to extract. When destructuring object literals, the syntax involves using curly braces to access the key of the property you want to extract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assigning Values to Variables
&lt;/h2&gt;

&lt;p&gt;By assigning values to variables in object destructuring, you can extract specific properties from an object and assign them to variables with the same names. Consider the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const countriesByContinent = { northAmerica: "Canada", europe:"England", africa:"Nigeria", asia:"China", southAmerica:"Brazil"
}
const {northAmerica, asia} = countriesByContinent;

console.log(northAmerica); // Canada
console.log(asia); // China

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

&lt;/div&gt;



&lt;p&gt;In this example, we extracted the values of the &lt;code&gt;northAmerica&lt;/code&gt; and &lt;code&gt;asia&lt;/code&gt; properties from the &lt;code&gt;countriesByContinent&lt;/code&gt; object and assign them to new variables with the same names. This means that the values of the &lt;code&gt;northAmerica&lt;/code&gt; and &lt;code&gt;asia&lt;/code&gt; properties are now stored in the &lt;code&gt;northAmerica&lt;/code&gt; and &lt;code&gt;asia&lt;/code&gt; variables, respectively.&lt;/p&gt;

&lt;p&gt;Before object destructuring was introduced in JavaScript, you would need to access object properties using the dot notation or square bracket notation to extract their values. For example, to access the values of the &lt;code&gt;northAmerica&lt;/code&gt; and &lt;code&gt;asia&lt;/code&gt; properties in the &lt;code&gt;countriesByContinent&lt;/code&gt; object without destructuring, you would do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const countriesByContinent = { northAmerica: "Canada", europe:"England", africa:"Nigeria", asia:"China", southAmerica:"Brazil" };

const northAmerica = countriesByContinent.northAmerica;
const asia = countriesByContinent.asia;

console.log(northAmerica); // "Canada"
console.log(asia); // "China"

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Renaming Variable
&lt;/h2&gt;

&lt;p&gt;Sometimes, it may be necessary to rename a variable in object destructuring to avoid conflicts in cases where the variable already exists in your code. If you already have a variable with the same name as a property you are trying to extract, it can cause conflicts and lead to unexpected results. To avoid this, you will need to rename the extracted property and assign it to a new variable with a different name.&lt;/p&gt;

&lt;p&gt;Consider the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const countriesByContinent = { australia:"New Zealand", northAmerica: "Canada", europe:"England", africa:"Nigeria", asia:"China", southAmerica:"Brazil"
}
const {australia:oceania, africa:motherland} = countriesByContinent;

console.log(oceania); // New Zealand
console.log(motherland); // Nigeria

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

&lt;/div&gt;



&lt;p&gt;In this code, we extract the values of the &lt;code&gt;australia&lt;/code&gt; and &lt;code&gt;africa&lt;/code&gt; properties from the &lt;code&gt;countriesByContinent&lt;/code&gt; object and assign them to new variables &lt;code&gt;oceania&lt;/code&gt; and &lt;code&gt;motherland&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Default Values
&lt;/h2&gt;

&lt;p&gt;Similar to array destructuring, we can also define default values for properties in object destructuring. This is useful when some properties are missing from the object, or if their values are undefined, as the default values can act as fallbacks.&lt;/p&gt;

&lt;p&gt;Let's consider the following code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const countriesByContinent = {europe:"England", northAmerica: "Canada", australia:"New Zealand" }

const {europe, northAmerica="USA", africa="Ghana", asia="India" } = countriesByContinent;

console.log(europe); // England
console.log(northAmerica); // Canada
console.log(africa); // Ghana
console.log(asia); // India

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

&lt;/div&gt;



&lt;p&gt;In the example above, &lt;code&gt;europe&lt;/code&gt; will be assigned the value &lt;code&gt;"England"&lt;/code&gt; because the &lt;code&gt;europe&lt;/code&gt; property is present in the &lt;code&gt;countriesByContinent&lt;/code&gt; object. &lt;code&gt;northAmerica&lt;/code&gt; will be assigned the value &lt;code&gt;"Canada"&lt;/code&gt; because that is the value of the &lt;code&gt;northAmerica&lt;/code&gt; property in the object.&lt;/p&gt;

&lt;p&gt;However, the &lt;code&gt;africa&lt;/code&gt; and &lt;code&gt;asia&lt;/code&gt; properties are not present in the &lt;code&gt;countriesByContinent&lt;/code&gt; object. Therefore, their default values of &lt;code&gt;"Ghana"&lt;/code&gt; and &lt;code&gt;"India"&lt;/code&gt;, respectively, will be used instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the &lt;code&gt;rest&lt;/code&gt; Syntax
&lt;/h2&gt;

&lt;p&gt;The rest syntax used in object destructuring functions similarly to its use in array destructuring. This syntax is used to gather the remaining properties of an object and store them in a new object variable. It involves using the three dots (`&lt;code&gt;) followed by the name of a variable within the curly braces&lt;/code&gt;{}`.&lt;/p&gt;

&lt;p&gt;Let's consider the example below:&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;br&gt;
const countriesByContinent = {europe:"England", northAmerica: "Canada", africa:"Nigeria", asia:"China", southAmerica:"Brazil"&lt;br&gt;
 }&lt;/p&gt;

&lt;p&gt;const {europe, northAmerica, ...remainings} = countriesByContinent;&lt;/p&gt;

&lt;p&gt;console.log(rest) // {africa:"Nigeria", asia:"China", southAmerica:"Brazil"}&lt;br&gt;
console.log(europe); // England&lt;br&gt;
console.log(northAmerica); // Canada&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;...rest&lt;/code&gt; syntax is used to collect all the remaining properties of the &lt;code&gt;countriesByContinent&lt;/code&gt; object that has not been assigned to &lt;code&gt;europe&lt;/code&gt; or &lt;code&gt;northAmerica&lt;/code&gt;. In this case, &lt;code&gt;remainings&lt;/code&gt; will be a new object that contains the &lt;code&gt;africa&lt;/code&gt;, &lt;code&gt;asia&lt;/code&gt;, and &lt;code&gt;southAmerica&lt;/code&gt; properties and their corresponding values.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Destructuring is an interesting concept in JavaScript that allows values to be extracted from arrays or objects. Although it can be very simple at first, destructuring has the potential to become very complex quite rapidly. That is why it is very important to maintain simplicity and readability when implementing destructuring in your code. Doing so will benefit both the developer and anyone who may review the code in the future, as well as make it easier to understand and maintain.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Learn Full-Stack Web Development with React and GraphQL by Building a Sticky Note App - Part three</title>
      <dc:creator>Temitope</dc:creator>
      <pubDate>Mon, 09 Jan 2023 16:47:18 +0000</pubDate>
      <link>https://dev.to/kingdavid/learn-full-stack-web-development-with-react-and-graphql-by-building-a-sticky-note-app-part-three-48nd</link>
      <guid>https://dev.to/kingdavid/learn-full-stack-web-development-with-react-and-graphql-by-building-a-sticky-note-app-part-three-48nd</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hello again!👋 In the previous part of the series, we covered how to build the backend of the Sticky Note app using GraphQL, Apollo Server 4, Nexus and MongoDB. In this section, we will be integrating our backend API with the frontend and enabling communication between the two. This will allow the frontend to send requests to and receive data from our GraphQL API.&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;We will be using the frontend code that we built in the first part of this series to connect to the GraphQL API that we created in the second part. It is important that you check out both of these sections before proceeding, as the knowledge gained in those parts will be essential for completing this section.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting the Project
&lt;/h1&gt;

&lt;p&gt;To get started with this section, we will first need to clone the &lt;a href="https://github.com/tope-olajide/sticky-note-react"&gt;GitHub repository&lt;/a&gt; that contains the code from the first part of this tutorial. To do this, open your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; git clone https://github.com/tope-olajide/sticky-note-react.git

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

&lt;/div&gt;



&lt;p&gt;This will create a local copy of the repository on your machine. Once the cloning process is complete, you can navigate to the repository directory by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bash cd sticky-note-react

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

&lt;/div&gt;



&lt;p&gt;To install all of the necessary dependencies for this project, run the following command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn install

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  What is Apollo Client?
&lt;/h1&gt;

&lt;p&gt;Apollo Client is a comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. It is designed to help you easily connect to a GraphQL server and retrieve data from it, as well as update and manipulate that data using GraphQL mutations. Apollo Client features automatic caching, reliable change detection, and a simple, declarative API that makes it easy to work with GraphQL in your JavaScript applications.&lt;/p&gt;

&lt;h1&gt;
  
  
  Installing the Apollo Client and GraphQL
&lt;/h1&gt;

&lt;p&gt;Run the following command to install Apollo Client and GraphQL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @apollo/client graphql

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Setting up the &lt;code&gt;InMemoryCache&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Apollo GraphQL's &lt;code&gt;InMemoryCache&lt;/code&gt; is a powerful and flexible caching library that is designed to work with GraphQL servers. It is an in-memory data store that stores the results of GraphQL queries, mutations, and subscriptions in a cache.&lt;/p&gt;

&lt;p&gt;Create a new file called &lt;code&gt;cache.ts&lt;/code&gt; in the root directory, then open it and enter the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { InMemoryCache } from '@apollo/client';

export const cache: InMemoryCache = new InMemoryCache({ })

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

&lt;/div&gt;



&lt;p&gt;This will create an instance of &lt;code&gt;InMemoryCache&lt;/code&gt;. We will use this cache instance to store the data that will be fetched from our GraphQL server. In addition, we will use the &lt;code&gt;InMemoryCache&lt;/code&gt; instead of React &lt;code&gt;useState&lt;/code&gt; hook to store local data that we want to manage within our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing the Apollo Client
&lt;/h2&gt;

&lt;p&gt;To initialize the Apollo Client in our project, let's create a new file called &lt;code&gt;client.ts&lt;/code&gt; in the root directory of our project and add the following code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import { ApolloClient, createHttpLink } from '@apollo/client';
import { cache } from './cache';

const link = createHttpLink({
    uri: 'http://localhost:4000/graphql',
    credentials: 'include'
});
const client = new ApolloClient({
    cache,
    link,
});

export default client

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;createHttpLink&lt;/code&gt; object will handle the communication with our GraphQL server. We passed in two properties, the &lt;code&gt;uri&lt;/code&gt; and &lt;code&gt;credentials&lt;/code&gt;. The &lt;code&gt;credential&lt;/code&gt; options provide the credential policy that will be applied to each API call, and the &lt;code&gt;uri&lt;/code&gt; options contain the URL of our GraphQL server.&lt;/p&gt;

&lt;p&gt;We set the value of the &lt;code&gt;credentials&lt;/code&gt; option to &lt;code&gt;include&lt;/code&gt;. If the front-end and back-end have different domain names, you should set the &lt;code&gt;credentials&lt;/code&gt; option to &lt;code&gt;include&lt;/code&gt;. If they have the same domain name, you should use &lt;code&gt;same-origin&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;in the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const client = new ApolloClient({
    cache,
    link,
});

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

&lt;/div&gt;



&lt;p&gt;We created an instance of the &lt;code&gt;ApolloClient&lt;/code&gt; object by passing in the &lt;code&gt;cache&lt;/code&gt; and &lt;code&gt;link&lt;/code&gt; objects as arguments.&lt;/p&gt;

&lt;h1&gt;
  
  
  Making the &lt;code&gt;ApolloClient&lt;/code&gt; instance available to all the React components in our App.
&lt;/h1&gt;

&lt;p&gt;To make the &lt;code&gt;client&lt;/code&gt; object we created in the &lt;code&gt;client.ts&lt;/code&gt; file available for use in all our components, we will wrap &lt;code&gt;ApolloProvider&lt;/code&gt; to the root component of our app. &lt;code&gt;ApolloProvider&lt;/code&gt; is a higher-order component (HOC) from the &lt;code&gt;react-apollo&lt;/code&gt; library that helps to provide our React components with the data they need from a GraphQL server.&lt;/p&gt;

&lt;p&gt;We will use the &lt;code&gt;ApolloProvider&lt;/code&gt; to provide the &lt;code&gt;client&lt;/code&gt; object to all of the components in the app.&lt;/p&gt;

&lt;p&gt;Overwrite everything in &lt;code&gt;pages/_app.tsx&lt;/code&gt; file with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import '../styles/globals.css'
import { AppProps } from 'next/app'
import { ApolloProvider } from '@apollo/client'
import client from '../client'
import { useEffect, useState } from 'react';
function MyApp({ Component, pageProps }: AppProps) {
  const [isClient, setIsClient] = useState(false)
  useEffect(() =&amp;gt; {
    if (typeof window !== "undefined") {
      setIsClient(true)
    }
  }, [])
  if (isClient) {
    return (
      &amp;lt;ApolloProvider client={client}&amp;gt;
        &amp;lt;Component {...pageProps} /&amp;gt;
      &amp;lt;/ApolloProvider&amp;gt;
    )
  }
return(
  &amp;lt;&amp;gt;
  &amp;lt;h1&amp;gt;Loading...&amp;lt;/h1&amp;gt;
  &amp;lt;/&amp;gt;
)
}
export default MyApp

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

&lt;/div&gt;



&lt;p&gt;We are using Next.js to build the front end of our app, which means that the content of our web app will be generated on the server side and sent to the client as a fully rendered HTML page. Later in this tutorial, we will need to access the browser's local storage to store the login status of our users. While the contents of the web app are being generated on the server, the localStorage will not be available for use, thereby causing errors in our app. To fix that, we will only render all our components only when they are available on the client side.&lt;/p&gt;

&lt;p&gt;So we created a new state called &lt;code&gt;isClient&lt;/code&gt; and initialized it with &lt;code&gt;false&lt;/code&gt; boolean value. In the &lt;code&gt;useEffect&lt;/code&gt; hook, we checked if the &lt;strong&gt;window object&lt;/strong&gt; was not &lt;code&gt;undefined&lt;/code&gt;. The &lt;strong&gt;window&lt;/strong&gt; object is only present on the client-side, once it is not undefined, we will change the &lt;code&gt;isClient&lt;/code&gt; boolean value to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the snippets below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; if (isClient) {
    return (
      &amp;lt;ApolloProvider client={client}&amp;gt;
        &amp;lt;Component {...pageProps} /&amp;gt;
      &amp;lt;/ApolloProvider&amp;gt;
    )
  }
return(
  &amp;lt;&amp;gt;
  &amp;lt;h1&amp;gt;Loading...&amp;lt;/h1&amp;gt;
  &amp;lt;/&amp;gt;
)

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

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;isClient&lt;/code&gt; boolean value is &lt;code&gt;true,&lt;/code&gt; we will render the pages wrapped in the &lt;code&gt;ApolloProvider&lt;/code&gt; component, which provides the &lt;code&gt;client&lt;/code&gt; object to the rest of the app via React's context API, otherwise, we'll render a loading text.&lt;/p&gt;

&lt;h1&gt;
  
  
  Updating the global styles
&lt;/h1&gt;

&lt;p&gt;I made some changes to the CSS file used in this project. Open the &lt;code&gt;styles/global.css&lt;/code&gt; file and overwrite everything in there with the following codes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: #F8FAFE;
  overflow: auto;

}

.main-container {
 min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.card, .delete-note-modal{
  width: 300px;
  height: 350px;
  background-color: #f9e675;
   box-shadow: 0 8px 16px 0 rgba(0,0,0,0.4); 
  border: 1px solid rgb(0, 0, 0,.5);
  margin: 1rem;
}
.delete-note-modal {
  text-align: center;
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  }
  .delete-note-modal h3 {
    margin: 0 0 1rem 0;
  }

  .delete-note-modal button {
    width: 90%;
    background-color: rgb(31, 15, 15);
  }
.card-maximized {
  width: 100%;
  height: 100%;
  background-color: #f9e675;
  box-shadow: 0 8px 16px 0 rgba(0,0,0,0.4);
  border: 1px solid rgb(0, 0, 0,.5);
  position: fixed;
  z-index: 10;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  top: 0;
}
.card-header {
 height: 10%;
}
.card-body {
  background-color: rgba(253, 253, 253, 0.4);
  height: 80%;
}

.text-area {
width: 100%;
height: 100%;
background-color: transparent;
border: none;
outline: none;
color: black;
z-index: 5;
resize: none;
}

.text-container{
width: 90%;
height: 100%;
margin: 0 auto;
}

.card-footer {
  width: 100%;
  height: 10%;
  border-top: 1px solid rgba(0, 0, 0, 0.4);
}

.icon-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 100%;
}

.right-icon, .left-icon {
    display: flex;
}

.icon {
  margin: 3px;
  color: black;
  padding: 5px 7px;
  cursor: pointer;
  opacity: .8;
  font-size: 1.2rem;
}

.icon:hover {
  background-color: rgba(10, 10, 9, 0.2);
  opacity: 1;
}

.theme-color-container {
  width: 100%;
  height: 100%;
  display: flex;
  background-color: black;
}

.theme-color:hover {
  opacity: .9;
  cursor: pointer;
}

.yellow, .green, .pink, .purple, .blue, .gray, .charcoal {
  width: 14.3%;

}

.yellow, #yellow {
background-color: #f9e675;
}

.green, #green {
  background-color: #b2ed9e ;
}
.pink, #pink {
  background-color: #f2b3e4;
}
.purple, #purple {
  background-color: #ceb1ff;
}
.blue, #blue {
  background-color: #addcfe;
}
.gray, #gray {
  background-color: #dcdee2;
}
.charcoal, #charcoal {
  background-color: #77797e;
}
.notes-container {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
align-items: flex-start;
}

.no-notes-container, .error-page-container{
  display: flex;
  flex-direction: column;
  width: 350px;
  margin: 3rem auto;
  align-items: center;
  border: 1px solid rgba(0, 0, 0, 0.2);
  padding: 3rem 1rem;
  box-shadow: 0 2px 4px 0 rgba(0,0,0,0.4);
  background-color: #f9e675;
  color: black;
  border-radius: 5px;
  text-align: center;
}
.no-notes-container button, .error-page-container button {
 background-color: #000000;
 border-radius: 5px;
}
.auth-container{
width: 350px;
margin: 2rem auto;
padding: 2rem;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.4);
background-color: white;
}

.auth-form{
flex-wrap: wrap;
display: flex;
width:320px;
margin: 0 auto;
justify-content: center;
}

input {
border: 1px solid black;
margin: .5rem;
padding: 1rem;
font-size: 1rem;
width:320px;
outline: none;
}

.auth-navbar{
  background-color: rgb(34, 32, 32);
  padding: 1rem;box-shadow: 0 2px 4px 0 rgba(0,0,0,0.4);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.auth-navbar h1{
  margin: 0;
  font-size: 1.3rem;
  padding-left: 1rem;
  color: white;
}
.auth-navbar h5{
  margin: 0;

}
.auth-navbar .menu {
  display: flex;
}

.auth-navbar .menu a{
  margin: 0;
  color: white;
  padding: 0 1rem;
  text-transform: uppercase;
  text-decoration: none;
}

.auth-navbar .menu a:hover {
  opacity: .8;
  cursor: pointer;
}

.welcome-text h2{
  text-align: center;
  text-transform: uppercase;
  margin: 2rem 0 0rem 0;
}

button {
  border: none;
  margin: .5rem;
  padding: 1rem;
  font-size: 1rem;
  width:320px;
  outline: none;
  background-color: blue;
  color: white;
  cursor: pointer;
}

button:hover {
  opacity: .7;
}
.logout-button{
  width: 80px;
  padding: .5rem;
  border-radius: 3px;
  margin: .1rem;
  font-size: .9rem;
}
.show-error{
  display: flex;
  flex-direction: column;
  align-items: center;
}
.show-error p {
  color: red;
  margin: 0;
  font-weight: 600;
}
.hide-error{
  display: none;
}
.error-icon {
margin:0;
color: red;
padding: .4rem;
}

.snackbar-container {
  min-width: 250px;
  background-color: rgb(29, 29, 32);
  color: #fff;
  text-align: center;
  border-radius: 2px;
  position: fixed;
  z-index: 1;
  right: 0%;
  bottom: 30px;
  font-size: 17px;
  padding: 0;
  margin-right: 30px;
  box-shadow: 0 8px 16px 0 rgba(0,0,0,0.4);
}
.hide{
  display: none;
}

 @media screen and (max-width: 468px) {
  .auth-container{
    width: 90%;
    padding: 2.5rem 0;
    }
    .auth-form {
      width:90%;
      }
      .auth-navbar h1{
        font-size: 1rem;
        padding-left: 0.5rem;
      }
      .auth-navbar .menu h5{
        font-size: .7rem;
      }
      .no-notes-container, .error-page-container{
        width: 80%;
      }
      .no-notes-container button, .error-page-container button {
        width: 80%;
       }
}

@media screen and (max-width: 280px) {
  .auth-container {
    width: 100%;
    }
} 

footer {
width: 100%;
left: 0;
bottom: 0;
background-color: black;
text-align: center;
color: white;
margin-top: 5rem;
}

footer p {
  padding: 2rem 0;
}
.loading-container{
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.loader{
  border: 5px solid #ffd900;
  border-top: 5px solid #000000;
  border-radius: 50%;
  width: 50px;
  height: 50px;
  animation: spin 2s linear infinite;
  margin: 0px;
  padding: 0;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Creating the &lt;code&gt;AuthNavigationBar&lt;/code&gt; Component
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;AuthNavigationBar&lt;/code&gt; component is the navigation bar that will be displayed on the sign up and login page. In the &lt;code&gt;components&lt;/code&gt; directory, create a new file called &lt;code&gt;AuthNavigationBar.tsx&lt;/code&gt; and type the following code into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Link from 'next/link'

const AuthNavigationbar = () =&amp;gt; {
    return (
        &amp;lt;&amp;gt;
        &amp;lt;div className="auth-navbar"&amp;gt;
        &amp;lt;h1&amp;gt;Sticky Note&amp;lt;/h1&amp;gt;
        &amp;lt;div className="menu"&amp;gt;
        &amp;lt;h5&amp;gt;&amp;lt;Link href="/sign-up"&amp;gt; Sign Up &amp;lt;/Link&amp;gt;&amp;lt;/h5&amp;gt;
        &amp;lt;h5&amp;gt;&amp;lt;Link href="/sign-in"&amp;gt; Log In &amp;lt;/Link&amp;gt;&amp;lt;/h5&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;/&amp;gt;
    )
}
export default AuthNavigationbar

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

&lt;/div&gt;



&lt;p&gt;We added two links to the navigation bar: &lt;code&gt;Sign Up&lt;/code&gt; and &lt;code&gt;Log In&lt;/code&gt;. We will create their corresponding pages very soon.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the &lt;code&gt;MainNavigationBar&lt;/code&gt; Component
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;MainNavigationBar&lt;/code&gt; component is the navigation bar that will be rendered on the main page after the user has been authenticated.&lt;/p&gt;

&lt;p&gt;To create the &lt;code&gt;MainNavigationBar&lt;/code&gt; component, locate &lt;code&gt;components&lt;/code&gt; directory, then create a new file called &lt;code&gt;MainNavigationBar.tsx&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const MainNavigationBar = () =&amp;gt; {
    return (
        &amp;lt;&amp;gt;
            &amp;lt;div className="auth-navbar"&amp;gt;
                &amp;lt;h1&amp;gt;Sticky Note&amp;lt;/h1&amp;gt;
                &amp;lt;div className="menu"&amp;gt;
                    &amp;lt;button className="logout-button"&amp;gt;Logout&amp;lt;/button&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/&amp;gt;
    )
}
export default MainNavigationBar

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;MainNavigationBar&lt;/code&gt; component has a logout button that does nothing for now. We will implement the logout feature toward the end of this tutorial.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the &lt;code&gt;ErrorPage&lt;/code&gt; Component
&lt;/h1&gt;

&lt;p&gt;When a user encounters an error on the website, the &lt;code&gt;ErrorPage&lt;/code&gt; component will be used to display an error message to the user.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;components&lt;/code&gt; directory, create a new file called &lt;code&gt;ErrorPage.tsx&lt;/code&gt; and type in the following code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ErrorPage = () =&amp;gt; {
    return (
        &amp;lt;&amp;gt;
        &amp;lt;section className="error-page-container"&amp;gt;
        &amp;lt;h3&amp;gt;An Error occured.&amp;lt;/h3&amp;gt;
        &amp;lt;button onClick={()=&amp;gt;window.location.reload()}&amp;gt; Reload Page &amp;lt;/button&amp;gt;
        &amp;lt;/section&amp;gt;
        &amp;lt;/&amp;gt;
    )
}

export default ErrorPage

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Creating the &lt;code&gt;Loading&lt;/code&gt; Component
&lt;/h1&gt;

&lt;p&gt;Create a new file called &lt;code&gt;Loading.tsx&lt;/code&gt; in the &lt;code&gt;components&lt;/code&gt; directory, and add the following code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Loading = () =&amp;gt; {
    return (
        &amp;lt;&amp;gt;
            &amp;lt;section className="loading-container"&amp;gt;
                &amp;lt;div className="loader"&amp;gt;&amp;lt;/div&amp;gt;
            &amp;lt;/section&amp;gt;
        &amp;lt;/&amp;gt;
    )
}

export default Loading;

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

&lt;/div&gt;



&lt;p&gt;The loading component will be displayed whenever the application is in the process of fetching all of the user's sticky notes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;note&lt;/code&gt; Mutations
&lt;/h1&gt;

&lt;p&gt;In GraphQL, a mutation is a type of operation that allows you to create, update, or delete data on the server. Mutations are used to modify data in a database or other persistent storage. In this part, we will create the mutations for &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;note&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before implementing those mutations, let's install &lt;code&gt;react-toastify&lt;/code&gt; by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add react-toastify

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;react-toastify&lt;/code&gt; library will be used to display notifications to the user. Once the installation is complete, open the &lt;code&gt;pages/_app.tsx&lt;/code&gt; file and import the &lt;code&gt;react-toastify&lt;/code&gt; css file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "react-toastify/dist/ReactToastify.css";

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating the &lt;code&gt;user&lt;/code&gt; Mutation
&lt;/h2&gt;

&lt;p&gt;At the root directory, create a new folder called &lt;code&gt;mutations&lt;/code&gt;. Open it up and create a new file called &lt;code&gt;users.ts&lt;/code&gt;. In the &lt;code&gt;user.ts&lt;/code&gt; file, add the following mutations to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { gql } from '@apollo/client';

export const SIGNUP_MUTATION = gql`
  mutation SignUp(
    $fullname: String!
    $email: String!
    $password: String!
    $username: String!
  ) {
    signupUser(
      data: {
        fullname: $fullname
        email: $email
        password: $password
        username: $username
      }
    ) {
      user{
        username
      }
    }
  }
`;

export const LOGIN_MUTATION = gql`
  mutation signin($usernameOrEmail: String!, $password: String!) {
    signinUser(data: { usernameOrEmail: $usernameOrEmail, password: $password }) {
      signupUser{
        username
      }
    }
  }
`;

export const LOGOUT_MUTATION = gql`
mutation signoutUser {
  signoutUser
}
`

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

&lt;/div&gt;



&lt;p&gt;We created three GraphQL mutations: &lt;code&gt;SIGNUP_MUTATION&lt;/code&gt;, &lt;code&gt;LOGIN_MUTATION&lt;/code&gt;, and &lt;code&gt;LOGOUT_MUTATION&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These mutations can be used to create a new user account, log in an existing user, and log out the current user, respectively.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SIGNUP_MUTATION&lt;/code&gt; mutation will be used to create a new user account with the given &lt;code&gt;fullname&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;, and &lt;code&gt;username&lt;/code&gt; data. It takes these four variables as input and passes them to the &lt;code&gt;signupUser&lt;/code&gt; mutation on the server, which creates a new user account with the provided data. The mutation returns the &lt;code&gt;username&lt;/code&gt; of the newly created user.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;LOGIN_MUTATION&lt;/code&gt; mutation will be used to log in an existing user with the given &lt;code&gt;usernameOrEmail&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt;. It passes these variables to the &lt;code&gt;signinUser&lt;/code&gt; mutation on the server, which authenticates the user and returns the &lt;code&gt;username&lt;/code&gt; of the logged in user. We can actually return more data if there's any need for them. The &lt;code&gt;username&lt;/code&gt; was only returned here because it will be used to welcome the user after registration or sign-in.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;LOGOUT_MUTATION&lt;/code&gt; mutation is used to log out the current user. It calls the &lt;code&gt;signoutUser&lt;/code&gt; mutation on the server, which logs out the user and removes the user's session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the &lt;code&gt;note&lt;/code&gt; Mutation
&lt;/h2&gt;

&lt;p&gt;Let's create another mutation for the notes. Inside the &lt;code&gt;mutation&lt;/code&gt; directory, create another file named &lt;code&gt;note.ts&lt;/code&gt;. Open it up and add the following mutations to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { gql } from '@apollo/client';

export const SAVE_NOTE = gql`
mutation newNote ($data: NoteData!) {
    newNote (data: $data) {
        color
        content
        id
    }
}
`
export const MODIFY_NOTE = gql `
mutation modifyNote ($data: NoteData!, $noteId: String!) {
    modifyNote (data: $data, noteId: $noteId) {
        color
        content
        id
    }
}
`
export const DELETE_NOTE = gql `
mutation deleteNote ($noteId: String!) {
    deleteNote (noteId: $noteId) {
        color
        content
        id
    }
}
`

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

&lt;/div&gt;



&lt;p&gt;We created three new mutations namely: &lt;code&gt;SAVE_NOTE&lt;/code&gt;, &lt;code&gt;MODIFY_NOTE&lt;/code&gt;, and &lt;code&gt;DELETE_NOTE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These mutations can be used to create a new sticky note, modify an existing sticky note, and delete an existing sticky note, respectively.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SAVE_NOTE&lt;/code&gt; mutation will be used to create a new sticky note with the given &lt;code&gt;data&lt;/code&gt;. It takes a single variable, &lt;code&gt;$data&lt;/code&gt;, as input and passes it to the &lt;code&gt;newNote&lt;/code&gt; mutation on the server, which creates a new sticky note with the provided data. The mutation returns the &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;id&lt;/code&gt; of the newly created sticky note.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;MODIFY_NOTE&lt;/code&gt; mutation will be used to modify an existing sticky note with the given &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;noteId&lt;/code&gt;. It takes these two variables as input and passes them to the &lt;code&gt;modifyNote&lt;/code&gt; mutation on the server, which modifies the sticky note with the provided data. The mutation returns the &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;id&lt;/code&gt; of the modified sticky note.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;DELETE_NOTE&lt;/code&gt; mutation will used to delete an existing sticky note with the given &lt;code&gt;noteId&lt;/code&gt;. It passes the &lt;code&gt;noteId&lt;/code&gt; variable to the &lt;code&gt;deleteNote&lt;/code&gt; mutation on the server, which deletes the sticky note with the provided &lt;code&gt;noteId&lt;/code&gt;. The mutation returns the &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;id&lt;/code&gt; of the deleted sticky note.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the &lt;code&gt;note&lt;/code&gt; Queries
&lt;/h1&gt;

&lt;p&gt;Next, we will create a query that will be used to fetch all the notes. Create another folder at the root directory of your project called &lt;code&gt;queries&lt;/code&gt;. After that, you will create a new file inside the folder named &lt;code&gt;note.ts&lt;/code&gt;. Open the file and add the following codes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import { gql } from '@apollo/client';

export const FETCH_ALL_NOTES = gql`
query allNotes {
    allNotes {
        color
        content
        id
        isSaved @client
        isMaximized @client
        isSaving @client
        isError @client
        isDeleteNoteConfirmationVisible @client
    }
}
`

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

&lt;/div&gt;



&lt;p&gt;We created a new GraphQL query called &lt;code&gt;FETCH_ALL_NOTES&lt;/code&gt; that will be used to fetch all of the sticky notes in the application.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;FETCH_ALL_NOTES&lt;/code&gt; query returns a list of all the sticky notes in the application, including their &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;id&lt;/code&gt;. It also includes several fields that are marked with the &lt;code&gt;@client&lt;/code&gt; directive, indicating that these fields are stored on the client and not returned by the server. The &lt;code&gt;isSaved&lt;/code&gt;, &lt;code&gt;isMaximized&lt;/code&gt;, &lt;code&gt;isSaving&lt;/code&gt;, &lt;code&gt;isError&lt;/code&gt;, and &lt;code&gt;isDeleteNoteConfirmationVisible&lt;/code&gt; fields are all client-side only fields that are used to store the state of the sticky notes in the client. We will be defining all these local-only fields in a moment,&lt;/p&gt;

&lt;p&gt;When the &lt;code&gt;FETCH_ALL_NOTES&lt;/code&gt; query is executed, it will request a list of all the sticky notes from the server and return the &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;id&lt;/code&gt; of each sticky note in the list. It will also include the client-side fields for each sticky note in the returned data.&lt;/p&gt;

&lt;h1&gt;
  
  
  Defining the local-only fields
&lt;/h1&gt;

&lt;p&gt;In Apollo Client, a &lt;strong&gt;local-only field&lt;/strong&gt; is a field that is defined in the client-side schema, but not in the server-side schema. This means that the field is not fetched from the server, but rather is used to store local data that is specific to the client. We'll be using these local-only fields to store and manage our local data instead of React state.&lt;/p&gt;

&lt;p&gt;To define the local-only fields, open the &lt;code&gt;cache.ts&lt;/code&gt; file and update it with the following codes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { InMemoryCache } from '@apollo/client';

export const cache: InMemoryCache = new InMemoryCache({
    typePolicies: {
       Note: {
         fields: {
           isMaximized:{
             read(isMaximized = false) {
               return isMaximized ;
             },
           },
           isDeleteNoteConfirmationVisible:{
            read(isDeleteNoteConfirmationVisible = false) {
              return isDeleteNoteConfirmationVisible ;
            },
          },
           isSaving:{
             read(isSaving = false) {
               return isSaving ;
             }
           },
            isError:{
             read(isError = false) {
               return isError ;
             }
           },
           isSaved:{
            read(isSaved = true) {
              return isSaved ;
            }
          } 
         }
       }
     }
})

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

&lt;/div&gt;



&lt;p&gt;We used the &lt;code&gt;typePolicies&lt;/code&gt; property of the &lt;code&gt;InMemoryCache&lt;/code&gt; object to define local-only fields. The &lt;code&gt;typePolicies&lt;/code&gt; property is an object that maps GraphQL type names to policy objects, which define the behavior for that type.&lt;/p&gt;

&lt;p&gt;In this case, the &lt;code&gt;typePolicies&lt;/code&gt; object includes a &lt;code&gt;Note&lt;/code&gt; field that defines custom caching behavior for &lt;code&gt;Note&lt;/code&gt; data in the cache.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Note&lt;/code&gt; type policy includes fields for &lt;code&gt;isMaximized&lt;/code&gt;, &lt;code&gt;isDeleteNoteConfirmationVisible&lt;/code&gt;, &lt;code&gt;isSaving&lt;/code&gt;, &lt;code&gt;isError&lt;/code&gt;, and &lt;code&gt;isSaved&lt;/code&gt;. Each of these fields has a &lt;a href="https://www.apollographql.com/docs/react/caching/cache-field-behavior/#the-read-function"&gt;&lt;code&gt;read&lt;/code&gt; function&lt;/a&gt; that specifies the default value for the field when it is not present in the cache. For example, the &lt;code&gt;isMaximized&lt;/code&gt; field has a default value of &lt;code&gt;false&lt;/code&gt;, and the &lt;code&gt;isSaved&lt;/code&gt; field has a default value of &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;read&lt;/code&gt; functions for these fields are called whenever a field is accessed in the cache. If the field is present in the cache, the value stored in the cache will be returned. If the field is not present in the cache, the default value specified in the &lt;code&gt;read&lt;/code&gt; function will be returned instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the &lt;code&gt;SignUp&lt;/code&gt; Component
&lt;/h2&gt;

&lt;p&gt;In the part, we will create a new component that will be used to register a new user. Navigate to the &lt;code&gt;components&lt;/code&gt; directory and create a new file called &lt;code&gt;SignUp.tsx&lt;/code&gt;. Open it up, then add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, ChangeEvent, FormEvent, useEffect } from 'react'
import Footer from './Footer'
import AuthNavigationbar from './AuthNavigationBar';
import { useMutation } from '@apollo/client';
import { ToastContainer, toast } from "react-toastify";
import { SIGNUP_MUTATION } from '../mutations/user';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSpinner } from '@fortawesome/free-solid-svg-icons';
import { useRouter } from 'next/router'
const SignUp = () =&amp;gt; {
const [signup, { loading, data, error }] = useMutation(SIGNUP_MUTATION);
const router = useRouter();
  const [userInputs, setUserInputs] = useState({})
  useEffect(() =&amp;gt; {
     if (data) {
       setTimeout(() =&amp;gt; router.push('/'), 3000);
       localStorage.setItem("isLoggedIn", 'true');
       const {username} = data.signupUser.user
      toast.success(`Welcome, ${username}!`, {
        position: "bottom-center"
      });
    }
    if (error) {
      toast.error('' + error, {
        position: "bottom-center",
        autoClose: false
      });
    }
 },[data, error, router]);
  const saveUserInputs = (event: ChangeEvent&amp;lt;HTMLInputElement&amp;gt;) =&amp;gt; {
    setUserInputs({ ...userInputs, [event.target.name]: event.target.value });
  }

  const handleFormSubmit = async (event: FormEvent) =&amp;gt; {
    event.preventDefault()
    await signup({
      variables: userInputs
    });
  };

  return (
    &amp;lt;&amp;gt;
      &amp;lt;section className='main-container'&amp;gt;
        &amp;lt;AuthNavigationbar /&amp;gt;
        &amp;lt;ToastContainer /&amp;gt;
        &amp;lt;div className="auth-container"&amp;gt;
          &amp;lt;form className="auth-form"&amp;gt;
            &amp;lt;h3&amp;gt;Create Acount&amp;lt;/h3&amp;gt;
            &amp;lt;input type='text' name="fullname" placeholder="fullname" onChange={(event) =&amp;gt; saveUserInputs(event)} minLength={4} /&amp;gt;
            &amp;lt;input type='text' name="username" placeholder="username" onChange={(event) =&amp;gt; saveUserInputs(event)} minLength={3} /&amp;gt;
            &amp;lt;input type='email' name="email" placeholder="email" onChange={(event) =&amp;gt; saveUserInputs(event)} required /&amp;gt;
            &amp;lt;input type='password' name="password" placeholder="password" onChange={(event) =&amp;gt; saveUserInputs(event)} minLength={5} /&amp;gt;
            &amp;lt;button disabled={loading} onClick={(event) =&amp;gt; handleFormSubmit(event)}&amp;gt;{loading?&amp;lt;FontAwesomeIcon icon={faSpinner} spin size="1x"/&amp;gt;:"Create Account"}&amp;lt;/button&amp;gt;
          &amp;lt;/form&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;Footer /&amp;gt;
      &amp;lt;/section&amp;gt;
    &amp;lt;/&amp;gt;

  )
}
export default SignUp

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

&lt;/div&gt;



&lt;p&gt;We created a new component called &lt;code&gt;SignUp&lt;/code&gt; that contains a form that will be used to collect the following user's data: &lt;code&gt;fullname&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, and &lt;code&gt;password&lt;/code&gt;. We also render the &lt;code&gt;AuthNavigationbar&lt;/code&gt;, &lt;code&gt;ToastContainer&lt;/code&gt; and &lt;code&gt;Footer&lt;/code&gt; components inside it. The &lt;code&gt;ToastContainer&lt;/code&gt; will be used to display some notifications to the user.&lt;/p&gt;

&lt;p&gt;Once a user clicks on the &lt;code&gt;Create Account&lt;/code&gt; button, the &lt;code&gt;handleFormSubmit()&lt;/code&gt; function will be invoked. The &lt;code&gt;handleFormSubmit()&lt;/code&gt; function will execute the &lt;code&gt;signup&lt;/code&gt; mutation function which takes in the &lt;code&gt;userInputs&lt;/code&gt; object as arguments.&lt;/p&gt;

&lt;p&gt;In the following snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [signup, { loading, data, error }] = useMutation(SIGNUP_MUTATION);

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

&lt;/div&gt;



&lt;p&gt;We used the &lt;code&gt;useMutation&lt;/code&gt; hook to execute the &lt;code&gt;SIGNUP_MUTATION&lt;/code&gt;. The &lt;code&gt;useMutation&lt;/code&gt; hook returns an object with several properties such as &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, etc and a function that can be used to execute the mutation, we named this function &lt;code&gt;signup&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the code below, we disabled the button and then displayed the &lt;code&gt;spinner&lt;/code&gt; icon instead of the &lt;code&gt;Create Account&lt;/code&gt; text on it when the &lt;code&gt;loading&lt;/code&gt; value is &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Truthy#"&gt;truthy&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button disabled={loading} onClick={(event) =&amp;gt; handleFormSubmit(event)}&amp;gt;{loading?&amp;lt;FontAwesomeIcon icon={faSpinner} spin size="1x"/&amp;gt;:"Create Account"}&amp;lt;/button&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;In the code below, we used the &lt;code&gt;react-toastify&lt;/code&gt; library to display an &lt;code&gt;error&lt;/code&gt; notification message if an error is encountered while running the &lt;code&gt;signup&lt;/code&gt; mutation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (error) { toast.error('' + error, { position: "bottom-center", autoClose: false }); }

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

&lt;/div&gt;



&lt;p&gt;In the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (data) { setTimeout(() =&amp;gt; router.push('/'), 3000); localStorage.setItem("isLoggedIn", 'true'); 
const {username} = data.signupUser.user;
toast.success(`Welcome, ${username}!`, { position: "bottom-center" }); 
}

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

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;data&lt;/code&gt; returns a &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Truthy#"&gt;truthy&lt;/a&gt; value, that means the mutation was successfully executed. We used the &lt;code&gt;react-toastify&lt;/code&gt; library to welcome the user using the &lt;code&gt;username&lt;/code&gt; returned from the execution of the &lt;code&gt;SIGNUP_MUTATION&lt;/code&gt; query and redirect the user to the homepage after three seconds.&lt;/p&gt;

&lt;p&gt;We saved the user's login status (&lt;code&gt;isLoggedIn&lt;/code&gt;) to the localStorage. We will update the &lt;code&gt;_app.tsx&lt;/code&gt; file to redirect the user straight to the homepage the next time they visit the website if the &lt;code&gt;isLoggedIn&lt;/code&gt; status of the user is true. We will also create a &lt;code&gt;logout()&lt;/code&gt; function that will change the &lt;code&gt;isLoggedIn&lt;/code&gt; status to false once the user signs out. If the user's token has expired and the &lt;code&gt;isLoggedIn&lt;/code&gt; value is &lt;code&gt;true&lt;/code&gt;, we will redirect the user back to the login page and change the &lt;code&gt;isLoggedIn&lt;/code&gt; value to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the &lt;code&gt;SignUp&lt;/code&gt; Page
&lt;/h3&gt;

&lt;p&gt;To create the &lt;code&gt;SignUp&lt;/code&gt; page in our Next.js app, we need to create a new file in the &lt;code&gt;pages&lt;/code&gt; directory of our project called &lt;code&gt;sign-up.tsx&lt;/code&gt;. Open the &lt;code&gt;sign-up.tsx&lt;/code&gt; file, then import and render the &lt;code&gt;SignUp&lt;/code&gt; component in it like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import SignUp from "../components/SignUp"
const SignUpPage = () =&amp;gt; {
  return (
    &amp;lt;&amp;gt;
      &amp;lt;SignUp /&amp;gt;
    &amp;lt;/&amp;gt;

  )
}
export default SignUpPage

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

&lt;/div&gt;



&lt;p&gt;When the &lt;code&gt;sign-up.tsx&lt;/code&gt; page is rendered by Next.js, the &lt;code&gt;SignUpPage&lt;/code&gt; component will be rendered to the page, which will in turn render the &lt;code&gt;SignUp&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Now you can navigate to &lt;code&gt;http://localhost:3000/sign-up&lt;/code&gt; on your browser to view the signup page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the &lt;code&gt;SignIn&lt;/code&gt; Component
&lt;/h2&gt;

&lt;p&gt;Inside the &lt;code&gt;components&lt;/code&gt; directory, create a new file named &lt;code&gt;SignIn.tsx&lt;/code&gt; and add the following code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useMutation } from '@apollo/client'
import { faSpinner } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import router from 'next/router'
import { useState, ChangeEvent, FormEvent, useEffect } from 'react'
import { toast, ToastContainer } from 'react-toastify'
import { LOGIN_MUTATION } from '../mutations/user'
import AuthNavigationBar from './AuthNavigationBar'
import Footer from './Footer'

const SignIn = () =&amp;gt; {
  const [userInputs, setUserInputs] = useState({})
  const [login, { loading, data, error }] = useMutation(LOGIN_MUTATION);
  useEffect(() =&amp;gt; {
    if (error) {
      toast.error('' + error, {
        position: "bottom-center",
        autoClose: false
      });
    }
    if (data) {
      console.log(data)
      const {username} = data.signinUser.user
      localStorage.setItem("isLoggedIn", 'true');
      setTimeout(() =&amp;gt; router.push('/'), 3000);
      toast.success(`Welcome back, ${username}`, {
        position: "bottom-center"
      });
    }
  }, [data, error]);
  const saveUserInputs = (event: ChangeEvent&amp;lt;HTMLInputElement&amp;gt;) =&amp;gt; {
    setUserInputs({ ...userInputs, [event.target.name]: event.target.value })
  }

  const handleFormSubmit = async (event: FormEvent) =&amp;gt; {
    event.preventDefault()
    await login({
      variables: userInputs
    });
  };

  return (
    &amp;lt;&amp;gt;
      &amp;lt;section className='main-container'&amp;gt;
        &amp;lt;AuthNavigationBar /&amp;gt;
        &amp;lt;ToastContainer /&amp;gt;
        &amp;lt;div className="auth-container"&amp;gt;
          &amp;lt;form className="auth-form"&amp;gt;
            &amp;lt;h3&amp;gt;Sign In&amp;lt;/h3&amp;gt;
            &amp;lt;input type='text' name="usernameOrEmail" placeholder="Username or Email" onChange={(event) =&amp;gt; saveUserInputs(event)} required /&amp;gt;
            &amp;lt;input type='password' name="password" placeholder="Password" onChange={(e) =&amp;gt; saveUserInputs(e)} required /&amp;gt;
            &amp;lt;button disabled={loading} onClick={(event) =&amp;gt; handleFormSubmit(event)}&amp;gt; {loading ? &amp;lt;FontAwesomeIcon icon={faSpinner} spin size="1x" /&amp;gt; : "Login"}&amp;lt;/button&amp;gt;
          &amp;lt;/form&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;Footer /&amp;gt;
      &amp;lt;/section&amp;gt;
    &amp;lt;/&amp;gt;
  )
}
export default SignIn

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

&lt;/div&gt;



&lt;p&gt;First, we created a new mutate function called &lt;code&gt;login&lt;/code&gt; that will be used to execute our &lt;code&gt;LOGIN_MUTATION&lt;/code&gt; anytime it is invoked. Then we rendered an input form that will be used to collect the user's &lt;code&gt;usernameOrEmail&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; data. After that, we created a function named &lt;code&gt;handleFormSubmit&lt;/code&gt;. The &lt;code&gt;handleFormSubmit&lt;/code&gt; will call the &lt;code&gt;login&lt;/code&gt; function any time it is invoked. We will call the &lt;code&gt;handleFormSubmit&lt;/code&gt; function any time the &lt;code&gt;Login&lt;/code&gt; button is clicked. The &lt;code&gt;useMutation&lt;/code&gt; hooks returns the following properties: &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and &lt;code&gt;data&lt;/code&gt; that will be used to track the &lt;strong&gt;mutate function&lt;/strong&gt; (&lt;code&gt;login&lt;/code&gt;) state. Just like we did in the &lt;code&gt;SignUp&lt;/code&gt; component, if the &lt;code&gt;loading&lt;/code&gt; status value is &lt;code&gt;truthy&lt;/code&gt; we'll display the font awesome spinner &lt;code&gt;icon&lt;/code&gt; on the button instead of the "Login" text.&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;error&lt;/code&gt; value is truthy, we'll display the error notification using the &lt;code&gt;react-toastify&lt;/code&gt; library, and if the &lt;code&gt;data&lt;/code&gt; value if &lt;code&gt;truthy&lt;/code&gt;, a success notification will be displayed, welcoming the user again with the &lt;code&gt;username&lt;/code&gt; returned from the &lt;code&gt;mutation&lt;/code&gt; function. Then the user will be redirected to the homepage after three seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the &lt;code&gt;sign-in&lt;/code&gt; Page
&lt;/h3&gt;

&lt;p&gt;Let's create a new file named &lt;code&gt;sign-in.ts&lt;/code&gt; in the &lt;code&gt;page&lt;/code&gt; directory, just like we did with the &lt;code&gt;sign-up&lt;/code&gt; page. We will import and render the &lt;code&gt;SignIn&lt;/code&gt; component in it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import SignIn from "../components/SignIn"

const SignInPage = () =&amp;gt; {

  return (
    &amp;lt;&amp;gt;
      &amp;lt;SignIn /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}
export default SignInPage

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

&lt;/div&gt;



&lt;p&gt;When the &lt;code&gt;sign-in.tsx&lt;/code&gt; page is rendered by Next.js, the &lt;code&gt;SignInPage&lt;/code&gt; component will be rendered to the page, which will in turn render the &lt;code&gt;SignIn&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Now you can navigate to &lt;code&gt;http://localhost:3000/sign-in&lt;/code&gt; on your browser to view the sign in page.&lt;/p&gt;

&lt;h1&gt;
  
  
  Updating Home Page
&lt;/h1&gt;

&lt;p&gt;Let's update the homepage to render the &lt;code&gt;NoteContainer&lt;/code&gt; if the &lt;code&gt;isLoggedIn&lt;/code&gt; value in the localStorage is true. But if the &lt;code&gt;isLoggedIn&lt;/code&gt; value is false, then the user will be redirected to the login page. Navigate to &lt;code&gt;pages/index.ts&lt;/code&gt; file and open it, and update it with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import NoteContainer from "../components/NoteContainer";
import SignIn from "../components/SignIn";

function HomePage() {
  const isLoggedIn = localStorage.getItem("isLoggedIn");
    if(isLoggedIn === 'true'){
      return &amp;lt;NoteContainer /&amp;gt;
    }
  return &amp;lt;SignIn /&amp;gt;
}

export default HomePage

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Updating the &lt;code&gt;INoteCardProps&lt;/code&gt; Interface
&lt;/h1&gt;

&lt;p&gt;Update the &lt;code&gt;INoteCardProps&lt;/code&gt; interface in the &lt;code&gt;typings/index.ts&lt;/code&gt; file to include the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;saveUserNote(id: string, color: Theme, contents: string, isSaved: boolean): Promise;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;deleteNote(noteId: string, isSaved:boolean): void;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;color:Theme;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;createNote(noteId: string): void;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything should be looking like this now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface INoteCardProps {
    createNote(noteId?: string): void;
    id:string;
    color:Theme;
    isMaximized:boolean;
    contents: string;
    isSaved: boolean;
    isSaving: boolean;
    isError: boolean;
    changeColor(id:string, color:Theme): void;
    toggleFullscreen(noteId:string):void;
    isDeleteNoteConfirmationVisible:boolean,
    toggleDeleteNoteConfirmationMessage(id:string):void;
    deleteNote(noteId: string, isSaved:boolean): void;
    saveUserNote(id: string, color: Theme, contents: string, isSaved: boolean): Promise&amp;lt;void&amp;gt;;
}

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Defining the &lt;code&gt;IAllNoteData&lt;/code&gt; interfaces
&lt;/h1&gt;

&lt;p&gt;Let's create a new file called:&lt;code&gt;IAllNoteData.&lt;/code&gt; We will use this type to define our query result.&lt;/p&gt;

&lt;p&gt;Let's open up the &lt;code&gt;typings/index.ts&lt;/code&gt; file and create a interface called &lt;code&gt;IAllNoteData&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  export interface IAllNoteData {
    allNotes:INote[] 
  }

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;IAllNoteData&lt;/code&gt; represents data for a collection of notes. It has a single property, &lt;code&gt;allNotes&lt;/code&gt;, which is an array of objects that implement the &lt;code&gt;INote&lt;/code&gt; interface.&lt;/p&gt;

&lt;h1&gt;
  
  
  Updating the &lt;code&gt;NoteCard&lt;/code&gt; component
&lt;/h1&gt;

&lt;p&gt;As discussed in the first part of this article, the &lt;code&gt;NoteCard&lt;/code&gt; component is a child component to &lt;code&gt;NoteContainer&lt;/code&gt; component. It will be used as a template to render all the sticky note that belongs to a user.&lt;/p&gt;

&lt;p&gt;Before we proceed, let's first update the &lt;code&gt;NoteCard.tsx&lt;/code&gt; file with the following code, which includes some changes to the original code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlus, faWindowMaximize, faTrash, faSave, faExclamationTriangle, faSpinner, faCheck } from '@fortawesome/free-solid-svg-icons'
import { ChangeEvent, useState } from 'react';
import { INoteCardProps, Theme } from '../typings';

const NoteCard: React.FC&amp;lt;INoteCardProps&amp;gt; = (props) =&amp;gt; {
const [noteContents, setNoteContents] = useState('');

const changeNoteColor = (id:string, color:Theme) =&amp;gt; {
    props.changeColor(id, color);
    props.saveUserNote(id, color, noteContents||props.contents, props.isSaved)
}

    let timer:NodeJS.Timeout;
    const handleContentChange = (event: ChangeEvent&amp;lt;HTMLTextAreaElement&amp;gt;) =&amp;gt; {
        clearTimeout(timer)
        const newTimer: NodeJS.Timeout = setTimeout(() =&amp;gt; {
            setNoteContents(event.target.value)
            props.saveUserNote(props.id, props.color, event.target.value, props.isSaved)
        }, 2000)
        timer = newTimer;
    }

    if (props.isDeleteNoteConfirmationVisible) {
        return (
            &amp;lt;section className="delete-note-modal" id={props.color}&amp;gt;
                &amp;lt;h3&amp;gt;This note will be permanently deleted, continue?&amp;lt;/h3&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;button onClick={() =&amp;gt; props.deleteNote(props.id, props.isSaved)}&amp;gt; Yes &amp;lt;/button&amp;gt;
                    &amp;lt;button onClick={() =&amp;gt; props.toggleDeleteNoteConfirmationMessage(props.id)}&amp;gt; No&amp;lt;/button&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/section&amp;gt;
        )
    }
    return (
        &amp;lt;&amp;gt;
            &amp;lt;div className={props.isMaximized ? "card-maximized" : "card"} id={props.color}&amp;gt;
                &amp;lt;div className="card-header"&amp;gt;
                    &amp;lt;div className="icon-container"&amp;gt;
                        &amp;lt;div className="left-icon"&amp;gt;
                            &amp;lt;div className="icon" onClick={() =&amp;gt; props.createNote(props.id)}&amp;gt;{props.isMaximized ?null:&amp;lt;FontAwesomeIcon icon={faPlus} /&amp;gt;}&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" &amp;gt;{props.isSaving ? &amp;lt;FontAwesomeIcon icon={faSpinner} spin /&amp;gt;:props.isError ? &amp;lt;FontAwesomeIcon icon={faExclamationTriangle} /&amp;gt;:props.isSaved ? &amp;lt;FontAwesomeIcon icon={faCheck} /&amp;gt; : null}&amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                        &amp;lt;div className="right-icon"&amp;gt;
                            &amp;lt;div className="icon" onClick={() =&amp;gt; props.toggleDeleteNoteConfirmationMessage(props.id)} &amp;gt;{props.isMaximized ?null:&amp;lt;FontAwesomeIcon icon={faTrash} /&amp;gt; }&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" onClick={()=&amp;gt;props.saveUserNote(props.id, props.color, noteContents||props.contents, props.isSaved)}&amp;gt;&amp;lt;FontAwesomeIcon icon={faSave} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" onClick={() =&amp;gt; props.toggleFullscreen(props.id)}&amp;gt;&amp;lt;FontAwesomeIcon icon={faWindowMaximize} /&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div className="card-body"&amp;gt;
                    &amp;lt;div className="text-container"&amp;gt;
                        &amp;lt;textarea defaultValue={props.contents} onChange={(e) =&amp;gt; handleContentChange(e)} className="text-area"&amp;gt;&amp;lt;/textarea&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div className="card-footer"&amp;gt;
                    &amp;lt;div className="theme-color-container"&amp;gt;
                        &amp;lt;div className="theme-color yellow" onClick={() =&amp;gt; changeNoteColor(props.id, Theme.Yellow)} &amp;gt; &amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color green" onClick={() =&amp;gt;changeNoteColor(props.id, Theme.Green)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color pink" onClick={() =&amp;gt; changeNoteColor(props.id, Theme.Pink)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color purple" onClick={() =&amp;gt; changeNoteColor(props.id, Theme.Purple)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color blue" onClick={() =&amp;gt; changeNoteColor(props.id, Theme.Blue)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color gray" onClick={() =&amp;gt; changeNoteColor(props.id, Theme.Gray)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color charcoal" onClick={() =&amp;gt; changeNoteColor(props.id, Theme.Charcoal)}&amp;gt;&amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/&amp;gt;
    )
}
export default NoteCard

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Breaking down the &lt;code&gt;NoteCard&lt;/code&gt; Component
&lt;/h2&gt;

&lt;p&gt;In the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                &amp;lt;div className="card-body"&amp;gt;
                    &amp;lt;div className="text-container"&amp;gt;
                        &amp;lt;textarea defaultValue={props.contents}
                            onChange={(e) =&amp;gt; handleContentChange(e)}
                            className="text-area"&amp;gt;&amp;lt;/textarea&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;We created the sticky note body, which is made up of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea"&gt;HTML &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; element&lt;/a&gt;. Anytime there's a change in the Textarea, the &lt;code&gt;handleContentChange&lt;/code&gt; function will be invoked.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;setTimeout&lt;/code&gt; method in the &lt;code&gt;handleContentChange()&lt;/code&gt; function is used in the following snippets to automatically save a sticky note if the user stops typing after two seconds by calling the &lt;code&gt;saveUserNote&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   let timer:NodeJS.Timeout;
    const handleContentChange = (event: ChangeEvent&amp;lt;HTMLTextAreaElement&amp;gt;) =&amp;gt; {
        clearTimeout(timer)
        const newTimer: NodeJS.Timeout = setTimeout(() =&amp;gt; {
            setNoteContents(event.target.value)
            props.saveUserNote(props.id, props.color, event.target.value, props.isSaved)
        }, 2000)
        timer = newTimer;
    }

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

&lt;/div&gt;



&lt;p&gt;If the user did not wait for 2 seconds before typing the next letter, the previous counter is cleared and another timer will start counting the moment the user starts typing again.&lt;/p&gt;

&lt;p&gt;The following snippets will call the &lt;code&gt;changeColor&lt;/code&gt; function in the &lt;code&gt;NoteContainer&lt;/code&gt; component with the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;color&lt;/code&gt; of the selected sticky note:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const changeNoteColor = (id:string, color:Theme) =&amp;gt; {
    props.changeColor(id, color);
    props.saveUserNote(id, color, noteContents||props.contents, props.isSaved)
}

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;changeNoteColor&lt;/code&gt; function will be invoked any time the user clicks on any theme color on the sticky note:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;changeNoteColor(props.id, Theme.Yellow)} &amp;gt;

changeNoteColor(props.id, Theme.Green)}&amp;gt;

 changeNoteColor(props.id, Theme.Pink)}&amp;gt;

 changeNoteColor(props.id, Theme.Purple)}&amp;gt;

 changeNoteColor(props.id, Theme.Blue)}&amp;gt;

 changeNoteColor(props.id, Theme.Gray)}&amp;gt;

 changeNoteColor(props.id, Theme.Charcoal)}&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;"The following code was used to toggle the class of the element between &lt;code&gt;card-maximized&lt;/code&gt; and &lt;code&gt;card&lt;/code&gt; based on the value of the &lt;code&gt;isMaximized&lt;/code&gt; boolean: "&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;div className={props.isMaximized ? "card-maximized" : "card"} id={props.color}&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;In the following snippets, we render the &lt;code&gt;faPlus&lt;/code&gt;, &lt;code&gt;faSpinner&lt;/code&gt;,&lt;code&gt;faExclamationTriangle&lt;/code&gt;, &lt;code&gt;faTrash&lt;/code&gt;, &lt;code&gt;faSave&lt;/code&gt;, &lt;code&gt;faWindowMaximize&lt;/code&gt;, &lt;code&gt;faCheck&lt;/code&gt; icons on the sticky notes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;div className="icon-container"&amp;gt;
                        &amp;lt;div className="left-icon"&amp;gt;
                            &amp;lt;div className="icon" onClick={() =&amp;gt; props.createNote(props.id)}&amp;gt;{props.isMaximized ?null:&amp;lt;FontAwesomeIcon icon={faPlus} /&amp;gt;}&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" &amp;gt;{props.isSaving ? &amp;lt;FontAwesomeIcon icon={faSpinner} spin /&amp;gt;:props.isError ? &amp;lt;FontAwesomeIcon icon={faExclamationTriangle} /&amp;gt;:props.isSaved ? &amp;lt;FontAwesomeIcon icon={faCheck} /&amp;gt; : null}&amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                        &amp;lt;div className="right-icon"&amp;gt;
                            &amp;lt;div className="icon" onClick={() =&amp;gt; props.toggleDeleteNoteConfirmationMessage(props.id)} &amp;gt;{props.isMaximized ?null:&amp;lt;FontAwesomeIcon icon={faTrash} /&amp;gt; }&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" onClick={()=&amp;gt;props.saveUserNote(props.id, props.color, noteContents||props.contents, props.isSaved)}&amp;gt;&amp;lt;FontAwesomeIcon icon={faSave} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" onClick={() =&amp;gt; props.toggleFullscreen(props.id)}&amp;gt;&amp;lt;FontAwesomeIcon icon={faWindowMaximize} /&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;faSave&lt;/code&gt; icon will be used to manually save a note once a user clicks on it, the icon will also be hidden whenever the sticky note is maximized.&lt;/p&gt;

&lt;p&gt;When the application is in the process of saving a sticky note, an icon representing a spinning circle (&lt;code&gt;faSpinner&lt;/code&gt;) will be shown to the user. If the note was saved successfully, the &lt;code&gt;faCheck&lt;/code&gt; icon will be displayed instead of the the &lt;code&gt;faSpinner&lt;/code&gt; icon. If there is an error while saving the note, the &lt;code&gt;faExclamationTriangle&lt;/code&gt; will be displayed.&lt;/p&gt;

&lt;p&gt;On the &lt;code&gt;right-icon&lt;/code&gt; section, whenever the &lt;code&gt;faTrash&lt;/code&gt; icon is clicked, the &lt;code&gt;toggleDeleteNoteConfirmationMessage&lt;/code&gt; function will be invoked, we'll talk more about all the functions soon.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;toggleFullscreen&lt;/code&gt; function will be called with the &lt;code&gt;id&lt;/code&gt; of the sticky note if a user clicks on the &lt;code&gt;faWindowMaximize&lt;/code&gt; icon.&lt;/p&gt;

&lt;h1&gt;
  
  
  Updating the &lt;code&gt;NoteContainer&lt;/code&gt; Component
&lt;/h1&gt;

&lt;p&gt;Let's update the &lt;code&gt;NoteContainer&lt;/code&gt; Component to render the &lt;code&gt;NoteCard&lt;/code&gt; with the latest changes.&lt;/p&gt;

&lt;p&gt;Replace the contents of the &lt;code&gt;components/NoteContainer.tsx&lt;/code&gt; file with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import NoteCard from "./NoteCard"
import MainNavigationBar from './MainNavigationBar';
import Footer from "./Footer";
import { FETCH_ALL_NOTES } from "../queries/note";
import { useMutation, useQuery } from "@apollo/client";
import client from "../client";
import { DELETE_NOTE, MODIFY_NOTE, SAVE_NOTE } from "../mutations/note";
import router from "next/router";
import Loading from "./Loading";
import ErrorPage from "./ErrorPage";
import { IAllNoteData, Theme } from "../typings";
import NoStickyNote from "./NoStickyNotes";
import { toast, ToastContainer } from 'react-toastify'

const NoteContainer = () =&amp;gt; {
  const { loading, error, data } = useQuery&amp;lt;IAllNoteData&amp;gt;(FETCH_ALL_NOTES);
  const [saveNote] = useMutation(SAVE_NOTE);
  const [modifyNote] = useMutation(MODIFY_NOTE);
  const [deleteNoteMutation] = useMutation(DELETE_NOTE);

  const createNote = (currentNoteId?: string) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const noteCopy = [...noteData!.allNotes];
    const currentNoteIndex: number = noteCopy.findIndex((note) =&amp;gt; note.id === currentNoteId);
    const emptyNote = {
      content: "",
      color: Theme.Yellow,
      id: `${Date.now()}`,
      isMaximized: false,
      isDeleteNoteConfirmationVisible: false,
      isSaved: false,
      isSaving: false,
      isError: true
    }
    noteCopy.splice(currentNoteIndex + 1, 0, emptyNote)
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: [...noteCopy],
      },
    });
  }

  const changeColor = (id: string, color: Theme) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const updatedNotes = noteData!.allNotes.map((note) =&amp;gt; {
      if (note.id === id) {
        return {
          ...note, color: color
        }
      }
      return note
    });

    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: updatedNotes
      },
    });
  }

  const toggleFullscreen = (id: string) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const updatedNote = noteData!.allNotes.map((note) =&amp;gt; {
      if (note.id === id) {
        return { ...note, isMaximized: !note.isMaximized }
      }
      return note
    })
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: updatedNote
      },
    });
  }

  const toggleDeleteNoteConfirmationMessage = (noteId: string) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const updatedNote = noteData!.allNotes.map((note) =&amp;gt; {
      if (note.id === noteId) {
        return { ...note, isDeleteNoteConfirmationVisible: !note.isDeleteNoteConfirmationVisible }
      }
      return note
    })
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: updatedNote
      },
    });
  }

  const showSavingNoteIcon = (id: string) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const updatedNote = noteData!.allNotes.map((note) =&amp;gt; {
      if (note.id === id) {
        return { ...note, isSaving: true }
      }
      return note
    })
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: updatedNote
      },
    });
  }
  const hideSavingNoteIcon = (id: string) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const updatedNote = noteData!.allNotes.map((note) =&amp;gt; {
      if (note.id === id) {
        return { ...note, isSaving: false }
      }
      return note
    })
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: updatedNote
      },
    });
  }

  const showErrorIcon = (id: string) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const updatedNote = noteData!.allNotes.map((note) =&amp;gt; {
      if (note.id === id) {
        return { ...note, isError: true }
      }
      return note
    })
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: updatedNote
      },
    });
  }

  const hideErrorIcon = (id: string) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const updatedNote = noteData!.allNotes.map((note) =&amp;gt; {
      if (note.id === id) {
        return { ...note, isError: false }
      }
      return note
    })
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: updatedNote
      },
    });
  }
  const deleteNote = async (noteId: string, isSaved: boolean) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const filteredNotes = noteData!.allNotes.filter((note) =&amp;gt; {
      return note.id !== noteId;
    })
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: filteredNotes
      },
    });
    if (isSaved) {
      await deleteNoteMutation({ variables: { noteId } });
    }
  }
  const saveUserNote = async (id: string, color: Theme, contents: string, isSaved: boolean) =&amp;gt; {
    try {
      if (isSaved) {
        showSavingNoteIcon(id);
        hideErrorIcon(id);
        await modifyNote({ variables: { data: { color, content: contents }, noteId: id } });
        hideSavingNoteIcon(id);
      }
      else {
        showSavingNoteIcon(id);
        hideErrorIcon(id);
        const savedNote = await saveNote({ variables: { data: { color, content: contents } } });
        hideSavingNoteIcon(id);
        const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
        const updatedNote = noteData!.allNotes.map((note) =&amp;gt; {
          if (note.id === id) {
            return { ...note, isSaved: true, id: savedNote.data.newNote.id, content: savedNote.data.newNote.content }
          }
          return note
        })
        client.writeQuery({
          query: FETCH_ALL_NOTES,
          data: {
            allNotes: updatedNote
          },
        });
      }
    }
    catch (error: any) {
      hideSavingNoteIcon(id);
      showErrorIcon(id);
      if (error.networkError?.message === "Response not successful: Received status code 401") {
        toast.error('Your session has expired. Kindly login again', {
          position: "bottom-center"
        });
        localStorage.setItem("isLoggedIn", 'false');
        router.push('/sign-in')
      }

    }
  }

  if (loading) {
    return (
      &amp;lt;&amp;gt;
        &amp;lt;Loading /&amp;gt;
      &amp;lt;/&amp;gt;
    )
  }
  if (error) {
    if (error.networkError?.message === "Response not successful: Received status code 401") {
      toast.error('Your session has expired. Kindly login again', {
        position: "bottom-center"
      });
      localStorage.setItem("isLoggedIn", 'false');
      router.push('/sign-in')
    }
    return (
      &amp;lt;&amp;gt;
        &amp;lt;section className='main-container'&amp;gt;
          &amp;lt;MainNavigationBar /&amp;gt;
          &amp;lt;ErrorPage /&amp;gt;
          &amp;lt;Footer /&amp;gt;
        &amp;lt;/section&amp;gt;
      &amp;lt;/&amp;gt;
    )
  }
  if (!data!.allNotes.length) {
    return (
      &amp;lt;&amp;gt;
        &amp;lt;section className='main-container'&amp;gt;
          &amp;lt;MainNavigationBar /&amp;gt;
          &amp;lt;NoStickyNote
            createNote={() =&amp;gt; createNote()}
          /&amp;gt;
          &amp;lt;Footer /&amp;gt;
        &amp;lt;/section&amp;gt;
      &amp;lt;/&amp;gt;
    )
  }
  return (&amp;lt;&amp;gt;
    &amp;lt;section className='main-container'&amp;gt;
      &amp;lt;MainNavigationBar /&amp;gt;
      &amp;lt;ToastContainer /&amp;gt;
      &amp;lt;section className="notes-container"&amp;gt;
        {data!.allNotes.map((eachNote) =&amp;gt; {
          return (
            &amp;lt;NoteCard
              createNote={createNote}
              key={eachNote.id}
              changeColor={changeColor}
              id={eachNote.id}
              color={eachNote.color}
              toggleFullscreen={toggleFullscreen}
              isMaximized={eachNote.isMaximized}
              deleteNote={deleteNote}
              toggleDeleteNoteConfirmationMessage={toggleDeleteNoteConfirmationMessage}
              isDeleteNoteConfirmationVisible={eachNote.isDeleteNoteConfirmationVisible}
              contents={eachNote.content}
              saveUserNote={saveUserNote}
              isSaved={eachNote.isSaved}
              isSaving={eachNote.isSaving}
              isError={eachNote.isError}
            /&amp;gt;
          )
        })
        }
      &amp;lt;/section&amp;gt;
      &amp;lt;Footer /&amp;gt;
    &amp;lt;/section&amp;gt;
  &amp;lt;/&amp;gt;
  )
}
export default NoteContainer

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Breaking Down the &lt;code&gt;NoteContainer&lt;/code&gt; component:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fetching and Rendering all the Sticky Notes
&lt;/h3&gt;

&lt;p&gt;Upon successful login, the first action performed is to retrieve all of the user's notes.&lt;/p&gt;

&lt;p&gt;The following query was used to retrieve all of the notes belonging to the user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { loading, error, data } = useQuery(FETCH_ALL_NOTES);

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;useQuery&lt;/code&gt; hook returns an object with &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and &lt;code&gt;data&lt;/code&gt; fields. While the &lt;code&gt;allNotes&lt;/code&gt; query is being fetched, the &lt;code&gt;Loading&lt;/code&gt; component will be rendered using the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  if (loading) {
    return (
      &amp;lt;&amp;gt;
        &amp;lt;Loading /&amp;gt;
      &amp;lt;/&amp;gt;
    )
  }

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

&lt;/div&gt;



&lt;p&gt;In the snippets below, if the &lt;code&gt;useQuery&lt;/code&gt; hooks encounters an error while retrieving the user's note, we check to see if the error was caused by an expired token and then redirect them to the login page; otherwise, the ErrorPage component is rendered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  if (error) {
    if (error.networkError?.message === "Response not successful: Received status code 401") {
      toast.error('Your session has expired. Kindly login again', {
        position: "bottom-center"
      });
      localStorage.setItem("isLoggedIn", 'false');
      router.push('/sign-in')
    }
    return (
      &amp;lt;&amp;gt;
        &amp;lt;section className='main-container'&amp;gt;
          &amp;lt;MainNavigationBar /&amp;gt;
          &amp;lt;ErrorPage /&amp;gt;
          &amp;lt;Footer /&amp;gt;
        &amp;lt;/section&amp;gt;
      &amp;lt;/&amp;gt;
    )
  }

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

&lt;/div&gt;



&lt;p&gt;What if the data was fetched but was empty because the user had not added any sticky notes? We've already created a component called &lt;code&gt;NoStickyNote&lt;/code&gt; that will be rendered to the screen. The &lt;code&gt;NoStickyNote&lt;/code&gt; component will render a text that informs the user that they do not have any sticky notes and a button to create a new sticky note.&lt;/p&gt;

&lt;p&gt;The following codes will be used to render the &lt;code&gt;NoStickyNote&lt;/code&gt; component if the &lt;code&gt;data.allNotes&lt;/code&gt; array is empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  if (!data!.allNotes.length) {
    return (
      &amp;lt;&amp;gt;
        &amp;lt;section className='main-container'&amp;gt;
          &amp;lt;MainNavigationBar /&amp;gt;
          &amp;lt;NoStickyNote
            createNote={() =&amp;gt; createNote()}
          /&amp;gt;
          &amp;lt;Footer /&amp;gt;
        &amp;lt;/section&amp;gt;
      &amp;lt;/&amp;gt;
    )
  }

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

&lt;/div&gt;



&lt;p&gt;Finally, the following snippet will be used to render all the user's notes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  return (&amp;lt;&amp;gt;
    &amp;lt;section className='main-container'&amp;gt;
      &amp;lt;MainNavigationBar /&amp;gt;
      &amp;lt;ToastContainer /&amp;gt;
      &amp;lt;section className="notes-container"&amp;gt;
        {data!.allNotes.map((eachNote) =&amp;gt; {
          return (
            &amp;lt;NoteCard
              createNote={createNote}
              key={eachNote.id}
              changeColor={changeColor}
              id={eachNote.id}
              color={eachNote.color}
              toggleFullscreen={toggleFullscreen}
              isMaximized={eachNote.isMaximized}
              deleteNote={deleteNote}
              toggleDeleteNoteConfirmationMessage={toggleDeleteNoteConfirmationMessage}
              isDeleteNoteConfirmationVisible={eachNote.isDeleteNoteConfirmationVisible}
              contents={eachNote.content}
              saveUserNote={saveUserNote}
              isSaved={eachNote.isSaved}
              isSaving={eachNote.isSaving}
              isError={eachNote.isError}
            /&amp;gt;
          )
        })
        }
      &amp;lt;/section&amp;gt;
      &amp;lt;Footer /&amp;gt;
    &amp;lt;/section&amp;gt;
  &amp;lt;/&amp;gt;
  )

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

&lt;/div&gt;



&lt;p&gt;We iterated through the &lt;code&gt;data.allNotes&lt;/code&gt; array using the &lt;code&gt;map()&lt;/code&gt; method, then used the &lt;code&gt;NoteCard&lt;/code&gt; component to render the &lt;code&gt;eachNote&lt;/code&gt; object in the &lt;code&gt;data.allNotes&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;NoteCard&lt;/code&gt; component is passed several props, including &lt;code&gt;createNote&lt;/code&gt;, &lt;code&gt;changeColor&lt;/code&gt;, &lt;code&gt;toggleFullscreen&lt;/code&gt;, &lt;code&gt;deleteNote&lt;/code&gt;, &lt;code&gt;toggleDeleteNoteConfirmationMessage&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;isMaximized&lt;/code&gt;, &lt;code&gt;isDeleteNoteConfirmationVisible&lt;/code&gt;, &lt;code&gt;contents&lt;/code&gt;, &lt;code&gt;saveUserNote&lt;/code&gt;, &lt;code&gt;isSaved&lt;/code&gt;, &lt;code&gt;isSaving&lt;/code&gt;, and &lt;code&gt;isError&lt;/code&gt;. These props are used to pass data and functions to the &lt;code&gt;NoteCard&lt;/code&gt; component that it can use to display and manipulate the sticky notes. A more detailed explanation of these props will be provided soon.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a new Sticky Note
&lt;/h3&gt;

&lt;p&gt;To create a new sticky note, we will call the &lt;code&gt;createNote()&lt;/code&gt; function in the &lt;code&gt;NoteContainer&lt;/code&gt; component. The &lt;code&gt;createNote()&lt;/code&gt; function has an optional parameter called &lt;code&gt;currentNoteId&lt;/code&gt;. Every sticky note has a &lt;code&gt;plus (+) icon&lt;/code&gt;, once a user click on the &lt;code&gt;icon&lt;/code&gt; we want a new sticky note to be created right beside it. The &lt;code&gt;id&lt;/code&gt; of the sticky note whose &lt;code&gt;plus icon&lt;/code&gt; is clicked is the &lt;code&gt;currentNoteId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We made the &lt;code&gt;currentNoteId&lt;/code&gt; parameter optional because sometimes the user does not have to click the &lt;code&gt;plus icon&lt;/code&gt; to create a new note. For example, when a user does not have a sticky note, the &lt;code&gt;NoStickyNotes&lt;/code&gt; component with a &lt;code&gt;Add New&lt;/code&gt; button will be rendered to the screen. Once the &lt;code&gt;Add New&lt;/code&gt; button is pressed we do not need the &lt;code&gt;currentNoteId&lt;/code&gt; parameter because the sticky note that will be created will be the first sticky note.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;createNote()&lt;/code&gt; function, we used the following line to read the cached data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });

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

&lt;/div&gt;



&lt;p&gt;After running the &lt;code&gt;FETCH_ALL_NOTES&lt;/code&gt; query to fetch all the user's notes, the result was stored into the &lt;code&gt;cache&lt;/code&gt; we created earlier. We used the &lt;code&gt;client.readQuery&lt;/code&gt; to read the current data of the &lt;code&gt;FETCH_ALL_NOTES&lt;/code&gt; GraphQL and store it into the &lt;code&gt;noteData&lt;/code&gt; variable. The type of &lt;code&gt;noteData&lt;/code&gt; is inferred to be &lt;code&gt;IAllNoteData&lt;/code&gt; from the type argument passed to &lt;code&gt;readQuery&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const noteCopy = [...noteData.allNotes];

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

&lt;/div&gt;



&lt;p&gt;We used the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_array_literals"&gt;spread operator&lt;/a&gt; to copy the &lt;code&gt;noteData&lt;/code&gt; and made modifications to the &lt;code&gt;noteCopy&lt;/code&gt; without touching the original result. Modifying the &lt;code&gt;noteData&lt;/code&gt; directly could lead to unexpected behavior in our application.&lt;/p&gt;

&lt;p&gt;We used the following code to get the index of the sticky note that the user clicks on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const currentNoteIndex: number = noteCopy.findIndex((note) =&amp;gt; note.id === currentNoteId);

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

&lt;/div&gt;



&lt;p&gt;Then we created a new json object called: &lt;code&gt;emptyNote&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const emptyNote = {
      content: "",
      color: Theme.Yellow,
      id: `${Date.now()}`,
      isMaximized: false,
      isDeleteNoteConfirmationVisible: false,
      isSaved: false,
      isSaving: false,
      isError: true
    }

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

&lt;/div&gt;



&lt;p&gt;This object will be used to initialize a new note.&lt;/p&gt;

&lt;p&gt;We used the following code to add a new note right beside the sticky note whose &lt;code&gt;plus&lt;/code&gt; icon was clicked on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;noteCopy.splice(currentNoteIndex + 1, 0, emptyNote)

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

&lt;/div&gt;



&lt;p&gt;Then we used the &lt;code&gt;client.writeQuery&lt;/code&gt; to update the &lt;code&gt;cache&lt;/code&gt; with the modified &lt;code&gt;noteCopy&lt;/code&gt; data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;client.writeQuery({ query: FETCH_ALL_NOTES, data: { allNotes: [...noteCopy], }, });

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Saving and Modifying the Sticky Notes
&lt;/h3&gt;

&lt;p&gt;Saving and modify the sticky notes is not a straight forward process. First, we have to check if the note has been saved before so that we can call the &lt;code&gt;MODIFY_NOTE&lt;/code&gt; mutation on it, but if the note has not been saved before, we'll make a request to the &lt;code&gt;SAVE_NOTE&lt;/code&gt; mutation instead.&lt;/p&gt;

&lt;p&gt;Two types of savings were also implemented here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;auto save and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;manual save.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The sticky note will be automatically saved two seconds after a user stops typing on it, and a user can also manually save the note by clicking the &lt;code&gt;save&lt;/code&gt; icon.&lt;/p&gt;

&lt;p&gt;To save the note automatically or manually, we will call the &lt;code&gt;saveUserNote()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;saveUserNote()&lt;/code&gt; function takes in the following parameter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;id&lt;/code&gt; : the &lt;code&gt;id&lt;/code&gt; of the sticky note to be saved&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;color&lt;/code&gt;: the &lt;code&gt;color&lt;/code&gt; of the note&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;contents&lt;/code&gt;: the note's content,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;isSaved&lt;/code&gt;: the &lt;code&gt;isSaved&lt;/code&gt; boolean will be used to check if the note has been saved or not.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the note has already been saved, that means we just have to modify it, which is exactly what the snippets below does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      if (isSaved) {
        showSavingNoteIcon(id);
        hideErrorIcon(id);
        await modifyNote({ variables: { data: { color, content: contents }, noteId: id } });
        hideSavingNoteIcon(id);
      }

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

&lt;/div&gt;



&lt;p&gt;We used the following mutations to modify a note:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await modifyNote({ variables: { data: { color, content: contents }, noteId: id } });

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

&lt;/div&gt;



&lt;p&gt;While while the mutation is being executed, we displayed the loading icon by calling the &lt;code&gt;showSavingNoteIcon(id)&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;We will call the &lt;code&gt;showErrorIcon(id)&lt;/code&gt; to dislay the error icon on the note if an error occured while modifying the note or call the &lt;code&gt;hideErrorIcon(id)&lt;/code&gt; function to clear the error if the error has been resolved.&lt;/p&gt;

&lt;p&gt;We will hide the loading icon after the execution is complete by calling &lt;code&gt;hideSavingNoteIcon(id)&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;If the sticky note has not been saved before, the following snippets will be executed instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       else {
        showSavingNoteIcon(id);
        hideErrorIcon(id);
        const savedNote = await saveNote({ variables: { data: { color, content: contents } } });
        hideSavingNoteIcon(id);
        const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
        const updatedNote = noteData!.allNotes.map((note) =&amp;gt; {
          if (note.id === id) {
            return { ...note, isSaved: true, id: savedNote.data.newNote.id, content: savedNote.data.newNote.content }
          }
          return note
        })
        client.writeQuery({
          query: FETCH_ALL_NOTES,
          data: {
            allNotes: updatedNote
          },
        });
      }

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

&lt;/div&gt;



&lt;p&gt;We display the saving icon and hide the error icon while the &lt;code&gt;saveNote&lt;/code&gt; mutation is being executed. Once the note has been successfully saved, we change the &lt;code&gt;id&lt;/code&gt; of the note from the temporary &lt;code&gt;id&lt;/code&gt; we were using before (i.e., the one generated by &lt;a href="http://date.Now"&gt;date.Now&lt;/a&gt;()) to the permanent &lt;code&gt;id&lt;/code&gt; generated from our GraphQL server. We also change the &lt;code&gt;isSaved&lt;/code&gt; boolean to &lt;code&gt;true&lt;/code&gt; and update the note content in the &lt;code&gt;cache&lt;/code&gt; with the saved note &lt;code&gt;content&lt;/code&gt; sent from the backend.&lt;/p&gt;

&lt;p&gt;If there are any errors while the note is being saved of or modified the following code will be executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    catch (error: any) {
      hideSavingNoteIcon(id);
      showErrorIcon(id);
      if (error.networkError?.message === "Response not successful: Received status code 401") {
        toast.error('Your session has expired. Kindly login again', {
          position: "bottom-center"
        });
        localStorage.setItem("isLoggedIn", 'false');
        router.push('/sign-in')
      }
    }

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

&lt;/div&gt;



&lt;p&gt;If the error message says "&lt;em&gt;Response not successful: Received status code 401&lt;/em&gt;" that means the user's session as expired. So we will log the user out and redirect the user to the login page, then hide the saving icon and display the error icon on the sticky note.&lt;/p&gt;

&lt;h3&gt;
  
  
  Changing the color of the notes
&lt;/h3&gt;

&lt;p&gt;We used the &lt;code&gt;changeColor()&lt;/code&gt; function to switch between the theme colors of a note. the function takes in two parameters: the &lt;code&gt;id&lt;/code&gt; of the note and the &lt;code&gt;color&lt;/code&gt; that the user want.&lt;/p&gt;

&lt;p&gt;We fetched all the sticky notes in the &lt;code&gt;cache&lt;/code&gt; by running the following query first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });

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

&lt;/div&gt;



&lt;p&gt;Then in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const updatedNotes = noteData!.allNotes.map((note) =&amp;gt; {
      if (note.id === id) {
        return {
          ...note, color: color
        }
      }
      return note
    });

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

&lt;/div&gt;



&lt;p&gt;We searched for the note that matched the note &lt;code&gt;id&lt;/code&gt; provided by the user using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"&gt;map()&lt;/a&gt; method, then changed the color to the color selected by the user. The &lt;code&gt;updatedNotes&lt;/code&gt; variable was then used to store the new array that was generated by the map function.&lt;/p&gt;

&lt;p&gt;The following snippets uses the &lt;code&gt;writeQuery&lt;/code&gt; method to update the &lt;code&gt;cache&lt;/code&gt; with the latest changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: updatedNotes
      },
    });

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Minimizing and Maximizing the sticky note
&lt;/h3&gt;

&lt;p&gt;To minimize and maximize a sticky note, we'll invoke the &lt;code&gt;toggleFullscreen(id)&lt;/code&gt; function. Here's what the &lt;code&gt;toggleFullscreen&lt;/code&gt; function looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const toggleFullscreen = (id: string) =&amp;gt; {
    const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const updatedNote = noteData!.allNotes.map((note) =&amp;gt; {
      if (note.id === id) {
        return { ...note, isMaximized: !note.isMaximized }
      }
      return note
    })
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: updatedNote
      },
    });
  }

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;toggleFullscreen&lt;/code&gt; function takes in the &lt;code&gt;id&lt;/code&gt; of the note that the user want to minimize or maximize then change its &lt;code&gt;isMaximized&lt;/code&gt; boolean value to the opposite of the previous value. That is, if the current boolean value of &lt;code&gt;isMaximized&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt; it changes it to &lt;code&gt;true&lt;/code&gt; and vice versa. Then modifies the &lt;code&gt;cache&lt;/code&gt; with the &lt;code&gt;updatedNote&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deleting a Sticky Note
&lt;/h3&gt;

&lt;p&gt;We called two functions to delete a sticky note, the &lt;code&gt;toggleDeleteNoteConfirmationMessage()&lt;/code&gt; and &lt;code&gt;deleteNote()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;We used the &lt;code&gt;deleteNote()&lt;/code&gt; function to permanently remove a user's note. But we just don't want to delete a note once the user presses the trash icon on the sticky note; we also want to confirm it first. That's why we called the &lt;code&gt;toggleDeleteNoteConfirmationMessage()&lt;/code&gt; function first. The &lt;code&gt;toggleDeleteNoteConfirmationMessage()&lt;/code&gt; will render a text asking the user to confirm their action by clicking on a &lt;code&gt;Yes&lt;/code&gt; or &lt;code&gt;No&lt;/code&gt; button. Once the user clicks on the &lt;code&gt;Yes&lt;/code&gt; button, the &lt;code&gt;deleteNote()&lt;/code&gt; function with the &lt;code&gt;id&lt;/code&gt; of the note will be invoked, but if the user clicks on the &lt;code&gt;No&lt;/code&gt; button, the confirmation message will be hidden.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;deleteNote&lt;/code&gt; function takes in two parameters, the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;isSaved&lt;/code&gt; value of the note. The following statement in the &lt;code&gt;deleteNote&lt;/code&gt; function searches for a note that matches the &lt;code&gt;id&lt;/code&gt; parameter in the cache and then deletes it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        const noteData = client.readQuery&amp;lt;IAllNoteData&amp;gt;({ query: FETCH_ALL_NOTES });
    const filteredNotes = noteData!.allNotes.filter((note) =&amp;gt; {
      return note.id !== noteId;
    })
    client.writeQuery({
      query: FETCH_ALL_NOTES,
      data: {
        allNotes: filteredNotes
      },
    });

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

&lt;/div&gt;



&lt;p&gt;This is okay if the note has not been saved into the database, and we just want to remove it from the &lt;code&gt;cache&lt;/code&gt;, but if the note has been saved, we need to execute a mutation that will delete the user's note from the database, that is what the following snippets does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    if (isSaved) {
      await deleteNoteMutation({ variables: { noteId } });
    }

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

&lt;/div&gt;



&lt;p&gt;The above statement will execute the query that will permanently delete the user's note from the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging Out the User
&lt;/h3&gt;

&lt;p&gt;To log the user out, we need to execute the &lt;code&gt;LOGOUT_MUTATION&lt;/code&gt; , clear the user data and redirect to login page. Open the &lt;code&gt;MainNavigationBar.tsx&lt;/code&gt; file in the components directory and update it with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import { LOGOUT_MUTATION } from "../mutations/users";
import { useMutation } from "@apollo/client";
import router from 'next/router';
import client from "../client";

const MainNavigationBar = () =&amp;gt; {
    const [signout] = useMutation(LOGOUT_MUTATION);

    const logout = () =&amp;gt; {
        localStorage.setItem("isLoggedIn", 'false');
        client.clearStore();
        client.cache.gc();
        router.push('/sign-in');
        signout();
    }
    return (
        &amp;lt;&amp;gt;
            &amp;lt;div className="auth-navbar"&amp;gt;
                &amp;lt;h1&amp;gt;Sticky Note&amp;lt;/h1&amp;gt;
                &amp;lt;div className="menu"&amp;gt;
                    &amp;lt;button onClick={logout} className="logout-button"&amp;gt;Logout&amp;lt;/button&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/&amp;gt;
    )
}
export default MainNavigationBar

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

&lt;/div&gt;



&lt;p&gt;We define a function called &lt;code&gt;logout.&lt;/code&gt; The function will be invoked anytime the logout button is clicked. Here's a brief explanation of what the function does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;sets the value of &lt;code&gt;isLoggedIn&lt;/code&gt; key in the browser's local storage to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;uses the &lt;code&gt;clearStore&lt;/code&gt; method to delete all the locally cached data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the &lt;code&gt;client.cache.gc()&lt;/code&gt; triggers garbage collection in the cache, which frees up memory by removing any unused data from memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;redirect the user to the login page&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>apolloclient</category>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Learn Fullstack Web Development with React and GraphQL by building a Sticky Note app - Part two</title>
      <dc:creator>Temitope</dc:creator>
      <pubDate>Mon, 09 Jan 2023 16:44:54 +0000</pubDate>
      <link>https://dev.to/kingdavid/learn-fullstack-web-development-with-react-and-graphql-by-building-a-sticky-note-app-part-two-3j8o</link>
      <guid>https://dev.to/kingdavid/learn-fullstack-web-development-with-react-and-graphql-by-building-a-sticky-note-app-part-two-3j8o</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello again! This article is the second part of a series titled, " &lt;strong&gt;Learn Fullstack Web Development with React and GraphQL by building a Sticky Note app&lt;/strong&gt;".&lt;/p&gt;

&lt;p&gt;In the first part of the series, we built the frontend aspect of this app using React and TypeScript.&lt;/p&gt;

&lt;p&gt;In this section, we will to build the backend using GraphQL, Apollo Server 4, Nexus, ExpressJS and MongoDB.&lt;/p&gt;

&lt;h2&gt;
  
  
  System Requirements
&lt;/h2&gt;

&lt;p&gt;Make sure you already have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="//nodejs.org"&gt;Nodejs&lt;/a&gt; v16 or later (This project uses v18.12.0)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VScode&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;This tutorial assumes knowledge of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JavaScript&lt;/strong&gt; : you are already familiar with ES6 features such as the fat arrow function and object destructuring&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TypeScript:&lt;/strong&gt; You have a little experience with TypeScript or at least know what TypeScript is and why it's being used in place of JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NPM:&lt;/strong&gt; You have used the Node Package Manager to install a library and perhaps also to run your code or start a server.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Tools
&lt;/h1&gt;

&lt;p&gt;We'll be using the following tools to build our GraphQL server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Nodejs&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mongoose&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expressjs&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Apollo Server&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Nexus&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Initializing the project
&lt;/h1&gt;

&lt;p&gt;Create a new folder called &lt;code&gt;sticky-notes-backend&lt;/code&gt; or you can give it any name you prefer. This folder will be used to store all the server files. Open your terminal, and navigate to the newly created folder, then run the following command:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Running the above command will initialize your project with &lt;strong&gt;NPM&lt;/strong&gt; and create &lt;code&gt;package.json&lt;/code&gt; file at the root directory of your project.&lt;/p&gt;

&lt;h1&gt;
  
  
  Installing TypeScript and &lt;code&gt;ts-node-dev&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TypeScript&lt;/strong&gt; is a strongly typed programming language that extends the capabilities of JavaScript with additional features and syntax. Since we are using it for our project, we need to install and configure it first. We also need to install the &lt;a href="https://www.npmjs.com/package/ts-node-dev" rel="noopener noreferrer"&gt;ts-node-dev&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ts-node-dev&lt;/code&gt; package will be used for two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;to transpile our TypeScript code to JavaScript before executing it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;to automatically restart the GraphQL dev server whenever a change is made to the code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Run the following command on your terminal to install them as dev dependencies:&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 typescript@^4.3.5 ts-node-dev@^1.1.8

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

&lt;/div&gt;



&lt;p&gt;After the installations, we'll create a new configuration file for TypeScript.&lt;/p&gt;

&lt;p&gt;In the root directory of your backend project, create a new file called &lt;code&gt;tsconfig.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;tsconfig.json&lt;/code&gt; with your editor, then copy and paste the following configurations into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "target": "ES2018",
    "module": "commonjs",
    "lib": [
      "esnext"
    ],
    "strict": true,
    "rootDir": ".",
    "outDir": "dist",
    "sourceMap": true,
    "esModuleInterop": true
  }
}

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

&lt;/div&gt;



&lt;p&gt;We use those options to set the TypeScript Compiler's behavious. For example we used the &lt;code&gt;target&lt;/code&gt; option too specify the ECMAScript target version that the code should be compiled to, which is "ES2018" and setting the &lt;code&gt;strict&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt; will enforce the compiler to use stricter type checking rules, which can help in catching potential type errors in your code.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up the Server
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Installing the necessary Libraries
&lt;/h2&gt;

&lt;p&gt;To install all of the necessary libraries for this project, run 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 @apollo/server express graphql nexus cors cookie-parser mongoose dotenv jsonwebtoken cookie-parser cors validator bcrypt

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

&lt;/div&gt;



&lt;p&gt;Once the installation is finished, use the following command to install the type definitions for the libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i --save-dev @types/node @types/jsonwebtoken @types/cors @types/cookie-parser @types/validator @types/bcrypt

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

&lt;/div&gt;



&lt;p&gt;Here is a summary of the installed libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/apollo"&gt;@apollo&lt;/a&gt;/server:&lt;/strong&gt; This is the core engine for the Apollo GraphQL server. It provides a set of tools for building a GraphQL server in Node.js.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Express:&lt;/strong&gt; It is a backend web application framework for building RESTful APIs with Node.js&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt; : is the library that implements the core GraphQL parsing and execution algorithms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Nexus&lt;/strong&gt; : A code-first, type-safe GraphQL schema construction library for JavaScript/TypeScript. We'll talk more on this and why we are using it later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cookie-parser&lt;/strong&gt; : A middleware that parses cookies attached to the client request object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mongoose:&lt;/strong&gt; A Node.js-based Object Data Modeling (ODM) library for MongoDB.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;dotenv:&lt;/strong&gt; A Node.js library that allows you to load environment variables from a &lt;code&gt;.env&lt;/code&gt; file into your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Jsonwebtoken&lt;/strong&gt; : This library will be used to generate a unique token for an authenticated user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cors&lt;/strong&gt; : is an express middleware that will be used to enable &lt;a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing" rel="noopener noreferrer"&gt;Cross-origin resource sharing&lt;/a&gt; on our app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validator&lt;/strong&gt; : will be used to verify the user's details before saving them into the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;bcrypt&lt;/strong&gt; : This library will be used to encrypt the user's password before saving them into the database.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Code First VS Schema First Approach in GraphQL
&lt;/h1&gt;

&lt;p&gt;There are two different ways to implement GraphQL API, they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Schema First Approach and,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code First Approach&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Schema First
&lt;/h3&gt;

&lt;p&gt;With this approach, the schema is defined first using the Schema Definition Language (SDL) before implementing the resolver functions. This method is also referred to as SDL-first Approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code First
&lt;/h3&gt;

&lt;p&gt;The Code first approach allows developers to use their programming language of choice (TypeScript in our case) to define the schema, which can be more expressive and easier to read and maintain than Schema Definition Language.&lt;/p&gt;

&lt;p&gt;We will be using the code-first approach in this project.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Nexus?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://nexusjs.org/" rel="noopener noreferrer"&gt;Nexus&lt;/a&gt; is a code-first, type-safe GraphQL schema construction library for JavaScript and TypeScript. It is a powerful tool that can be used to build and deploy GraphQL servers in JavaScript/TypeScript more efficiently.&lt;/p&gt;

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

&lt;p&gt;At the root directory of the project, create a new folder called &lt;code&gt;src&lt;/code&gt;. Inside the &lt;code&gt;src&lt;/code&gt; directory, create two new TypeScript files named &lt;code&gt;schema.ts&lt;/code&gt; and &lt;code&gt;index.ts.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;schema.ts&lt;/code&gt; file will be used for generating our GraphQL schema with Nexus. The &lt;code&gt;index.ts&lt;/code&gt; file will be used to setup our GraphQL web server with Apollo server and express.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;src/schema.ts&lt;/code&gt; file, type in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { makeSchema } from 'nexus'
import { join } from 'path'

export const schema = makeSchema({
  types: [],
  outputs: {
    schema: join(process.cwd(), "schema.graphql"),
    typegen: join(process.cwd(), "nexus-typegen.ts"), 
  },
})

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;types:[]&lt;/code&gt; will contain GraphQL types that will be used to generate our GraphQL schema, it is empty for now. Soon, we will create the types and replace the empty array with them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;schema: join(process.cwd(), "schema.graphql")&lt;/code&gt; will configure Nexus to generate a &lt;code&gt;schema.graphql&lt;/code&gt; file at the root directory of our project where nexus will automatically write the SDL version of our GraphQL schema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;typegen: join(process.cwd(), "nexus-typegen.ts")&lt;/code&gt; will set up nexus to generate &lt;code&gt;nexus-typegen.ts&lt;/code&gt; file at the root directory of our project where nexus should write the generated TypeScript definition types derived from our schema.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's run the following command in the terminal and see what happens next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx ts-node --transpile-only src/schema

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

&lt;/div&gt;



&lt;p&gt;After executing the script above, Nexus will automatically generate two new files in the root directory of your project, they are: &lt;code&gt;schema.graphql&lt;/code&gt; and &lt;code&gt;nexus-typegen.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;schema.graphql&lt;/code&gt; file has a type named Query, with a single field called &lt;code&gt;ok&lt;/code&gt; because we did not provide Nexus with more information about the types we wanted in the schema, this was constructed as a default schema.&lt;/p&gt;

&lt;p&gt;Let's add a &lt;code&gt;generate&lt;/code&gt; script to the package.json file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"generate": "ts-node --transpile-only src/schema.ts"

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

&lt;/div&gt;



&lt;p&gt;Any time you run &lt;code&gt;npn run generate&lt;/code&gt; on your terminal, it will regenerate your schema by updating the &lt;code&gt;schema.graphql&lt;/code&gt; and &lt;code&gt;nexus-typegen.ts&lt;/code&gt; file if there are any changes in your Nexus code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the Apollo GraphQL Server with Express.js
&lt;/h2&gt;

&lt;p&gt;There are different ways to create an &lt;code&gt;Apollo Server&lt;/code&gt;. This tutorial uses Apollo Server as a middleware with &lt;code&gt;express.js&lt;/code&gt;, there's also a tutorial that uses &lt;a href="https://www.apollographql.com/blog/apollo-client/next-js/next-js-getting-started/" rel="noopener noreferrer"&gt;the Apollo Server's&lt;/a&gt; &lt;code&gt;startStandaloneServer&lt;/code&gt; on Apollo's website.&lt;/p&gt;

&lt;p&gt;In this situation, it is not recommended to use the &lt;code&gt;startStandaloneServer&lt;/code&gt; function because we want to be able to customize the CORS' behavior and run the &lt;code&gt;cookieParser&lt;/code&gt; middleware before processing the GraphQL requests.&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;src/index.ts&lt;/code&gt; file we created earlier, and add the following codes to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import express, { Response } from "express";
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServer } from '@apollo/server';

import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import http from 'http';
import { schema } from "./schema";
import cors from 'cors';
import cookieParser from "cookie-parser";
import { json } from 'body-parser';

require('dotenv').config()

async function startApolloServer() {
  const app = express();

   const corsOptions = {
    origin: process.env.FRONTEND_URL!,
    credentials: true,
  };

  const httpServer = http.createServer(app);

  const server = new ApolloServer({
    schema,
    plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
  });

  await server.start();
  app.use(
    '/graphql',
    cors(corsOptions),
    json(),
    cookieParser(),
    expressMiddleware(server, {
      context: async ({ res }:{ res:Response })=&amp;gt; {
        return {
          res
        }
      }
    })
  );
  await new Promise&amp;lt;void&amp;gt;((resolve) =&amp;gt; httpServer.listen({ port: 4000 }, resolve));
  console.log(`🚀 Server ready at http://localhost:4000/graphql`);
}

startApolloServer();

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Understanding what is going on in the server file:
&lt;/h2&gt;

&lt;p&gt;We created a function called &lt;code&gt;startApolloServer&lt;/code&gt;. This is the function that will be called anytime we want to start the server. Inside the function, we created an instance of &lt;code&gt;express()&lt;/code&gt; called &lt;code&gt;app&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that, we created a new object called &lt;code&gt;corsOptions&lt;/code&gt;. Inside the &lt;code&gt;corsOptions&lt;/code&gt; we set the &lt;code&gt;origin&lt;/code&gt; to our front-end URL meaning only the requests from the front-end URL will be allowed. This will protect our GraphQL server from being accessed from an unknown origin.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;credentials: true&lt;/code&gt; option will set the [Access-Control-Allow-Credentials](&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials#:%7E:text=The%20Access%2DControl%2DAllow%2D,a%20request's%20credentials%20mode%20(%20Request.)" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials#:~:text=The%20Access%2DControl%2DAllow%2D,a%20request's%20credentials%20mode%20(%20Request.)&lt;/a&gt; option to &lt;code&gt;true&lt;/code&gt;. This will enable the browser to read the cookies that will be sent to it from the server.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;const httpServer = http.createServer(app);&lt;/code&gt; creates a new HTTP server and passes Express.js (&lt;code&gt;app)&lt;/code&gt; as a callback to handle HTTP requests.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;app.use(cookieParser());&lt;/code&gt; is used to register &lt;code&gt;cookieParser&lt;/code&gt; as an express &lt;code&gt;middleware&lt;/code&gt; function. Middleware functions are functions that have access to the &lt;code&gt;request&lt;/code&gt; object (req), the &lt;code&gt;response&lt;/code&gt; object (res), and the &lt;code&gt;next&lt;/code&gt; middleware function in the applications request-response cycle.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;cookieParser()&lt;/code&gt; function will be used to parse the &lt;code&gt;cookies&lt;/code&gt; sent from the user's browser. More about &lt;code&gt;cookies&lt;/code&gt; and why they are being used will be discussed in the authentication part of this tutorial.&lt;/p&gt;

&lt;p&gt;We used the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const server = new ApolloServer({
    schema,
    plugins: [ApolloServerPluginDrainHttpServer({ httpServer })]
  });

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

&lt;/div&gt;



&lt;p&gt;to create an instance of ApolloServer and passed the &lt;code&gt;schema&lt;/code&gt; that we created earlier, and the &lt;code&gt;ApolloServerPluginDrainHttpServer&lt;/code&gt; object to it. We used the &lt;code&gt;ApolloServerPluginDrainHttpServer&lt;/code&gt; plugin to ensure the server gracefully shuts down.&lt;/p&gt;

&lt;p&gt;We used the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  app.use(
    cors(corsOptions),
    json(),
    cookieParser(),
       expressMiddleware(server, {
      context: async ({ res }:{ res:Response })=&amp;gt; {
        return {
          res
        }
      }
    }),
    '/graphql'
  )

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

&lt;/div&gt;



&lt;p&gt;to register &lt;code&gt;cors()&lt;/code&gt;, &lt;code&gt;json()&lt;/code&gt;, &lt;code&gt;cookieParser()&lt;/code&gt;, &lt;code&gt;expressMiddleware()&lt;/code&gt; as an express &lt;code&gt;middleware&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;expressMiddleware()&lt;/code&gt; function enables us to attach the Apollo Server to the Express server as a middleware function. It also has a second optional argument which is an object that contains a &lt;code&gt;context&lt;/code&gt; function. The &lt;code&gt;context&lt;/code&gt; function will return an object (&lt;code&gt;res&lt;/code&gt; in this case and &lt;code&gt;req&lt;/code&gt; later in this tutorial) which will be shared by all the &lt;code&gt;resolvers&lt;/code&gt; during the executions of an operation. We will see more of &lt;code&gt;context&lt;/code&gt; and &lt;code&gt;resolvers&lt;/code&gt; in action later in this tutorial.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;/graphql&lt;/code&gt; registered to the middleware will set the &lt;code&gt;/graphql&lt;/code&gt; URL path as the default part of our server. This will enable us to access our server only on the following path: &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the package.json file, add the following &lt;code&gt;dev&lt;/code&gt; script to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"dev": "ts-node-dev --transpile-only --no-notify --exit-child src/index.ts"

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

&lt;/div&gt;



&lt;p&gt;Now we can run the following command to start the backend development server:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Once the server has started running, we should see something like this on the &lt;code&gt;CLI&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%2Fbrtkkgvd9rclyhg8kn83.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%2Fbrtkkgvd9rclyhg8kn83.png" alt="Screenshot_5.png" width="800" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you visit &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt; on your browser:&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%2Fyes28kup65e1rjv322yq.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%2Fyes28kup65e1rjv322yq.png" alt="Screenshot_7.png" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll notice that Apollo no longer uses GraphQL Playground and is now using &lt;a href="https://www.apollographql.com/docs/graphos/explorer/sandbox/" rel="noopener noreferrer"&gt;Apollo Sandbox&lt;/a&gt;, as the standard landing page in Apollo Server 4.&lt;/p&gt;

&lt;p&gt;Additionally, you need an internet connection to view &lt;a href="http://localhost:4000/graphql" rel="noopener noreferrer"&gt;http://localhost:4000/graphql&lt;/a&gt; on your browser.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up the Database
&lt;/h1&gt;

&lt;p&gt;We'll be using MongoDB Atlass for this tutorial. MongoDB Atlas is a fast, easy, and free way to get started with MongoDB. Signup on the &lt;a href="https://www.mongodb.com/cloud/atlas/register" rel="noopener noreferrer"&gt;MongoDB website&lt;/a&gt; to get your database URI string.&lt;/p&gt;

&lt;p&gt;The URI string will be used to connect to your database. It looks like this: &lt;code&gt;mongodb+srv://&amp;lt;username&amp;gt;:&amp;lt;password&amp;gt;@&amp;lt;cluster-name&amp;gt;yocfhhk.mongodb.net/?retryWrites=true&amp;amp;w=majority&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can follow this guide on &lt;a href="https://www.freecodecamp.org/news/get-started-with-mongodb-atlas/" rel="noopener noreferrer"&gt;freecodecamp's website&lt;/a&gt; on how to set up your MongoDB Atlas account and get your MongoDB database URI string.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the environment variables
&lt;/h2&gt;

&lt;p&gt;At the root directory of your project, create a &lt;code&gt;.env&lt;/code&gt; file. Open it in your editor and add your MongoDB URI string to it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL='Your-MongoDB-URL-String-goes-here'

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

&lt;/div&gt;



&lt;p&gt;That's all for now, later in the article, we'll be adding our &lt;code&gt;JWT_SECRET&lt;/code&gt; and &lt;code&gt;FRONTEND_URL&lt;/code&gt; to the &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to the Database
&lt;/h2&gt;

&lt;p&gt;Open up the server file in &lt;code&gt;src/index.ts&lt;/code&gt; and import the mongoose object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import mongoose from 'mongoose';

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

&lt;/div&gt;



&lt;p&gt;After that, we will create a new function called &lt;code&gt;connectToMongoDB&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function connectToMongoDB() {
  await mongoose.connect(process.env.DATABASE_URL!);
  console.log("Connected to Mongo atlas successfully...");
}

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

&lt;/div&gt;



&lt;p&gt;Then call the &lt;code&gt;connectToMongoDB()&lt;/code&gt; function inside the &lt;code&gt;startApolloServer()&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  console.log(`🚀 Server ready at http://localhost:4000/graphql`);
  connectToMongoDB().catch(err =&amp;gt; console.log(err));
}

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

&lt;/div&gt;



&lt;p&gt;Run the following command on your terminal to start your server&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;When the server starts, it should automatically establish a connection to your database URI if everything goes according to plan.&lt;/p&gt;

&lt;p&gt;An internet connection is required to connect to the MongoDB Atlas.&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%2Fv29ayxuuwskiempkizch.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%2Fv29ayxuuwskiempkizch.png" alt="Screenshot_8.png" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the models
&lt;/h2&gt;

&lt;p&gt;In this part, we will define the structure of our database for the users and their sticky notes with &lt;code&gt;Mongoose&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mongoosejs.com/" rel="noopener noreferrer"&gt;Mongoose&lt;/a&gt; is an Object Data Modeling (ODM) library for MongoDB and Node.js. It provides a simple and straightforward way to interact with MongoDB databases from a Node.js application, allowing you to work with your data as native JavaScript objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the &lt;code&gt;User&lt;/code&gt; Model
&lt;/h3&gt;

&lt;p&gt;Create a new directory in the &lt;code&gt;src&lt;/code&gt; folder named: &lt;code&gt;models&lt;/code&gt;. Open the &lt;code&gt;models&lt;/code&gt; folder and create a new file named: &lt;code&gt;user.ts&lt;/code&gt; inside it.&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;user.ts&lt;/code&gt; file and add the following code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Schema, model } from 'mongoose';

interface IUser {
  id:string;
  fullname: string;
  username: string;
  email: string;
  password: string;
}

const userSchema = new Schema&amp;lt;IUser&amp;gt;({
  email: {
    type: String,
    required: true,
    unique: true,
  },
  username: {
    type: String,
    unique: true,
    required: true,
    trim: true,
  },
  password: {
    type: String,
    required: true,
  },
  fullname: {
    type: String,
    required: true,
    trim: true,
  },
});

const User = model&amp;lt;IUser&amp;gt;('User', userSchema);

export default User;

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

&lt;/div&gt;



&lt;p&gt;First, we created an interface called &lt;code&gt;IUser&lt;/code&gt; that will represent a user in our database, then we defined a &lt;code&gt;userSchema&lt;/code&gt; that conformed with the &lt;code&gt;IUser&lt;/code&gt; interface before generating a &lt;code&gt;User&lt;/code&gt; model from the &lt;code&gt;userSchema&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;User&lt;/code&gt; model can then be used to create, read, update, and delete documents in the &lt;code&gt;users&lt;/code&gt; collection in the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining The Notes Model
&lt;/h3&gt;

&lt;p&gt;Create another file named &lt;code&gt;note.ts&lt;/code&gt; in the &lt;code&gt;src/models&lt;/code&gt; directory, and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Schema, model, Document } from 'mongoose';

enum Theme {
    Yellow = "yellow",
    Green = "green",
    Pink = "pink",
    Purple = "purple",
    Blue = "blue",
    Gray = "gray",
    Charcoal = "charcoal"
}

interface INote {
    content: string;
    color: Theme;
    userId: string;
}

const noteSchema = new Schema&amp;lt;INote&amp;gt;({
    content: {
        type: String,
        required: true
    },
    color: {
        type: String,
        enum: ['yellow', 'green', 'pink', 'purple', 'blue', 'gray', 'charcoal'],
        default: Theme.Yellow
    },
    userId: {
        type: String, required: true
    },
});

const Note = model&amp;lt;INote&amp;gt;('Note', noteSchema);
export default Note;

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

&lt;/div&gt;



&lt;p&gt;We used the TypeScript's enum type to define all the colors that are available for use on the note app, and created an interface for the note called &lt;code&gt;INote&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we defined a &lt;code&gt;noteSchema&lt;/code&gt; that corresponds with the &lt;code&gt;INote&lt;/code&gt; interface before generating a Note model from the &lt;code&gt;noteSchema&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that, we exported the model for later use. We also used the Mongoose enum type to specify the accepted colors (&lt;code&gt;enum: ['yellow', 'green', 'pink', 'purple', 'blue', 'gray', 'charcoal'],&lt;/code&gt;), any other color than those listed will be rejected.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating The User Types
&lt;/h1&gt;

&lt;p&gt;Create a new folder in the &lt;code&gt;src&lt;/code&gt; directory called &lt;code&gt;graphql&lt;/code&gt;. Inside the &lt;code&gt;graphql&lt;/code&gt; directory, create a new TypeScript file called &lt;code&gt;User.ts&lt;/code&gt; and open it up in your editor, then import the following objects into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import bcrypt from "bcrypt";
import jsonwebtoken from "jsonwebtoken";
import {GraphQLError } from "graphql"
import validator from 'validator';
import { extendType, objectType, inputObjectType, nonNull } from "nexus";
import userModel from "../models/user";

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

&lt;/div&gt;



&lt;p&gt;Before we proceed, let's quickly go through the imports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;bcrypts&lt;/code&gt; object will be used to encrypt the user's password before saving it to the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;jsonwebtoken&lt;/code&gt; will be used to generate a safe token that will be used to authenticate a user after successful registration or login.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;GraphQLError&lt;/code&gt; will be used to specify HTTP status code when throwing a GraphQL error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;validator&lt;/code&gt; will be used to validate user inputs before saving them into the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;extendType&lt;/code&gt; will be used to extend the GraphQL root types in this project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;objectType&lt;/code&gt; will be used to define our object types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;inputObjectType&lt;/code&gt; will be used to define the object type that will be passed as an input value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the &lt;code&gt;nonNull&lt;/code&gt; function will be used to prevent the return value of a type from being empty&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Defining the types for a User
&lt;/h2&gt;

&lt;p&gt;Remember we are using the code-first approach to build our GraphQL server, which means we have to write our schemas in TypeScript then later, we'll use Nexus to generate the Schema Definition Language from our code. Let's define the following types for a user:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;User&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;AuthPayLoad&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;SignupUserInput&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;SignInUserInput&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add the following snippets below the imports to create the &lt;code&gt;User&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const User = objectType({
    name: "User", 
    definition(t) {
      t.nonNull.string("id");
      t.nonNull.string("email");
      t.nonNull.string("username");
      t.nonNull.string("password");
      t.nonNull.string("fullname");
    },
  });

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

&lt;/div&gt;



&lt;p&gt;We used the Nexus &lt;code&gt;objectType&lt;/code&gt; function to create a new type called &lt;code&gt;User&lt;/code&gt;. The &lt;code&gt;User&lt;/code&gt; type will be used to retrieve the user's data from the server. Five fields are defined in the &lt;code&gt;User&lt;/code&gt; object types, they are: &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt; and &lt;code&gt;fullname&lt;/code&gt;. Each field is defined as a non-nullable &lt;code&gt;string&lt;/code&gt; type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the &lt;code&gt;AuthPayLoad&lt;/code&gt; Type
&lt;/h3&gt;

&lt;p&gt;Let's create another object type called &lt;code&gt;AuthPayLoad&lt;/code&gt;. This type will be used to retrieve a user's token and data after successful registration or login.&lt;/p&gt;

&lt;p&gt;Add the following code below the &lt;code&gt;User&lt;/code&gt; object type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   const AuthPayLoad = objectType({
    name: "AuthPayLoad",
    definition(t) {
      t.nonNull.string("token");
      t.nonNull.field("user", { type: User });
    },
  });

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;AuthPayLoad&lt;/code&gt; type contains two fields: &lt;code&gt;token&lt;/code&gt; and &lt;code&gt;user&lt;/code&gt;. The &lt;code&gt;token&lt;/code&gt; field is defined as non-nullable &lt;code&gt;string&lt;/code&gt; type while the &lt;code&gt;user&lt;/code&gt; field is defined as the non-nullable &lt;code&gt;User&lt;/code&gt; type we created previously.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the &lt;code&gt;SignupUserInput&lt;/code&gt; Type
&lt;/h3&gt;

&lt;p&gt;We will define a new input object type that will be used to collect user's data anytime they want to register for a new account.&lt;/p&gt;

&lt;p&gt;Add the following code below the &lt;code&gt;AuthPayLoad&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   const SignupUserInput = inputObjectType({
    name: "SignupUserInput",
    definition(t) {
      t.nonNull.string("email");
      t.nonNull.string("username");
      t.nonNull.string("password");
      t.nonNull.string("fullname");
    },
  });

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

&lt;/div&gt;



&lt;p&gt;We used Nexus &lt;code&gt;inputObjectType&lt;/code&gt; function to create a new input object type called &lt;code&gt;SignupUserInput&lt;/code&gt;. Then we defined the following fields inside the &lt;code&gt;SignupUserInput&lt;/code&gt; type: &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt; and &lt;code&gt;fullname&lt;/code&gt;. Each field is defined as a non-nullable &lt;code&gt;string&lt;/code&gt; type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the &lt;code&gt;SigninUserInput&lt;/code&gt; Type
&lt;/h3&gt;

&lt;p&gt;Below the &lt;code&gt;SignupUserInput&lt;/code&gt; type, let's create another input object type and name it &lt;code&gt;SigninUserInput&lt;/code&gt; which will be used to collect login details from a user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   const SignInUserInput = inputObjectType({
    name: "SignInUserInput",
    definition(t) {
      t.nonNull.string("usernameOrEmail");
      t.nonNull.string("password");
    },
  });

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

&lt;/div&gt;



&lt;p&gt;Within the SigninUserInput type, we defined two fields: &lt;code&gt;usernameOrEmail&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; and they are both defined as non-nullable &lt;code&gt;string&lt;/code&gt; type.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Special Root Operation Types in GraphQL
&lt;/h3&gt;

&lt;p&gt;In GraphQL, there are three special root operation types, they are: &lt;code&gt;query&lt;/code&gt;, &lt;code&gt;mutation&lt;/code&gt;, and &lt;code&gt;subscription&lt;/code&gt;. These operation types represent the entry points for executing operations in the GraphQL API.&lt;/p&gt;

&lt;h4&gt;
  
  
  Query Type
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;Query&lt;/code&gt; type is used for read-only operations, such as retrieving data from the server. You can define fields on the &lt;code&gt;Query&lt;/code&gt; type to allow clients to request specific pieces of data from the server.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mutation Type
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;Mutation&lt;/code&gt; type is used for write operations, such as creating, updating, or deleting data. You can define fields on the &lt;code&gt;Mutation&lt;/code&gt; type to allow clients to make changes to the data stored on the server.&lt;/p&gt;

&lt;h4&gt;
  
  
  Subscription Type
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;Subscription&lt;/code&gt; type is used for long-lived connections that allow the server to push updates to the client in real-time. You can define fields on the &lt;code&gt;Subscription&lt;/code&gt; type to allow clients to subscribe to specific types of updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signing Up A New User
&lt;/h3&gt;

&lt;p&gt;To sign up a new user, we will create a new type called &lt;code&gt;SignupUser&lt;/code&gt; that will be used to register them.&lt;/p&gt;

&lt;p&gt;Let's add the following snippets below the &lt;code&gt;SignInUserInput&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  export const SignupUser = extendType({
    type: 'Mutation',
    definition(t) {
      t.nonNull.field('signupUser', {
        type: AuthPayLoad,
        args: {
          data: nonNull(SignupUserInput)
        },
        async resolve(_parent, args, { res }, _info) {
          const { data: { email, username, password, fullname } } = args;

          if (!validator.isEmail(email)) {
            throw new GraphQLError('Please enter a valid E-mail!', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }
          if (!validator.isLength(password, { min: 5 })) {

            throw new GraphQLError('Password must have atleast 5 characters', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }
          if (!validator.isLength(username, { min: 3 })) {
            throw new GraphQLError('username must have at least 3 characters', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }
          if (!validator.isLength(fullname, { min: 4 })) {
            throw new GraphQLError('fullname have atleast 4 characters', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }

          const encryptedPassword = bcrypt.hashSync(password, 10);
          const userData = {
            email: email.toLowerCase(),
            username: username.toLowerCase(),
            fullname,
            password: encryptedPassword,
          };
          try {
            const usernameExist = await userModel.findOne({ username: username.toLowerCase() });
            if (usernameExist) {
              throw new GraphQLError('Username is already in use!', {
                extensions: {
                  code: 'UNAUTHENTICATED',
                  http: { status: 401 },
                }
              });
            }
            const emailExist = await userModel.findOne({ email: email.toLowerCase() });
            if (emailExist) {
              throw new GraphQLError('Email is already in use!', {
                extensions: {
                  code: 'UNAUTHENTICATED',
                  http: { status: 401 },
                }
              });
            }
            const createdUser = await userModel.create(userData);
            console.log(createdUser)
            const token = jsonwebtoken.sign(
              {
                id: createdUser._id,
                username: createdUser.username,
                exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24,
              },
              process.env.JWT_SECRET!
            );
            res
               .cookie("access_token", token, {
                httpOnly: true,
                secure: process.env.SECURE_COOKIE === 'true'? true : false,
                maxAge: Math.floor(Date.now() / 1000) + (60 * 60 * 24),
                sameSite: 'none'
               })
            return {
              user: createdUser,
              token,
            };
          } catch (error) {
            throw error
          }
        },
      })
    }
  });

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Demystifying the &lt;code&gt;SignupUser&lt;/code&gt; code
&lt;/h4&gt;

&lt;p&gt;In the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; export const SignupUser = extendType({
    type: 'Mutation',
    definition(t) {
      t.nonNull.field('signupUser', {
        type: AuthPayLoad,
        args: {
          data: nonNull(SignupUserInput)
        },

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We defined a new field called &lt;code&gt;signupUser&lt;/code&gt; that extends the GraphQL root &lt;code&gt;Mutation&lt;/code&gt; root type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the return type for the &lt;code&gt;signupUser&lt;/code&gt; mutation was defined as the &lt;code&gt;AuthPayLoad&lt;/code&gt; type we created previously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;then we defined the expected argument as &lt;code&gt;data&lt;/code&gt; object whose value is expected to be a non-nullable &lt;code&gt;SignupUserInput&lt;/code&gt; object type that will be passed to the &lt;code&gt;signupUser&lt;/code&gt; field.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the snippet below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async resolve(_parent, args, { res }, _info) {
          const { data: { email, username, password, fullname } } = args;

          if (!validator.isEmail(email)) {
            throw new GraphQLError('Please enter a valid E-mail!', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }
          if (!validator.isLength(password, { min: 5 })) {

            throw new GraphQLError('Password must have atleast 5 characters', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }
          if (!validator.isLength(username, { min: 3 })) {
            throw new GraphQLError('username must have at least 3 characters', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }
          if (!validator.isLength(fullname, { min: 4 })) {
            throw new GraphQLError('fullname have atleast 4 characters', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We created a resolver function called &lt;code&gt;resolve&lt;/code&gt; for the &lt;code&gt;signupUser&lt;/code&gt; field.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;parent&lt;/code&gt; is the return value of the resolver for this field's parent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;args&lt;/code&gt; is the GraphQL arguments provided for this field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;context&lt;/code&gt; is used for sharing data that the resolvers might need. We created this function earlier in the server file and then passed the express response object (&lt;code&gt;res&lt;/code&gt;) to it. The &lt;code&gt;res&lt;/code&gt; object will be made available to all the &lt;code&gt;resolver&lt;/code&gt; functions through the &lt;code&gt;context&lt;/code&gt; object.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You might have noticed the &lt;code&gt;{res}&lt;/code&gt; instead of &lt;code&gt;context&lt;/code&gt; in the &lt;code&gt;signupUser&lt;/code&gt; resolver function arguments, that is because we unpacked the &lt;code&gt;context&lt;/code&gt; parameter using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#object_destructuring" rel="noopener noreferrer"&gt;Object Destructuring&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;Instead of having the &lt;code&gt;context&lt;/code&gt; in the parameters, and then later doing something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const res = context.res

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

&lt;/div&gt;



&lt;p&gt;Or this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const {res} = context

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

&lt;/div&gt;



&lt;p&gt;We just unpacked the &lt;code&gt;res&lt;/code&gt; object directly in the arguments.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;info&lt;/code&gt; contains details on the present status of the operation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The underscore (&lt;code&gt;_&lt;/code&gt;) was used to prefix &lt;code&gt;_parent&lt;/code&gt; and &lt;code&gt;_info&lt;/code&gt; parameters to bypass the linter error because they are unused. We don't need the &lt;code&gt;parent&lt;/code&gt; and &lt;code&gt;info&lt;/code&gt; parameters now, removing them will cause an error because the four parameters are expected in that position, and not using them will result to the linter warning us about unused parameters. To fix all of the above problems, we prefixed the unused parameters with an underscore (&lt;code&gt;_&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In thefollowing line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { data: { email, username, password, fullname } } = args;

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

&lt;/div&gt;



&lt;p&gt;we unpacked the &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;fullname&lt;/code&gt; from the &lt;code&gt;data&lt;/code&gt; object passed into the &lt;code&gt;args&lt;/code&gt;. We could also remove the &lt;code&gt;args&lt;/code&gt; object from the resolve's argument like we did with the context and do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async resolve(_parent, { data: { email, username, password, fullname } }, { res }, _info) {
...

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

&lt;/div&gt;



&lt;p&gt;But doing so would only make the resolver arguments longer.&lt;/p&gt;

&lt;p&gt;In the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          if (!validator.isEmail(email)) {
            throw new GraphQLError('Please enter a valid E-mail!', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }
          if (!validator.isLength(password, { min: 5 })) {

            throw new GraphQLError('Password must have atleast 5 characters', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }
          if (!validator.isLength(username, { min: 3 })) {
            throw new GraphQLError('username must have at least 3 characters', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }
          if (!validator.isLength(fullname, { min: 4 })) {
            throw new GraphQLError('fullname have atleast 4 characters', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
          }

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

&lt;/div&gt;



&lt;p&gt;We used the &lt;code&gt;validator&lt;/code&gt; library to verify the &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt; and the &lt;code&gt;fullname&lt;/code&gt; details provided by the user, and throw an &lt;code&gt;UNAUTHENTICATED&lt;/code&gt; error using the &lt;code&gt;GraphQLError&lt;/code&gt; library whenever the validations fail.&lt;/p&gt;

&lt;p&gt;In the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const encryptedPassword = bcrypt.hashSync(password, 10);
          const userData = {
            email: email.toLowerCase(),
            username: username.toLowerCase(),
            fullname,
            password: encryptedPassword,
          };

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

&lt;/div&gt;



&lt;p&gt;We encrypted the user's password using the &lt;code&gt;bcrypt&lt;/code&gt; library. Then creates a &lt;code&gt;userData&lt;/code&gt; object that stores the &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;fullname&lt;/code&gt; and the encrypted &lt;code&gt;password&lt;/code&gt; data.&lt;/p&gt;

&lt;p&gt;In the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try {
            const usernameExist = await userModel.findOne({ username: username.toLowerCase() });
            if (usernameExist) {
              throw new GraphQLError('Username is already in use!', {
                extensions: {
                  code: 'UNAUTHENTICATED',
                  http: { status: 401 },
                }
              });
            }
            const emailExist = await userModel.findOne({ email: email.toLowerCase() });
            if (emailExist) {
              throw new GraphQLError('Email is already in use!', {
                extensions: {
                  code: 'UNAUTHENTICATED',
                  http: { status: 401 },
                }
              });
            }
            const createdUser = await userModel.create(userData);

            const token = jsonwebtoken.sign(
              {
                id: createdUser._id,
                username: createdUser.username,
                exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24,
              },
              process.env.JWT_SECRET!
            );
            res
               .cookie("access_token", token, {
                httpOnly: true,
                secure: process.env.SECURE_COOKIE === 'true'? true : false,
                maxAge: Math.floor(Date.now() / 1000) + (60 * 60 * 24),
                sameSite: 'none'
               })
            return {
              user: createdUser,
              token,
            };
          } catch (error) {
            throw error
          }
        },
      })
    }
  });

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

&lt;/div&gt;



&lt;p&gt;We checked if the username exist already in the database by executing the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const usernameExist = await userModel.findOne({ username: username.toLowerCase() });

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

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;usernameExist&lt;/code&gt;, we'll throw the &lt;code&gt;Username is already in use&lt;/code&gt; error message. We also verified if the user's email address exists in the database by running the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const emailExist = await userModel.findOne({ email: email.toLowerCase() });

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

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;emailExist&lt;/code&gt; value is truthy, we'll return &lt;code&gt;Email is already in use&lt;/code&gt; error to the user.&lt;/p&gt;

&lt;p&gt;Then we created the user using the data stored in the &lt;code&gt;userData&lt;/code&gt;'s variable by running the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const createdUser = await userModel.create(userData);

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

&lt;/div&gt;



&lt;p&gt;We used the &lt;a href="https://github.com/auth0/node-jsonwebtoken" rel="noopener noreferrer"&gt;jsonwebtoken&lt;/a&gt; library with a secret key (we'll create the key very soon) to generate a secure token from the created user data using the following snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            const token = jsonwebtoken.sign(
              {
                id: createdUser._id,
                username: createdUser.username,
                exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24,
              },
              process.env.JWT_SECRET!
            );

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

&lt;/div&gt;



&lt;p&gt;By default, when we create a new document in MongoDB, mongoose automatically adds an &lt;code&gt;_id&lt;/code&gt; field that acts as a primary key. That was how we came about &lt;code&gt;createdUser._id&lt;/code&gt;. To create your &lt;code&gt;JWT&lt;/code&gt; secret key, open up the &lt;code&gt;.env&lt;/code&gt; file and add the following below the &lt;code&gt;DATABASE_URL&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL='Your-MongoDB-URL-String-goes-here'
JWT_SECRET = 'Your-JWT_SECRET-goes-here'

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

&lt;/div&gt;



&lt;p&gt;Note that your JWT secret key is private to you, it must be very difficult to guess and must be secured. Whenever the server receives a JWT from the user's computer, the &lt;code&gt;JWT_SECRET&lt;/code&gt; will be used to decrypt the user's token. We'll discuss more about how the authentication work soon.&lt;/p&gt;

&lt;p&gt;In the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;res
               .cookie("access_token", token, {
                httpOnly: true,
                secure: process.env.SECURE_COOKIE === 'true'? true : false,
                maxAge: Math.floor(Date.now() / 1000) + (60 * 60 * 24),
                sameSite: 'none'
               })
            return {
              user: createdUser,
              token,
            };

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

&lt;/div&gt;



&lt;p&gt;We used the &lt;code&gt;res&lt;/code&gt; object in express to store the &lt;code&gt;tokens&lt;/code&gt; on the user's web browser &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#third-party_cookies" rel="noopener noreferrer"&gt;using HTTP cookies&lt;/a&gt;. In part three of this tutorial, we will configure the browser to send the cookies back to the server anytime the user is making an API request.&lt;/p&gt;

&lt;p&gt;We added some attributes to the cookie so that the browser will know how to handle the cookies when it receives them. Below are what they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;httpOnly&lt;/code&gt; : Setting this attribute to &lt;code&gt;true&lt;/code&gt; will prevent the cookie from being accessed by JavaScript. The aim of this is to prevent &lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting" rel="noopener noreferrer"&gt;XSS Attack&lt;/a&gt; on our app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;secure&lt;/code&gt;: Setting this attribute to &lt;code&gt;true&lt;/code&gt; is used to indicate to the browser that the cookies should only be transmitted over a secure (encrypted) connection. This will keep our app secure and prevent the &lt;a href="https://www.imperva.com/learn/application-security/man-in-the-middle-attack-mitm/" rel="noopener noreferrer"&gt;Man in the middle (MITM) attack&lt;/a&gt; on it. Add the following to your &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;maxAge&lt;/code&gt;: The maximum lifetime of the cookie before it expires, I set it to 24 hours&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;sameSite&lt;/code&gt;: This option will only allow the cookie to be sent to the same domain name. I set it to &lt;code&gt;none&lt;/code&gt; because the front end and the back end of this app will be hosted on different domains.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Authenticating the User
&lt;/h2&gt;

&lt;p&gt;A user needs to be authenticated anytime they make an API request to our GraphQL server. If not, we will have to keep redirecting the user to the login page and have them enter their username and password every time they want to perform any operation like fetching all notes, modifying and deleting them to confirm their identity.&lt;/p&gt;

&lt;p&gt;Nobody should have to go through that stress. We need a secure way to authenticate a user each time they make an API request to the server and this is why we are using a &lt;strong&gt;token-based authentication system.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Token-Based Authentication System?
&lt;/h3&gt;

&lt;p&gt;Token-Based Authentication is a secure way of verifying a user's identity using encrypted security tokens. Once the token has been generated after the initial logins, the token will be shared between the user's computer and the server rather than having the user re-enter their credentials every time they need to make a request to the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does it work?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The user logins or signup for a new account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The server verifies the user's credentials&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the credentials are confirmed, the server generates a secure token using &lt;a href="https://jwt.io/" rel="noopener noreferrer"&gt;JSON Web Token&lt;/a&gt;(JWT)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The tokens are then placed on the user's computer (We used a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies" rel="noopener noreferrer"&gt;Cookie&lt;/a&gt; with the &lt;a href="https://owasp.org/www-community/HttpOnly#:~:text=What%20is%20HttpOnly%3F,if%20the%20browser%20supports%20it" rel="noopener noreferrer"&gt;&lt;code&gt;HttpOnly&lt;/code&gt;&lt;/a&gt;.) attribute for this app)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The next time a user makes an API request to access secured data from the browser, the JWT tokens will be attached to the request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The server then verifies the user's token before allowing the user to perform any operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the tokens are confirmed, access will be granted to the user&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why use &lt;code&gt;Cookies&lt;/code&gt; with &lt;code&gt;HttpOnly&lt;/code&gt; attribute to store JSON Web Tokens?
&lt;/h3&gt;

&lt;p&gt;Using HTML Web Storage to save the user's token is considered a bad idea because it makes the website vulnerable to XSS attack. An attacker can have access to an authenticated user's token by injecting JavaScript code that will run on the user's website. When &lt;code&gt;Cookies&lt;/code&gt; are used with the &lt;code&gt;HttpOnly&lt;/code&gt; attribute, they will not be accessible with JavaScript thereby making them invulnerable to XSS attack.&lt;/p&gt;

&lt;p&gt;However, they can still be susceptible to &lt;a href="https://owasp.org/www-community/attacks/csrf" rel="noopener noreferrer"&gt;Cross Site Request Forgery (CSRF) attack&lt;/a&gt; if we did not restrict access to the cookies by setting the &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;secure&lt;/code&gt; and &lt;code&gt;SameSite&lt;/code&gt; flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signing In the User
&lt;/h2&gt;

&lt;p&gt;To sign in a user, let's create a &lt;code&gt;SigninUser&lt;/code&gt; type. This type will be used to login a verified user.&lt;/p&gt;

&lt;p&gt;Add the following code below the &lt;code&gt;SignupUser&lt;/code&gt; object inside the &lt;code&gt;src/graphql/User.ts&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    export const SigninUser = extendType({
    type: 'Mutation',
    definition(t) {
      t.nonNull.field('signinUser', {
        type: AuthPayLoad,
        args: {
         data: nonNull(
          SignInUserInput
         ),
        },
        async resolve(_parent, args, { res }, _info) {
         try {
           const { data: { usernameOrEmail, password } } = args

           const userFound = await userModel.findOne({
             $or: [{ email: usernameOrEmail.toLowerCase() },
             { username: usernameOrEmail.toLowerCase() }],
           }).exec();
           if (!userFound) {
             throw new GraphQLError('User does not exist', {
              extensions: {
                code: 'UNAUTHENTICATED',
                http: { status: 401 },
              }
            });
           }
           if (bcrypt.compareSync(password, userFound.password)) {
             const username = userFound.username;
             const id = userFound._id;
             const token = jsonwebtoken.sign({
               id,
               username,
               exp: Math.floor(Date.now() / 1000) + (60 * 60 * 24),
             }, process.env.JWT_SECRET!);
             res
               .cookie("access_token", token, {
                 httpOnly: true,
                 secure: true,
                 maxAge: Math.floor(Date.now() / 1000) + (60 * 60 * 24),
                 sameSite: 'none'
               })
             return {
               user: userFound,
               token,
             };
           }
           throw new GraphQLError('Incorrect password', {
            extensions: {
              code: 'UNAUTHENTICATED',
              http: { status: 401 },
            }
          });
         }
         catch (error: any) {
           throw new GraphQLError(error, {
            extensions: {
              code: 'UNAUTHENTICATED',
              http: { status: 401 },
            }
          });
         }
       }
     })
    }
  });

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Demystifying the &lt;code&gt;SigninUser&lt;/code&gt; code
&lt;/h3&gt;

&lt;p&gt;We created a new field called &lt;code&gt;signinUser&lt;/code&gt;. Just like the &lt;code&gt;signupUser&lt;/code&gt; field, it extends the GraphQL &lt;code&gt;Mutation&lt;/code&gt; root type and returns a non-nullable &lt;code&gt;AuthPayLoad&lt;/code&gt; type. It also has a non-nullable argument of &lt;code&gt;SignInUserInput&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;Then we created a resolver function called &lt;code&gt;resolve&lt;/code&gt; for the &lt;code&gt;signinUser&lt;/code&gt; mutation. Inside the &lt;code&gt;resolve&lt;/code&gt; function, we unpacked the &lt;code&gt;usernameOrEmail&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; arguments using object destructuring, then we checked if the &lt;code&gt;usernameOrEmail&lt;/code&gt; exists in the database by running the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const userFound = await userModel.findOne({
             $or: [{ email: usernameOrEmail.toLowerCase() },
             { username: usernameOrEmail.toLowerCase() }],
           }).exec();

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

&lt;/div&gt;



&lt;p&gt;A user can use their username or email to log in. The query will select one document where either the &lt;code&gt;username&lt;/code&gt; field value is equal to &lt;code&gt;usernameOrEmail&lt;/code&gt; or &lt;code&gt;email&lt;/code&gt; field value is equal to &lt;code&gt;usernameOrEmail&lt;/code&gt;. The query result will be saved into the &lt;code&gt;userFound&lt;/code&gt; variable. If the &lt;code&gt;userFound&lt;/code&gt; value is &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy" rel="noopener noreferrer"&gt;falsy&lt;/a&gt;, we'll throw a new &lt;code&gt;GraphQLError&lt;/code&gt; that says: 'User does not exist'.&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;userFound&lt;/code&gt; value is not &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy" rel="noopener noreferrer"&gt;falsy&lt;/a&gt;, we'll compare the password in the database with the user's entered password using the &lt;code&gt;bcrypt&lt;/code&gt; library. Once the password is confirmed, a new token will be generated with the user's &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;username&lt;/code&gt; . After that, the generated token will be sent to the client's computer via &lt;code&gt;cookies&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But if the user's password in the database does not match the entered password, then a &lt;code&gt;GraphQLError&lt;/code&gt; that says: 'Incorrect password' will be returned to the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging Out The User
&lt;/h2&gt;

&lt;p&gt;To log the user out is very easy, all we have to do is delete the user's token from the cookies. Without the token, a user will have to login again to access their data.&lt;/p&gt;

&lt;p&gt;Let's write the following code below the &lt;code&gt;SigninUser&lt;/code&gt; object in &lt;code&gt;src/graphql/User.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  export const LogoutUser = extendType({
    type: "Mutation",
    definition(t) {
      t.nonNull.field("signoutUser", {
        type: "Boolean",
        async resolve (_parent, _args, { res }, _info) {
         res.clearCookie("access_token")
          return true
        },
      });
    },
  });

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

&lt;/div&gt;



&lt;p&gt;We created a new field that extends the &lt;code&gt;Mutation&lt;/code&gt; root type called &lt;code&gt;signoutUser&lt;/code&gt;. The return type for this field is defined as &lt;code&gt;Boolean&lt;/code&gt;. Then we created a new resolver function called &lt;code&gt;resolve&lt;/code&gt;. What this function does is very simple. It clears the &lt;code&gt;access_token&lt;/code&gt; cookies, then returns a &lt;code&gt;true&lt;/code&gt; boolean value to the client.&lt;/p&gt;

&lt;h1&gt;
  
  
  Generating the Schema definition language (SDL) from the &lt;code&gt;User&lt;/code&gt; Code
&lt;/h1&gt;

&lt;p&gt;In this part, we are going to use Nexus to generate the GraphQL schema from all the user's code we've been writing.&lt;/p&gt;

&lt;p&gt;Create a new TypeScript file named &lt;code&gt;index.ts&lt;/code&gt; in &lt;code&gt;scr/graphql/&lt;/code&gt;, then add the following export to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export * from "./User";

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

&lt;/div&gt;



&lt;p&gt;update &lt;code&gt;src/schema.ts&lt;/code&gt; file to use all the imports coming from &lt;code&gt;scr/graphql/index.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { makeSchema } from 'nexus'
import { join } from 'path'
import * as types from "./graphql";
export const schema = makeSchema({
  types,
  outputs: {
    schema: join(process.cwd(), "schema.graphql"), 
    typegen: join(process.cwd(), "nexus-typegen.ts"), 
  },
})

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

&lt;/div&gt;



&lt;p&gt;First, we imported everything in &lt;code&gt;scr/graphql/index.ts&lt;/code&gt; file as &lt;code&gt;types&lt;/code&gt; using the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as types from "./graphql";

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

&lt;/div&gt;



&lt;p&gt;Then we update the &lt;code&gt;makeSchema&lt;/code&gt; method to use the imported &lt;code&gt;types&lt;/code&gt; instead of the empty array (&lt;code&gt;[]&lt;/code&gt;) that was there before with the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const schema = makeSchema({
  types, // same as: types:types
...

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

&lt;/div&gt;



&lt;p&gt;Open up the &lt;code&gt;schema.graphql&lt;/code&gt; file at the root directory of your project, If your terminal is still running on the dev server you should see that the file has been automatically updated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### This file was generated by Nexus Schema
### Do not make changes to this file directly

type AuthPayLoad {
  token: String!
  user: User!
}

type Mutation {
  signinUser(data: SignInUserInput!): AuthPayLoad!
  signupUser(data: SignupUserInput!): AuthPayLoad!
}

type Query {
  ok: Boolean!
}

input SignInUserInput {
  password: String!
  usernameOrEmail: String!
}

input SignupUserInput {
  email: String!
  fullname: String!
  password: String!
  username: String!
}

type User {
  email: String!
  fullname: String!
  id: String!
  password: String!
  username: String!
}

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

&lt;/div&gt;



&lt;p&gt;If you open the &lt;code&gt;nexus-typegen.ts&lt;/code&gt; file, you should see something like this too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * This file was generated by Nexus Schema
 * Do not make changes to this file directly
 */

declare global {
  interface NexusGen extends NexusGenTypes {}
}

export interface NexusGenInputs {
  SignInUserInput: { // input type
    password: string; // String!
    usernameOrEmail: string; // String!
  }
  SignupUserInput: { // input type
    email: string; // String!
    fullname: string; // String!
    password: string; // String!
    username: string; // String!
  }
}

export interface NexusGenEnums {
}

export interface NexusGenScalars {
  String: string
  Int: number
  Float: number
  Boolean: boolean
  ID: string
}

export interface NexusGenObjects {
  AuthPayLoad: { // root type
    token: string; // String!
    user: NexusGenRootTypes['User']; // User!
  }
  Mutation: {};
  Query: {};
  User: { // root type
    email: string; // String!
    fullname: string; // String!
    id: string; // String!
    password: string; // String!
    username: string; // String!
  }
}

export interface NexusGenInterfaces {
}

export interface NexusGenUnions {
}

export type NexusGenRootTypes = NexusGenObjects

export type NexusGenAllTypes = NexusGenRootTypes &amp;amp; NexusGenScalars

export interface NexusGenFieldTypes {
  AuthPayLoad: { // field return type
    token: string; // String!
    user: NexusGenRootTypes['User']; // User!
  }
  Mutation: { // field return type
    signinUser: NexusGenRootTypes['AuthPayLoad']; // AuthPayLoad!
    signupUser: NexusGenRootTypes['AuthPayLoad']; // AuthPayLoad!
  }
  Query: { // field return type
    ok: boolean; // Boolean!
  }
  User: { // field return type
    email: string; // String!
    fullname: string; // String!
    id: string; // String!
    password: string; // String!
    username: string; // String!
  }
}

export interface NexusGenFieldTypeNames {
  AuthPayLoad: { // field return type name
    token: 'String'
    user: 'User'
  }
  Mutation: { // field return type name
    signinUser: 'AuthPayLoad'
    signupUser: 'AuthPayLoad'
  }
  Query: { // field return type name
    ok: 'Boolean'
  }
  User: { // field return type name
    email: 'String'
    fullname: 'String'
    id: 'String'
    password: 'String'
    username: 'String'
  }
}

export interface NexusGenArgTypes {
  Mutation: {
    signinUser: { // args
      data: NexusGenInputs['SignInUserInput']; // SignInUserInput!
    }
    signupUser: { // args
      data: NexusGenInputs['SignupUserInput']; // SignupUserInput!
    }
  }
}

export interface NexusGenAbstractTypeMembers {
}

export interface NexusGenTypeInterfaces {
}

export type NexusGenObjectNames = keyof NexusGenObjects;

export type NexusGenInputNames = keyof NexusGenInputs;

export type NexusGenEnumNames = never;

export type NexusGenInterfaceNames = never;

export type NexusGenScalarNames = keyof NexusGenScalars;

export type NexusGenUnionNames = never;

export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never;

export type NexusGenAbstractsUsingStrategyResolveType = never;

export type NexusGenFeaturesConfig = {
  abstractTypeStrategies: {
    isTypeOf: false
    resolveType: true
    __typename: false
  }
}

export interface NexusGenTypes {
  context: any;
  inputTypes: NexusGenInputs;
  rootTypes: NexusGenRootTypes;
  inputTypeShapes: NexusGenInputs &amp;amp; NexusGenEnums &amp;amp; NexusGenScalars;
  argTypes: NexusGenArgTypes;
  fieldTypes: NexusGenFieldTypes;
  fieldTypeNames: NexusGenFieldTypeNames;
  allTypes: NexusGenAllTypes;
  typeInterfaces: NexusGenTypeInterfaces;
  objectNames: NexusGenObjectNames;
  inputNames: NexusGenInputNames;
  enumNames: NexusGenEnumNames;
  interfaceNames: NexusGenInterfaceNames;
  scalarNames: NexusGenScalarNames;
  unionNames: NexusGenUnionNames;
  allInputTypes: NexusGenTypes['inputNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['scalarNames'];
  allOutputTypes: NexusGenTypes['objectNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['unionNames'] | NexusGenTypes['interfaceNames'] | NexusGenTypes['scalarNames'];
  allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes']
  abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames'];
  abstractTypeMembers: NexusGenAbstractTypeMembers;
  objectsUsingAbstractStrategyIsTypeOf: NexusGenObjectsUsingAbstractStrategyIsTypeOf;
  abstractsUsingStrategyResolveType: NexusGenAbstractsUsingStrategyResolveType;
  features: NexusGenFeaturesConfig;
}

declare global {
  interface NexusGenPluginTypeConfig&amp;lt;TypeName extends string&amp;gt; {
  }
  interface NexusGenPluginInputTypeConfig&amp;lt;TypeName extends string&amp;gt; {
  }
  interface NexusGenPluginFieldConfig&amp;lt;TypeName extends string, FieldName extends string&amp;gt; {
  }
  interface NexusGenPluginInputFieldConfig&amp;lt;TypeName extends string, FieldName extends string&amp;gt; {
  }
  interface NexusGenPluginSchemaConfig {
  }
  interface NexusGenPluginArgConfig {
  }
}

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

&lt;/div&gt;



&lt;p&gt;If the file has not been updated, you might need to restart your server by running the following command:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Or you can run the &lt;code&gt;generate&lt;/code&gt; script if you don't feel like starting the server to update the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run generate

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Verifying a User's JSON Web Tokens
&lt;/h1&gt;

&lt;p&gt;Before we can create a new note or make any modifications to it, we need to verify the owner of the note first. We will be verifying the owner by decrypting the owner's JSON Web Tokens. The decrypted JWT contains the user's &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;username&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;id&lt;/code&gt; will be used to uniquely identify each user and their sticky notes. The user will be able to create, fetch, edit, and delete any notes that belong to them using the &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;src/index.ts&lt;/code&gt; file and import the &lt;code&gt;jsonwebtoken&lt;/code&gt; library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import jsonwebtoken from 'jsonwebtoken'

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

&lt;/div&gt;



&lt;p&gt;After the import, we'll create a new function that verifies the user's token right above the &lt;code&gt;startApolloServer()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getUser = (token: string, res: Response) =&amp;gt; {
  try {
    if (token) {
      return jsonwebtoken.verify(token, process.env.JWT_SECRET!)
    }
    res.clearCookie("access_token");
    return null
  } catch (error) {
    return null
  }
}

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;getUser&lt;/code&gt; function takes a user's token and the Express response object as parameters, then verifies and returns the user's token.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Null&lt;/code&gt; will be returned if either no token was supplied or if an error occurred while verifying the user's token.&lt;/p&gt;

&lt;p&gt;Now, let's update the &lt;code&gt;context&lt;/code&gt; object to return the decoded JWT so that it can be used in the resolver function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      context: async ({ req, res }:{req:Request, res:Response})=&amp;gt; {
        if (req) {
          const token = req.cookies.access_token || ""
          const user = getUser(token, res);
          return {
            user,
            res
          };
        }
        return {
          res
        }
      }

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

&lt;/div&gt;



&lt;p&gt;If a request is sent to our GraphQL server, we will get the tokens from the request cookies using &lt;code&gt;req.cookies.access_token&lt;/code&gt; or return an empty string(&lt;code&gt;""&lt;/code&gt;) if non was found using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;req.cookies.access_token || ""

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

&lt;/div&gt;



&lt;p&gt;We stored the decoded tokens into the &lt;code&gt;user&lt;/code&gt; variable. Both the &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;res&lt;/code&gt; object will be sent to the &lt;code&gt;context&lt;/code&gt; object whenever a user makes a &lt;code&gt;request&lt;/code&gt; to the server; otherwise, we'll simply return only the &lt;code&gt;res&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Let's update the express import to include the &lt;code&gt;Request&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import express, { Response, Request } from "express";

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining the Types for the Sticky Note
&lt;/h2&gt;

&lt;p&gt;Let's create a new file in &lt;code&gt;src/graphql&lt;/code&gt; called &lt;code&gt;Note.ts&lt;/code&gt; and import the following objects into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { extendType, objectType, inputObjectType, nonNull } from "nexus";
import noteModel from './../models/note';
import {GraphQLError} from "graphql"

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

&lt;/div&gt;



&lt;p&gt;We've already discussed what &lt;code&gt;extendType&lt;/code&gt;, &lt;code&gt;objectType&lt;/code&gt;, &lt;code&gt;inputObjectType&lt;/code&gt;, &lt;code&gt;nonNull&lt;/code&gt; and &lt;code&gt;GraphQLError&lt;/code&gt; are used for when we are creating the User types. In the second line, we imported the &lt;code&gt;noteModel&lt;/code&gt; we created previously.&lt;/p&gt;

&lt;p&gt;Below the imports, let's create a new &lt;code&gt;objectType&lt;/code&gt; called &lt;code&gt;Note&lt;/code&gt; and a new &lt;code&gt;inputObjectType&lt;/code&gt; called &lt;code&gt;NoteData&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Note = objectType({
    name: "Note",
    definition(t) {
        t.string("id");
        t.nonNull.string("content");
        t.nonNull.string("color");
        t.nonNull.string("userId");
    },
});
const NoteData = inputObjectType({
    name: "NoteData",
    definition(t) {
        t.nonNull.string("content");
        t.nonNull.string("color");
    },
});

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Note&lt;/code&gt; type has the following fields: &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, and &lt;code&gt;userId&lt;/code&gt; that can be used to query the notes.&lt;/p&gt;

&lt;p&gt;Also, we defined the following fields: &lt;code&gt;content&lt;/code&gt; and &lt;code&gt;color&lt;/code&gt; in the &lt;code&gt;NoteData&lt;/code&gt; type. Both fields have non-nullable string type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching All Notes Belonging to a User
&lt;/h2&gt;

&lt;p&gt;In this part, we will create our first GraphQL &lt;code&gt;query&lt;/code&gt; that will be used to fetch every note that belongs to a user.&lt;/p&gt;

&lt;p&gt;Type the following code below the &lt;code&gt;NoteData&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const AllNotes = extendType({
    type: 'Query',
    definition(t) {
        t.nonNull.list.field('allNotes', {
            type: Note,
            async resolve(_parent, _args, context, _info) {
                try {
                    const { user } = context;
                    if (!user) {
                        throw new GraphQLError('You are not authenticated', {
                            extensions: {
                              code: 'UNAUTHENTICATED',
                              http: { status: 401 },
                            }
                          });
                    }
                    const notes = await noteModel.find(
                        {
                            userId: user.id,
                        }
                    );
                    console.log(notes)
                    return notes;
                }
                catch (error) {
                    throw error;
                }
            }
        })
    }
});

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

&lt;/div&gt;



&lt;p&gt;Using the Nexus &lt;code&gt;extendType&lt;/code&gt; function, we extended the GraphQL &lt;code&gt;query&lt;/code&gt; root type and added a new root field to it called &lt;code&gt;allNotes&lt;/code&gt;. This time, we extended the GraphQL &lt;code&gt;query&lt;/code&gt; root type instead of the &lt;code&gt;mutation&lt;/code&gt; type because we are only fetching from the database and no modifications will be made to the note data.&lt;/p&gt;

&lt;p&gt;We defined the return type of the query as an array of the &lt;code&gt;Note&lt;/code&gt; type we created previously. Then we created a resolver function for the &lt;code&gt;allNotes&lt;/code&gt; query named &lt;code&gt;resolve&lt;/code&gt;. We performed all the operations that fetch the user's note inside the resolver function.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;context&lt;/code&gt; is the only argument we're using on this field's resolver function, so we prefixed &lt;code&gt;_parent&lt;/code&gt;, &lt;code&gt;_args&lt;/code&gt;, and &lt;code&gt;_info&lt;/code&gt; with an underscore(&lt;code&gt;_&lt;/code&gt;). Using the object destructuring method, we unpacked the &lt;code&gt;user&lt;/code&gt; object that was passed down to the &lt;code&gt;resolver&lt;/code&gt; via the &lt;code&gt;context&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;In the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!user) {
    throw new GraphQLError('You are not authenticated', {
       extensions: {
          code: 'UNAUTHENTICATED',
             http: { status: 401 },
                }
             });
          }

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

&lt;/div&gt;



&lt;p&gt;We checked if the &lt;code&gt;user&lt;/code&gt; object passed down from &lt;code&gt;context&lt;/code&gt; is valid. Remember, we returned a &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy" rel="noopener noreferrer"&gt;falsy&lt;/a&gt; value if the token is empty or not successfully decoded, and we returned the &lt;code&gt;user&lt;/code&gt; if the token was successful in the &lt;code&gt;getUser&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;user&lt;/code&gt; value is &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy" rel="noopener noreferrer"&gt;falsy&lt;/a&gt;, we will throw an &lt;code&gt;UNAUTHENTICATED&lt;/code&gt; error, but if the user is valid, then we will fetch all the notes that belong to the user by executing the following Mongoose query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const notes = await noteModel.find(
                     {
                            userId: user.id,
                        }
                    );

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

&lt;/div&gt;



&lt;p&gt;The query above will search for all the notes whose &lt;code&gt;userId&lt;/code&gt; matches the id of the user that is currently logged in, then stores the results into the &lt;code&gt;notes&lt;/code&gt; variable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching a Single Note
&lt;/h2&gt;

&lt;p&gt;Let's create another query that will be used to fetch a single note for an authenticated user. The user will have to provide the &lt;code&gt;id&lt;/code&gt; of the note to be fetched. Add the following code below the &lt;code&gt;AllNotes&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const SingleNote = extendType({
    type: 'Query',
    definition(t) {
        t.nonNull.field('singleNote', {
            type: Note,
            args: {
                noteId: 'String',
            },
            async resolve(_parent, args, context, _info) {
                const { noteId } = args;
                const { user } = context;
                const userId = user.id
                if (!user) {
                    throw new GraphQLError('You are not authenticated', {
                        extensions: {
                          code: 'UNAUTHENTICATED',
                          http: { status: 401 },
                        }
                      });
                }
                try {
                    const noteDetails = await noteModel.findOne({ _id: noteId, userId });
                    if(!noteDetails){
                        throw new Error("Note not found");
                    }
                    return noteDetails;
                } catch (error) {
                    throw error;
                }
            },
        })
    }
});

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

&lt;/div&gt;



&lt;p&gt;We extended the &lt;code&gt;Query&lt;/code&gt; root type again and added a new root field to it called &lt;code&gt;singleNote&lt;/code&gt;. After that, we defined the return type of the &lt;code&gt;singleNote&lt;/code&gt; query as a non-nullable &lt;code&gt;Note&lt;/code&gt; &lt;code&gt;objectType&lt;/code&gt;. Also, we defined the expected argument for the &lt;code&gt;singleNote&lt;/code&gt; query (&lt;code&gt;noteId&lt;/code&gt;) as a &lt;code&gt;string&lt;/code&gt;. Then we created a resolver function named &lt;code&gt;resolve&lt;/code&gt; that query the database for the note.&lt;/p&gt;

&lt;p&gt;We used the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const noteDetails = await noteModel.findOne({ _id: noteId, userId });

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

&lt;/div&gt;



&lt;p&gt;to fetch the first note that matches the &lt;code&gt;id&lt;/code&gt; and the &lt;code&gt;userId&lt;/code&gt; provided then stores the query result into &lt;code&gt;noteDetails&lt;/code&gt; variable. We used the following snippets to throw a not found error if the note was not found:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(!noteDetails){
                        throw new Error("Note not found");
                    }

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating A New Note
&lt;/h2&gt;

&lt;p&gt;Now that we are done implementing the &lt;code&gt;singleNote&lt;/code&gt; query, let's create our first &lt;code&gt;mutation&lt;/code&gt; for the sticky note by adding a new type that will be used to create a new note.&lt;/p&gt;

&lt;p&gt;Type the following code below the &lt;code&gt;SingleNote&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const NewNote = extendType({
    type: 'Mutation',
    definition(t) {
        t.nonNull.field('newNote', {
            type: Note,
            args: {
                data: nonNull(NoteData)
            },
            async resolve(_parent, args, context, _info) {
                const { data } = args;
                const { user } = context;
                try {
                    if (!user) {
                        throw new GraphQLError('You are not authenticated', {
                            extensions: {
                              code: 'UNAUTHENTICATED',
                              http: { status: 401 },
                            }
                          });
                    }
                    const createdNoted = await noteModel.create({
                        content: data.content, color: data.color || 'yellow', userId: user.id
                    });
                    return createdNoted;
                } catch (error) {
                    throw error;
                }
            }
        })
    }
});

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

&lt;/div&gt;



&lt;p&gt;We extended the &lt;code&gt;Mutation&lt;/code&gt; root type and added a new root field to it called &lt;code&gt;newNote&lt;/code&gt;. Then we defined the return type of the &lt;code&gt;newNote&lt;/code&gt; mutation as non-nullable &lt;code&gt;Note&lt;/code&gt; type. Also, we defined the expected argument as a non-nullable &lt;code&gt;noteData&lt;/code&gt; type. After that, we created a resolver function that creates the user's note if the user is authenticated.&lt;/p&gt;

&lt;p&gt;We used the following queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const createdNoted = await noteModel.create({
                        content: data.content, color: data.color || 'yellow', userId: user.id
                    });

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

&lt;/div&gt;



&lt;p&gt;to create a new note document with the provided &lt;code&gt;content&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt; and &lt;code&gt;userId&lt;/code&gt; by using the &lt;code&gt;create()&lt;/code&gt; function in Mongoose.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;data.color || 'yellow'&lt;/code&gt; means yellow will be used as the default &lt;code&gt;color&lt;/code&gt; if the &lt;code&gt;color&lt;/code&gt; args wasn't provided.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modifying an existing Note
&lt;/h2&gt;

&lt;p&gt;In this part, we are going to create a new type that edits an existing note belonging to a user. To know the specific note that the user wants to modify, the note &lt;code&gt;id&lt;/code&gt; must be provided as an argument.&lt;/p&gt;

&lt;p&gt;Let's add the following code below the &lt;code&gt;NewNote&lt;/code&gt; type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const ModifyNote = extendType({
    type: 'Mutation',
    definition(t) {
        t.nonNull.field('modifyNote', {
            type: Note,
            args: {
                noteId: nonNull('String'),
                data: nonNull(NoteData)
            },
            async resolve(_parent, args, context, _info) {
                const { noteId, data: { content, color } } = args;
                const { user } = context;
                if (!user) {
                    throw new GraphQLError('You are not authenticated', {
                        extensions: {
                          code: 'UNAUTHENTICATED',
                          http: { status: 401 },
                        }
                      });
                }
                try {
                    const modifiedNote = await noteModel.findOneAndUpdate(
                        {
                            _id: noteId, userId: user.id,
                        },
                        { content, color },
                        {
                            runValidators: true,
                            new: true,
                        }
                    );
                    if (!modifiedNote) {
                        throw new Error("Unable to update note");
                    }
                    console.log(modifiedNote)
                    return modifiedNote;
                } catch (error) {
                    throw error;
                }
            }
        })
    }
});

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

&lt;/div&gt;



&lt;p&gt;Here's the summary of what we did in the code above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We created a new field called &lt;code&gt;modifyNote&lt;/code&gt; that extends the GraphQL &lt;code&gt;Mutation&lt;/code&gt; root type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We defined &lt;code&gt;Note&lt;/code&gt; type as the return type for the field&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;we defined &lt;code&gt;noteId&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; as the expected argument for the &lt;code&gt;modifyNote&lt;/code&gt; mutation. The &lt;code&gt;noteId&lt;/code&gt; will be used used to search for the specific note that a user wants to modify. The note &lt;code&gt;data&lt;/code&gt; will be used to make changes to the note when found.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;noteId&lt;/code&gt; argument is a non-nullable &lt;code&gt;String&lt;/code&gt; while the type for the &lt;code&gt;data&lt;/code&gt; argument is non-nullable &lt;code&gt;NoteData&lt;/code&gt; type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We created a resolver function named &lt;code&gt;resolve&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The resolver function checks if a user is authenticated, then modifies the user's note if the user is confirmed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The following query:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const modifiedNote = await noteModel.findOneAndUpdate(
                        {
                            _id: noteId, userId: user.id,
                        },
                        { content, color },
                        {
                            runValidators: true,
                            new: true,
                        }
                    );

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;uses the &lt;code&gt;findOneAndUpdate&lt;/code&gt; function in Mongoose to search for the first note that matches the &lt;code&gt;noteId&lt;/code&gt; and &lt;code&gt;userId&lt;/code&gt; provided in the arguments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;by default, Mongoose does not run validation on updates. We need to set the &lt;code&gt;runValidators&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt; every time we call the &lt;code&gt;findOneAndUpdate&lt;/code&gt; or any &lt;code&gt;update&lt;/code&gt; method to run the update validators on the query.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;also by default, &lt;code&gt;findOneAndUpdate&lt;/code&gt; does not return the updated document, it returns the document as it was before the update was applied. Setting the &lt;code&gt;new&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt; will return the updated document instead of the old document.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;we saved the result of the query to &lt;code&gt;modifiedNote&lt;/code&gt; variable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then return the &lt;code&gt;modifiedNote&lt;/code&gt; if the update was successful or throw the &lt;code&gt;Unable to update note&lt;/code&gt; error if it wasn't.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deleting a Note
&lt;/h2&gt;

&lt;p&gt;Let's perform the final &lt;code&gt;mutation&lt;/code&gt; on this app by creating a new type that deletes a user's note. Only notes that the user has added can be deleted. To delete a note, the &lt;code&gt;noteId&lt;/code&gt; must be provided.&lt;/p&gt;

&lt;p&gt;Type the following code below the &lt;code&gt;ModifyNote&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const DeleteNote = extendType({
    type: 'Mutation',
    definition(t) {
        t.nonNull.field('deleteNote', {
            type: Note,
            args: {
                noteId: nonNull('String')
            },
            async resolve(_parent, args, context, _info) {
                const { noteId } = args;
                const { user } = context;
                if (!user) {
                    throw new GraphQLError('You are not authenticated', {
                        extensions: {
                          code: 'UNAUTHENTICATED',
                          http: { status: 401 },
                        }
                      });
                }
                try {
                    const deletedNote = await noteModel.findOneAndDelete({
                        _id: noteId,
                        userId: user.id,
                    });
                    if (!deletedNote) {
                        throw new Error(" Note not found");
                    }
                    return deletedNote;
                } catch (error) {
                    throw error;
                }
            },
        })
    }
});

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We extended the &lt;code&gt;Mutation&lt;/code&gt; root type and added a new root field to it called &lt;code&gt;deleteNote&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The return type for the &lt;code&gt;deleteNote&lt;/code&gt; field is defined as non-nullable &lt;code&gt;Note&lt;/code&gt; type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We also defined the &lt;code&gt;noteId&lt;/code&gt; as the expected argument for the &lt;code&gt;deleteNote&lt;/code&gt; mutation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the &lt;code&gt;noteId&lt;/code&gt; has a non-nullable &lt;code&gt;String&lt;/code&gt; type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We created a resolver function named &lt;code&gt;resolve&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The resolver function deletes the note after verifying the user&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the following query:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const deletedNote = await noteModel.findOneAndDelete({
                        _id: noteId,
                        userId: user.id,
                    });

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

&lt;/div&gt;



&lt;p&gt;searches for the first note that matches the &lt;code&gt;noteId&lt;/code&gt; and the &lt;code&gt;userId,&lt;/code&gt; deletes it, and then stores the deleted note into the &lt;code&gt;deletedNote&lt;/code&gt; variable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We return an error if the delete wasn't successful&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;or return the deleted note if the note was successfully removed from the database.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Generating the Note Schemas with Nexus
&lt;/h2&gt;

&lt;p&gt;Let's connect all our exported note types to the &lt;code&gt;makeSchema&lt;/code&gt; function. Open the &lt;code&gt;src/graphql/index.ts&lt;/code&gt; file and add the following code below the user export that was there before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export * from "./Note";

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

&lt;/div&gt;



&lt;p&gt;So everything looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export * from "./User"; 
export * from "./Note";

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

&lt;/div&gt;



&lt;p&gt;If we check the &lt;code&gt;schema.graphql&lt;/code&gt; file now, we will notice that all the note types we created earlier have been converted to GraphQL schemas by Nexus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### This file was generated by Nexus Schema
### Do not make changes to this file directly

type AuthPayLoad {
  token: String!
  user: User!
}

type Mutation {
  deleteNote(noteId: String!): Note!
  modifyNote(data: NoteData!, noteId: String!): Note!
  newNote(data: NoteData!): Note!
  signinUser(data: SignInUserInput!): AuthPayLoad!
  signupUser(data: SignupUserInput!): AuthPayLoad!
}

type Note {
  color: String!
  content: String!
  id: String
  userId: String!
}

input NoteData {
  color: String!
  content: String!
}

type Query {
  allNotes: [Note]!
  singleNote(noteId: String): Note!
}

input SignInUserInput {
  password: String!
  usernameOrEmail: String!
}

input SignupUserInput {
  email: String!
  fullname: String!
  password: String!
  username: String!
}

type User {
  email: String!
  fullname: String!
  id: String!
  password: String!
  username: String!
}

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

&lt;/div&gt;



&lt;p&gt;These are the GraphQL Schema Definition Language (SDL) codes that were generated by Nexus from the &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Note&lt;/code&gt; type codes that we wrote previously.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;AuthPayLoad&lt;/code&gt; type represents the payload that is returned when a user successfully signs in or signs up. It has two fields: &lt;code&gt;token&lt;/code&gt; (which is a string representing an authentication token) and &lt;code&gt;user&lt;/code&gt; (which is an object of type &lt;code&gt;User&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Note&lt;/code&gt; type represents a note object. It has four fields: &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, and &lt;code&gt;userId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;NoteData&lt;/code&gt; input type represents the data that is passed as an argument to the &lt;code&gt;newNote&lt;/code&gt; and &lt;code&gt;modifyNote&lt;/code&gt; mutations. It has two fields: &lt;code&gt;content&lt;/code&gt; and &lt;code&gt;color&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SignInUserInput&lt;/code&gt; and &lt;code&gt;SignupUserInput&lt;/code&gt; input types represent the data that is passed as an argument to the &lt;code&gt;signinUser&lt;/code&gt; and &lt;code&gt;signupUser&lt;/code&gt; mutations. They have different fields, depending on the information that is needed to sign in or sign up.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;User&lt;/code&gt; type represents a user object. It has five fields: &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;fullname&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;, and &lt;code&gt;username&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Mutation&lt;/code&gt; type represents the root type for GraphQL mutations in this API. It has five fields: &lt;code&gt;deleteNote&lt;/code&gt;, &lt;code&gt;modifyNote&lt;/code&gt;, &lt;code&gt;newNote&lt;/code&gt;, &lt;code&gt;signinUser&lt;/code&gt;, and &lt;code&gt;signupUser&lt;/code&gt; each of which corresponds to a different mutation that can be performed.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Query&lt;/code&gt; type represents the root type for GraphQL queries in this API. It has two fields: &lt;code&gt;allNotes&lt;/code&gt; and &lt;code&gt;singleNote&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing the GraphQL APIs with Postman
&lt;/h1&gt;

&lt;p&gt;One of the easiest and fastest ways to test our GraphQL API endpoints locally is through &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt;. Postman is a powerful software for testing API requests, inspecting their responses, and easily debugging them. Click &lt;a href="https://www.postman.com/downloads/" rel="noopener noreferrer"&gt;here&lt;/a&gt; to download and install it if you don't have it already.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changing the &lt;code&gt;Secure&lt;/code&gt; Cookie Attribute to &lt;code&gt;false&lt;/code&gt; for testing purposes only
&lt;/h2&gt;

&lt;p&gt;We need to modify a few settings specifically for these tests in order to test our APIs.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;.env&lt;/code&gt; file and change the &lt;code&gt;SECURE_COOKIE&lt;/code&gt; from &lt;code&gt;true&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;. Without changing it, Postman will not send the cookies along with the request any time an authenticated user tries to access a secure endpoint (or maybe Postman sent it but the server rejected).&lt;/p&gt;

&lt;p&gt;Changing the setting like that will make our website vulnerable, but we are only doing this for testing our API in development mode only. During production, the &lt;code&gt;secure&lt;/code&gt; attribute must be set back to &lt;code&gt;true&lt;/code&gt; because we set the &lt;code&gt;sameSite&lt;/code&gt; attribute to &lt;code&gt;none&lt;/code&gt;. Doing this is one of many ways to prevent &lt;a href="https://www.imperva.com/learn/application-security/csrf-cross-site-request-forgery/" rel="noopener noreferrer"&gt;Cross-site request forgery&lt;/a&gt; on the website.&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing the &lt;code&gt;signupUser&lt;/code&gt; Mutation
&lt;/h1&gt;

&lt;p&gt;Launch your Postman and make sure your development server is running already at &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt;. If it isn't, run the following command to start it:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Create a new collection by clicking on the &lt;code&gt;Collections&lt;/code&gt; tab, then click on the plus icon. You will be prompted to give your collection a name, let's name it &lt;code&gt;Sticky Notes&lt;/code&gt; for now. You can rename it later if you prefer. Right-click on the created &lt;code&gt;Sticky Notes&lt;/code&gt; collection or click on the three dots option button on it, then select &lt;code&gt;Add request&lt;/code&gt; from the drop-down options. Name the request &lt;code&gt;SignupUser&lt;/code&gt;. After that, change the request method from &lt;code&gt;GET&lt;/code&gt; to &lt;code&gt;POST&lt;/code&gt;. The &lt;code&gt;Post&lt;/code&gt; request method is the method we are going to use throughout our test.&lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt; in the URL text box. Below the URL textbox, select &lt;code&gt;Body&lt;/code&gt; from the options tab, then select the &lt;code&gt;GraphQL&lt;/code&gt; radio button.&lt;/p&gt;

&lt;p&gt;After that, you will be presented with two text-area boxes named: &lt;code&gt;QUERY&lt;/code&gt; and &lt;code&gt;GRAPHQL VARIABLES&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Type the following queries into the &lt;code&gt;QUERY&lt;/code&gt; box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutation SignupUser($data: SignupUserInput!) {
  signupUser(data: $data) {
    token
    user {
      email
      fullname
      id
      password
      username
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;And type the following into &lt;code&gt;GRAPHQL VARIABLES&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": {
    "email": "janedoe@email.com",
    "fullname": "Jane Doe",
    "password": "invisible",
    "username": "janedoe"
  }
}

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

&lt;/div&gt;



&lt;p&gt;Then click on the &lt;strong&gt;Send&lt;/strong&gt; button&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zo8syu65a7xb31p2jwv.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%2F0zo8syu65a7xb31p2jwv.png" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a successful registration, click on the &lt;code&gt;Cookies&lt;/code&gt; below the &lt;strong&gt;Send&lt;/strong&gt; button, you will see the &lt;code&gt;access_token&lt;/code&gt; cookies sent from our GraphQL server. This token will be automatically attached to every request from now until we signout or maybe when it expires.&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing the &lt;code&gt;signinUser&lt;/code&gt; Mutation
&lt;/h1&gt;

&lt;p&gt;To test the &lt;code&gt;signinUser&lt;/code&gt; mutation, we'll add another request to the &lt;strong&gt;Sticky Notes&lt;/strong&gt; collection and name it &lt;code&gt;SigninUser&lt;/code&gt;. Then change the request method from &lt;code&gt;GET&lt;/code&gt; to &lt;code&gt;POST&lt;/code&gt;, and enter &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt; in the URL textbox. Select &lt;code&gt;Body&lt;/code&gt; in the options tab below the URL textbox, then check the &lt;code&gt;GraphQL&lt;/code&gt; radio button.&lt;/p&gt;

&lt;p&gt;Type the following queries into the &lt;code&gt;QUERY&lt;/code&gt; box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutation SignupUser($data: SignInUserInput!) {
  signinUser(data: $data) {
    token
    user {
      email
      fullname
      id
      password
      username
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;And type the following into the &lt;code&gt;GRAPHQL VARIABLES&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": {
    "password": "invisible",
    "usernameOrEmail": "janedoe"
  }
}

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

&lt;/div&gt;



&lt;p&gt;Then click on the &lt;strong&gt;Send&lt;/strong&gt; button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84sza4xwkgqckidsqwn5.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%2F84sza4xwkgqckidsqwn5.png" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing the &lt;code&gt;newNote&lt;/code&gt; Mutation
&lt;/h1&gt;

&lt;p&gt;To test the &lt;code&gt;NewNote&lt;/code&gt; mutation, we'll go through the same process we've been following since, we'll add another request to the &lt;strong&gt;Sticky Notes&lt;/strong&gt; collection and name it &lt;code&gt;NewNote&lt;/code&gt;. Then change the request method from &lt;code&gt;GET&lt;/code&gt; to &lt;code&gt;POST&lt;/code&gt;, and enter &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt; in the URL textbox. Select &lt;code&gt;Body&lt;/code&gt; in the options tab below the URL textbox, then check the &lt;code&gt;GraphQL&lt;/code&gt; radio button.&lt;/p&gt;

&lt;p&gt;Type the following queries into the &lt;code&gt;QUERY&lt;/code&gt; box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutation NewNote($data: NoteData!) {
  newNote(data: $data) {
    color
    content
    id
    userId
  }
}

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

&lt;/div&gt;



&lt;p&gt;GRAPHQL VARIABLES:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": {
    "content": "sample",
    "color": "yellow"
  }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fos3eap2bctuuurblzgbm.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%2Fos3eap2bctuuurblzgbm.png" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing the &lt;code&gt;modifyNote&lt;/code&gt; Mutation
&lt;/h1&gt;

&lt;p&gt;Add another request to the &lt;strong&gt;Sticky Notes&lt;/strong&gt; collection and name it &lt;code&gt;ModifyNote&lt;/code&gt; . Then change the request method from &lt;code&gt;GET&lt;/code&gt; to &lt;code&gt;POST&lt;/code&gt;, and enter &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt; in the URL textbox. Select &lt;code&gt;Body&lt;/code&gt; in the options tab below the URL textbox, then check the &lt;code&gt;GraphQL&lt;/code&gt; radio button.&lt;/p&gt;

&lt;p&gt;Type the following queries into the &lt;code&gt;QUERY&lt;/code&gt; box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutation ModifyNote($noteId: String!, $data: NoteData!) {
  modifyNote(noteId: $noteId, data: $data) {
    color
    content
    id
    userId
  }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;GRAPHQL VARIABLES:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  { "noteId": "639a7cf1946da6008c0aba01",
  "data": {
    "content": "Note sample modified",
    "color": "green"
  }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdj5vycb06lg8fwwipkqy.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%2Fdj5vycb06lg8fwwipkqy.png" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing the &lt;code&gt;allNotes&lt;/code&gt; Query
&lt;/h1&gt;

&lt;p&gt;To fetch all the sticky notes belonging to a user, add another request to the &lt;strong&gt;Sticky Notes&lt;/strong&gt; collection and name it &lt;code&gt;AllNotes&lt;/code&gt;. Then change the request method from &lt;code&gt;GET&lt;/code&gt; to &lt;code&gt;POST&lt;/code&gt;, and enter &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt; in the URL textbox. Select &lt;code&gt;Body&lt;/code&gt; in the options tab below the URL textbox, then check the &lt;code&gt;GraphQL&lt;/code&gt; radio button.&lt;/p&gt;

&lt;p&gt;Type the following queries into the &lt;code&gt;QUERY&lt;/code&gt; box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query AllNotes {
  allNotes {
    id
    content
    color
    userId
  }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvd15fx3tazi3no7bl5gx.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%2Fvd15fx3tazi3no7bl5gx.png" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing the &lt;code&gt;deleteNote&lt;/code&gt; Mutation
&lt;/h1&gt;

&lt;p&gt;To delete a note, add another request to the &lt;strong&gt;Sticky Notes&lt;/strong&gt; collection and name it &lt;code&gt;DeleteNote&lt;/code&gt;. Then change the request method from &lt;code&gt;GET&lt;/code&gt; to &lt;code&gt;POST&lt;/code&gt;, and enter &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt; in the URL textbox. Select &lt;code&gt;Body&lt;/code&gt; in the options tab below the URL textbox, then check the &lt;code&gt;GraphQL&lt;/code&gt; radio button.&lt;/p&gt;

&lt;p&gt;Type the following queries into the &lt;code&gt;QUERY&lt;/code&gt; box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutation Mutation($noteId: String!) {
  deleteNote(noteId: $noteId) {
    color
    content
    userId
    id
  }
}

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

&lt;/div&gt;



&lt;p&gt;GRAPHQL VARIABLES:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "noteId": "639a7cf1946da6008c0aba01"
}

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Testing the &lt;code&gt;signoutUser&lt;/code&gt; Mutation
&lt;/h1&gt;

&lt;p&gt;To test the &lt;code&gt;signoutUser&lt;/code&gt; Mutation, add another request to the &lt;strong&gt;Sticky Notes&lt;/strong&gt; collection and name it &lt;code&gt;DeleteNote&lt;/code&gt;. Then change the request method from &lt;code&gt;GET&lt;/code&gt; to &lt;code&gt;POST&lt;/code&gt;, and enter &lt;code&gt;http://localhost:4000/graphql&lt;/code&gt; in the URL textbox. Select &lt;code&gt;Body&lt;/code&gt; in the options tab below the URL textbox, then check the &lt;code&gt;GraphQL&lt;/code&gt; radio button.&lt;/p&gt;

&lt;p&gt;Type the following queries into the &lt;code&gt;QUERY&lt;/code&gt; box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutation signoutUser {
  signoutUser
}

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwssein8z4dwjt1s0yz2.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%2Fwwssein8z4dwjt1s0yz2.png" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you click on "Cookies" below the send button after signing out the user, you will see that the access token cookies have been deleted:&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%2F0cns5myotedqjl437ovs.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%2F0cns5myotedqjl437ovs.png" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In this section, we built the GraphQL server for the Sticky Note app using Apollo Server 4, Express.js, and MongoDB, following the code-first approach. We then defined various types and fields that can be used to query and modify the API. Finally, we tested the GraphQL APIs using Postman.&lt;/p&gt;

&lt;p&gt;In the next section, we will make the frontend aspect built in the previous part communicate with the GraphQL APIs built in this section.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>apolloserver</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Learn Full-Stack Web Development with React and GraphQL by Building a Sticky Note App - Part one</title>
      <dc:creator>Temitope</dc:creator>
      <pubDate>Mon, 09 Jan 2023 16:42:43 +0000</pubDate>
      <link>https://dev.to/kingdavid/learn-full-stack-web-development-with-react-and-graphql-by-building-a-sticky-note-app-part-one-4kck</link>
      <guid>https://dev.to/kingdavid/learn-full-stack-web-development-with-react-and-graphql-by-building-a-sticky-note-app-part-one-4kck</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;👋 Hello everyone! This is a full-stack tutorial on how to build a Sticky Note app using GraphQL, React, and TypeScript.&lt;/p&gt;

&lt;p&gt;GraphQL is a modern and advanced way of creating APIs that provides a flexible and efficient way to request data from a server. It was developed by Facebook and released publicly in 2015.&lt;/p&gt;

&lt;p&gt;One of the major selling points of GraphQL is that it allows the client to request only the data it needs, nothing more and nothing less, rather than getting a fixed set of data from an endpoint. This can be more efficient and reduce the amount of data transferred over the network, which can be particularly useful when building mobile applications or when working with limited bandwidth.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are We building?
&lt;/h2&gt;

&lt;p&gt;We are developing &lt;a href="http://sticky-note-app.vercel.app" rel="noopener noreferrer"&gt;Sticky Notes,&lt;/a&gt; a full-stack note-taking web application that enables you to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create and edit notes:&lt;/strong&gt; create and manage your sticky notes everywhere you are on your computer or mobile device.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customize appearance:&lt;/strong&gt; The background colors of your Sticky Notes can be changed and you can choose from seven different theme colors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create an account:&lt;/strong&gt; sign up and create a new account to keep all your notes secure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auto-Save:&lt;/strong&gt; Automatically save changes to your note as you are typing them, ensuring that changes to a note are not lost, even if the app or device crashes or the user closes the browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manually save note:&lt;/strong&gt; You can also manually save your note by clicking on the save icon.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Minimize or Maximize note:&lt;/strong&gt; Maximize your note to concentrate only on the note you are working on or you can minimize to see all the notes you are working on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Delete Note&lt;/strong&gt; : You can permanently remove your Sticky Notes if they are no longer needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The Structure of this Tutorial
&lt;/h1&gt;

&lt;p&gt;This tutorial is divided into three parts: &lt;strong&gt;frontend&lt;/strong&gt; , &lt;strong&gt;backend&lt;/strong&gt; , and &lt;strong&gt;fullstack&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Frontend
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;frontend section&lt;/strong&gt; will focus on building the app using only React and TypeScript. We will use React to create the user interface and manage the state of the app. The purpose of this part is to demonstrate how the app works with React state before transitioning to using the Apollo GraphQL Client in the final section.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Backend
&lt;/h2&gt;

&lt;p&gt;This is the second part of the tutorial. In this section, we will build the GraphQL server for the app using Apollo Server 4, Express.js, Nexus, and MongoDB. We will define the schema and resolvers for our GraphQL API, as well as handle authentication, authorization, and data persistence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fullstack
&lt;/h2&gt;

&lt;p&gt;This is the final part of the tutorial. In this part, we will make the frontend communicate with the GraphQL server built in the backend and migrate the app state from the React state to the Apollo client cache.&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;To get started with the frontend aspect of this tutorial, it is assumed that you are familiar with the following tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HTML and CSS&lt;/strong&gt; : Since most of the HTML and CSS code used in this tutorial won't be discussed, a good understanding of HTML and CSS is expected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JavaScript&lt;/strong&gt; : A good knowledge of JavaScript is required. If you are already familiar with ES6 features such as the fat arrow function and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment" rel="noopener noreferrer"&gt;object destructuring&lt;/a&gt;, you are ready to go.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;React&lt;/strong&gt; : You are good to go if you have interacted with a React state and component or, even better, created a to-do app with React.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TypeScript:&lt;/strong&gt; Basic knowledge of TypeScript is what is needed here; if you already know what TypeScript is and why it's being used in the tech industry, along with your JavaScript skills, you're set to start.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Tools
&lt;/h1&gt;

&lt;p&gt;The following tools will be used to build the frontend aspect of this tutorial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Nodejs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TypeScript&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nextjs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Font Awesome&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The GitHub Repository for this Project
&lt;/h1&gt;

&lt;p&gt;The GitHub repository containing the finished code for this app can be found here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend:&lt;/strong&gt; &lt;a href="https://github.com/tope-olajide/sticky-note-react" rel="noopener noreferrer"&gt;https://github.com/tope-olajide/sticky-note-react&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend:&lt;/strong&gt; &lt;a href="https://github.com/tope-olajide/sticky-notes-backend" rel="noopener noreferrer"&gt;https://github.com/tope-olajide/sticky-notes-backend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fullstack:&lt;/strong&gt; &lt;a href="https://github.com/tope-olajide/sticky-notes" rel="noopener noreferrer"&gt;https://github.com/tope-olajide/sticky-notes&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Deployed Website
&lt;/h1&gt;

&lt;p&gt;I deployed the frontend code of this project on &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; and hosted the backend code on &lt;a href="https://render.com" rel="noopener noreferrer"&gt;Render&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can use the following link to view the deployed website for each section:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend:&lt;/strong&gt; &lt;a href="http://sticky-note-react.vercel.app" rel="noopener noreferrer"&gt;sticky-note-react.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend:&lt;/strong&gt; &lt;a href="https://sticky-note-app.onrender.com/graphql" rel="noopener noreferrer"&gt;https://sticky-note-app.onrender.com/graphql&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fullstack:&lt;/strong&gt; &lt;a href="http://sticky-note-app.vercel.app" rel="noopener noreferrer"&gt;sticky-note-app.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting Started
&lt;/h1&gt;

&lt;p&gt;Create a new directory called &lt;code&gt;sticky-note-frontend&lt;/code&gt;. Navigate to the folder on your &lt;code&gt;termainal&lt;/code&gt; and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn create next-app --typescript

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

&lt;/div&gt;



&lt;p&gt;When asked for your project name, either type &lt;code&gt;./&lt;/code&gt; to use the name of your current folder or manually type in the name of your project.&lt;/p&gt;

&lt;p&gt;Next, you will be prompted to decide if you will like to use &lt;code&gt;ESLint&lt;/code&gt;, select &lt;code&gt;Yes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that, you'll need to wait for some seconds for Nextjs to finish installing TypeScript, React, and other dependencies.&lt;/p&gt;

&lt;p&gt;After the installations, Nextjs will set up TypeScript support for our project and add a few folders and files to the root directory.&lt;/p&gt;

&lt;p&gt;Let's install font awesome by running the following command on 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;yarn add @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/react-fontawesome

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

&lt;/div&gt;



&lt;p&gt;Finally, we can run the following command on the terminal to start our frontend development server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn run dev

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

&lt;/div&gt;



&lt;p&gt;The command will start our frontend &lt;strong&gt;development server&lt;/strong&gt; on the following URL: &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Launch your browser and visit: &lt;code&gt;http://localhost:3000&lt;/code&gt; on it, you should see a " &lt;strong&gt;Welcome to Next.js!"&lt;/strong&gt; screen that 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5j9l1yj6oajrrje2h4xr.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%2F5j9l1yj6oajrrje2h4xr.png" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, Next.js will look for a file at &lt;code&gt;pages/index.ts&lt;/code&gt; and render the contents of that file as the default page for the root URL. If a file at &lt;code&gt;pages/index.ts&lt;/code&gt; does not exist, Next.js will display an error message.&lt;/p&gt;

&lt;p&gt;We will be modifying the &lt;code&gt;pages/index.ts&lt;/code&gt; file soon but before then, let's create a new folder inside the root directory called: &lt;code&gt;components&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;components&lt;/code&gt; folder will be used to store all the react components that we will be creating very soon.&lt;/p&gt;

&lt;h1&gt;
  
  
  Updating the &lt;code&gt;styles/global.css&lt;/code&gt; file
&lt;/h1&gt;

&lt;p&gt;Open up the &lt;code&gt;styles/global.css&lt;/code&gt; file in your editor and replace everything inside with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: #F8FAFE;
  overflow: auto;

}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}
.main-container {
 min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.card, .delete-note-modal{
  width: 300px;
  height: 350px;
  background-color: #f9e675;
   box-shadow: 0 8px 16px 0 rgba(0,0,0,0.4); 
  border: 1px solid rgb(0, 0, 0,.5);
  margin: 1rem;
}
.delete-note-modal {
text-align: center;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
.delete-note-modal h3 {
  margin: 0 0 1rem 0;
}

.delete-note-modal button {
  width: 90%;
  background-color: rgb(31, 15, 15);
}
.card-maximized {
  width: 100%;
  height: 100%;
  background-color: #f9e675;
  box-shadow: 0 8px 16px 0 rgba(0,0,0,0.4);
  border: 1px solid rgb(0, 0, 0,.5);
  position: fixed
  ;
  z-index: 10;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  top: 0;

}
.card-header {
 height: 10%;
}

.card-body {
  background-color: rgba(253, 253, 253, 0.4);
  height: 80%;
}

.text-area {
width: 100%;
height: 100%;
background-color: transparent;
border: none;
outline: none;
color: black;
z-index: 5;
resize: none;
font-size: 1rem;
font-family: 'Segoe UI', 'Roboto', 'Oxygen';
font-weight: 400;

}

.text-container{
width: 90%;
height: 100%;
margin: 0 auto;
}

.card-footer {
  width: 100%;
  height: 10%;
  border-top: 1px solid rgba(0, 0, 0, 0.4);
}

.icon-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 100%;
}

.right-icon, .left-icon {
    display: flex;
}

.icon {
  margin: 3px;
  color: rgb(12, 11, 11);
  padding: 5px 7px;
  cursor: pointer;
  opacity: .8;
  font-size: 1.2rem;
}

.icon:hover {
  background-color: rgba(10, 10, 9, 0.2);
  opacity: 1;
}

.theme-color-container {
  width: 100%;
  height: 100%;
  display: flex;
  background-color: black;
}

.theme-color:hover {
  opacity: .9;
  cursor: pointer;
}

.yellow, .green, .pink, .purple, .blue, .gray, .charcoal {
  width: 14.3%;

}

.yellow, #yellow {
background-color: #f9e675;
}

.green, #green {  
  background-color: #b2ed9e ;
}
.pink, #pink {
  background-color: #f2b3e4;
}
.purple, #purple {
  background-color: #ceb1ff;
}
.blue, #blue {
  background-color: #addcfe;
}
.gray, #gray {
  background-color: #dcdee2;
}
.charcoal, #charcoal {
  background-color: #77797e;
}
.notes-container {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
}

.no-notes-container {
  display: flex;
  flex-direction: column;
  width: 350px;
  margin: 4rem auto;
  align-items: center;
  border: 1px solid rgba(0, 0, 0, 0.2);
  padding: 3rem 1rem;
  box-shadow: 0 2px 4px 0 rgba(0,0,0,0.4);
  background-color: #f9e675; ;
}
.no-notes-container button {
  background-color: #09060e; ;
}

.auth-container{
width: 350px;
margin: 2rem auto;
padding: 2rem;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.4);
background-color: white;
}

.auth-form{
flex-wrap: wrap;
display: flex;
width:320px;
margin: 0 auto;
justify-content: center;
}
.auth-container h3 {
 text-align: center;
}
input {
border: 1px solid black;
margin: .5rem;
padding: 1rem;
font-size: 1rem;
width:320px;
outline: none;
}

.navbar{
  background-color: rgb(34, 32, 32);
  padding: 1rem;box-shadow: 0 2px 4px 0 rgba(0,0,0,0.4);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.navbar h1{
  margin: 0;
  font-size: 1.3rem;
  padding-left: 1rem;
  color: white;
}

.navbar .menu {
  display: flex;
}

.navbar .menu h5{
  margin: 0;
  color: white;
  padding: 0 1rem;
  text-transform: uppercase;
}

.navbar .menu h5:hover {
  opacity: .8;
  cursor: pointer;
}

.welcome-text h2{
  text-align: center;
  text-transform: uppercase;
  margin: 2rem 0 0rem 0;
}

button {
  border: none;
  margin: .5rem;
  padding: 1rem;
  font-size: 1rem;
  width:320px;
  outline: none;
  background-color: blue;
  color: white;
  cursor: pointer;
}

button:hover {
  opacity: .7;
}
.logout-button{
  width: 80px;
  padding: .5rem;
  border-radius: 3px;
  margin: .1rem;
  font-size: .9rem;
}
.show-error{
  display: flex;
  flex-direction: column;
  align-items: center;
}
.show-error p {
  color: red;
  margin: 0;
  font-weight: 600;
}
.hide-error{
  display: none;
}
.error-icon {
margin:0;
color: red;
padding: .4rem;
}

.snackbar-container {
  min-width: 250px;
  background-color: rgb(29, 29, 32);
  color: #fff;
  text-align: center;
  border-radius: 2px;
  position: fixed;
  z-index: 1;
  right: 0%;
  bottom: 30px;
  font-size: 17px;
  padding: 0;
  margin-right: 30px;
  box-shadow: 0 8px 16px 0 rgba(0,0,0,0.4);
}
.hide{
  display: none;
}

 @media screen and (max-width: 468px) {
  .auth-container{
    width: 90%;
    padding: 2.5rem 0;
    }
    .auth-form {
      width:90%;
      }
      .navbar h1{
        font-size: 1rem;
        padding-left: 0.5rem;
      }
      .navbar .menu h5{
        font-size: .7rem;
      }
}

@media screen and (max-width: 280px) {
  .auth-container {
    width: 100%;
    }
} 

footer {
width: 100%;
left: 0;
bottom: 0;
background-color: black;
text-align: center;
color: white;
margin-top: 5rem;
}

footer p {
  padding: 2rem 0;
}

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

&lt;/div&gt;



&lt;p&gt;Inside the &lt;code&gt;styles&lt;/code&gt; directory, delete the &lt;code&gt;Home.module.css&lt;/code&gt; file, we won't be needing it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the NoteCard Component
&lt;/h1&gt;

&lt;p&gt;Open up the &lt;code&gt;components&lt;/code&gt; directory and create a new file called &lt;code&gt;NoteCard.tsx&lt;/code&gt; inside it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;NoteCard&lt;/code&gt; component will serve as a template that will be used to create a new sticky note.&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;NoteCard.tsx&lt;/code&gt; file and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlus, faWindowMaximize, faTrash, faSave, faExclamationTriangle, faSpinner, faCheck } from '@fortawesome/free-solid-svg-icons'

const NoteCard: React.FC = () =&amp;gt; {
    return (
        &amp;lt;&amp;gt;
            &amp;lt;div className="card"&amp;gt;
                &amp;lt;div className="card-header"&amp;gt;
                    &amp;lt;div className="icon-container"&amp;gt;
                        &amp;lt;div className="left-icon"&amp;gt;
                            &amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faPlus} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" &amp;gt;&amp;lt;FontAwesomeIcon icon={faExclamationTriangle} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" &amp;gt; &amp;lt;FontAwesomeIcon icon={faCheck} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" &amp;gt; &amp;lt;FontAwesomeIcon icon={faSpinner} spin /&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                        &amp;lt;div className="right-icon"&amp;gt;
                            &amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faSave} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faWindowMaximize} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faTrash} /&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div className="card-body"&amp;gt;
                    &amp;lt;div className="text-container"&amp;gt;
                        &amp;lt;textarea className="text-area"&amp;gt;&amp;lt;/textarea&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div className="card-footer"&amp;gt;
                    &amp;lt;div className="theme-color-container"&amp;gt;
                        &amp;lt;div className="theme-color yellow"&amp;gt; &amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color green"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color pink"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color purple"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color blue"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color gray"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color charcoal"&amp;gt;&amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/&amp;gt;
    )
}
export default NoteCard

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;NoteCard&lt;/code&gt; component is the react version of the &lt;a href="https://github.com/tope-olajide/sticky-note-html-template/blob/main/templates/card-single.html" rel="noopener noreferrer"&gt;&lt;code&gt;card-single.html&lt;/code&gt;&lt;/a&gt; file which can be found inside the &lt;a href="https://github.com/tope-olajide/sticky-note-html-template/tree/main/templates" rel="noopener noreferrer"&gt;&lt;code&gt;templates&lt;/code&gt;&lt;/a&gt; repository.&lt;/p&gt;

&lt;p&gt;Next, we'll create a new file inside the &lt;code&gt;components&lt;/code&gt; directory called &lt;code&gt;NoteContainer.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open up the newly created &lt;code&gt;NoteContainer.tsx&lt;/code&gt; file in your editor and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import NoteCard from "./NoteCard";

const NoteContainer = () =&amp;gt; {
    return (
        &amp;lt;&amp;gt;
            &amp;lt;section className="notes-container"&amp;gt;
                &amp;lt;NoteCard /&amp;gt;
            &amp;lt;/section&amp;gt;
        &amp;lt;/&amp;gt;
    )
}

export default NoteContainer

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

&lt;/div&gt;



&lt;p&gt;We imported and rendered the &lt;code&gt;NoteCard&lt;/code&gt; component inside the &lt;code&gt;NoteContainer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To see all our components in action, open the &lt;code&gt;pages/index.ts&lt;/code&gt; file and delete everything inside it, then import and render the &lt;code&gt;NoteContainer&lt;/code&gt; component in it like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import NoteContainer from "../components/NoteContainer";

function HomePage() {
  return &amp;lt;NoteContainer /&amp;gt;
}

export default HomePage

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

&lt;/div&gt;



&lt;p&gt;If everything works fine, the screen should display a sticky note that 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzudpdeidit5dqeia8fk.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%2Fuzudpdeidit5dqeia8fk.png" alt="Screenshot_3.png" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have checked out the completed version of this project from the link provided earlier, you already know what each icon on the sticky note card represents and what they will be used for. We will implement all the features very soon.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating A New Sticky-Note
&lt;/h1&gt;

&lt;p&gt;In this part, we will add another sticky note once a user clicks on the &lt;code&gt;plus icon&lt;/code&gt; on a sticky note or the &lt;code&gt;Add new&lt;/code&gt; button that will be created very soon.&lt;/p&gt;

&lt;p&gt;At the root folder of our project, let's create a new folder called &lt;code&gt;typings&lt;/code&gt;. All the typings file used for this project will be saved here. Inside the &lt;code&gt;typings&lt;/code&gt; file, let's create a new file called &lt;code&gt;index.tsx&lt;/code&gt;. open the &lt;code&gt;index.tsx&lt;/code&gt; file, and create a new enum type called &lt;code&gt;Theme&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export enum Theme {
    Yellow = "yellow",
    Green = "green",
    Pink = "pink",
    Purple = "purple",
    Blue = "blue",
    Gray = "gray",
    Charcoal = "charcoal"
}

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

&lt;/div&gt;



&lt;p&gt;We're using the &lt;a href="https://www.typescriptlang.org/docs/handbook/enums.html" rel="noopener noreferrer"&gt;enum&lt;/a&gt; keyword to declare all the theme colors available for use in our sticky notes app, which are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Yellow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Green&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pink&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Purple&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blue&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gray, and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Charcoal&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's create another type definition for each sticky note called &lt;code&gt;INote&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface INote {
    content: string;
    color: Theme;
    id: string;
    isMaximized: boolean;
    isDeleteNoteConfirmationVisible:boolean;
    isSaved: boolean;
    isSaving: boolean;
    isError: boolean;
}

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

&lt;/div&gt;



&lt;p&gt;We set some rules for the note data; for example, each note &lt;code&gt;content&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt; must be in string format, the &lt;code&gt;color&lt;/code&gt; must conform with the &lt;code&gt;Theme&lt;/code&gt; rules, and &lt;code&gt;isMaximized&lt;/code&gt;, &lt;code&gt;isDeleteNoteConfirmationVisible&lt;/code&gt;, &lt;code&gt;isSaved&lt;/code&gt;, &lt;code&gt;isSaving&lt;/code&gt;, &lt;code&gt;isError&lt;/code&gt; as boolean. Inside the &lt;code&gt;NoteContainer&lt;/code&gt; component, let's create a new object called &lt;code&gt;defaultNoteData&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const defaultNoteData = {
        content: "",
        color: Theme.Yellow,
        id: `${Date.now()}`,
        isMaximized: false,
        isDeleteNoteConfirmationVisible: false,
        isSaved: false,
        isSaving: false,
        isError: true,
    }

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;defaultNoteData&lt;/code&gt; object will be used to set the default value of the newly created note. The note &lt;code&gt;content&lt;/code&gt; will be initialized with an empty &lt;code&gt;string&lt;/code&gt;, and the default theme &lt;code&gt;color&lt;/code&gt; will be yellow. I used &lt;code&gt;Date.now()&lt;/code&gt; method to generate a temporary &lt;code&gt;id&lt;/code&gt; for the sake of building the frontend part of this project.&lt;/p&gt;

&lt;p&gt;The original &lt;code&gt;id&lt;/code&gt; will be generated from the backend and will replace the temporary &lt;code&gt;id&lt;/code&gt; once the note data is saved into the database. Also, notice how &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals" rel="noopener noreferrer"&gt;Template Literal&lt;/a&gt; was used to convert the &lt;code&gt;Date.now()&lt;/code&gt; value to string. The rules we set for the &lt;code&gt;id&lt;/code&gt; type is string, but the &lt;code&gt;Date.now()&lt;/code&gt; return type is &lt;code&gt;number&lt;/code&gt; so we converted it to &lt;code&gt;string&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, let's import the &lt;code&gt;Theme&lt;/code&gt; and &lt;code&gt;INote&lt;/code&gt; typings we created earlier into the &lt;code&gt;NoteContainer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Theme, INote } from '../typings'

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

&lt;/div&gt;



&lt;p&gt;After that, we will create a new state called &lt;code&gt;notes&lt;/code&gt; in the &lt;code&gt;NoteContainer&lt;/code&gt;. To do that, let's import the &lt;code&gt;useState&lt;/code&gt; hook from react first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';

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

&lt;/div&gt;



&lt;p&gt;Then create the &lt;code&gt;notes&lt;/code&gt; state below the &lt;code&gt;defaultNoteData&lt;/code&gt; object like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [notes, setNotes] = useState&amp;lt;Array&amp;lt;INote&amp;gt;&amp;gt;([]);

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;notes&lt;/code&gt; state is an &lt;code&gt;Array&lt;/code&gt; of the &lt;code&gt;INote&lt;/code&gt; object type we created earlier. If any &lt;code&gt;notes&lt;/code&gt; data provided does not conform with the &lt;code&gt;Array&lt;/code&gt; of &lt;code&gt;INote&lt;/code&gt; type, expect TypeScript to throw some errors.&lt;/p&gt;

&lt;p&gt;Next, we will create a function that creates a new sticky note below the &lt;code&gt;notes&lt;/code&gt; state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const createNote = () =&amp;gt; {
        setNotes([...notes, defaultNoteData]);
        console.log(notes);
    }

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;createNote&lt;/code&gt; function will create a new sticky note by inserting the &lt;code&gt;defaultNoteData&lt;/code&gt; object into the &lt;code&gt;notes&lt;/code&gt; state anytime we call the &lt;code&gt;createNote&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Next, we will invoke this function when a user clicks on the plus icon on a sticky note.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define the type for the &lt;code&gt;NoteCard&lt;/code&gt; component.
&lt;/h2&gt;

&lt;p&gt;Let's create a new interface called &lt;code&gt;INoteCardProps&lt;/code&gt; for the &lt;code&gt;NoteCard&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;typings/index.ts&lt;/code&gt; file and create a new interface called &lt;code&gt;INoteCardProps&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface INoteCardProps {

}

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;INoteCardProps&lt;/code&gt; will be used to provide type checking for the &lt;code&gt;NoteCard&lt;/code&gt; component &lt;code&gt;props&lt;/code&gt; which will be discussed very soon, but before then let's update the &lt;code&gt;NoteCard&lt;/code&gt; component to use the &lt;code&gt;INoteCardProps&lt;/code&gt; types.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;NoteCard&lt;/code&gt; component, replace the following line of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const NoteCard: React.FC = () =&amp;gt; {

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

&lt;/div&gt;



&lt;p&gt;With this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const NoteCard: React.FC&amp;lt;INoteCardProps&amp;gt; = (props) =&amp;gt; {

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

&lt;/div&gt;



&lt;p&gt;Notice how we passed a &lt;code&gt;props&lt;/code&gt; as parameters to the &lt;code&gt;NoteCard&lt;/code&gt; component. The &lt;code&gt;props&lt;/code&gt; stand for properties in React. It is used for passing data from a parent component (the &lt;code&gt;NoteContainer&lt;/code&gt; in this case) to a child component (the &lt;code&gt;NoteCard&lt;/code&gt;). The &lt;code&gt;React.FC&lt;/code&gt; (can also be written as &lt;code&gt;React.FunctionComponent&lt;/code&gt;) is just like an interface that provides the props types (&lt;code&gt;INoteCardProps&lt;/code&gt; in our case) for a React component (&lt;code&gt;NoteCard&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Let's import the &lt;code&gt;INoteCardProps&lt;/code&gt; into the &lt;code&gt;NoteCard&lt;/code&gt; component like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { INoteCardProps } from '../typings'

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

&lt;/div&gt;



&lt;p&gt;and update the &lt;code&gt;INoteCardProps&lt;/code&gt; with more data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface INoteCardProps {
    createNote(): void;
    id:string;
    color:string;
    isMaximized:boolean;
    contents: string;
    isSaved: boolean;
    isSaving: boolean;
    isError: boolean;
}

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

&lt;/div&gt;



&lt;p&gt;After that, we'll update the &lt;code&gt;NoteContainer&lt;/code&gt; to render the &lt;code&gt;NoteCard&lt;/code&gt; component with the &lt;code&gt;notes&lt;/code&gt; data.&lt;/p&gt;

&lt;p&gt;Replace the following lines of code in the &lt;code&gt;NoteContainer&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;section className="notes-container"&amp;gt;
                &amp;lt;NoteCard /&amp;gt;
            &amp;lt;/section&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;with the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            &amp;lt;section className="notes-container"&amp;gt;
                {notes.map((note: INote) =&amp;gt; {
                    return (
                        &amp;lt;NoteCard
                            createNote={createNote}
                            key={note.id}
                            id={note.id}
                            color={note.color}
                            isMaximized={note.isMaximized}
                            contents ={note.content}
                            isSaved={note.isSaved}
                            isSaving={note.isSaving}
                            isError={note.isError}
                        /&amp;gt;
                    )
                })}
            &amp;lt;/section&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;We iterated through the &lt;code&gt;notes&lt;/code&gt; state and rendered each data with the &lt;code&gt;NoteCard&lt;/code&gt; components. If we refresh the browser now, we should see a blank page.&lt;/p&gt;

&lt;p&gt;There's no need to panic; this occured because the notes state is empty. Remember, we initialized it with an empty array, therefore React has nothing to render just yet. To fix that, we need to create a component that will be rendered anytime the state is empty. This component will inform the user that they have not added any notes, it will also include an &lt;code&gt;Add New&lt;/code&gt; button that will be used to invoke the &lt;code&gt;createNote&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the &lt;code&gt;NoStickyNotes&lt;/code&gt; Component
&lt;/h2&gt;

&lt;p&gt;To create the &lt;code&gt;NoStickyNotes&lt;/code&gt; Component, let's create a new file called &lt;code&gt;NoStickyNotes.tsx&lt;/code&gt; and add the following code in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const NoStickyNotes: React.FC = (props) =&amp;gt; {
    return (
        &amp;lt;&amp;gt;
            &amp;lt;section className="no-notes-container"&amp;gt;
              &amp;lt;h3&amp;gt;You have no sticky notes&amp;lt;/h3&amp;gt;&amp;lt;button&amp;gt; Add New &amp;lt;/button&amp;gt;
            &amp;lt;/section&amp;gt;
        &amp;lt;/&amp;gt;
    )
}
export default NoStickyNotes

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

&lt;/div&gt;



&lt;p&gt;This component will display a text that says: "You have no sticky notes" with an &lt;code&gt;Add New&lt;/code&gt; Button. This button does nothing for now. Let's make it call the &lt;code&gt;createNote&lt;/code&gt; function once a user clicks on it.&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;typings/index.ts&lt;/code&gt; file and create another type definition for the &lt;code&gt;NoStickyNotes&lt;/code&gt; component called &lt;code&gt;INoStickyNotesProps&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface INoStickyNotesProps{
    createNote():void
}

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

&lt;/div&gt;



&lt;p&gt;Now let's update the &lt;code&gt;NoStickyNotes&lt;/code&gt; component to use the &lt;code&gt;INoStickyNotesProps&lt;/code&gt; type definitions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { INoStickyNotesProps } from "../typings"

const NoStickyNotes: React.FC&amp;lt;INoStickyNotesProps&amp;gt; = (props) =&amp;gt; {
    return (
        &amp;lt;&amp;gt;
            &amp;lt;section className="no-notes-container"&amp;gt;
              &amp;lt;h3&amp;gt;You have no sticky notes&amp;lt;/h3&amp;gt;&amp;lt;button onClick={props.createNote}&amp;gt; Add New &amp;lt;/button&amp;gt;
            &amp;lt;/section&amp;gt;
        &amp;lt;/&amp;gt;
    )
}
export default NoStickyNotes

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

&lt;/div&gt;



&lt;p&gt;First, we imported the &lt;code&gt;INoStickyNotesProps&lt;/code&gt; from the &lt;code&gt;typings.tsx&lt;/code&gt; file, then invoke the &lt;code&gt;createNote&lt;/code&gt; function anytime the "Add New" button is clicked.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createNote&lt;/code&gt; function will be passed down as props to the &lt;code&gt;NoStickyNotes&lt;/code&gt; component from the &lt;code&gt;NotesContainer&lt;/code&gt; component soon.&lt;/p&gt;

&lt;p&gt;Let's render the &lt;code&gt;NoStickyNotes&lt;/code&gt; component in the &lt;code&gt;NotesContainer&lt;/code&gt; component &lt;strong&gt;only&lt;/strong&gt; when the &lt;code&gt;notes&lt;/code&gt; state array is empty:&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;NotesContainer&lt;/code&gt; component and import the &lt;code&gt;NoStickyNotes&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import NoStickyNotes from "./NoStickyNotes";

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

&lt;/div&gt;



&lt;p&gt;Then add the following snippets below the &lt;code&gt;createNote&lt;/code&gt; function and right above the &lt;code&gt;return&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    if (!notes.length) {
        return (
            &amp;lt;&amp;gt;
            &amp;lt;section className="notes-container"&amp;gt;
                &amp;lt;NoStickyNotes
                    createNote={createNote}
                /&amp;gt;
                &amp;lt;/section&amp;gt;
            &amp;lt;/&amp;gt;
        )
    }

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

&lt;/div&gt;



&lt;p&gt;We told React to render the &lt;code&gt;NoStickyNotes&lt;/code&gt; components when the &lt;code&gt;notes&lt;/code&gt; state array is empty. Also, notice how we pass down the &lt;code&gt;createNote&lt;/code&gt; function as props to the &lt;code&gt;NoStickyNotes&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;createNote={createNote}

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

&lt;/div&gt;



&lt;p&gt;If you check your browser now, you should see the &lt;code&gt;NoStickyNotes&lt;/code&gt; component being rendered on the screen 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlix9gqtdptbwa0sfgkd.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%2Fqlix9gqtdptbwa0sfgkd.png" alt="Screenshot_4.png" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And when you click on the "Add New" Button, an empty sticky note with the &lt;code&gt;defaultNoteData&lt;/code&gt; should be created, but nothing happens when you click on the plus icon. We will fix that in the section below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating A New Sticky Note When a User Clicks on the Plus Icon
&lt;/h2&gt;

&lt;p&gt;We want to be able to add more notes when a user clicks on the plus icon on any of the sticky notes. All we have to do now is to invoke the &lt;code&gt;createNote&lt;/code&gt; function once the plus icon is clicked.&lt;/p&gt;

&lt;p&gt;Let's open up the &lt;code&gt;NoteCard&lt;/code&gt; component and locate this line of code inside the &lt;code&gt;left-icon&lt;/code&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faPlus} /&amp;gt;&amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;then replace it with the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="icon" onClick={props.createNote}&amp;gt;&amp;lt;FontAwesomeIcon icon={faPlus} /&amp;gt;&amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;And now, we can create as many notes as we want when we click on the plus icon:&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%2F1oh8jh719atd9i5aljay.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1oh8jh719atd9i5aljay.gif" alt="screen-capture001.gif" width="760" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's how the &lt;code&gt;NoteContainer&lt;/code&gt; component is looking at the moment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// NoteContainer.tsx
import NoteCard from "./NoteCard";
import { Theme, INote } from '../typings'
import { useState } from 'react';
import NoStickyNotes from "./NoStickyNotes";

const NoteContainer = () =&amp;gt; {
    const defaultNoteData = {
        content: "",
        color: Theme.Yellow,
        id: `${Date.now()}`,
        isMaximized: false,
        isDeleteNoteConfirmationVisible: false,
        isSaved: false,
        isSaving: false,
        isError: true,
    }

    const [notes, setNotes] = useState&amp;lt;Array&amp;lt;INote&amp;gt;&amp;gt;([]);

    const createNote = () =&amp;gt; {
        setNotes([...notes, defaultNoteData]);
        console.log(notes);
    }
    if (!notes.length) {
        return (
            &amp;lt;&amp;gt;
            &amp;lt;section className="notes-container"&amp;gt;
                &amp;lt;NoStickyNotes
                    createNote={createNote}
                /&amp;gt;
                &amp;lt;/section&amp;gt;
            &amp;lt;/&amp;gt;
        )
    }
    return (
        &amp;lt;&amp;gt;
            &amp;lt;section className="notes-container"&amp;gt;
                {notes.map((note: INote) =&amp;gt; {
                    return (
                        &amp;lt;NoteCard
                            createNote={createNote}
                            key={note.id}
                            id={note.id}
                            color={note.color}
                            isMaximized={note.isMaximized}
                            contents={note.content}
                            isSaved={note.isSaved}
                            isSaving={note.isSaving}
                            isError={note.isError}
                        /&amp;gt;
                    )
                })}
            &amp;lt;/section&amp;gt;

        &amp;lt;/&amp;gt;
    )
}

export default NoteContainer

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

&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;NoteCard&lt;/code&gt; component should be looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// NoteCard component
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlus, faWindowMaximize, faTrash, faSave, faExclamationTriangle, faSpinner, faCheck } from '@fortawesome/free-solid-svg-icons'
import { INoteCardProps } from '../typings'

const NoteCard: React.FC&amp;lt;INoteCardProps&amp;gt; = (props) =&amp;gt; {
    return (
        &amp;lt;&amp;gt;
            &amp;lt;div className="card"&amp;gt;
                &amp;lt;div className="card-header"&amp;gt;
                    &amp;lt;div className="icon-container"&amp;gt;
                        &amp;lt;div className="left-icon"&amp;gt;
                        &amp;lt;div className="icon" onClick={props.createNote}&amp;gt;&amp;lt;FontAwesomeIcon icon={faPlus} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" &amp;gt;&amp;lt;FontAwesomeIcon icon={faExclamationTriangle} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" &amp;gt; &amp;lt;FontAwesomeIcon icon={faCheck} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon" &amp;gt; &amp;lt;FontAwesomeIcon icon={faSpinner} spin /&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                        &amp;lt;div className="right-icon"&amp;gt;
                            &amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faSave} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faWindowMaximize} /&amp;gt;&amp;lt;/div&amp;gt;
                            &amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faTrash} /&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div className="card-body"&amp;gt;
                    &amp;lt;div className="text-container"&amp;gt;
                        &amp;lt;textarea className="text-area"&amp;gt;&amp;lt;/textarea&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div className="card-footer"&amp;gt;
                    &amp;lt;div className="theme-color-container"&amp;gt;
                        &amp;lt;div className="theme-color yellow"&amp;gt; &amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color green"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color pink"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color purple"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color blue"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color gray"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color charcoal"&amp;gt;&amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/&amp;gt;
    )
}
export default NoteCard

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Changing the Theme Color
&lt;/h1&gt;

&lt;p&gt;We already have different theme colors selected for this app. All the available colors are provided in the &lt;code&gt;Themes&lt;/code&gt; enum we created earlier, and they can be selected at the bottom of each sticky note.&lt;/p&gt;

&lt;p&gt;What we are going to do next is allow a user to customize each note with a different color from the list of colors provided in the &lt;code&gt;Themes&lt;/code&gt; type. To do that, we'll create a new function called &lt;code&gt;createNote&lt;/code&gt;, this function will receive the &lt;code&gt;noteId&lt;/code&gt; and the note &lt;code&gt;color&lt;/code&gt; as parameters.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;NoteContainer&lt;/code&gt; component, let's create the &lt;code&gt;changeColor&lt;/code&gt; function right below the&lt;code&gt;createNote&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const changeColor = (noteId: string, color: Theme) =&amp;gt; {
        const updatedNotes = notes.map((note: INote) =&amp;gt; {
            if (note.id === noteId) {
                return {
                    ...note, color
                }
            }
            return note
        })
        setNotes(updatedNotes)
    }

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;changeColor&lt;/code&gt; function will iterate through the &lt;code&gt;notes&lt;/code&gt; state using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" rel="noopener noreferrer"&gt;Array.map&lt;/a&gt; method, if any of the &lt;code&gt;id&lt;/code&gt;s of the &lt;code&gt;note&lt;/code&gt; object inside the &lt;code&gt;notes&lt;/code&gt; array matches the &lt;code&gt;noteId&lt;/code&gt; provided in the parameter, it will change the &lt;code&gt;color&lt;/code&gt; of the &lt;code&gt;note&lt;/code&gt; to the &lt;code&gt;color&lt;/code&gt; provided in the parameter. The &lt;code&gt;map&lt;/code&gt; method will always return a new array, which will be stored into the &lt;code&gt;updatedNotes&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;NoteCard&lt;/code&gt; component, add &lt;code&gt;id={props.color}&lt;/code&gt; to the &lt;code&gt;&amp;lt;div className="card"&amp;gt;&lt;/code&gt; element like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className = "card" id = {props.color}&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Doing this means the background color in the &lt;code&gt;id&lt;/code&gt; will be used instead of the background color in the class name. Remember &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity" rel="noopener noreferrer"&gt;Specificity in CSS&lt;/a&gt;, &lt;code&gt;id&lt;/code&gt; selectors are given higher priority over class selectors.&lt;/p&gt;

&lt;p&gt;Replace the following lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                &amp;lt;div className="card-footer"&amp;gt;
                    &amp;lt;div className="theme-color-container"&amp;gt;
                        &amp;lt;div className="theme-color yellow"&amp;gt; &amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color green"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color pink"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color purple"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color blue"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color gray"&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color charcoal"&amp;gt;&amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;With the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                &amp;lt;div className="card-footer"&amp;gt;
                    &amp;lt;div className="theme-color-container"&amp;gt;
                        &amp;lt;div className="theme-color yellow" onClick={() =&amp;gt; props.changeColor(props.id, Theme.Yellow)} &amp;gt; &amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color green" onClick={() =&amp;gt; props.changeColor(props.id, Theme.Green)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color pink" onClick={() =&amp;gt; props.changeColor(props.id, Theme.Pink)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color purple" onClick={() =&amp;gt; props.changeColor(props.id, Theme.Purple)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color blue" onClick={() =&amp;gt; props.changeColor(props.id, Theme.Blue)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color gray" onClick={() =&amp;gt; props.changeColor(props.id, Theme.Gray)}&amp;gt;&amp;lt;/div&amp;gt;
                        &amp;lt;div className="theme-color charcoal" onClick={() =&amp;gt; props.changeColor(props.id, Theme.Charcoal)}&amp;gt;&amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;So anytime a user clicks on any color on the sticky note, it calls the &lt;code&gt;changeColor&lt;/code&gt; function with the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;color&lt;/code&gt; of the note selected as arguments.&lt;/p&gt;

&lt;p&gt;Update the import from the typing file in the &lt;code&gt;NoteCard&lt;/code&gt; component to include the &lt;code&gt;Theme&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { INoteCardProps, Theme } from '../typings'

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

&lt;/div&gt;



&lt;p&gt;After that, update the &lt;code&gt;INoteCardProps&lt;/code&gt; by adding &lt;code&gt;changeColor(id:string, color:Theme): void;&lt;/code&gt; to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface INoteCardProps {
    createNote(): void;
    id:string;
    color:string;
    isMaximized:boolean;
    contents: string;
    isSaved: boolean;
    isSaving: boolean;
    isError: boolean;
    changeColor(id:string, color:Theme): void;
}

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

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;NoteContainer&lt;/code&gt;, let's pass down the &lt;code&gt;changeColor&lt;/code&gt; function as props to the &lt;code&gt;NoteCard&lt;/code&gt; component by adding &lt;code&gt;changeColor={changeColor}&lt;/code&gt; to it so everything looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;section className="notes-container"&amp;gt;
                {notes.map((note: INote) =&amp;gt; {
                    return (
                        &amp;lt;NoteCard
                            createNote={createNote}
                            key={note.id}
                            id={note.id}
                            color={note.color}
                            isMaximized={note.isMaximized}
                            contents ={note.content}
                            isSaved={note.isSaved}
                            isSaving={note.isSaving}
                            isError={note.isError}
                            changeColor={changeColor}
                        /&amp;gt;
                    )
                })}
            &amp;lt;/section&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Now you can check your browser, select any color you want, and watch your sticky note's background color change 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64ho6byvz6rzadc836xb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64ho6byvz6rzadc836xb.gif" alt="screen-capture (1).gif" width="1304" height="652"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Minimizing and Maximizing a Stick Note
&lt;/h1&gt;

&lt;p&gt;In this part, we will implement the feature that will allow a user to work in a distraction-free mode by maximizing a sticky note to cover the screen and minimize it when they are done.&lt;/p&gt;

&lt;p&gt;Create a new function called &lt;code&gt;toggleFullscreen&lt;/code&gt; below the &lt;code&gt;changeColor&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const toggleFullscreen = (noteId: string) =&amp;gt; {
        const updatedNotes = notes.map((note: INote) =&amp;gt; {
            if (note.id === noteId) {
                return { ...note, isMaximized: !note.isMaximized }
            }
            return note
        })
        setNotes(updatedNotes)
    }

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;toggleFullscreen&lt;/code&gt; function takes the &lt;code&gt;noteId&lt;/code&gt; of the note the user wants to maximize as a parameter, then toggles its boolean value. If the &lt;code&gt;isMaximized&lt;/code&gt; value of the selected note is &lt;code&gt;true&lt;/code&gt;, it changes it to &lt;code&gt;false&lt;/code&gt; and if it's &lt;code&gt;false&lt;/code&gt; it will be changed to &lt;code&gt;true&lt;/code&gt;. That is exactly what this line does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return { ...note, isMaximized: !note.isMaximized }

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

&lt;/div&gt;



&lt;p&gt;There are two classes in the &lt;code&gt;styles/global.css&lt;/code&gt; called &lt;code&gt;card&lt;/code&gt; and &lt;code&gt;card-maximized&lt;/code&gt;. The &lt;code&gt;card&lt;/code&gt; class is the default size of every sticky note while the &lt;code&gt;card-maximized&lt;/code&gt; class contains the styles that will maximize the sticky note card. All we have to do is switch between both classes with react anytime the minimize and maximize icon is clicked.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;NoteCard&lt;/code&gt; component, let's update the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className= "card" id={props.color}&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;with this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className={props.isMaximized ? "card-maximized" : "card"} id={props.color}&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;When a sticky note's &lt;code&gt;isMaximized&lt;/code&gt; property is &lt;code&gt;true&lt;/code&gt;, the &lt;code&gt;card-maximized&lt;/code&gt; class is used; otherwise, the &lt;code&gt;card&lt;/code&gt; class is used.&lt;/p&gt;

&lt;p&gt;Let's make the &lt;code&gt;faWindowMaximize&lt;/code&gt; icon call the &lt;code&gt;toggleFullscreen&lt;/code&gt; function with the &lt;code&gt;id&lt;/code&gt; of the note anytime it is clicked.&lt;/p&gt;

&lt;p&gt;Update the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faWindowMaximize} /&amp;gt;&amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;With the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="icon" onClick={() =&amp;gt; props.toggleFullscreen(props.id)}&amp;gt;&amp;lt;FontAwesomeIcon icon={faWindowMaximize} /&amp;gt;&amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;After that, we'll update the &lt;code&gt;INoteCardProps&lt;/code&gt; object in the typing file to include the &lt;code&gt;toggleFullscreen&lt;/code&gt; function with the &lt;code&gt;noteId&lt;/code&gt; as parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface INoteCardProps {
    createNote(): void;
    id:string;
    color:string;
    isMaximized:boolean;
    contents: string;
    isSaved: boolean;
    isSaving: boolean;
    isError: boolean;
    changeColor(id:string, color:Theme): void;
    toggleFullscreen(noteId:string):void;
}

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

&lt;/div&gt;



&lt;p&gt;Finally, we'll pass the &lt;code&gt;toggleFullscreen()&lt;/code&gt; function down to the &lt;code&gt;NoteCard&lt;/code&gt; component in the &lt;code&gt;NoteContainer&lt;/code&gt; components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            &amp;lt;section className="notes-container"&amp;gt;
                {notes.map((note: INote) =&amp;gt; {
                    return (
                        &amp;lt;NoteCard
                            createNote={createNote}
                            key={note.id}
                            id={note.id}
                            color={note.color}
                            isMaximized={note.isMaximized}
                            contents ={note.content}
                            isSaved={note.isSaved}
                            isSaving={note.isSaving}
                            isError={note.isError}
                            changeColor={changeColor}
                            toggleFullscreen={toggleFullscreen}
                        /&amp;gt;
                    )
                })}
            &amp;lt;/section&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Anytime time a user clicks on the &lt;code&gt;faWindowMaximize&lt;/code&gt;, the window should be minimized and maximized 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl7c3cu31sy8v9gvv257j.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl7c3cu31sy8v9gvv257j.gif" alt="screen-capture (2).gif" width="1304" height="652"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Deleting A Sticky Note
&lt;/h1&gt;

&lt;p&gt;In this section, we will allow a user to permanently delete a sticky note. But before deleting the note, we'll display a confirmation message that will ask the user if they really want to continue with the action.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;NoteContainer&lt;/code&gt; component, let's create a new function called &lt;code&gt;toggleDeleteNoteConfirmationMessage&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const toggleDeleteNoteConfirmationMessage = (noteId: string) =&amp;gt; {
        const updatedNotes = notes.map((note: INote) =&amp;gt; {
            if (note.id === noteId) {
                return { ...note, isDeleteNoteConfirmationVisible: !note.isDeleteNoteConfirmationVisible }
            }
            return note
        })
        setNotes(updatedNotes)
    }

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

&lt;/div&gt;



&lt;p&gt;This function will be used to toggle the visibility of the delete confirmation message on a sticky note.&lt;/p&gt;

&lt;p&gt;Now let's create a function that can delete a note. Below the &lt;code&gt;toggleDeleteNoteConfirmationMessage&lt;/code&gt; function, create a new function called &lt;code&gt;deleteNote&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const deleteNote = (noteId: string) =&amp;gt; {
        const filteredNotes = notes.filter((note: INote) =&amp;gt; {
            return note.id !== noteId;
        })
        setNotes(filteredNotes)
    }

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;deleteNote&lt;/code&gt; function takes in the &lt;code&gt;noteId&lt;/code&gt; as a parameter.&lt;/p&gt;

&lt;p&gt;Right above the &lt;code&gt;return&lt;/code&gt; statement in &lt;code&gt;NoteCard&lt;/code&gt; component, let's add the following snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    if (props.isDeleteNoteConfirmationVisible) {
        return (
            &amp;lt;section className="delete-note-modal" id={props.color}&amp;gt;
                &amp;lt;h3&amp;gt;This note will be permanently deleted, continue?&amp;lt;/h3&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;button onClick={() =&amp;gt; props.deleteNote(props.id)}&amp;gt; Yes &amp;lt;/button&amp;gt;
                    &amp;lt;button onClick={() =&amp;gt; props.toggleDeleteNoteConfirmationMessage(props.id)}&amp;gt; No&amp;lt;/button&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/section&amp;gt;
        )
    }

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

&lt;/div&gt;



&lt;p&gt;Update the &lt;code&gt;INoteCardProps&lt;/code&gt; object in the typing file to include the &lt;code&gt;isDeleteNoteConfirmationVisible&lt;/code&gt; boolean, &lt;code&gt;toggleDeleteNoteModal&lt;/code&gt;, and &lt;code&gt;toggleDeleteNoteConfirmationMessage&lt;/code&gt;function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface INoteCardProps {
    createNote(): void;
    id:string;
    color:string;
    isMaximized:boolean;
    contents: string;
    isSaved: boolean;
    isSaving: boolean;
    isError: boolean;
    changeColor(id:string, color:Theme): void;
    toggleFullscreen(noteId:string):void;
    isDeleteNoteConfirmationVisible:boolean,
    toggleDeleteNoteConfirmationMessage(id:string):void;
    deleteNote(id:string):void;
}

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

&lt;/div&gt;



&lt;p&gt;Next, we need to call the &lt;code&gt;toggleDeleteNoteConfirmationMessage&lt;/code&gt; function once a user clicks on the &lt;code&gt;faTrash&lt;/code&gt; icon.&lt;/p&gt;

&lt;p&gt;Update the following line of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;div className="icon"&amp;gt;&amp;lt;FontAwesomeIcon icon={faTrash} /&amp;gt;&amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;With this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="icon" onClick={()=&amp;gt;props.toggleDeleteNoteConfirmationMessage(props.id)}&amp;gt;&amp;lt;FontAwesomeIcon icon={faTrash} /&amp;gt;&amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Now we can pass down the &lt;code&gt;isDeleteNoteConfirmationVisible&lt;/code&gt; , &lt;code&gt;toggleDeleteNoteConfirmationMessage&lt;/code&gt; , and &lt;code&gt;deleteNote&lt;/code&gt; function as props to the &lt;code&gt;NoteCard&lt;/code&gt; component like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;section className="notes-container"&amp;gt;
                {notes.map((note: INote) =&amp;gt; {
                    return (
                        &amp;lt;NoteCard
                            createNote={createNote}
                            key={note.id}
                            id={note.id}
                            color={note.color}
                            isMaximized={note.isMaximized}
                            contents ={note.content}
                            isSaved={note.isSaved}
                            isSaving={note.isSaving}
                            isError={note.isError}
                            changeColor={changeColor}
                            toggleFullscreen={toggleFullscreen}
                            isDeleteNoteConfirmationVisible={note.isDeleteNoteConfirmationVisible}
                            toggleDeleteNoteConfirmationMessage = {toggleDeleteNoteConfirmationMessage}
                            deleteNote = {deleteNote}

                        /&amp;gt;
                    )
                })}
            &amp;lt;/section&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;When you visit your browser and click on the &lt;code&gt;trash&lt;/code&gt; icon on a sticky note, you should see a confirmation message with &lt;code&gt;Yes&lt;/code&gt; and &lt;code&gt;No&lt;/code&gt; buttons. When you click on the &lt;code&gt;yes&lt;/code&gt; button, the note should be permanently deleted but when the &lt;code&gt;No&lt;/code&gt; is clicked the confirmation message will be removed and your note will not be touched.&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%2Fli7y6djr590kum3pp4eq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fli7y6djr590kum3pp4eq.gif" alt="screen-capture (3).gif" width="760" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary and Next Step
&lt;/h1&gt;

&lt;p&gt;In this section, we built the frontend aspect of this project using React and TypeScript . We implemented features that allow a user to create a new sticky note, delete it, minimize and maximize it, and change the background of each note.&lt;/p&gt;

&lt;p&gt;We used &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now" rel="noopener noreferrer"&gt;Date.now()&lt;/a&gt; to generate a temporary &lt;code&gt;id&lt;/code&gt; that will be used to uniquely identify a sticky note that the user is interacting with.&lt;/p&gt;

&lt;p&gt;In the next part of this tutorial, we will build the GraphQL server for this app using Apollo Server 4. We will also add some authentication and authorization to the app.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>nexus</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Deepgram Word Solver - An anagram game that involves rearranging letter</title>
      <dc:creator>Temitope</dc:creator>
      <pubDate>Mon, 11 Apr 2022 22:18:40 +0000</pubDate>
      <link>https://dev.to/kingdavid/deepgram-x-dev-hackathon-submission-post-placeholder-title-j7o</link>
      <guid>https://dev.to/kingdavid/deepgram-x-dev-hackathon-submission-post-placeholder-title-j7o</guid>
      <description>&lt;p&gt;— &lt;/p&gt;

&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;Deepgram Word Solver, is an endless letter re-arrangement game built with Deepgram and React and NextJS. The goal is to form words out of given letters.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works?
&lt;/h3&gt;

&lt;p&gt;The players will record their answers by holding the record button and releasing it to submit.&lt;/p&gt;

&lt;p&gt;The recorded answer is then sent to a serverless function at the backend where Deepgram is allowed to perform its magic by transcribing the recorded answer into text. The text is now compared to the lists of anagrams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Gram Gamers&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Code on GitHub
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/tope-olajide"&gt;
        tope-olajide
      &lt;/a&gt; / &lt;a href="https://github.com/tope-olajide/deepgram-word-solver"&gt;
        deepgram-word-solver
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;This is a &lt;a href="https://nextjs.org/" rel="nofollow"&gt;Next.js&lt;/a&gt; project bootstrapped with &lt;a href="https://github.com/vercel/next.js/tree/canary/packages/create-next-app"&gt;&lt;code&gt;create-next-app&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Getting Started&lt;/h2&gt;
&lt;p&gt;First, run the development server:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run dev
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or&lt;/span&gt;
yarn dev&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="nofollow"&gt;http://localhost:3000&lt;/a&gt; with your browser to see the result.&lt;/p&gt;
&lt;p&gt;You can start editing the page by modifying &lt;code&gt;pages/index.js&lt;/code&gt;. The page auto-updates as you edit the file.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nextjs.org/docs/api-routes/introduction" rel="nofollow"&gt;API routes&lt;/a&gt; can be accessed on &lt;a href="http://localhost:3000/api/hello" rel="nofollow"&gt;http://localhost:3000/api/hello&lt;/a&gt;. This endpoint can be edited in &lt;code&gt;pages/api/hello.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;pages/api&lt;/code&gt; directory is mapped to &lt;code&gt;/api/*&lt;/code&gt;. Files in this directory are treated as &lt;a href="https://nextjs.org/docs/api-routes/introduction" rel="nofollow"&gt;API routes&lt;/a&gt; instead of React pages.&lt;/p&gt;
&lt;h2&gt;
Learn More&lt;/h2&gt;
&lt;p&gt;To learn more about Next.js, take a look at the following resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/docs" rel="nofollow"&gt;Next.js Documentation&lt;/a&gt; - learn about Next.js features and API.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/learn" rel="nofollow"&gt;Learn Next.js&lt;/a&gt; - an interactive Next.js tutorial.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can check out &lt;a href="https://github.com/vercel/next.js/"&gt;the Next.js GitHub repository&lt;/a&gt; - your feedback and contributions are welcome!&lt;/p&gt;
&lt;h2&gt;
Deploy on Vercel&lt;/h2&gt;
&lt;p&gt;The easiest way to deploy your Next.js app is to use the &lt;a href="https://vercel.com/new?utm_medium=default-template&amp;amp;filter=next.js&amp;amp;utm_source=create-next-app&amp;amp;utm_campaign=create-next-app-readme" rel="nofollow"&gt;Vercel Platform&lt;/a&gt; from…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/tope-olajide/deepgram-word-solver"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---5jVPmYw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lrgit9y5q3sarobrxv6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---5jVPmYw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lrgit9y5q3sarobrxv6f.png" alt="Image description" width="404" height="632"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

</description>
      <category>hackwithdg</category>
      <category>deepgram</category>
      <category>deeplearning</category>
      <category>ai</category>
    </item>
    <item>
      <title>Learn React Hook by building a Simple Blog App</title>
      <dc:creator>Temitope</dc:creator>
      <pubDate>Thu, 16 Apr 2020 01:26:23 +0000</pubDate>
      <link>https://dev.to/kingdavid/learn-react-hook-by-building-a-simple-blog-app-22i2</link>
      <guid>https://dev.to/kingdavid/learn-react-hook-by-building-a-simple-blog-app-22i2</guid>
      <description>&lt;h1&gt;
  
  
  What is React?
&lt;/h1&gt;

&lt;p&gt;React is a popular JavaScript library developed by Facebook for building user interfaces. It uses the concept of Virtual DOM to render Elements into the browser DOM because it is a popular belief that manipulating the browser DOM directly can be very slow and costly.&lt;/p&gt;

&lt;p&gt;React developers often manipulate the virtual DOM and let React take care of updating the Browser DOM.&lt;/p&gt;

&lt;p&gt;One of the biggest advantages of using React is the reusability of code. Components can be easily reused throughout an application or even across different applications, saving time and effort for developers.&lt;br&gt;
This is especially helpful in large projects where there may be a lot of repetitive code. Additionally, React's modular architecture allows for easier testing and debugging, which can further speed up the development process.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hooks in React
&lt;/h2&gt;

&lt;p&gt;Hooks are functions that let you “hook into” React state and lifecycle features from function components.&lt;br&gt;
Before the arrival of Hook, state and React lifecycles can only be used in a class component. Starting from version 16.8, React rolled out a lot of features that enable developers to hook into a React state without having to write a single class component.&lt;/p&gt;

&lt;p&gt;Hooks provide a way for developers to manage state and other React features without needing to convert their functional components to class components. They also make it easier to reuse stateful logic across different components, as the logic can be encapsulated in a custom hook.&lt;/p&gt;
&lt;h1&gt;
  
  
  What we’re building
&lt;/h1&gt;

&lt;p&gt;We are building a simple frontend CRUD blog app where a user can create a post, read the post, update post, and delete the post without making any API request to the server. You can view the final project here: &lt;a href="https://react-simple-blog.now.sh" rel="noopener noreferrer"&gt;https://react-simple-blog.now.sh&lt;/a&gt; or download the source code here: &lt;a href="https://github.com/tope-olajide/react-simple-blog" rel="noopener noreferrer"&gt;https://github.com/tope-olajide/react-simple-blog&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  The Setup
&lt;/h1&gt;

&lt;p&gt;To follow up with this tutorial and get the app running, we are going to download and install the latest version of Node.js. (I am currently using version 12.13.1 for this tutorial)&lt;br&gt;
Next, you'll launch your Command-Line Interface, install React and create a new project by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app react-simple-blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will create a new directory called react-simple-blog and install React and its dependencies on it.&lt;/p&gt;

&lt;p&gt;To make sure React is working, launch your CLI, navigate to the &lt;code&gt;react-simple-blog&lt;/code&gt; folder (or whatever you chose to name the folder) and run :&lt;br&gt;
&lt;code&gt;npm start&lt;/code&gt; to start your React development server.&lt;br&gt;
Once the server is running, React will automatically launch your browser and navigate to &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt; in it, which is the default homepage for our React app. If all goes well, you should see the create-react-app splash screen that looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585201127%2Freact-blog%2Freact-splash.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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585201127%2Freact-blog%2Freact-splash.png" title="React welcome splash screen" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Modify the &lt;code&gt;App.js&lt;/code&gt; file
&lt;/h2&gt;

&lt;p&gt;Let's update the &lt;code&gt;App.js&lt;/code&gt; to display a welcoming message instead of the default flash screen.&lt;br&gt;
Navigate to &lt;code&gt;react-simple-blog/src&lt;/code&gt; on your computer, then&lt;br&gt;
open the &lt;code&gt;App.js&lt;/code&gt; file in your editor, and replace everything in it with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="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="o"&gt;&amp;gt;&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;Hello&lt;/span&gt; &lt;span class="nx"&gt;World&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;Here, we modified the App component to display &lt;em&gt;Hello World&lt;/em&gt;. Your browser should automatically refresh and display a similar output like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-3.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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-3.png" title="code output 3" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first line imports React from the node-modules. In the third line, we created a functional component called App, using the JavaScript fat arrow function.&lt;br&gt;
Then we render the following JSX elements:&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;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="o"&gt;&amp;gt;&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;Hello&lt;/span&gt; &lt;span class="nx"&gt;World&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the last line, we exported the App component so that it can be used later.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is JSX?
&lt;/h1&gt;

&lt;p&gt;JSX stands for JavaScript Syntax Extension. It has a familiar syntax with plain HTML and it can also be used directly in your JavaScript file but no browser can read it without transpiling it first. JSX can be transpiled into JavaScript code by using a preprocessor build-tool like babel.&lt;br&gt;
Babel has already been pre-installed with create-React-app, so you don't have to be worried about configuring the app to transform your JSX code into javascript.&lt;br&gt;
You can read more about JSX &lt;a href="https://Reactjs.org/docs/introducing-jsx.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to &lt;code&gt;React-simple-blog/src&lt;/code&gt; and open the &lt;code&gt;index.js&lt;/code&gt; file in your editor. This file serves as the starting point of the application and it is responsible for rendering the main component, which is the "App" component, to the &lt;code&gt;root&lt;/code&gt; element located in the &lt;code&gt;public/index.html&lt;/code&gt; file.&lt;br&gt;
In the &lt;code&gt;index.js&lt;/code&gt; file, the &lt;code&gt;App&lt;/code&gt; component is imported on line 4 and then rendered to the browser using the &lt;code&gt;React.render&lt;/code&gt; method on line 7. This means that when the user loads the webpage, the &lt;code&gt;App&lt;/code&gt; component will be displayed inside the &lt;code&gt;root&lt;/code&gt; div. This is how React components are rendered to the browser - by being inserted into the DOM through the "React.render" method.&lt;/p&gt;

&lt;p&gt;Next, we are going to delete some files we are not using but came bundled with create-React-app. Navigate to &lt;code&gt;react-simple-blog/src&lt;/code&gt; and delete the following files:&lt;br&gt;
&lt;em&gt;App.css&lt;/em&gt;,&lt;br&gt;
&lt;em&gt;App.test.js&lt;/em&gt;,&lt;br&gt;
&lt;em&gt;index.css&lt;/em&gt;, &lt;br&gt;
&lt;em&gt;logo.svg&lt;/em&gt;, and&lt;br&gt;
&lt;em&gt;setupTests.js&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After that, open your index.js file and delete the third line:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-2.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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-2.png" title="code output 2" alt="alt text"&gt;&lt;/a&gt;&lt;br&gt;
Since we have removed the index.css file, there is no reason to import it again in the index.js, else we might end up with a "failed to compile" error.&lt;br&gt;
By now, you should have just 3 files left in the src folder (i.e App.js, index.js and serviceWorker.js). &lt;/p&gt;

&lt;p&gt;Let's create a new folder called Components inside the src folder. This folder will be used to store the remaining components we'll be building for this app:&lt;br&gt;
&lt;code&gt;react-simple-blog/src/Components&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside the Components folder, create a new file called &lt;code&gt;CreateNewPost.jsx&lt;/code&gt;. From its name, you can easily guess what this new file will be used for.&lt;br&gt;
Let us add the following code into the newly &lt;code&gt;CreateNewPost.jsx&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="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;const&lt;/span&gt; &lt;span class="nx"&gt;CreateNewPost&lt;/span&gt; &lt;span class="o"&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="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;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeHolder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;39&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/input&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;br&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;br&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;textarea&lt;/span&gt; &lt;span class="nx"&gt;placeHolder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;41&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/textarea&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;br&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;br&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Save&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/form&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;/&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;CreateNewPost&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 have been following up with this tutorial from the beginning and you're familiar with HTML, there should be nothing strange to you here except for this opening and closing empty tag: &lt;code&gt;&amp;lt;&amp;gt; &amp;lt;/&amp;gt;&lt;/code&gt;  which is a short syntax for &lt;code&gt;&amp;lt;React.Fragment&amp;gt; &amp;lt;/React.Fragment&amp;gt;&lt;/code&gt;. Using fragments instead of &lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; is a little bit faster and has less memory usage. All we did here was create a new form that will be used to collect the user's input.&lt;/p&gt;

&lt;p&gt;Also, it is good to know that React component name starts with an uppercase letter because this is how React distinguishes components from regular HTML elements or other functions.&lt;br&gt;
By convention, only components that start with a capital letter are considered to be React components, while lower-case elements are assumed to be standard HTML elements.&lt;/p&gt;

&lt;p&gt;To display the CreateNewPost component, we need to import it first in into the App component and render it.&lt;br&gt;
To do that, open up the &lt;code&gt;App.js&lt;/code&gt; and add the following code below the import React statement:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import CreateNewPost from './components/CreateNewPost'&lt;/code&gt;&lt;br&gt;
To render CreateNewPost component, we'll replace&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Hello World &amp;lt;/h1&amp;gt;.&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;with&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;CreateNewPost /&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;So the App component looks like this:&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="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="nx"&gt;CreateNewPost&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;./Components/CreateNewPost&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;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="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="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateNewPost&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="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;You may refresh your browser if React hasn't done so.&lt;/p&gt;

&lt;p&gt;If everything went right, you should see an output that looks almost the same as this one:&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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-4.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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-4.png" title="code output 4" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are not adding any CSS for now. Everything styling will be done towards the end of this app.&lt;/p&gt;

&lt;p&gt;The 'Save Post' button does nothing for now, we'll add some functionalities to it once we're done with creating all the necessary components.&lt;/p&gt;

&lt;p&gt;Our next task is to create the Post component, which will be responsible for displaying each individual post. If you are finding the concept of multiple components confusing, don't worry. As you see these components working together, everything will become clearer.&lt;/p&gt;

&lt;p&gt;Let's create a new file inside the Components folder called &lt;code&gt;Post.jsx&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="o"&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="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;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&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;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;appear&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="nx"&gt;contents&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;appear&lt;/span&gt; &lt;span class="nx"&gt;here&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="nx"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Edit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Delete&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/section&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;/&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;Post&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, we import the React library, which is a prerequisite for writing React code. We then define the &lt;code&gt;Post&lt;/code&gt; component as a function using arrow function syntax.&lt;/p&gt;

&lt;p&gt;Inside the function, we use JSX to create a section element with a title and content of a blog post, as well as two buttons for editing and deleting the post. &lt;/p&gt;

&lt;p&gt;These buttons are not working for now, we'll make them work later once we're done with building the remaining components.&lt;br&gt;
To display the Post component, navigate to the &lt;code&gt;App.js&lt;/code&gt; file and update it with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Posts&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;./Components/Post&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;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Posts&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="sr"&gt;/&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;After refreshing your browser, you should have a typical output that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-5.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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-5.png" title="code output 5" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you will create a new component named &lt;code&gt;ModifyPost&lt;/code&gt;, which will be used for modifying a selected post. As the name suggests, this component will be used to modify the post, and we want it to be rendered by React only when a user clicks the &lt;code&gt;Edit&lt;/code&gt; button. To create this component, navigate to the &lt;code&gt;Components&lt;/code&gt; directory and create a new file called &lt;code&gt;ModifyPost.jsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then add the following code to the &lt;code&gt;ModifyPost.jsx&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="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;const&lt;/span&gt; &lt;span class="nx"&gt;ModifyPost&lt;/span&gt; &lt;span class="o"&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="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;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Modify&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;39&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/input&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;br&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;br&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;textarea&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;41&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/textarea&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;br&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;br&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Update&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/form&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;/&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;ModifyPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the &lt;code&gt;DisplayAllPosts&lt;/code&gt; component
&lt;/h2&gt;

&lt;p&gt;The final component we will be creating for this tutorial is the &lt;code&gt;DisplayAllPosts&lt;/code&gt; component.&lt;br&gt;
This component will serve as a parent component to &lt;code&gt;CreatePost&lt;/code&gt;, &lt;code&gt;ModifyPost&lt;/code&gt;, and &lt;code&gt;Post&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Navigate to the &lt;code&gt;Components&lt;/code&gt; directory and create a new file called &lt;code&gt;DisplayAllPosts.jsx&lt;/code&gt;, then add the following code to it:&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="nx"&gt;CreateNewPost&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;./CreateNewPost&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;DisplayAllPosts&lt;/span&gt; &lt;span class="o"&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="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;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateNewPost&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="sr"&gt;/&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;DisplayAllPosts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we created a new component called &lt;code&gt;DisplayAllPost&lt;/code&gt; and rendered the &lt;code&gt;CreateNewPost&lt;/code&gt; component inside it.&lt;/p&gt;

&lt;p&gt;Now that we have finished building the components, it's time to bring them to life. As mentioned earlier, we intentionally did not add CSS to all the components at this stage, as the styling will be implemented once all the functionalities of this app are completed.&lt;/p&gt;

&lt;p&gt;The next step is to capture user input as they type into the text field and directly save it into the component state variable. To do this, we'll be using the first React hook in this tutorial called &lt;code&gt;useState&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  State in React
&lt;/h2&gt;

&lt;p&gt;In React, &lt;code&gt;state&lt;/code&gt; is means an object that stores information about how a component works. It is important in React and helps to handle the changing parts of a user interface. The component keeps track of the state object, and you can change it using the &lt;code&gt;setState()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Here are a few key points to keep in mind about state in React:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;States in React are changeable and dynamic, meaning they can be updated throughout the lifecycle of a component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A state holds information about the component it was declared in, and the component that declares a state is the owner of that state. No other components can directly access or modify it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the state of a component changes, the component will re-render itself, updating the corresponding elements in the DOM to reflect the new state. This makes it an efficient way to manage dynamic data and user input in React applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we declare a state variable with &lt;code&gt;useState&lt;/code&gt;, it returns an array with two items. The first item is the current value(state), and the second item is its updater function(setState) that is used to update the state. The array items returned from the &lt;code&gt;useState&lt;/code&gt; function are destructured into &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;setState&lt;/code&gt; variables respectively.&lt;/p&gt;

&lt;p&gt;Having gained a brief understanding of the &lt;code&gt;useState&lt;/code&gt; concept, let's modify the &lt;code&gt;DisplayAllPosts&lt;/code&gt; component in the following ways:&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="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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CreateNewPost&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;./CreateNewPost&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;DisplayAllPosts&lt;/span&gt; &lt;span class="o"&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="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;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&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;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setContent&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="nx"&gt;savePostTitleToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;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;title&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;savePostContentToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;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;content&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;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateNewPost&lt;/span&gt; 
    &lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&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;/&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;DisplayAllPosts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, two state variables, &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt;, are created using the &lt;code&gt;useState&lt;/code&gt; hook along with their corresponding updater functions, &lt;code&gt;setTitle&lt;/code&gt; and &lt;code&gt;setContent&lt;/code&gt;. Two functions, &lt;code&gt;savePostTitleToState&lt;/code&gt; and &lt;code&gt;savePostContentToState&lt;/code&gt;, are also defined to save user input values into the corresponding state variables. console.log() statements are added to these functions to view the input value as the user types. &lt;br&gt;
Finally, the two functions are passed as props to the &lt;code&gt;CreateNewPost&lt;/code&gt; component using the &lt;code&gt;props&lt;/code&gt; keyword. Props are used to pass data, including functions and state, from a parent component, &lt;code&gt;DisplayAllPosts&lt;/code&gt; in this case, to its child components, such as &lt;code&gt;CreateNewPost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The next step involves passing down the props data from the parent component, &lt;code&gt;DisplayAllPosts&lt;/code&gt;, to its child component, &lt;code&gt;CreateNewPost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open  the &lt;code&gt;CreateNewPost&lt;/code&gt; component and update the component to look like this:&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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreateNewPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;input&lt;/span&gt;
          &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;39&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;required&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/input&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;br&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;br&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;textarea&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;41&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;required&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/textarea&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;br&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;br&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Save&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/form&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;/&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;CreateNewPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see the changes you have made, refresh your browser and open your browser console (press &lt;code&gt;ctrl+shift+i&lt;/code&gt; if you are using Chrome) to view the captured data. Enter some text in the input fields and if everything works correctly, you should see a similar output like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585268496%2Freact-blog%2Fcode-output-6.gif" 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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585268496%2Freact-blog%2Fcode-output-6.gif" title="code output 6" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will now move on to the next step, which involves saving the post title and content captured from the user into a new state variable called &lt;code&gt;allPosts&lt;/code&gt;. This will be done by handling the &lt;code&gt;onClick&lt;/code&gt; event of the &lt;code&gt;Save Post&lt;/code&gt; button. &lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;DisplayAllPosts.jsx&lt;/code&gt; file, create a new state called &lt;code&gt;allPost&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const [allPosts, setAllPosts] = useState([]);&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;After that, we'll create a new function called &lt;code&gt;savePost&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savePost&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;setAllPost&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;allPost&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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;allPost&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 &lt;code&gt;savePost()&lt;/code&gt; function will be used to save the current post's &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; into the &lt;code&gt;allPost&lt;/code&gt; state variable. The function first generates a unique ID using the Date.now() method and then uses the &lt;code&gt;setAllPost()&lt;/code&gt; function, which is provided by the useState() hook, to add a new post to the &lt;code&gt;allPost&lt;/code&gt; array. The new post is an object with &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;id&lt;/code&gt; properties that are set to the values of the &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;id&lt;/code&gt; variables, respectively. Finally, the function logs the allPost array to the console to show the new post has been added.&lt;/p&gt;

&lt;p&gt;Let's update the savePost function to reset the &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; once the post has been added to the &lt;code&gt;allPost&lt;/code&gt; array:&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;savePost&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setAllPost&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;allPost&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;}]);&lt;/span&gt;
    &lt;span class="nf"&gt;setTitle&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="nf"&gt;setContent&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="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;allPost&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;h1&gt;
  
  
  Clearing the input field with &lt;code&gt;useRef&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;We need to make sure a user can easily create a new post without having to manually delete the old content from the input fields. Clearing the state value will not affect the input field value on the DOM. To locate the input fields on the DOM and clear their value, we are going to use another React hook called &lt;code&gt;useRef&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In React, the &lt;code&gt;useRef&lt;/code&gt; hook creates a reference to a specific element or value in a component. This creates an object that can be updated without causing a re-render. With this hook, you can access and manipulate the properties of HTML elements like buttons or input fields, or store and access previous values of a component's props or state.&lt;/p&gt;

&lt;p&gt;We are going to import &lt;code&gt;useRef&lt;/code&gt; by updating the React import statement like this:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import React, { useState, useRef } from "react";&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Next, we will initialize the useRef:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const getTitle = useRef();
  const getContent = useRef();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then pass down the refs to &lt;code&gt;CreateNewPost&lt;/code&gt; component as props:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateNewPost&lt;/span&gt;
        &lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we'll navigate to the &lt;code&gt;CreateNewPost.jsx&lt;/code&gt; and make it use the new props data we passed down to it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CreateNewPost&lt;/code&gt; component should be looking like this:&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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreateNewPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;input&lt;/span&gt;
          &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;39&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;required&lt;/span&gt;
          &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/input&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;br&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;br&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;textarea&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;41&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
         &lt;span class="nx"&gt;required&lt;/span&gt;
          &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/textarea&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;br&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;br&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Save&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/form&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;/&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;CreateNewPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ref&lt;/code&gt; attribute is used to get the value of the &lt;code&gt;input&lt;/code&gt; and &lt;code&gt;textarea&lt;/code&gt; fields, and the functions &lt;code&gt;getTitle&lt;/code&gt; and &lt;code&gt;getContent&lt;/code&gt; passed in as props are used to set the value of the ref.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;DisplayAllPosts.jsx&lt;/code&gt; file and update the &lt;code&gt;savePost&lt;/code&gt; function to look like this:&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;savePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&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="nf"&gt;setAllPosts&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;content&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;allPosts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We used the &lt;code&gt;event.preventDefault()&lt;/code&gt; to prevent the default refreshing behaviour of HTML form when a user clicks on the submit button.&lt;/p&gt;

&lt;p&gt;The fourth and fifth lines of the function are used to clear the input fields by setting the value of the getTitle and getContent refs to an empty string. &lt;/p&gt;

&lt;p&gt;To use the savePost function, we'll pass it down as props to the CreateNewPost component. Let's update the return statement in &lt;code&gt;DisplayAllPosts.jsx&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  return (
    &amp;lt;&amp;gt;
      &amp;lt;CreateNewPost
        savePostTitleToState={savePostTitleToState}
        savePostContentToState={savePostContentToState}
        getTitle={getTitle}
        getContent={getContent}
        savePost={savePost}
      /&amp;gt;
    &amp;lt;/&amp;gt;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the &lt;code&gt;CreateNewPost&lt;/code&gt; component and make it use the &lt;code&gt;savePost&lt;/code&gt; function we passed down to it like this:&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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreateNewPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savePost&lt;/span&gt;&lt;span class="p"&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;input&lt;/span&gt;
          &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;39&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;required&lt;/span&gt;
          &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/input&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;br&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;br&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;textarea&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;41&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;required&lt;/span&gt;
          &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/textarea&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;br&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;br&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Save&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/form&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;/&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;CreateNewPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each time a user submits a post by clicking on the Save Post button, the &lt;code&gt;onSubmit()&lt;/code&gt; event will trigger the &lt;code&gt;savePost&lt;/code&gt; function we created earlier.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;DisplayAllPosts&lt;/code&gt; component should be looking like this:&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="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="nx"&gt;useRef&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="nx"&gt;CreateNewPost&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;./CreateNewPost&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;DisplayAllPosts&lt;/span&gt; &lt;span class="o"&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="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;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&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;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setContent&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;allPosts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAllPosts&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="c1"&gt;// Initialize useRef&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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;getContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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;savePostTitleToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&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="nf"&gt;setAllPosts&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;content&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;allPosts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateNewPost&lt;/span&gt;
        &lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;savePost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&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;/&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;DisplayAllPosts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can refresh the browser now and launch the browser console to see if the captured data is being saved correctly into the AllPosts state variable. &lt;/p&gt;

&lt;p&gt;You should have a similar output that looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585275453%2Freact-blog%2Fcode-output-7.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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585275453%2Freact-blog%2Fcode-output-7.png" title="code output 6" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that the post data has been captured successfully, it's time to display them in the &lt;code&gt;DisplayAllPost&lt;/code&gt; component. But before then, let's render the &lt;code&gt;CreateNewPost&lt;/code&gt; component only when a user clicks on the &lt;code&gt;Add New&lt;/code&gt; button and remove the component immediately the user clicks on the &lt;code&gt;Save Post&lt;/code&gt; button. To do that, let's update the &lt;code&gt;DisplayAllPost&lt;/code&gt; component to look like this:&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="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="nx"&gt;useRef&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="nx"&gt;CreateNewPost&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;./CreateNewPost&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;DisplayAllPosts&lt;/span&gt; &lt;span class="o"&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="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;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&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;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setContent&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;allPosts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAllPosts&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isCreateNewPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsCreateNewPost&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="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Initialize useRef&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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;getContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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;savePostTitleToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toggleCreateNewPost&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIsCreateNewPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isCreateNewPost&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;savePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;setAllPosts&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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;allPosts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;toggleCreateNewPost&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isCreateNewPost&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;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateNewPost&lt;/span&gt;
        &lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;savePost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&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;/&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="nx"&gt;Posts&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&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;br&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;br&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleCreateNewPost&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;Create&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/&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;DisplayAllPosts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We created a new state variable called &lt;code&gt;isCreateNewPost&lt;/code&gt; and we initialized it with a boolean value, false. &lt;br&gt;
Then we created another function called &lt;code&gt;toggleCreateNewpost&lt;/code&gt;, this function will make the &lt;code&gt;isCreateNewPost&lt;/code&gt; state variable to swicth between true and false. If the previous state value of &lt;code&gt;isCreateNewPost&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;toggleCreateNewpost&lt;/code&gt; will change it to &lt;code&gt;false&lt;/code&gt; otherwise, &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We added a new button called &lt;code&gt;Create New&lt;/code&gt;. This button will call the &lt;code&gt;toggleCreateNewpost&lt;/code&gt; function once it is invoked. Finally, we created a conditional statement that only renders the &lt;code&gt;CreateNewPost&lt;/code&gt; component if the &lt;code&gt;isCreateNewPost&lt;/code&gt; boolean value is true.&lt;/p&gt;

&lt;p&gt;This process of rendering a component only when a condition is met is called &lt;strong&gt;&lt;code&gt;Conditional Rendering&lt;/code&gt;&lt;/strong&gt; in React.&lt;/p&gt;

&lt;p&gt;After refreshing the browser, you can preview your changes. The output you see should be nearly identical to this one:&lt;/p&gt;

&lt;p&gt;When you click on the &lt;code&gt;Create New&lt;/code&gt; button, it should render the &lt;code&gt;CreateNewPost&lt;/code&gt; component like so:&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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585277138%2Freact-blog%2Fcode-output-8.gif" 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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585277138%2Freact-blog%2Fcode-output-8.gif" title="code output 8" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you enter the post title and contents and click on the &lt;code&gt;Save Post&lt;/code&gt; button, it should save them and render back the &lt;code&gt;DisplayAllPosts&lt;/code&gt; component, but the post will not be displayed yet. &lt;br&gt;
To display all the posts, we need to modify the Post component to receive the props that will be passed down to it from its parent component, &lt;code&gt;DisplayAllPosts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open the&lt;code&gt;Post.jsx&lt;/code&gt; and modify it to look like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&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;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&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="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="nx"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Edit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Delete&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/section&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;/&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;Post&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we are done with the &lt;code&gt;Post&lt;/code&gt; component, let's modify the &lt;code&gt;DisplayAllPosts&lt;/code&gt; to look like this:&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="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="nx"&gt;useRef&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="nx"&gt;CreateNewPost&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;./CreateNewPost&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;Post&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;./Post&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;DisplayAllPosts&lt;/span&gt; &lt;span class="o"&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="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;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&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;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setContent&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;allPosts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAllPosts&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isCreateNewPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsCreateNewPost&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="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Initialize useRef&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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;getContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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;savePostTitleToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;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;title&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;savePostContentToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;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;content&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;toggleCreateNewPost&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIsCreateNewPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isCreateNewPost&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;savePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&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="nf"&gt;setAllPosts&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;content&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;allPosts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;toggleCreateNewPost&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isCreateNewPost&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;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateNewPost&lt;/span&gt;
          &lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;savePost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="sr"&gt;/&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;/&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="nx"&gt;Posts&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;allPosts&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;There&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;nothing&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;see&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&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="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;
              &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&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="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&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="sr"&gt;/&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="p"&gt;)}&lt;/span&gt;

      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&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;br&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleCreateNewPost&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;Create&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/&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;DisplayAllPosts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the &lt;code&gt;DisplayAllPosts&lt;/code&gt; component has been modified to display the post data. If the &lt;code&gt;allPosts&lt;/code&gt; array is empty it is going to display &lt;code&gt;There is nothing to see here!&lt;/code&gt; on the screen else it is going to use the array.map() method to loop through the &lt;code&gt;allPosts&lt;/code&gt; array data and pass down each post &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; as &lt;code&gt;props&lt;/code&gt; to the &lt;code&gt;Post&lt;/code&gt; component.&lt;br&gt;
Refresh your browser, click on the &lt;code&gt;Add New&lt;/code&gt; button, enter some value into the title and contents field and click on save.&lt;br&gt;
If everything goes well, you should have a similar output that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-9.gif" 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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-9.gif" title="code output 9" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can click on the &lt;code&gt;Create New&lt;/code&gt; button to add more posts and see all the posts being rendered to the screen.&lt;/p&gt;

&lt;p&gt;So far, we are done with the C and R (Create and Read) feature of our CRUD app. The next feature we are going to implement now is the Update feature. &lt;/p&gt;

&lt;p&gt;This feature will enable the user to modify a selected post once the &lt;code&gt;Edit&lt;/code&gt; button is clicked.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;DisplayAllPosts.js&lt;/code&gt; and create a new state called &lt;code&gt;isModifyPost&lt;/code&gt; below the &lt;code&gt;isCreateNewPost&lt;/code&gt; state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [isModifyPost, setIsModifyPost] = useState(false);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use this state to render the &lt;code&gt;ModifyPost&lt;/code&gt; component once &lt;code&gt;isModifyPost&lt;/code&gt; boolean value is true. &lt;/p&gt;

&lt;p&gt;Next, we'll to create another function called &lt;code&gt;toggleModifyPostComponent&lt;/code&gt; just below the &lt;code&gt;toggleCreateNewPost&lt;/code&gt; function:&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;toggleModifyPostComponent&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIsModifyPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isModifyPost&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 function switches the value of the &lt;code&gt;isModifyPost&lt;/code&gt; variable between &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt;. If the previous value of the variable is &lt;code&gt;false&lt;/code&gt;, it changes it to &lt;code&gt;true&lt;/code&gt;, and if the previous value is &lt;code&gt;true&lt;/code&gt;, it changes it to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's create another state called &lt;code&gt;editPostId&lt;/code&gt;, below the &lt;code&gt;isModifyPost&lt;/code&gt; state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [editPostId, setEditPostId] = useState("");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This state variable will be used to save the &lt;code&gt;id&lt;/code&gt; of the post that a user wants to modify.&lt;/p&gt;

&lt;p&gt;After that, you will create another function called &lt;code&gt;editPost&lt;/code&gt; below the &lt;code&gt;toggleModifyPostComponent&lt;/code&gt; function:&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;editPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setEditPostId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;toggleModifyPostComponent&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 function will be passed down to the &lt;code&gt;Post&lt;/code&gt; component and get called from inside the &lt;code&gt;Post&lt;/code&gt; component with the &lt;code&gt;id&lt;/code&gt; of the post that the user clicks on as its parameter. The &lt;code&gt;setEditPostId&lt;/code&gt; function will save the post id into &lt;code&gt;editPostId&lt;/code&gt; state, while the &lt;code&gt;toggleModifyPost&lt;/code&gt; function will render or remove the &lt;code&gt;ModifyPost&lt;/code&gt; component depending on the &lt;code&gt;isModifyPost&lt;/code&gt; state boolean value.&lt;/p&gt;

&lt;p&gt;We are saving the &lt;code&gt;id&lt;/code&gt; of the post that a user wants to modify into the &lt;code&gt;editPostId&lt;/code&gt; state variable because we want the &lt;code&gt;updatePost&lt;/code&gt; function to have access to it.&lt;/p&gt;

&lt;p&gt;Now, we will create a new function called &lt;code&gt;updatePost&lt;/code&gt;. This function will be used to update the modified post:\&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;updatePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&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;updatedPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;editPostId&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;...&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;eachPost&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="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;eachPost&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="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;setAllPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedPost&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;toggleModifyPostComponent&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;In this code, we used the &lt;code&gt;map()&lt;/code&gt; method to loop through each post in the &lt;code&gt;allPosts&lt;/code&gt; component to locate the post that the user wants to edit, based on the post &lt;code&gt;id&lt;/code&gt; stored in the &lt;code&gt;editPostId&lt;/code&gt; state variable. Then, we used the rest syntax (&lt;code&gt;...&lt;/code&gt;) to modify only the &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; of the post, while keeping the &lt;code&gt;id&lt;/code&gt; of the post unchanged. To prevent empty values from being saved when the user updates a post without making changes, we used the &lt;code&gt;OR&lt;/code&gt; operator (&lt;code&gt;||&lt;/code&gt;) to save the previous post title and content. &lt;/p&gt;

&lt;p&gt;The next thing we need to do now is to render the &lt;code&gt;ModifyPost&lt;/code&gt; component if the &lt;code&gt;isModifyPost&lt;/code&gt; state variable is &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;DisplayAllPost.jsx&lt;/code&gt;, let's add the following code below the &lt;br&gt;
&lt;code&gt;if (isCreateNewPost){...}&lt;/code&gt;&lt;br&gt;
statement:&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;else&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;isModifyPost&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;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;editPostId&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;ModifyPost&lt;/span&gt;
        &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&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="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&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="nx"&gt;updatePost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;updatePost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&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;What we are tryig to achieve here is to preload the input fields in the &lt;code&gt;ModifyPost&lt;/code&gt; component with the data of the selected post.&lt;br&gt;
We also passed down the &lt;code&gt;updatePost&lt;/code&gt;, &lt;code&gt;saveTitleToState&lt;/code&gt;, &lt;code&gt;savePostContentToState&lt;/code&gt; function to the &lt;code&gt;ModifyPost&lt;/code&gt; component respectively. We have used &lt;code&gt;saveTitleToState&lt;/code&gt; and &lt;code&gt;savePostContentToState&lt;/code&gt; before in the &lt;code&gt;CreateNewPost&lt;/code&gt; component to save user input value to the state variable.&lt;/p&gt;

&lt;p&gt;Now we are going to use the props that was passed to the &lt;code&gt;ModifyPost&lt;/code&gt; component. Open the &lt;code&gt;ModifyPost.jsx&lt;/code&gt; and update its code to look like this:&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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ModifyPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&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;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Modify&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&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;input&lt;/span&gt;
          &lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&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="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;text&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;39&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/input&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;br&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;br&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;textarea&lt;/span&gt;
          &lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&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="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;41&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/textarea&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;br&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;br&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updatePost&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;Update&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/form&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;/&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;ModifyPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We set the default value of the inputs field that will be rendered to the user with the post &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; that was passed down to this component. We also set the submit button with an onClick event which will call the &lt;code&gt;updatePost&lt;/code&gt; function that was passed down to the &lt;code&gt;ModifyPost&lt;/code&gt; component.&lt;br&gt;
One more thing before we test the &lt;code&gt;ModifyPost&lt;/code&gt; component, we will trigger the &lt;code&gt;ModifyPost&lt;/code&gt; component once a user clicks on the edit button. Let's pass down  the &lt;code&gt;editPost&lt;/code&gt; function to the &lt;code&gt;Post&lt;/code&gt; component from &lt;code&gt;DisplayAllPosts&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Let's modify the &lt;code&gt;DisplayAllPosts&lt;/code&gt; component to render the &lt;code&gt;Post&lt;/code&gt; component like this:&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="nx"&gt;Posts&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;allPosts&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;There&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;nothing&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;see&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&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="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;
              &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&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="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&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="nx"&gt;editPost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;editPost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="sr"&gt;/&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="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&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;br&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleCreateNewPost&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;Create&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/&lt;/span&gt;&lt;span class="err"&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;Now we are going to update the Post component to use the &lt;code&gt;editPost&lt;/code&gt; function that was passed to it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Post&lt;/code&gt; Component should be looking like this:&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="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;const&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;=&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="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;editPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&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;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&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;/h3&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="o"&gt;&amp;gt;&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="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="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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;editPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;Edit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Delete&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/section&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;/&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;Post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before running the app, let's compare the &lt;code&gt;DisplayAllPost.jsx&lt;/code&gt; file and make sure it looks like this:&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="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="nx"&gt;useRef&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="nx"&gt;CreateNewPost&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;./CreateNewPost&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;Post&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;./Post&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;ModifyPost&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;./ModifyPost&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;DisplayAllPosts&lt;/span&gt; &lt;span class="o"&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="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;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&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;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setContent&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;allPosts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAllPosts&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isCreateNewPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsCreateNewPost&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="kc"&gt;false&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;isModifyPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsModifyPost&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="kc"&gt;false&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;editPostId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEditPostId&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="c1"&gt;// Initialize useRef&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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;getContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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;savePostTitleToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toggleCreateNewPost&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIsCreateNewPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isCreateNewPost&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;toggleModifyPostComponent&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIsModifyPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isModifyPost&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;editPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setEditPostId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;toggleModifyPostComponent&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;updatePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&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;updatedPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;editPostId&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;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;editPostId&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;...&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;eachPost&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="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;eachPost&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="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;eachPost&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;eachPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;setAllPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedPost&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;toggleModifyPostComponent&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;savePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;setAllPosts&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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;allPosts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTitle&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="nf"&gt;setContent&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="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;toggleCreateNewPost&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isCreateNewPost&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;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateNewPost&lt;/span&gt;
          &lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;savePost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="sr"&gt;/&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;/&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;else&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;isModifyPost&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;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;editPostId&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;ModifyPost&lt;/span&gt;
        &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&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="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&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="nx"&gt;updatePost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;updatePost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostTitleToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;savePostContentToState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="nx"&gt;Posts&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;allPosts&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;There&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;nothing&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;see&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&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="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;
              &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&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="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&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="nx"&gt;editPost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;editPost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="sr"&gt;/&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="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&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;br&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleCreateNewPost&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;Create&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/&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;DisplayAllPosts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can refresh the browser to view the changes&lt;/p&gt;

&lt;p&gt;Finally, we will to implement the last and probably the easiest feature of our &lt;code&gt;CRUD&lt;/code&gt; app, the &lt;code&gt;Delete&lt;/code&gt; feature.&lt;/p&gt;

&lt;p&gt;This feature will enable a user to remove a specific post once they click on the delete button.  &lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;DisplayAllPosts.jsx&lt;/code&gt; file and create a &lt;code&gt;deletePost&lt;/code&gt; function below &lt;code&gt;editPost&lt;/code&gt; function:&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;deletePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modifiedPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;setAllPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modifiedPost&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 &lt;code&gt;deletePost&lt;/code&gt; function takes in the &lt;code&gt;id&lt;/code&gt; of the post that a user wants to remove as its parameter. We used one of the JavaScript array methods called &lt;code&gt;filter()&lt;/code&gt; to remove the post that matches the &lt;code&gt;id&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Next we are going to pass down the &lt;code&gt;deletePost&lt;/code&gt; function from the  &lt;code&gt;DisplayAllPosts&lt;/code&gt; component to the &lt;code&gt;Post&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;To do that, we are going update the Post component we imported in &lt;code&gt;DisplayAllPost.jsx&lt;/code&gt; by adding &lt;code&gt;deletePost={deletePost}&lt;/code&gt; to the child component like so:&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="nx"&gt;Posts&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;allPosts&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;There&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;nothing&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;see&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&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="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;
              &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&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="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eachPost&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="nx"&gt;editPost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;editPost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;deletePost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;deletePost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="sr"&gt;/&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="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&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;br&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleCreateNewPost&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;Create&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/&lt;/span&gt;&lt;span class="err"&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;Finally, we will make use of the &lt;code&gt;deletePost&lt;/code&gt; function we passed down to Post component by launching the Post.jsx file and updating it to look like this:&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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;=&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="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;editPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deletePost&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&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;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&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;/h3&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="o"&gt;&amp;gt;&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="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="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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;editPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;Edit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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;deletePost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;Delete&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/section&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;/&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;Post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a user click on the &lt;code&gt;Delete&lt;/code&gt; button, it will invoke the &lt;code&gt;deletePost&lt;/code&gt; function we passed down to &lt;code&gt;Post&lt;/code&gt; component with the &lt;code&gt;id&lt;/code&gt; of the current post.&lt;/p&gt;

&lt;p&gt;If all goes well we should have a similar output that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-10.gif" 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%2Fres.cloudinary.com%2Ftemitope%2Fimage%2Fupload%2Fv1585202891%2Freact-blog%2Fcode-output-10.gif" title="code output 10" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;This tutorial showed us how to create a basic blog frontend using React without making any API requests to a backend server. We didn't need to rely on a server to provide the data to our application, instead, we used React to create and manage our data. We also learned how to manipulate the state by performing CRUD (Create, Read, Update, Delete) operations on the state data. By doing so, we were able to add, read, update, and delete posts from our blog application.&lt;/p&gt;

&lt;p&gt;We also used conditional rendering in our application to switch between two components. Conditional rendering allowed us to only display a specific component when a particular condition is met. This way, we could show or hide certain parts of our application based on user interactions or other factors. Overall, this tutorial provided a foundation for creating more complex React applications and using its features to manage data and manipulate the user interface.&lt;/p&gt;

&lt;p&gt;Thanks for reading. The full code used in this tutorial can be found here: &lt;a href="https://github.com/tope-olajide/react-simple-blog" rel="noopener noreferrer"&gt;https://github.com/tope-olajide/react-simple-blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you enjoy my post, please share it with others and give it some emojis so people can see it.  &lt;/p&gt;

</description>
      <category>react</category>
      <category>hook</category>
    </item>
  </channel>
</rss>
