<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: TThroo-Dev</title>
    <description>The latest articles on Forem by TThroo-Dev (@tthroo).</description>
    <link>https://forem.com/tthroo</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%2F1245988%2F50245d8f-0a27-4708-95a2-3f57dd471fe4.png</url>
      <title>Forem: TThroo-Dev</title>
      <link>https://forem.com/tthroo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/tthroo"/>
    <language>en</language>
    <item>
      <title>Build your SaaS landing page in 15 minutes using Mantine</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Thu, 11 Jan 2024 23:37:56 +0000</pubDate>
      <link>https://forem.com/tthroo/build-your-saas-landing-page-in-15-minutes-using-mantine-111a</link>
      <guid>https://forem.com/tthroo/build-your-saas-landing-page-in-15-minutes-using-mantine-111a</guid>
      <description>&lt;p&gt;After the &lt;a href="https://dev.to/tthroo/jsoncrack-codebase-analysis-part-5-toolbar-and-bottom-bar-55gl"&gt;Jsoncrack codebase analysis&lt;/a&gt; series, I have decided to update my website &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt; to use &lt;a href="https://mantine.dev/"&gt;Mantine&lt;/a&gt; components.&lt;/p&gt;

&lt;p&gt;I was able to create components required in less than 15minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait, what components?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://ui.mantine.dev/category/headers/"&gt;Header&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ui.mantine.dev/category/hero/"&gt;Hero Section&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ui.mantine.dev/category/features/"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ui.mantine.dev/category/faq/"&gt;FAQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ui.mantine.dev/category/footers/"&gt;Footer&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can find them in &lt;a href="https://github.com/TThroo-Dev/TThroo.com"&gt;TThroo&lt;/a&gt; repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose the starter project
&lt;/h2&gt;

&lt;p&gt;Mantine provides &lt;a href="https://mantine.dev/guides/next/"&gt;Nextjs starter&lt;/a&gt; configured with Mantine.&lt;/p&gt;

&lt;p&gt;I chose &lt;a href="https://github.com/mantinedev/next-app-min-template"&gt;next-app-min-template&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then copied the code from Mantine components listed above and that's it. You now have your SaaS landing page.&lt;/p&gt;

&lt;p&gt;But is it though?&lt;/p&gt;

&lt;p&gt;You still need to update the copy writing for your website content, update the logo to match your brand's values, but atleast you have a website ready. One less problem...&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;I used to host my website on firebase hosting, with nextjs, you have to perform &lt;a href="https://firebase.google.com/docs/hosting/frameworks/nextjs"&gt;additional steps&lt;/a&gt;. Keep this in mind.&lt;/p&gt;

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

&lt;p&gt;Jsoncrack codebase analysis helped me learn about Mantine and I liked their components. This is what you do, you apply from your learnings. &lt;/p&gt;

&lt;p&gt;It can be something a small thing such as this one to decide to go with Mantine or it can be a huge pattern that you decided to apply when you have a &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/layout/ModalController/index.tsx#L28"&gt;lot of modals&lt;/a&gt; in your project.&lt;/p&gt;

&lt;p&gt;Sure, I could have used tailwind, but it is alright. I want to demonstrate as much as possible how powerful and useful opensource to learn from.&lt;/p&gt;

&lt;p&gt;If you have any questions or need help with your project, feel free to reach out to me at &lt;a href="mailto:ram@tthroo.com"&gt;ram@tthroo.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>nextjs</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis - Part 6 - Lemonsqueezy integration</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Wed, 10 Jan 2024 21:37:21 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-6-lemonsqueezy-integration-5co2</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-6-lemonsqueezy-integration-5co2</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/editor" rel="noopener noreferrer"&gt;jsoncrack&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/" rel="noopener noreferrer"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;In this part 6, we understand how &lt;a href="https://www.lemonsqueezy.com/" rel="noopener noreferrer"&gt;Lemonsqueezy&lt;/a&gt; is used for payment subscription.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/pages/pricing.tsx#L162" rel="noopener noreferrer"&gt;Pricing.tsx&lt;/a&gt; in &lt;code&gt;src/pages/pricing.tsx&lt;/code&gt; has &lt;code&gt;Upgrade&lt;/code&gt; that redirects you to Lemonsqueezy checkout.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checkout
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  Webhook listener
&lt;/h2&gt;

&lt;p&gt;So, I could not figure out the webhook listener used to listen subscriptions created via this checkout in this codebase, I was hoping I could find an endpoint.&lt;/p&gt;

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

&lt;p&gt;The idea is to listen to webhook events whenever there is a new subscription created and update the database record.&lt;/p&gt;

&lt;p&gt;I will make sure to include this as part my next tutorial series where we build a product similar to jsoncrack.&lt;/p&gt;

&lt;p&gt;But you get the idea now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Premium
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;setSession&lt;/code&gt; object used in &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useUser.ts#L33" rel="noopener noreferrer"&gt;useFile&lt;/a&gt; store calls &lt;code&gt;supabase.rpc("get_subscription_info")&lt;/code&gt; to fetch the user data if they have paid for subscription and &lt;code&gt;premium&lt;/code&gt; flag in the store.&lt;/p&gt;

&lt;p&gt;rpc? &lt;a href="https://supabase.com/docs/reference/javascript/rpc" rel="noopener noreferrer"&gt;remote procedure call&lt;/a&gt; from &lt;code&gt;Supabase&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;That's it, You now just have to call 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;const premium = useUser(state =&amp;gt; state.premium);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To find out if a user is a premium user and allow to user premium features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conlusion
&lt;/h2&gt;

&lt;p&gt;Lemonsqueezy makes it easy to handle subscriptions for SaaS. This was a brief overview of how jsoncrack handles payment subscription. &lt;/p&gt;

&lt;p&gt;We have &lt;code&gt;rpc&lt;/code&gt;, &lt;code&gt;webhook&lt;/code&gt; and &lt;code&gt;useUser&lt;/code&gt; to reuse &lt;code&gt;premium&lt;/code&gt; logic across the codebase.&lt;/p&gt;

&lt;p&gt;This concludes our jsoncrack codebase analysis.&lt;/p&gt;

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

&lt;p&gt;I will create a tutorial that mainly uses the logic and design patterns used in this project. I am not a fan of copying exactly what is available in opensource codebases. I would rather build a unique application from sratch and apply the learnings. That's how you really learn. You APPLY :)&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we building next?
&lt;/h2&gt;

&lt;p&gt;A simple application that uses the same tech stack as jsoncrack.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;Supabase&lt;/li&gt;
&lt;li&gt;Monaco Editor&lt;/li&gt;
&lt;li&gt;Lemonsqueezy&lt;/li&gt;
&lt;li&gt;Reaflow&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;and yes, it will be opensource.&lt;/p&gt;

&lt;p&gt;I will make all these tutorials available at &lt;a href="https://practicefrontend.tthroo.com/practice" rel="noopener noreferrer"&gt;Practice Frontend&lt;/a&gt; after a significant to that website. That'll be opensource too.&lt;/p&gt;

&lt;p&gt;If you have any questions or need help with your project, feel free to reach out to me at &lt;a href="mailto:ram@tthroo.com"&gt;ram@tthroo.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis - Part 5 - Toolbar and Bottom bar</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Tue, 09 Jan 2024 21:41:54 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-5-toolbar-and-bottom-bar-55gl</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-5-toolbar-and-bottom-bar-55gl</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/editor"&gt;jsoncrack&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;In this part 5, we understand how &lt;code&gt;Toolbar&lt;/code&gt; and &lt;code&gt;BottomBar&lt;/code&gt; are configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interested to learn from opensource?
&lt;/h2&gt;

&lt;p&gt;I am going to write a tutorial series where we use what we learnt from this jsoncrack codebase analysis, potentially involves usage of monaco editor, mantine, authentication and zustand configuration and modals, pretty much everything that is worth applying.&lt;/p&gt;

&lt;p&gt;Before You ask, no, it is not going to be a jsoncrack clone but a unique project that uses similar codebase and similar approach and configuration to what we have seen in this series. It involves using supabase, zustand, mantine, monaco editor, nextjs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://forms.gle/HECxzhUgH1JHxTnm6"&gt;Join the waitlist&lt;/a&gt; and I will send you the link to the tutorials once they are ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where are they used?
&lt;/h2&gt;

&lt;p&gt;They are used in &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/pages/editor.tsx"&gt;Editor&lt;/a&gt; component. &lt;a href="https://dev.to/tthroo/jsoncrack-codebase-analysis-part-4-editor-56eh"&gt;Part 4&lt;/a&gt; explains about &lt;code&gt;Editor&lt;/code&gt; component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Toolbar
&lt;/h2&gt;

&lt;p&gt;You will find Toolbar inside &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Toolbar/index.tsx"&gt;src/containers/Toolbar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6n_-QDsw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ogl1rjj03ph9nvq0gnb2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6n_-QDsw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ogl1rjj03ph9nvq0gnb2.png" alt="Toolbar" width="660" height="860"&gt;&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;export const Toolbar: React.FC&amp;lt;{ isWidget?: boolean }&amp;gt; = ({ isWidget = false }) =&amp;gt; {
  const getJson = useJson(state =&amp;gt; state.getJson);
  const setVisible = useModal(state =&amp;gt; state.setVisible);

  const setFormat = useFile(state =&amp;gt; state.setFormat);
  const format = useFile(state =&amp;gt; state.format);
  const premium = useUser(state =&amp;gt; state.premium);

  const handleSave = () =&amp;gt; {
    const a = document.createElement("a");
    const file = new Blob([getJson()], { type: "text/plain" });

    a.href = window.URL.createObjectURL(file);
    a.download = "jsoncrack.json";
    a.click();
  };

  return (
    &amp;lt;Styles.StyledTools&amp;gt;
      {isWidget &amp;amp;&amp;amp; &amp;lt;Logo /&amp;gt;}
      {!isWidget &amp;amp;&amp;amp; (
        &amp;lt;Group gap="xs" justify="left" w="100%" style={{ flexWrap: "nowrap" }}&amp;gt;
          &amp;lt;Styles.StyledToolElement title="JSON Crack"&amp;gt;
            &amp;lt;Flex gap="xs" align="center" justify="center"&amp;gt;
              &amp;lt;JSONCrackLogo fontSize="1.2em" /&amp;gt;
            &amp;lt;/Flex&amp;gt;
          &amp;lt;/Styles.StyledToolElement&amp;gt;

          &amp;lt;Select
            defaultValue="json"
            size="xs"
            value={format}
            onChange={e =&amp;gt; setFormat(e as FileFormat)}
            miw={80}
            w={120}
            data={[
              { value: FileFormat.JSON, label: "JSON" },
              { value: FileFormat.YAML, label: "YAML" },
              { value: FileFormat.XML, label: "XML" },
              { value: FileFormat.TOML, label: "TOML" },
              { value: FileFormat.CSV, label: "CSV" },
            ]}
          /&amp;gt;

          &amp;lt;ViewModeMenu /&amp;gt;
          &amp;lt;Styles.StyledToolElement title="Import File" onClick={() =&amp;gt; setVisible("import")(true)}&amp;gt;
            Import
          &amp;lt;/Styles.StyledToolElement&amp;gt;
          &amp;lt;ViewMenu /&amp;gt;
          &amp;lt;ToolsMenu /&amp;gt;
          &amp;lt;Styles.StyledToolElement title="Cloud" onClick={() =&amp;gt; setVisible("cloud")(true)}&amp;gt;
            Cloud
          &amp;lt;/Styles.StyledToolElement&amp;gt;
          &amp;lt;Styles.StyledToolElement title="Download as File" onClick={handleSave}&amp;gt;
            Download
          &amp;lt;/Styles.StyledToolElement&amp;gt;
        &amp;lt;/Group&amp;gt;
      )}
      &amp;lt;Group gap="xs" justify="right" w="100%" style={{ flexWrap: "nowrap" }}&amp;gt;
        {!premium &amp;amp;&amp;amp; !isWidget &amp;amp;&amp;amp; (
          &amp;lt;Styles.StyledToolElement onClick={() =&amp;gt; setVisible("premium")(true)}&amp;gt;
            &amp;lt;Text display="flex" c="teal" fz="xs" fw="bold" style={{ textAlign: "center", gap: 4 }}&amp;gt;
              &amp;lt;MdWorkspacePremium size="18" /&amp;gt;
              Get Premium
            &amp;lt;/Text&amp;gt;
          &amp;lt;/Styles.StyledToolElement&amp;gt;
        )}

        &amp;lt;SearchInput /&amp;gt;
        {!isWidget &amp;amp;&amp;amp; (
          &amp;lt;&amp;gt;
            &amp;lt;Styles.StyledToolElement
              title="Save as Image"
              onClick={() =&amp;gt; setVisible("download")(true)}
            &amp;gt;
              &amp;lt;FiDownload size="18" /&amp;gt;
            &amp;lt;/Styles.StyledToolElement&amp;gt;
            &amp;lt;ZoomMenu /&amp;gt;
            &amp;lt;AccountMenu /&amp;gt;
            &amp;lt;OptionsMenu /&amp;gt;
            &amp;lt;Styles.StyledToolElement
              title="Fullscreen"
              $hide={isWidget}
              onClick={fullscreenBrowser}
            &amp;gt;
              &amp;lt;AiOutlineFullscreen size="18" /&amp;gt;
            &amp;lt;/Styles.StyledToolElement&amp;gt;
          &amp;lt;/&amp;gt;
        )}
      &amp;lt;/Group&amp;gt;
    &amp;lt;/Styles.StyledTools&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;isWidget&lt;/code&gt; flag is used to show either logo or the below optiions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ORAAtK3h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ji0qxtkf2rsxr8l4e1fa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ORAAtK3h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ji0qxtkf2rsxr8l4e1fa.png" alt="Header Options" width="800" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Select
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Select
  defaultValue="json"
  size="xs"
  value={format}
  onChange={e =&amp;gt; setFormat(e as FileFormat)}
  miw={80}
  w={120}
  data={[
   { value: FileFormat.JSON, label: "JSON" },
   { value: FileFormat.YAML, label: "YAML" },
   { value: FileFormat.XML, label: "XML" },
   { value: FileFormat.TOML, label: "TOML" },
   { value: FileFormat.CSV, label: "CSV" },
  ]}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is a Select component from mantine&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Flex, Group, Select, Text } from "@mantine/core";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;onChange&lt;/code&gt; sets format in &lt;code&gt;useFile&lt;/code&gt; store&lt;/p&gt;

&lt;h2&gt;
  
  
  ViewMode
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Toolbar/ViewModeMenu.tsx"&gt;ViewMode&lt;/a&gt; deserves a file with its own html and is a standalone that directly updates zustand store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Import
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Toolbar/index.tsx#L79"&gt;Import&lt;/a&gt; sets &lt;code&gt;visible&lt;/code&gt; prop in &lt;code&gt;useModal&lt;/code&gt; store.&lt;/p&gt;

&lt;h2&gt;
  
  
  ViewMenu
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Toolbar/ViewMenu.tsx"&gt;ViewMenu&lt;/a&gt; has a lot of changes to update &lt;code&gt;useGraph&lt;/code&gt; store that is directly correlated to the way visualisation is rendered using Reaflow.&lt;/p&gt;

&lt;p&gt;And this is again in it own file under Toolbar folder because it has additional HTML that is not the right fit to be in &lt;code&gt;Toolbar/index.tsx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The same approach above is applied to &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Toolbar/ToolsMenu.tsx"&gt;ToolsMenu&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud
&lt;/h2&gt;

&lt;p&gt;Cloud triggers a modal by setting visible prop in &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useModal.ts"&gt;useModal&lt;/a&gt; store.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OoDeov2V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qj1karpmus19rrpv1b4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OoDeov2V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qj1karpmus19rrpv1b4l.png" alt="Modals" width="630" height="1220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modals are handled super neatly.&lt;br&gt;
Took me a while to figure this one out. &lt;/p&gt;

&lt;p&gt;If you open &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/pages/_app.tsx#L62"&gt;_app.tsx&lt;/a&gt;, You will find &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/layout/ModalController/index.tsx#L28"&gt;ModalController&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;const ModalController = () =&amp;gt; {
  const setVisible = useModal(state =&amp;gt; state.setVisible);
  const modalStates = useModal(state =&amp;gt; modalComponents.map(modal =&amp;gt; state[modal.key]));

  return (
    &amp;lt;EditorWrapper&amp;gt;
      {modalComponents.map(({ key, component }, index) =&amp;gt; {
        const ModalComponent = component;
        const opened = modalStates[index];

        return &amp;lt;ModalComponent key={key} opened={opened} onClose={() =&amp;gt; setVisible(key)(false)} /&amp;gt;;
      })}
    &amp;lt;/EditorWrapper&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is basically telling to render what is set to true in useModal store. All the Modals used are placed in a container specifically dedicated for Modals. How NEAT!.&lt;/p&gt;

&lt;p&gt;This is one of the way cleanest ways to deal with Modals especially when you have a lot of them :)&lt;/p&gt;

&lt;p&gt;You can follow through similarly to understand the other items available in Toolbar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fullscreen Bar Icon
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function fullscreenBrowser() {
  if (!document.fullscreenElement) {
    document.documentElement.requestFullscreen().catch(() =&amp;gt; {
      toast.error("Unable to enter fullscreen mode.");
    });
  } else if (document.exitFullscreen) {
    document.exitFullscreen();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next time, You are looking for a piece of code to toggle in and out of a full screenmode, You now know how!&lt;/p&gt;

&lt;h2&gt;
  
  
  BottomBar
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;BottomBar&lt;/code&gt; does not contain as many options as &lt;code&gt;Topbar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZngF8G1s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zw1ouk2l01lmshym8skr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZngF8G1s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zw1ouk2l01lmshym8skr.png" alt="Bottom Bar" width="800" height="80"&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Interestingly, &lt;code&gt;Bottombar&lt;/code&gt; is part of &lt;code&gt;Editor&lt;/code&gt;, instead of it being a separate folder due to its limited number of options/features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_4MjG7dL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6553qkrl48uvo2pnw267.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_4MjG7dL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6553qkrl48uvo2pnw267.png" alt="Bottombar" width="650" height="398"&gt;&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;StyledBottomBar&amp;gt;
      {data?.name &amp;amp;&amp;amp; (
        &amp;lt;Head&amp;gt;
          &amp;lt;title&amp;gt;{data.name} | JSON Crack&amp;lt;/title&amp;gt;
        &amp;lt;/Head&amp;gt;
      )}
      &amp;lt;StyledLeft&amp;gt;
        &amp;lt;StyledBottomBarItem onClick={toggleEditor}&amp;gt;
          &amp;lt;BiSolidDockLeft /&amp;gt;
        &amp;lt;/StyledBottomBarItem&amp;gt;

        {fileName &amp;amp;&amp;amp; (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; setVisible("cloud")(true)}&amp;gt;
            &amp;lt;VscSourceControl /&amp;gt;
            {fileName}
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
        &amp;lt;StyledBottomBarItem&amp;gt;
          {error ? (
            &amp;lt;Popover width="auto" shadow="md" position="top" withArrow&amp;gt;
              &amp;lt;Popover.Target&amp;gt;
                &amp;lt;Flex align="center" gap={2}&amp;gt;
                  &amp;lt;VscError color="red" size={16} /&amp;gt;
                  &amp;lt;Text c="red" fw={500} fz="xs"&amp;gt;
                    Invalid
                  &amp;lt;/Text&amp;gt;
                &amp;lt;/Flex&amp;gt;
              &amp;lt;/Popover.Target&amp;gt;
              &amp;lt;Popover.Dropdown
                style={{
                  pointerEvents: "none",
                }}
              &amp;gt;
                &amp;lt;Text size="xs"&amp;gt;{error}&amp;lt;/Text&amp;gt;
              &amp;lt;/Popover.Dropdown&amp;gt;
            &amp;lt;/Popover&amp;gt;
          ) : (
            &amp;lt;Flex align="center" gap={2}&amp;gt;
              &amp;lt;MdOutlineCheckCircleOutline /&amp;gt;
              &amp;lt;Text size="xs"&amp;gt;Valid&amp;lt;/Text&amp;gt;
            &amp;lt;/Flex&amp;gt;
          )}
        &amp;lt;/StyledBottomBarItem&amp;gt;
        {(data?.owner_email === user?.email || (!data &amp;amp;&amp;amp; user)) &amp;amp;&amp;amp; (
          &amp;lt;StyledBottomBarItem onClick={handleSaveJson} disabled={isUpdating || error}&amp;gt;
            {hasChanges || !user ? &amp;lt;AiOutlineCloudUpload /&amp;gt; : &amp;lt;AiOutlineCloudSync /&amp;gt;}
            {hasChanges || !user ? (query?.json ? "Unsaved Changes" : "Save to Cloud") : "Saved"}
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
        {data?.owner_email === user?.email &amp;amp;&amp;amp; (
          &amp;lt;StyledBottomBarItem onClick={setPrivate} disabled={isUpdating}&amp;gt;
            {isPrivate ? &amp;lt;AiOutlineLock /&amp;gt; : &amp;lt;AiOutlineUnlock /&amp;gt;}
            {isPrivate ? "Private" : "Public"}
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
        &amp;lt;StyledBottomBarItem
          onClick={() =&amp;gt; setVisible("share")(true)}
          disabled={isPrivate || !data}
        &amp;gt;
          &amp;lt;AiOutlineLink /&amp;gt;
          Share
        &amp;lt;/StyledBottomBarItem&amp;gt;
        {liveTransformEnabled ? (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; toggleLiveTransform(false)}&amp;gt;
            &amp;lt;VscSync /&amp;gt;
            &amp;lt;Text fz="xs"&amp;gt;Live Transform&amp;lt;/Text&amp;gt;
          &amp;lt;/StyledBottomBarItem&amp;gt;
        ) : (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; toggleLiveTransform(true)}&amp;gt;
            &amp;lt;VscSyncIgnored /&amp;gt;
            &amp;lt;Text fz="xs"&amp;gt;Manual Transform&amp;lt;/Text&amp;gt;
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
        {!liveTransformEnabled &amp;amp;&amp;amp; (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; setContents({})}&amp;gt;
            &amp;lt;TbTransform /&amp;gt;
            Transform
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
      &amp;lt;/StyledLeft&amp;gt;

      &amp;lt;StyledRight&amp;gt;
        &amp;lt;StyledBottomBarItem&amp;gt;Nodes: {nodeCount}&amp;lt;/StyledBottomBarItem&amp;gt;
        &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; setVisible("review")(true)}&amp;gt;
          &amp;lt;VscFeedback /&amp;gt;
          Feedback
        &amp;lt;/StyledBottomBarItem&amp;gt;
      &amp;lt;/StyledRight&amp;gt;
    &amp;lt;/StyledBottomBar&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is pretty straigt forward, modifies what needs to be set in stores and few flags are to display what's needed.&lt;/p&gt;

&lt;p&gt;If You ask me to refactor the above code, I would choose to move the following to separate component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{liveTransformEnabled ? (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; toggleLiveTransform(false)}&amp;gt;
            &amp;lt;VscSync /&amp;gt;
            &amp;lt;Text fz="xs"&amp;gt;Live Transform&amp;lt;/Text&amp;gt;
          &amp;lt;/StyledBottomBarItem&amp;gt;
        ) : (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; toggleLiveTransform(true)}&amp;gt;
            &amp;lt;VscSyncIgnored /&amp;gt;
            &amp;lt;Text fz="xs"&amp;gt;Manual Transform&amp;lt;/Text&amp;gt;
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
        {!liveTransformEnabled &amp;amp;&amp;amp; (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; setContents({})}&amp;gt;
            &amp;lt;TbTransform /&amp;gt;
            Transform
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this new file, You could do 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;const liveTransformEnabled = useConfig(state =&amp;gt; state.liveTransformEnabled);

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

&lt;/div&gt;



&lt;p&gt;This could improve the readability, again, it is choice and not hard set rule, depends on dev teams and their preferences. You cannot over engineer at the same time, it is a fine balance. How you draw this fine balance is directly correlated to code maintainability and readability.&lt;/p&gt;

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

&lt;p&gt;We learnt how to use zustand stores and perform operations and do the state updates. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Modal&lt;/code&gt; configuration was interesting, I have never seen it before. All the modals are placed inside a folder and a separate store for modals. You can leverage this pattern if your project is dealing with modals heavy operations to handle and maintain the code easily.&lt;/p&gt;

&lt;p&gt;Up next, we have part 6 where we talk about how the payments and subscription is integrated into this product using &lt;a href="https://www.lemonsqueezy.com/"&gt;lemonsqueezy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have any questions or need help with your project, feel free to reach out to me at &lt;a href="mailto:ram@tthroo.com"&gt;ram@tthroo.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis — Part 4.3 — LiveEditor</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Mon, 08 Jan 2024 20:24:37 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-43-liveeditor-3m95</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-43-liveeditor-3m95</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/editor"&gt;jsoncrack&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tthroo/jsoncrack-codebase-analysis-part-41-editor-panes-component-26lg"&gt;Part 4.1 - Editor - Panes Component&lt;/a&gt; has 2 main components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JsonEditor Component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev.to/tthroo/jsoncrack-codebase-analysis-part-421-editor-jsoneditor-component-2ef8"&gt;Part 4.2.1 — Editor — JsonEditor Component&lt;/a&gt;&lt;br&gt;
and &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tthroo/jsoncrack-codebase-analysis-part-4211-jsoneditor-debouncedupdatejson-cld"&gt;Part 4.2.1.1 — JsonEditor — debouncedUpdateJson&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LiveEditor Component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, let's understand how &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Editor/LiveEditor.tsx"&gt;LiveEditor&lt;/a&gt; works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const LiveEditor: React.FC = () =&amp;gt; {
  const [contextOpened, setContextOpened] = React.useState(false);
  const [contextPosition, setContextPosition] = React.useState({
    x: 0,
    y: 0,
  });

  return (
    &amp;lt;StyledLiveEditor
      onContextMenuCapture={e =&amp;gt; {
        e.preventDefault();
        setContextOpened(true);
        setContextPosition({ x: e.pageX, y: e.pageY });
      }}
      onClick={() =&amp;gt; setContextOpened(false)}
    &amp;gt;
      &amp;lt;div
        style={{
          position: "fixed",
          top: contextPosition.y,
          left: contextPosition.x,
          zIndex: 100,
        }}
      &amp;gt;
        &amp;lt;Menu opened={false} shadow="sm"&amp;gt;
          &amp;lt;Menu.Dropdown&amp;gt;
            &amp;lt;Menu.Item&amp;gt;
              &amp;lt;Text size="xs"&amp;gt;Download as Image&amp;lt;/Text&amp;gt;
            &amp;lt;/Menu.Item&amp;gt;
            &amp;lt;Menu.Item&amp;gt;
              &amp;lt;Text size="xs"&amp;gt;Zoom to Fit&amp;lt;/Text&amp;gt;
            &amp;lt;/Menu.Item&amp;gt;
            &amp;lt;Menu.Item&amp;gt;
              &amp;lt;Text size="xs"&amp;gt;Rotate&amp;lt;/Text&amp;gt;
            &amp;lt;/Menu.Item&amp;gt;
          &amp;lt;/Menu.Dropdown&amp;gt;
        &amp;lt;/Menu&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;View /&amp;gt;
    &amp;lt;/StyledLiveEditor&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hang on minute? where is the &lt;code&gt;LiveEditor&lt;/code&gt;? On the first look, it might be apparent but what are interested in is here: &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Editor/LiveEditor.tsx#L72"&gt;View&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;const View = () =&amp;gt; {
  const viewMode = useConfig(state =&amp;gt; state.viewMode);

  if (viewMode === ViewMode.Graph) return &amp;lt;Graph /&amp;gt;;
  if (viewMode === ViewMode.Tree) return &amp;lt;TreeView /&amp;gt;;
  return null;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By this time, you must have understood the power off zustand to simplify the state management. &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useConfig.ts"&gt;useConfig&lt;/a&gt; is a zustand store.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hxyahkXf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbllbyx5io9ot0v2742d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hxyahkXf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbllbyx5io9ot0v2742d.png" alt="View mode" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A view mode that is header aka &lt;code&gt;Toolbar&lt;/code&gt; is used to set the view type. You guessed it. We are now moving away from &lt;code&gt;LiveEditor&lt;/code&gt; to &lt;code&gt;Graph&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A rookie mistake here would be dump all the &lt;code&gt;Graph&lt;/code&gt; and &lt;code&gt;TreeView&lt;/code&gt; code in the same file, this only makes your life hard when it comes to maintenance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Graph&lt;/code&gt; is in &lt;code&gt;src/containers/Views/GraphView&lt;/code&gt;. Can the &lt;code&gt;containers&lt;/code&gt; folder have &lt;code&gt;Views&lt;/code&gt;? It it makes sense, so be it. Because this &lt;code&gt;Views&lt;/code&gt; contains &lt;code&gt;Graph&lt;/code&gt; and &lt;code&gt;TreeView&lt;/code&gt; are in a way containers.&lt;/p&gt;

&lt;p&gt;There is no strict rule to follow to place your files, you be the best judge and place them where it makes sense. You can move the files around as your project grows in size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Graph
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jK6AKDIK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zzh79fsgkhf9hp8wstjj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jK6AKDIK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zzh79fsgkhf9hp8wstjj.png" alt="Graphs File Placement" width="672" height="756"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No wonder &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Views/GraphView/index.tsx"&gt;Graph&lt;/a&gt; is placed in &lt;code&gt;containers/Views&lt;/code&gt;. It just has more modularity 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;return (
    &amp;lt;&amp;gt;
      &amp;lt;Loading loading={loading} message="Painting graph..." /&amp;gt;
      &amp;lt;StyledEditorWrapper
        $widget={isWidget}
        onContextMenu={e =&amp;gt; e.preventDefault()}
        onClick={blurOnClick}
        key={String(gesturesEnabled)}
        $showRulers={rulersEnabled}
        {...bindLongPress()}
      &amp;gt;
        &amp;lt;Space
          onCreate={setViewPort}
          onContextMenu={e =&amp;gt; e.preventDefault()}
          treatTwoFingerTrackPadGesturesLikeTouch={gesturesEnabled}
          pollForElementResizing
        &amp;gt;
          &amp;lt;GraphCanvas isWidget={isWidget} /&amp;gt;
        &amp;lt;/Space&amp;gt;
      &amp;lt;/StyledEditorWrapper&amp;gt;
    &amp;lt;/&amp;gt;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Graph&lt;/code&gt; to &lt;code&gt;GraphCanvas&lt;/code&gt;, Notice how the component we are interested is now changed &lt;code&gt;GraphCanvas&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;But why &lt;code&gt;GraphCanvas&lt;/code&gt;? It is because &lt;a href="https://reaflow.dev/?path=/story/demos-basic--simple"&gt;Reaflow&lt;/a&gt; uses Canvas to render visualisations. Context matters here. Hence the name &lt;code&gt;Canvas&lt;/code&gt; appended to &lt;code&gt;GraphCanvas&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 GraphCanvas = ({ isWidget }: GraphProps) =&amp;gt; {
  const { validateHiddenNodes } = useToggleHide();
  const setLoading = useGraph(state =&amp;gt; state.setLoading);
  const centerView = useGraph(state =&amp;gt; state.centerView);
  const direction = useGraph(state =&amp;gt; state.direction);
  const nodes = useGraph(state =&amp;gt; state.nodes);
  const edges = useGraph(state =&amp;gt; state.edges);

  const [paneWidth, setPaneWidth] = React.useState(2000);
  const [paneHeight, setPaneHeight] = React.useState(2000);

  const onLayoutChange = React.useCallback(
    (layout: ElkRoot) =&amp;gt; {
      if (layout.width &amp;amp;&amp;amp; layout.height) {
        const areaSize = layout.width * layout.height;
        const changeRatio = Math.abs((areaSize * 100) / (paneWidth * paneHeight) - 100);

        setPaneWidth(layout.width + 50);
        setPaneHeight((layout.height as number) + 50);

        setTimeout(() =&amp;gt; {
          validateHiddenNodes();
          window.requestAnimationFrame(() =&amp;gt; {
            if (changeRatio &amp;gt; 70 || isWidget) centerView();
            setLoading(false);
          });
        });
      }
    },
    [isWidget, paneHeight, paneWidth, centerView, setLoading, validateHiddenNodes]
  );

  return (
    &amp;lt;Canvas
      className="jsoncrack-canvas"
      onLayoutChange={onLayoutChange}
      node={p =&amp;gt; &amp;lt;CustomNode {...p} /&amp;gt;}
      edge={p =&amp;gt; &amp;lt;CustomEdge {...p} /&amp;gt;}
      nodes={nodes}
      edges={edges}
      maxHeight={paneHeight}
      maxWidth={paneWidth}
      height={paneHeight}
      width={paneWidth}
      direction={direction}
      layoutOptions={layoutOptions}
      key={direction}
      pannable={false}
      zoomable={false}
      animated={false}
      readonly={true}
      dragEdge={null}
      dragNode={null}
      fit={true}
    /&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember when we were looking to understanding what was responsible for generating nodes and edges in &lt;a href="https://dev.to/tthroo/jsoncrack-codebase-analysis-part-4211-jsoneditor-debouncedupdatejson-cld"&gt;Part 4.2.1.1 — JsonEditor — debouncedUpdateJson&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GraphCanvas&lt;/code&gt; uses nodes and edges to render the visualisation.&lt;/p&gt;

&lt;p&gt;This is how what you entered as a json in code editor visualised using Reaflow in the LiveEditor.&lt;/p&gt;

&lt;p&gt;I just love how efficiently props management is done using zustand. &lt;/p&gt;

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

&lt;p&gt;We navigated between few files to understand the workings for &lt;code&gt;LiveEditor&lt;/code&gt; and saw how powerful zustand can be when it comes to state management.&lt;/p&gt;

&lt;p&gt;Part 5 would be about &lt;code&gt;Toolbar&lt;/code&gt; and &lt;code&gt;Bottombar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Part 6 - How the payments and subscription is integrated into this product using lemonsqueezy.&lt;/p&gt;

&lt;p&gt;Thank you for reading till the end. If you have any questions or need help with a project, feel free to reach out to me at &lt;a href="mailto:ram@tthroo.com"&gt;ram@tthroo.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis — Part 4.2.1.1 — JsonEditor — debouncedUpdateJson</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Sun, 07 Jan 2024 17:19:06 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-4211-jsoneditor-debouncedupdatejson-cld</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-4211-jsoneditor-debouncedupdatejson-cld</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/editor"&gt;jsoncrack&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tthroo/jsoncrack-codebase-analysis-part-421-editor-jsoneditor-component-2ef8"&gt;Part 4.2.1&lt;/a&gt; talks in detail about &lt;code&gt;JsonEditor&lt;/code&gt; and &lt;code&gt;MonacoEditor&lt;/code&gt; and we also look into understanding the &lt;code&gt;MonacoEditor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we will get a better understanding of &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useFile.ts#L71"&gt;debouncedUpdateJson(json)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A recap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setContents: async ({ contents, hasChanges = true, skipUpdate = false }) =&amp;gt; {
    try {
      set({ ...(contents &amp;amp;&amp;amp; { contents }), error: null, hasChanges });

      const isFetchURL = window.location.href.includes("?");
      const json = await contentToJson(get().contents, get().format);

      if (!useConfig.getState().liveTransformEnabled &amp;amp;&amp;amp; skipUpdate) return;

      if (get().hasChanges &amp;amp;&amp;amp; contents &amp;amp;&amp;amp; contents.length &amp;lt; 80_000 &amp;amp;&amp;amp; !isIframe() &amp;amp;&amp;amp; !isFetchURL) {
        sessionStorage.setItem("content", contents);
        sessionStorage.setItem("format", get().format);
        set({ hasChanges: true });
      }

      debouncedUpdateJson(json);
    } catch (error: any) {
      if (error?.mark?.snippet) return set({ error: error.mark.snippet });
      if (error?.message) set({ error: error.message });
      useJson.setState({ loading: false });
      useGraph.setState({ loading: false });
    }
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We went into great details about the above code snippet in &lt;a href="https://dev.to/tthroo/jsoncrack-codebase-analysis-part-421-editor-jsoneditor-component-2ef8"&gt;Part 4.2.1&lt;/a&gt; except for &lt;code&gt;debouncedUpdateJson(json);&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What is inside the &lt;code&gt;debouncedUpdateJson&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 debouncedUpdateJson = debounce((value: unknown) =&amp;gt; {
  useGraph.getState().setLoading(true);
  useJson.getState().setJson(JSON.stringify(value, null, 2));
}, 800);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just two calls to zustand stores, named as &lt;code&gt;useGraph&lt;/code&gt; and &lt;code&gt;useJson&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  useJson.getState().setJson(JSON.stringify(value, null, 2));
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;setJson&lt;/code&gt; has a side effect, it updates &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useJson.ts#L22"&gt;graph&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;setJson: json =&amp;gt; {
    set({ json, loading: false });
    useGraph.getState().setGraph(json);
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This article strictly goes into only details of the &lt;code&gt;debouncedUpdateJson&lt;/code&gt; and the side effects involved in it. This article does not provide a complete overview of the zustand stores yet, because we do not see a need yet. When trying to understand a new codebase, set a well defined scope.&lt;/p&gt;

&lt;p&gt;But you might be wondering, what is a graph?&lt;/p&gt;

&lt;p&gt;The following screenshot helps you understand what we are referring to and talking about.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dj5-0i94--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2w5fneqo8sqifejtif0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dj5-0i94--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2w5fneqo8sqifejtif0z.png" alt="Graph view mode" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Graph&lt;/code&gt; is a view mode.&lt;/p&gt;

&lt;p&gt;But why to have 2 stores, one for json and one for graph? the answer is, separation of concern. Json is used in monaco editor to load the json code and graph is used to render the mindmap or visualisation. Beginners would use one store to deal with json and graph in a single file. Don't do it. Separate your concerns through variables names, files names, folder organisation. It helps you in the long run.&lt;/p&gt;

&lt;h2&gt;
  
  
  useGraph
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useGraph.ts"&gt;useGraph&lt;/a&gt; has a lot going on, but we will look for &lt;code&gt;setGraph&lt;/code&gt; as this is the side effect performed in &lt;code&gt;setJson&lt;/code&gt; explained above.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useGraph.getState().setGraph(json);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useGraph.ts#L77C3-L94C5"&gt;setGraph&lt;/a&gt; has 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;setGraph: (data, options) =&amp;gt; {
    const { nodes, edges } = parser(data ?? useJson.getState().json);

    if (get().collapseAll) {
      set({ nodes, edges, ...options });
      get().collapseGraph();
    } else {
      set({
        nodes,
        edges,
        collapsedParents: [],
        collapsedNodes: [],
        collapsedEdges: [],
        graphCollapsed: false,
        ...options,
      });
    }
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You go step by step, exploring your unknowns.&lt;/p&gt;

&lt;h3&gt;
  
  
  parser
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useGraph.ts#L6C1-L6C56"&gt;parser&lt;/a&gt; is imported on top of the file from &lt;code&gt;src/lib/utils/json/jsonParser&lt;/code&gt; we saw a similar strategy for helpers that was using &lt;code&gt;jsonAdapter&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It is a good practice to put all your helpers in a file. Initially you might not see a need to put certains functions in a file, but as you add more code/features, you should make the best judgement about which functions can be moved into a file. &lt;/p&gt;

&lt;p&gt;You will reduce number of lines in a file, you do not want to end up 3k+ lines of code in a single file, rookie mistake. I have seen it before. My thoughts on such a file "God Almighty!?"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function parser(jsonStr: string): Graph {
  try {
    const states = initializeStates();
    const parsedJsonTree = parseTree(jsonStr);

    if (!parsedJsonTree) {
      throw new Error("Invalid document");
    }

    traverse({ states, objectToTraverse: parsedJsonTree });

    const { notHaveParent, graph } = states;

    if (notHaveParent.length &amp;gt; 1 &amp;amp;&amp;amp; parsedJsonTree.type !== "array") {
      const emptyNode = { id: null, text: "", isEmpty: true, data: {} };
      const emptyId = addNodeToGraph({ graph, ...emptyNode });

      notHaveParent.forEach(childId =&amp;gt; addEdgeToGraph(graph, emptyId, childId));
    }

    if (states.graph.nodes.length === 0) {
      if (parsedJsonTree.type === "array") {
        addNodeToGraph({ graph: states.graph, text: "[]" });
      } else {
        addNodeToGraph({ graph: states.graph, text: "{}" });
      }
    }

    states.graph.nodes = states.graph.nodes.map(node =&amp;gt; ({
      ...node,
      path: getNodePath(states.graph.nodes, states.graph.edges, node.id),
    }));

    return states.graph;
  } catch (error) {
    console.error(error);
    return { nodes: [], edges: [] };
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take some time to try to understand the code above. It makes sense to introduce &lt;a href="https://reaflow.dev/?path=/docs/docs-getting-started-basics--docs"&gt;Reaflow&lt;/a&gt;. Reaflow is used to show the nodes and edges and form a mindmap. &lt;/p&gt;

&lt;p&gt;Unknowns in the above code are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;parseTree - This comes from &lt;a href="https://www.npmjs.com/package/jsonc-parser"&gt;jsonc-parser&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/lib/utils/core/traverse.ts#L32"&gt;Traverse&lt;/a&gt;: a core util that deals with creating nodes and edges. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We could go into details of this, but the point of these tutorials is to understand how open sourced software is built ,the best practices around file structure, tech stack used. &lt;/p&gt;

&lt;p&gt;Looking at &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/lib/utils/core/traverse.ts#L32"&gt;traverse file's code&lt;/a&gt; you will understand that it has a lot of cases handled, all to build nodes and edges. Again be comfortable with this. You know how the core is now put together.&lt;/p&gt;

&lt;p&gt;If you were to contribute to jsoncrack, atleast you now where to look for, how the codebase is organised.&lt;/p&gt;

&lt;p&gt;Any changes in core should be dealt with extra care. It is named &lt;code&gt;core&lt;/code&gt; for a good reason.&lt;/p&gt;

&lt;p&gt;So, in the end parser returns a graph with nodes and edges that are used in Reaflow to render a map.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FZSo9ySt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4qvhrp9sitb3tr8d06s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FZSo9ySt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4qvhrp9sitb3tr8d06s.png" alt="Reaflow map" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Setting a json has a side effect that deals with updating graph. This graph with nodes and edges is used to Reaflow to render a mindmap. We touched the core utils when we looked at traverse functionality. You do not see any comments in the traverse file, because code is self explanatory by using variable names and function names that fit into the context.&lt;/p&gt;

&lt;p&gt;In part 4.3, we will look at &lt;code&gt;LiveEditor&lt;/code&gt; and understand how these &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Views/GraphView/index.tsx#L126"&gt;nodes and edges in graph are put together to laod a visualisation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the upcoming parts, we will also talk about Toolbar and bottombar. This is where we can understand how the payments and subscription is integrated into this product using &lt;a href="https://www.lemonsqueezy.com/"&gt;lemonsqueezy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that would be the end of jsoncrack codebase analysis.&lt;/p&gt;

&lt;p&gt;The next codebase to analyse is &lt;a href="https://github.com/calcom/cal.com"&gt;cal.com&lt;/a&gt;. This repo is larger than jsoncrack. It is a monorepo with packages and lots of stuff going behind the scenes.&lt;/p&gt;

&lt;p&gt;Our approach and the intention behind writing these analysis of open source codebase is not get into complete details and understand how the core works, but to understand the design patterns, file structure, tech stack used so you can take these learnings and apply them in your projects. Because every project deals with different business logic, it would not make sense to get into business logic but rather the structure around it, in essence, laying down the foundation.&lt;/p&gt;

&lt;p&gt;Thank you for reading till the end. If you have any questions or need help with a project or looking for an IT partner for your business, feel free to reach out to us at &lt;a href="mailto:ram@tthroo.com"&gt;ram@tthroo.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nextjs</category>
      <category>opensource</category>
      <category>react</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis — Part 4.2.1 — Editor — JsonEditor Component</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Sat, 06 Jan 2024 23:11:51 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-421-editor-jsoneditor-component-2ef8</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-421-editor-jsoneditor-component-2ef8</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/editor"&gt;jsoncrack&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@ram_89216/jsoncrack-codebase-analysis-part-4-1-editor-panes-component-5e2124ceb911"&gt;Part 4.1&lt;/a&gt; talks about &lt;code&gt;Panes&lt;/code&gt; component that has this component &lt;code&gt;JsonEditor&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Do what does &lt;code&gt;JsonEditor&lt;/code&gt; do? the below image shows what it is responsible for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ERmGt61N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ajr4b1r7pqaqgku9ty0p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ERmGt61N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ajr4b1r7pqaqgku9ty0p.png" alt="JsonEditor" width="800" height="1342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Editor/JsonEditor.tsx#L14"&gt;JsonEditor.tsx&lt;/a&gt; has about 23 lines at the time of writing this article.&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 from "react";
import styled from "styled-components";
import { MonacoEditor } from "src/components/MonacoEditor";

// import { PromptInput } from "src/components/PromptInput";

const StyledEditorWrapper = styled.div`
  display: flex;
  flex-direction: column;
  height: 100%;
  user-select: none;
`;

export const JsonEditor: React.FC = () =&amp;gt; {
  return (
    &amp;lt;StyledEditorWrapper&amp;gt;
      {/* &amp;lt;PromptInput /&amp;gt; */}
      &amp;lt;MonacoEditor /&amp;gt;
    &amp;lt;/StyledEditorWrapper&amp;gt;
  );
};

export default JsonEditor;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aye, commented code? anyways, You see this tool uses popular &lt;a href="https://github.com/microsoft/monaco-editor"&gt;MonacoEditor&lt;/a&gt;, a browser based open source code editor from Microsoft.&lt;/p&gt;

&lt;h2&gt;
  
  
  MonacoEditor component
&lt;/h2&gt;

&lt;p&gt;Now notice how we are now moving away from JsonEditor component to MonacoEditor. The author could have just put all the code related to &lt;code&gt;MonacoEditor&lt;/code&gt; in this &lt;code&gt;JsonEditor&lt;/code&gt; component, but no, it has been moved to &lt;code&gt;components&lt;/code&gt; folder. One possible answer could be jsoncrack author must have decided to include PromtInput as part of JsonEditor, but it was commented. Purely, to add more features along side the monaco editor, I think &lt;code&gt;MonacoEditor&lt;/code&gt; is made a separate new component. &lt;/p&gt;

&lt;p&gt;Let's now understand what &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/components/MonacoEditor/index.tsx#L29"&gt;MonacoEditor&lt;/a&gt; does.&lt;/p&gt;

&lt;p&gt;Top down approach, this component returns 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;return (
    &amp;lt;StyledWrapper&amp;gt;
      &amp;lt;Editor
        height="100%"
        language={fileType}
        theme={theme}
        value={contents}
        options={editorOptions}
        onValidate={errors =&amp;gt; setError(errors[0]?.message)}
        onChange={contents =&amp;gt; setContents({ contents, skipUpdate: true })}
        loading={&amp;lt;Loading message="Loading Monaco Editor..." loading /&amp;gt;}
      /&amp;gt;
    &amp;lt;/StyledWrapper&amp;gt;
  );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go through each prop in detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;language={fileType}&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Where is &lt;code&gt;fileType&lt;/code&gt; coming from? Checking the &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/components/MonacoEditor/index.tsx"&gt;MonacoEditor.tsx&lt;/a&gt; code, we see&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const fileType = useFile(state =&amp;gt; state.format);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useFile.ts#L89"&gt;useFile&lt;/a&gt;? no worries, it is &lt;a href="https://docs.pmnd.rs/zustand/getting-started/introduction"&gt;zustand store&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;useFile&lt;/code&gt; has initial state as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const initialStates = {
  fileData: null as File | null,
  format: FileFormat.JSON,
  contents: defaultJson,
  error: null as any,
  hasChanges: false,
  jsonSchema: null as object | null,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always look for what you are interested in, do not let the extra props, additions functions, fancy typescript type scare you away. It helps you stay focused. so what we are looking for is &lt;code&gt;FileFormat.JSON&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/enums/file.enum.ts#L2"&gt;FileFormat&lt;/a&gt;? it is simple enum file. This goes to say that jsoncrack author follows standard coding practices in not using magical strings or numbers instead relies on enums. &lt;/p&gt;

&lt;p&gt;Notice how we approached in understanding &lt;code&gt;fileType&lt;/code&gt; prop, it was unknown but we carefully looked at imports and specifically looked for it without letting the code inside &lt;code&gt;useFile&lt;/code&gt; scare us away :)&lt;/p&gt;

&lt;h3&gt;
  
  
  theme={theme}
&lt;/h3&gt;

&lt;p&gt;Let's take the same approach as we did for &lt;code&gt;fileType&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;const theme = useConfig(state =&amp;gt; (state.darkmodeEnabled ? "vs-dark" : "light"));&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;you will find the above snippet &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/components/MonacoEditor/index.tsx#L36C1-L37C1"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What are the unknowns here? yes, &lt;code&gt;useConfig&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useConfig.ts"&gt;useConfig&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are specifically looking for an initialState with the prop &lt;code&gt;darkModeEnabled&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 initialStates = {
  darkmodeEnabled: false,
  collapseButtonVisible: true,
  childrenCountVisible: true,
  imagePreviewEnabled: true,
  liveTransformEnabled: true,
  gesturesEnabled: false,
  rulersEnabled: true,
  viewMode: ViewMode.Graph,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will find the above code snippet &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useConfig.ts#L6C1-L15C3"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So by default, &lt;code&gt;darkmodeEnabled&lt;/code&gt; is set to false as part of initial state.&lt;/p&gt;

&lt;h3&gt;
  
  
  value={contents}
&lt;/h3&gt;

&lt;p&gt;Let's take the same approach as we did for &lt;code&gt;theme&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;const contents = useFile(state =&amp;gt; state.contents);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will find the above code snippet &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/components/MonacoEditor/index.tsx#L31C1-L32C1"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;back to &lt;code&gt;useFile&lt;/code&gt;, except this time we are interested in a different prop named &lt;code&gt;contents&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useFile.ts#L54"&gt;useFile&lt;/a&gt; initialState&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const initialStates = {
  fileData: null as File | null,
  format: FileFormat.JSON,
  contents: defaultJson,
  error: null as any,
  hasChanges: false,
  jsonSchema: null as object | null,
};

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

&lt;/div&gt;



&lt;p&gt;Pick what you are interested in, yes, &lt;code&gt;contents&lt;/code&gt;. what is a &lt;code&gt;defaulJson&lt;/code&gt; ? the answer is in &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useFile.ts#L7"&gt;import&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This is how you find answers, You have to be patient. There is a back and forth jumping between different files, that is because author has defined such a pattern. &lt;/p&gt;

&lt;p&gt;Meaning, all the zustand stores and inside a folder called store inside src. Large project complexity can be maintained well when you have well defined design pattern. You should keep it simple and know where to look for. Back to the code analysis now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/constants/data.ts"&gt;defaultJson&lt;/a&gt; is used to render some placeholder json. Notice how this is inside &lt;code&gt;src/constants/data.ts&lt;/code&gt;. Again, I am praising the way it is organised.&lt;/p&gt;

&lt;h3&gt;
  
  
  options={editorOptions}
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/components/MonacoEditor/index.tsx#L14"&gt;editorOptions&lt;/a&gt; are to provide your options for your monaco editor.&lt;/p&gt;

&lt;h3&gt;
  
  
  onValidate={errors =&amp;gt; setError(errors[0]?.message)}
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useFile.ts#L144"&gt;onValidate&lt;/a&gt; used to set errors in the &lt;code&gt;useFile&lt;/code&gt; store&lt;/p&gt;

&lt;p&gt;You can read more about it &lt;a href="https://www.npmjs.com/package/@monaco-editor/react#onvalidate"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  onChange={contents =&amp;gt; setContents({ contents, skipUpdate: true })}
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useFile.ts#L121"&gt;setContents&lt;/a&gt; has few side effects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setContents: async ({ contents, hasChanges = true, skipUpdate = false }) =&amp;gt; {
    try {
      set({ ...(contents &amp;amp;&amp;amp; { contents }), error: null, hasChanges });

      const isFetchURL = window.location.href.includes("?");
      const json = await contentToJson(get().contents, get().format);

      if (!useConfig.getState().liveTransformEnabled &amp;amp;&amp;amp; skipUpdate) return;

      if (get().hasChanges &amp;amp;&amp;amp; contents &amp;amp;&amp;amp; contents.length &amp;lt; 80_000 &amp;amp;&amp;amp; !isIframe() &amp;amp;&amp;amp; !isFetchURL) {
        sessionStorage.setItem("content", contents);
        sessionStorage.setItem("format", get().format);
        set({ hasChanges: true });
      }

      debouncedUpdateJson(json);
    } catch (error: any) {
      if (error?.mark?.snippet) return set({ error: error.mark.snippet });
      if (error?.message) set({ error: error.message });
      useJson.setState({ loading: false });
      useGraph.setState({ loading: false });
    }
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prop &lt;code&gt;setContents({ contents, skipUpdate: true })&lt;/code&gt; only sets skipUpdate and contents, &lt;code&gt;setContents: async ({ contents, hasChanges = true, skipUpdate = false })&lt;/code&gt; hasChanges is defaulted to true.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;set({ ...(contents &amp;amp;&amp;amp; { contents }), error: null, hasChanges });&lt;/code&gt; updates the contents in the &lt;code&gt;useFile&lt;/code&gt; store.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const isFetchURL = window.location.href.includes("?");&lt;/code&gt; apparently, jsoncrack does not auto save your edits. You have to click on &lt;code&gt;save to cloud&lt;/code&gt; in the &lt;code&gt;BottomBar&lt;/code&gt; to save your json and then you will see your url changing to something like &lt;code&gt;https://jsoncrack.com/editor?json=0d15b1a928fdbd3c3283d1e6&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8ccnLjqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2vlyoutlg7cpcy73um5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8ccnLjqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2vlyoutlg7cpcy73um5n.png" alt="Save to cloud" width="800" height="77"&gt;&lt;/a&gt; I have done to understand what isFetchURL does. now we know why.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const json = await contentToJson(get().contents, get().format);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;contentToJson&lt;/code&gt; function name indicates that it takes monacoeditor content and converts it to json. Let's see what code is. &lt;/p&gt;

&lt;p&gt;This &lt;code&gt;contentToJson&lt;/code&gt; is coming from &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/lib/utils/json/jsonAdapter.ts#L34"&gt;https://github.com/AykutSarac/jsoncrack.com/blob/main/src/lib/utils/json/jsonAdapter.ts#L34&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Notice how we are using a file from &lt;code&gt;src/lib/utils/json/jsonAdapter&lt;/code&gt;. Author could have just put this in MonacoEditor, but when you are interested and making efforts to organise your code to use &lt;code&gt;lib/utils/json/jsonAdapter&lt;/code&gt; to put your helpers in a different file is how you level up your coding game. Nobody will teach you this. Seasoned devs always try to put helper functions where they belong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const contentToJson = async (value: string, format = FileFormat.JSON): Promise&amp;lt;object&amp;gt; =&amp;gt; {
  try {
    let json: object = {};

    if (format === FileFormat.JSON) json = parse(value);
    if (format === FileFormat.YAML) json = load(value) as object;
    if (format === FileFormat.XML) json = jxon.stringToJs(value);
    if (format === FileFormat.TOML) json = toml.parse(value);
    if (format === FileFormat.CSV) json = await csv2json(value);
    if (format === FileFormat.XML &amp;amp;&amp;amp; keyExists(json, "parsererror")) throw Error("Unknown error!");

    if (!json) throw Error("Invalid JSON!");

    return Promise.resolve(json);
  } catch (error: any) {
    throw error;
  }
};

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

&lt;/div&gt;



&lt;p&gt;Okay, it is simple parse on contents from monaco editor since contents are json.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if (!useConfig.getState().liveTransformEnabled &amp;amp;&amp;amp; skipUpdate) return;&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_DO_tJ69--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8urq2th0rcjngyxfalnv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_DO_tJ69--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8urq2th0rcjngyxfalnv.png" alt="liveTransformEnabled" width="800" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is directly related to the &lt;code&gt;BottomBar&lt;/code&gt; as shown in image, notice how zustand makes it easy to establish state communication between &lt;code&gt;Editor&lt;/code&gt; component and &lt;code&gt;Bottombar&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;if (get().hasChanges &amp;amp;&amp;amp; contents &amp;amp;&amp;amp; contents.length &amp;lt; 80_000 &amp;amp;&amp;amp; !isIframe() &amp;amp;&amp;amp; !isFetchURL) {
        sessionStorage.setItem("content", contents);
        sessionStorage.setItem("format", get().format);
        set({ hasChanges: true });
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, hasChanges is true, contents has got some data, isIframe is false and isFetchURL is false. This if block gets executed and saves the data into &lt;code&gt;sessionStorage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debouncedUpdateJson(json);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useFile.ts#L71"&gt;debouncedupdateJson&lt;/a&gt; has 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 debouncedUpdateJson = debounce((value: unknown) =&amp;gt; {
  useGraph.getState().setLoading(true);
  useJson.getState().setJson(JSON.stringify(value, null, 2));
}, 800);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is a super common pattern to use debounce when you are dealing with user input and to save the data. Read more about it &lt;a href="https://www.npmjs.com/package/lodash.debounce"&gt;here&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;useJson.getState().setJson&lt;/code&gt; deserves a new article 4.2.1 because of the following code snippets and the side effects involved with useGraph&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const useJson = create&amp;lt;JsonStates &amp;amp; JsonActions&amp;gt;()((set, get) =&amp;gt; ({
  ...initialStates,
  getJson: () =&amp;gt; get().json,
  setJson: json =&amp;gt; {
    set({ json, loading: false });
    useGraph.getState().setGraph(json);
  },
  clear: () =&amp;gt; {
    set({ json: "", loading: false });
    useGraph.getState().clearGraph();
  },
}));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above snippet is from &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useJson.ts#L20"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we understand, useJson and useGraph, it lays a foundation to further explore different use cases involved with yaml, xml, csv formats as well.&lt;/p&gt;

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

&lt;p&gt;We looked at how you need to be specific about what you are looking for, especially when you have lot of unknowns, do not let this scare you away, I keep saying this, you have to comfortable with not knowing enough YET. We looked at props used in MonacoEditor, a lot of the props were straight forward. Because of the complexity and side effects involved in &lt;code&gt;debouncedJson&lt;/code&gt;'s useGraph and useJson, we decided to make a new article 4.2.1.1 talking in depth about &lt;code&gt;useJson.getState().setJson&lt;/code&gt; and the side effect involving &lt;code&gt;setGraph&lt;/code&gt;. Thank you for reading till the end. If you have any questions or need help with a project or looking for an IT partner for your business, feel free to reach out to us at &lt;a href="mailto:ram@tthroo.com"&gt;ram@tthroo.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>react</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis - Part 4.1 - Editor - Panes Component</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Fri, 05 Jan 2024 22:12:12 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-41-editor-panes-component-26lg</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-41-editor-panes-component-26lg</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/editor"&gt;jsoncrack.com&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@ram_89216/jsoncrack-codebase-analysis-part-4-editor-c90b2f047d72"&gt;Part 4&lt;/a&gt; talks about how Editor component is configured for the JSONCrack. It has the components overview, but let's dig deeper into how these components are entagled together. Interesting stuff from here on as this is where we will see the usage of zustand, hooks and draw more conclusions about design patterns used in this codebase.&lt;/p&gt;

&lt;p&gt;In this post, let's understand the editor's Panes component used in &lt;a href="https://jsoncrack.com/"&gt;jsoncrack.com&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Panes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/containers/Editor/Panes.tsx#L27"&gt;Panes&lt;/a&gt; comprise of two main components. One is the json editor and the other component renders the json as a mindmap&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eBrR-uzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/guap2fdrl4mrrnkfeayp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eBrR-uzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/guap2fdrl4mrrnkfeayp.png" alt="Panes" width="800" height="414"&gt;&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;const Panes: React.FC = () =&amp;gt; {
  const fullscreen = useGraph(state =&amp;gt; state.fullscreen);

  return (
    &amp;lt;StyledEditor proportionalLayout={false}&amp;gt;
      &amp;lt;Allotment.Pane
        preferredSize={450}
        minSize={fullscreen ? 0 : 300}
        maxSize={800}
        visible={!fullscreen}
      &amp;gt;
        &amp;lt;JsonEditor /&amp;gt;
      &amp;lt;/Allotment.Pane&amp;gt;
      &amp;lt;Allotment.Pane minSize={0}&amp;gt;
        &amp;lt;LiveEditor /&amp;gt;
      &amp;lt;/Allotment.Pane&amp;gt;
    &amp;lt;/StyledEditor&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, Let's understand what &lt;code&gt;useGraph&lt;/code&gt; is.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[useGraph](https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useGraph.ts)&lt;/code&gt; is imported from &lt;code&gt;src/store/useGraph&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;useGraph&lt;/code&gt; is a &lt;a href="https://docs.pmnd.rs/zustand/getting-started/introduction"&gt;&lt;code&gt;zustand&lt;/code&gt;&lt;/a&gt; store. You could be tempted to understand useGraph fully but hang on, we will get there. Let's take a step back and check first line inside &lt;code&gt;Panes&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;const fullscreen = useGraph(state =&amp;gt; state.fullscreen);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It only relies on one value called fullscreen and that's all we have to know for now. &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/store/useGraph.ts"&gt;useGraph&lt;/a&gt; has a lot going on, more on that in the later of part of this series.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fullscreen&lt;/code&gt; is used to set &lt;code&gt;minSize&lt;/code&gt; prop in &lt;code&gt;Panes&lt;/code&gt; component, then we have &lt;code&gt;JsonEditor&lt;/code&gt; and &lt;code&gt;LiveEditor&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;When you are studying a new codebase, know when to stop. You cannot consume it all in one go. Which is what we did with &lt;code&gt;useGraph&lt;/code&gt;, we just looked at it at high level and learnt that it uses &lt;code&gt;zustand&lt;/code&gt; store and &lt;code&gt;Panes&lt;/code&gt; only depends on &lt;code&gt;fullscreen&lt;/code&gt; prop. In part 4.2, we will look at &lt;code&gt;JsonEditor&lt;/code&gt; and in part 4.3, we will look at &lt;code&gt;LiveEditor&lt;/code&gt;, this, in turn, gives us a better understanding as to how the editor changes trigger a live reload for the mindmap and how the stores are used to establish communication between these two components. It is going to be fun understanding this complicated entanglement.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis — Part 4 — Editor</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Thu, 04 Jan 2024 20:17:04 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-4-editor-56eh</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-4-editor-56eh</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/editor"&gt;jsoncrack.com&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;In this post, let’s understand the editor functionality used in jsoncrack.com.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4be5DjNR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n346ohodtpunka78z9wl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4be5DjNR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n346ohodtpunka78z9wl.png" alt="Image description" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/pages/editor.tsx"&gt;src/pages/editor.tsx&lt;/a&gt; in a new tab and let’s take the top down approach. Let’s first look into the components used.&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;EditorWrapper&amp;gt;
      &amp;lt;StyledEditorWrapper&amp;gt;
        &amp;lt;Head&amp;gt;
          &amp;lt;title&amp;gt;Editor | JSON Crack&amp;lt;/title&amp;gt;
          {hasQuery &amp;amp;&amp;amp; &amp;lt;meta name="robots" content="noindex,nofollow" /&amp;gt;}
        &amp;lt;/Head&amp;gt;
        &amp;lt;StyledPageWrapper&amp;gt;
          &amp;lt;Toolbar /&amp;gt;
          &amp;lt;StyledEditorWrapper&amp;gt;
            &amp;lt;Panes /&amp;gt;
          &amp;lt;/StyledEditorWrapper&amp;gt;
        &amp;lt;/StyledPageWrapper&amp;gt;
        &amp;lt;BottomBar /&amp;gt;
      &amp;lt;/StyledEditorWrapper&amp;gt;
&amp;lt;/EditorWrapper&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  EditorWrapper
&lt;/h2&gt;

&lt;p&gt;This is the first component used in page loaded when you visit &lt;a href="https://jsoncrack.com/editor"&gt;https://jsoncrack.com/editor&lt;/a&gt; and contains 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;export const EditorWrapper: React.FC&amp;lt;{
  children: React.ReactNode;
}&amp;gt; = ({ children }) =&amp;gt; {
  const darkmodeEnabled = useConfig(state =&amp;gt; state.darkmodeEnabled);

  return (
    &amp;lt;ThemeProvider theme={darkmodeEnabled ? darkTheme : lightTheme}&amp;gt;
      &amp;lt;MantineProvider forceColorScheme={darkmodeEnabled ? "dark" : "light"}&amp;gt;
        &amp;lt;QueryClientProvider client={queryClient}&amp;gt;{children}&amp;lt;/QueryClientProvider&amp;gt;
      &amp;lt;/MantineProvider&amp;gt;
    &amp;lt;/ThemeProvider&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Providers are imported at the top of the 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 { MantineProvider } from "@mantine/core";
import { ThemeProvider } from "styled-components";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Toolbar
&lt;/h2&gt;

&lt;p&gt;Toolbar is what you see as header/navigation on top of the page&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uomJ3A_6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cybxlqaak6ipnaf24qhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uomJ3A_6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cybxlqaak6ipnaf24qhb.png" alt="Toolbar" width="800" height="29"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code is as below:&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;Styles.StyledTools&amp;gt;
      {isWidget &amp;amp;&amp;amp; &amp;lt;Logo /&amp;gt;}
      {!isWidget &amp;amp;&amp;amp; (
        &amp;lt;Group gap="xs" justify="left" w="100%" style={{ flexWrap: "nowrap" }}&amp;gt;
          &amp;lt;Styles.StyledToolElement title="JSON Crack"&amp;gt;
            &amp;lt;Flex gap="xs" align="center" justify="center"&amp;gt;
              &amp;lt;JSONCrackLogo fontSize="1.2em" /&amp;gt;
            &amp;lt;/Flex&amp;gt;
          &amp;lt;/Styles.StyledToolElement&amp;gt;

          &amp;lt;Select
            defaultValue="json"
            size="xs"
            value={format}
            onChange={e =&amp;gt; setFormat(e as FileFormat)}
            miw={80}
            w={120}
            data={[
              { value: FileFormat.JSON, label: "JSON" },
              { value: FileFormat.YAML, label: "YAML" },
              { value: FileFormat.XML, label: "XML" },
              { value: FileFormat.TOML, label: "TOML" },
              { value: FileFormat.CSV, label: "CSV" },
            ]}
          /&amp;gt;

          &amp;lt;ViewModeMenu /&amp;gt;
          &amp;lt;Styles.StyledToolElement title="Import File" onClick={() =&amp;gt; setVisible("import")(true)}&amp;gt;
            Import
          &amp;lt;/Styles.StyledToolElement&amp;gt;
          &amp;lt;ViewMenu /&amp;gt;
          &amp;lt;ToolsMenu /&amp;gt;
          &amp;lt;Styles.StyledToolElement title="Cloud" onClick={() =&amp;gt; setVisible("cloud")(true)}&amp;gt;
            Cloud
          &amp;lt;/Styles.StyledToolElement&amp;gt;
          &amp;lt;Styles.StyledToolElement title="Download as File" onClick={handleSave}&amp;gt;
            Download
          &amp;lt;/Styles.StyledToolElement&amp;gt;
        &amp;lt;/Group&amp;gt;
      )}
      &amp;lt;Group gap="xs" justify="right" w="100%" style={{ flexWrap: "nowrap" }}&amp;gt;
        {!premium &amp;amp;&amp;amp; !isWidget &amp;amp;&amp;amp; (
          &amp;lt;Styles.StyledToolElement onClick={() =&amp;gt; setVisible("premium")(true)}&amp;gt;
            &amp;lt;Text display="flex" c="teal" fz="xs" fw="bold" style={{ textAlign: "center", gap: 4 }}&amp;gt;
              &amp;lt;MdWorkspacePremium size="18" /&amp;gt;
              Get Premium
            &amp;lt;/Text&amp;gt;
          &amp;lt;/Styles.StyledToolElement&amp;gt;
        )}

        &amp;lt;SearchInput /&amp;gt;
        {!isWidget &amp;amp;&amp;amp; (
          &amp;lt;&amp;gt;
            &amp;lt;Styles.StyledToolElement
              title="Save as Image"
              onClick={() =&amp;gt; setVisible("download")(true)}
            &amp;gt;
              &amp;lt;FiDownload size="18" /&amp;gt;
            &amp;lt;/Styles.StyledToolElement&amp;gt;
            &amp;lt;ZoomMenu /&amp;gt;
            &amp;lt;AccountMenu /&amp;gt;
            &amp;lt;OptionsMenu /&amp;gt;
            &amp;lt;Styles.StyledToolElement
              title="Fullscreen"
              $hide={isWidget}
              onClick={fullscreenBrowser}
            &amp;gt;
              &amp;lt;AiOutlineFullscreen size="18" /&amp;gt;
            &amp;lt;/Styles.StyledToolElement&amp;gt;
          &amp;lt;/&amp;gt;
        )}
      &amp;lt;/Group&amp;gt;
    &amp;lt;/Styles.StyledTools&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code above is self explanatory, the options that you see in the toolbar are listed here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Panes
&lt;/h2&gt;

&lt;p&gt;Panes comprise of two main components, JsonEditor and LiveEditor. I thought why not name this to LivePreview, but then I realised you could edit the mindmap from the livepreview — this is only possible when you are on paid plan, well it isn’t exactly a preview anymore. is it? Yup, naming conventions and their meaning matter. Seasoned devs have constructive discourse about variable or function naming conventions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--esU1xDH6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6esztqg1ybhrpc179pvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--esU1xDH6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6esztqg1ybhrpc179pvz.png" alt="Panes" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;“Hang on a minute, what do you mean constructive discourse? appendText() appends a random text and returns the updated string.” Right mate, shouldn’t it be appendAndGetText() or even better, write two functions, one for append and one for get. This is just an example. Anyways, let’s get back to the code now.&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;StyledEditor proportionalLayout={false}&amp;gt;
      &amp;lt;Allotment.Pane
        preferredSize={450}
        minSize={fullscreen ? 0 : 300}
        maxSize={800}
        visible={!fullscreen}
      &amp;gt;
        &amp;lt;JsonEditor /&amp;gt;
      &amp;lt;/Allotment.Pane&amp;gt;
      &amp;lt;Allotment.Pane minSize={0}&amp;gt;
        &amp;lt;LiveEditor /&amp;gt;
      &amp;lt;/Allotment.Pane&amp;gt;
&amp;lt;/StyledEditor&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  BottomBar
&lt;/h2&gt;

&lt;p&gt;BottomBar has features like Valid, Save to cloud, Private, Share, Live Transform etc.,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DHZ1nxwR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/653sm5varg6fa8fs7i4q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DHZ1nxwR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/653sm5varg6fa8fs7i4q.png" alt="BottomBar" width="800" height="29"&gt;&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;StyledBottomBar&amp;gt;
      {data?.name &amp;amp;&amp;amp; (
        &amp;lt;Head&amp;gt;
          &amp;lt;title&amp;gt;{data.name} | JSON Crack&amp;lt;/title&amp;gt;
        &amp;lt;/Head&amp;gt;
      )}
      &amp;lt;StyledLeft&amp;gt;
        &amp;lt;StyledBottomBarItem onClick={toggleEditor}&amp;gt;
          &amp;lt;BiSolidDockLeft /&amp;gt;
        &amp;lt;/StyledBottomBarItem&amp;gt;

        {fileName &amp;amp;&amp;amp; (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; setVisible("cloud")(true)}&amp;gt;
            &amp;lt;VscSourceControl /&amp;gt;
            {fileName}
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
        &amp;lt;StyledBottomBarItem&amp;gt;
          {error ? (
            &amp;lt;Popover width="auto" shadow="md" position="top" withArrow&amp;gt;
              &amp;lt;Popover.Target&amp;gt;
                &amp;lt;Flex align="center" gap={2}&amp;gt;
                  &amp;lt;VscError color="red" size={16} /&amp;gt;
                  &amp;lt;Text c="red" fw={500} fz="xs"&amp;gt;
                    Invalid
                  &amp;lt;/Text&amp;gt;
                &amp;lt;/Flex&amp;gt;
              &amp;lt;/Popover.Target&amp;gt;
              &amp;lt;Popover.Dropdown
                style={{
                  pointerEvents: "none",
                }}
              &amp;gt;
                &amp;lt;Text size="xs"&amp;gt;{error}&amp;lt;/Text&amp;gt;
              &amp;lt;/Popover.Dropdown&amp;gt;
            &amp;lt;/Popover&amp;gt;
          ) : (
            &amp;lt;Flex align="center" gap={2}&amp;gt;
              &amp;lt;MdOutlineCheckCircleOutline /&amp;gt;
              &amp;lt;Text size="xs"&amp;gt;Valid&amp;lt;/Text&amp;gt;
            &amp;lt;/Flex&amp;gt;
          )}
        &amp;lt;/StyledBottomBarItem&amp;gt;
        {(data?.owner_email === user?.email || (!data &amp;amp;&amp;amp; user)) &amp;amp;&amp;amp; (
          &amp;lt;StyledBottomBarItem onClick={handleSaveJson} disabled={isUpdating || error}&amp;gt;
            {hasChanges || !user ? &amp;lt;AiOutlineCloudUpload /&amp;gt; : &amp;lt;AiOutlineCloudSync /&amp;gt;}
            {hasChanges || !user ? (query?.json ? "Unsaved Changes" : "Save to Cloud") : "Saved"}
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
        {data?.owner_email === user?.email &amp;amp;&amp;amp; (
          &amp;lt;StyledBottomBarItem onClick={setPrivate} disabled={isUpdating}&amp;gt;
            {isPrivate ? &amp;lt;AiOutlineLock /&amp;gt; : &amp;lt;AiOutlineUnlock /&amp;gt;}
            {isPrivate ? "Private" : "Public"}
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
        &amp;lt;StyledBottomBarItem
          onClick={() =&amp;gt; setVisible("share")(true)}
          disabled={isPrivate || !data}
        &amp;gt;
          &amp;lt;AiOutlineLink /&amp;gt;
          Share
        &amp;lt;/StyledBottomBarItem&amp;gt;
        {liveTransformEnabled ? (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; toggleLiveTransform(false)}&amp;gt;
            &amp;lt;VscSync /&amp;gt;
            &amp;lt;Text fz="xs"&amp;gt;Live Transform&amp;lt;/Text&amp;gt;
          &amp;lt;/StyledBottomBarItem&amp;gt;
        ) : (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; toggleLiveTransform(true)}&amp;gt;
            &amp;lt;VscSyncIgnored /&amp;gt;
            &amp;lt;Text fz="xs"&amp;gt;Manual Transform&amp;lt;/Text&amp;gt;
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
        {!liveTransformEnabled &amp;amp;&amp;amp; (
          &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; setContents({})}&amp;gt;
            &amp;lt;TbTransform /&amp;gt;
            Transform
          &amp;lt;/StyledBottomBarItem&amp;gt;
        )}
      &amp;lt;/StyledLeft&amp;gt;

      &amp;lt;StyledRight&amp;gt;
        &amp;lt;StyledBottomBarItem&amp;gt;Nodes: {nodeCount}&amp;lt;/StyledBottomBarItem&amp;gt;
        &amp;lt;StyledBottomBarItem onClick={() =&amp;gt; setVisible("review")(true)}&amp;gt;
          &amp;lt;VscFeedback /&amp;gt;
          Feedback
        &amp;lt;/StyledBottomBarItem&amp;gt;
      &amp;lt;/StyledRight&amp;gt;
    &amp;lt;/StyledBottomBar&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a lot happening in the above code, but don’t worry. I will explain each of these components in detail in the upcoming tutorials.&lt;/p&gt;

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

&lt;p&gt;We looked at 3 main components in Editor for jsoncrack.com, Toolbar, Panes, BottomBar. In the upcoming tutorials, I will pick each of these components and go into details such as custom hooks used and how this application zustand configured. If you have any questions, feel free to email us at &lt;a href="mailto:ram@tthroo.com"&gt;ram@tthroo.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis — Part 3 — Signin</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Wed, 03 Jan 2024 23:03:50 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-3-signin-52a4</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-3-signin-52a4</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/sign-up"&gt;jsoncrack.com&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;In this post, let’s understand the signin functionality used in &lt;a href="https://jsoncrack.com/sign-up"&gt;jsoncrack.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wECaLwMP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4mjnb5xvcz44cjqawqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wECaLwMP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4mjnb5xvcz44cjqawqa.png" alt="Image description" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Signin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/pages/sign-in.tsx"&gt;src/pages/sign-in.tsx&lt;/a&gt; has the code. Again, let’s do a top down approach.&lt;/p&gt;

&lt;p&gt;You will see this file does the following export at the end of file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const SignIn = () =&amp;gt; {
  const { isReady, push, query } = useRouter();
  const session = useSession();
  const isPasswordReset = query?.type === "recovery" &amp;amp;&amp;amp; !query?.error;

  React.useEffect(() =&amp;gt; {
    if (isIframe()) push("/");
    if (isReady &amp;amp;&amp;amp; session &amp;amp;&amp;amp; !isPasswordReset) push("/editor");
  }, [isReady, session, push, isPasswordReset]);

  return (
    &amp;lt;Layout&amp;gt;
      &amp;lt;Head&amp;gt;
        &amp;lt;title&amp;gt;Sign In - JSON Crack&amp;lt;/title&amp;gt;
      &amp;lt;/Head&amp;gt;
      &amp;lt;Paper mt={50} mx="auto" maw={400} p="lg" withBorder&amp;gt;
        &amp;lt;AuthenticationForm /&amp;gt;
      &amp;lt;/Paper&amp;gt;
      &amp;lt;Center my="xl"&amp;gt;
        &amp;lt;Anchor component={Link} prefetch={false} href="/sign-up" c="dark" fw="bold"&amp;gt;
          Don&amp;amp;apos;t have an account?
        &amp;lt;/Anchor&amp;gt;
      &amp;lt;/Center&amp;gt;
    &amp;lt;/Layout&amp;gt;
  );
};

export default SignIn;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/src/layout/Layout/index.tsx"&gt;Layout&lt;/a&gt;, Head are known components. Paper is an import from @mantine/core. The real stuff is in AuthenticationForm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication Form
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function AuthenticationForm(props: PaperProps) {
  const setSession = useUser(state =&amp;gt; state.setSession);
  const [loading, setLoading] = React.useState(false);
  const [userData, setUserData] = React.useState({
    name: "",
    email: "",
    password: "",
  });

  const onSubmit = (e: React.FormEvent&amp;lt;HTMLFormElement&amp;gt;) =&amp;gt; {
    e.preventDefault();
    setLoading(true);

    supabase.auth
      .signInWithPassword({
        email: userData.email,
        password: userData.password,
      })
      .then(({ data, error }) =&amp;gt; {
        if (error) return toast.error(error.message);
        setSession(data.session);
      })
      .finally(() =&amp;gt; setLoading(false));
  };

  const handleLoginClick = (provider: "github" | "google") =&amp;gt; {
    supabase.auth.signInWithOAuth({
      provider,
      options: { redirectTo: "https://jsoncrack.com/editor" },
    });
  };

  return (
    &amp;lt;Paper {...props}&amp;gt;
      &amp;lt;form onSubmit={onSubmit}&amp;gt;
        &amp;lt;Stack&amp;gt;
          &amp;lt;TextInput
            name="email"
            required
            label="Email"
            placeholder="hello@jsoncrack.com"
            value={userData.email}
            onChange={event =&amp;gt; setUserData(d =&amp;gt; ({ ...d, email: event.target.value }))}
            radius="sm"
            style={{ color: "black" }}
          /&amp;gt;

          &amp;lt;PasswordInput
            name="password"
            required
            label="Password"
            placeholder="∗∗∗∗∗∗∗∗∗∗∗"
            value={userData.password}
            onChange={event =&amp;gt; setUserData(d =&amp;gt; ({ ...d, password: event.target.value }))}
            radius="sm"
            style={{ color: "black" }}
          /&amp;gt;

          &amp;lt;Button color="dark" type="submit" radius="sm" loading={loading}&amp;gt;
            Sign in
          &amp;lt;/Button&amp;gt;

          &amp;lt;Stack gap="sm" mx="auto" align="center"&amp;gt;
            &amp;lt;Anchor component={Link} prefetch={false} href="/forgot-password" c="dark" size="xs"&amp;gt;
              Forgot your password?
            &amp;lt;/Anchor&amp;gt;
          &amp;lt;/Stack&amp;gt;
        &amp;lt;/Stack&amp;gt;
      &amp;lt;/form&amp;gt;

      &amp;lt;Divider my="lg" /&amp;gt;

      &amp;lt;Stack mb="md" mt="md"&amp;gt;
        &amp;lt;Button
          radius="sm"
          leftSection={&amp;lt;AiOutlineGoogle size="20" /&amp;gt;}
          onClick={() =&amp;gt; handleLoginClick("google")}
          color="red"
          variant="outline"
        &amp;gt;
          Sign in with Google
        &amp;lt;/Button&amp;gt;
        &amp;lt;Button
          radius="sm"
          leftSection={&amp;lt;AiOutlineGithub size="20" /&amp;gt;}
          onClick={() =&amp;gt; handleLoginClick("github")}
          color="dark"
          variant="outline"
        &amp;gt;
          Sign in with GitHub
        &amp;lt;/Button&amp;gt;
      &amp;lt;/Stack&amp;gt;
    &amp;lt;/Paper&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is a simple component with input elements and social login buttons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sign in using email
&lt;/h2&gt;

&lt;p&gt;onSubmit function is called when you try to login with your email and password.&lt;br&gt;
As you can see &lt;a href="https://supabase.com/"&gt;supabase&lt;/a&gt; is used to &lt;a href="https://supabase.com/docs/reference/javascript/auth-signinwithpassword"&gt;sign in with password&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sign in using Google or Github
&lt;/h2&gt;

&lt;p&gt;handleLoginClick function is called when you try to login with either Google or Github account.&lt;br&gt;
As you can see &lt;a href="https://supabase.com/"&gt;supabase&lt;/a&gt; is used to &lt;a href="https://supabase.com/docs/guides/auth/social-login/auth-google"&gt;sign in with Google or Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We recommend to check the supabase docs to read further how you can easily solve/implement Auth into your application.&lt;/p&gt;

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

&lt;p&gt;Supabase has simplified the Auth used in &lt;a href="https://jsoncrack.com/"&gt;jsoncrack.com&lt;/a&gt;. We also see the how this sign-in component used &lt;a href="https://mantine.dev/"&gt;@mantine/core&lt;/a&gt; components. If you have any questions, feel free to email us at &lt;a href="mailto:ram@tthroo.com"&gt;ram@tthroo.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>javascript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis - Part 2 - Landing Page</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Tue, 02 Jan 2024 21:10:18 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-2-landing-page-j2d</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-2-landing-page-j2d</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/"&gt;jsoncrack.com&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;In this post, let’s understand the code responsible to load the &lt;a href="https://jsoncrack.com/"&gt;jsoncrack.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8ToUoM2c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nxknfwbetdy5gkozhde4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8ToUoM2c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nxknfwbetdy5gkozhde4.png" alt="jsoncrack landing page" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The file, we are interested in, is located at &lt;code&gt;src/pages/index.tsx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you are wondering what is &lt;code&gt;pages&lt;/code&gt; folder, checkout the following documentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts"&gt;Pages and Layout&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read code?
&lt;/h2&gt;

&lt;p&gt;As a developer, you have to read other people’s code. I recommend top-down approach. If the codebase is small in size, you can easily get familiarised with the code. But, if the codebase is large, ideally, you should only consider those files that are directly related to the bug fix or feature upgrade you are handling. Small steps until eventually you get the big picture. Let’s follow the similar strategy here.&lt;/p&gt;

&lt;p&gt;Considering top-down approach, since we are dealing with a Next.js project, I would look at the HTML code returned by this &lt;code&gt;src/pages.index.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HomePage&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;ads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAds&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;JSON Crack | Visualize Instantly Into Graphs&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HeroSection&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://m.servedby-buysellads.com/monetization.js"&lt;/span&gt; &lt;span class="na"&gt;onLoad&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setAds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s see what &lt;code&gt;HeroSection&lt;/code&gt; component looks like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HeroSection&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StyledHeroSection&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hero-section"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StyledHeroSectionBody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Stack&lt;/span&gt; &lt;span class="na"&gt;w&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"100%"&lt;/span&gt; &lt;span class="na"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt; &lt;span class="na"&gt;align&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StyledHeroTitle&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Understand your&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StyledHighlightedText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Typewriter&lt;/span&gt;
              &lt;span class="na"&gt;words&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JSON&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YAML&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;XML&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TOML&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CSV&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;typeSpeed&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;deleteSpeed&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;delaySpeed&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;loop&lt;/span&gt;
            &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StyledHighlightedText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          better by visualizing
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StyledHeroTitle&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StyledHeroText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Visualize, analyze, and manipulate data with ease, a versatile and powerful tool for data
          representation and exploration.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StyledHeroText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt; &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"xl"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
            &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"orange"&lt;/span&gt;
            &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"light"&lt;/span&gt;
            &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/editor"&lt;/span&gt;
            &lt;span class="na"&gt;fw&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bold"&lt;/span&gt;
            &lt;span class="na"&gt;rightSection&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FaChevronRight&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"xl"&lt;/span&gt;
            &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2px solid orange&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;visibleFrom&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            GO TO EDITOR
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
            &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"orange"&lt;/span&gt;
            &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"light"&lt;/span&gt;
            &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/editor"&lt;/span&gt;
            &lt;span class="na"&gt;fw&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bold"&lt;/span&gt;
            &lt;span class="na"&gt;rightSection&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FaChevronRight&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;
            &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2px solid orange&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;hiddenFrom&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            GO TO EDITOR
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StyledHeroSectionBody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StyledHeroSection&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tags like &lt;code&gt;StyledHeroSection&lt;/code&gt;, &lt;code&gt;StyledHeroSectionBody&lt;/code&gt; indicate that this project uses &lt;a href="https://styled-components.com/"&gt;styled-components&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/typewriter-effect"&gt;Typewriter&lt;/a&gt; component is used&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Stack, Button, Group&lt;/code&gt; are from &lt;a href="https://mantine.dev/"&gt;Mantine&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to find what packages are used?
&lt;/h2&gt;

&lt;p&gt;You can figure this out from the imports used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@mantine/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&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;styled-components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Typewriter&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-simple-typewriter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More over, a nice detailed explanation about tech stack used is provided in &lt;strong&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/CONTRIBUTING.md"&gt;CONTRIBUTING.md&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now &lt;code&gt;HeroSection&lt;/code&gt; code snippet from above is responsible for the following screen&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PdnPeXqJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://tthroo.com/images/posts/post-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PdnPeXqJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://tthroo.com/images/posts/post-2.png" alt="test.PNG" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Be comfortable with the fact that you &lt;strong&gt;&lt;em&gt;do not&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;know&lt;/em&gt;&lt;/strong&gt; everything about the code you are currently dealing with.&lt;/p&gt;

&lt;p&gt;But what about the header?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I1Hcj1nc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://tthroo.com/images/posts/post-2-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I1Hcj1nc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://tthroo.com/images/posts/post-2-1.png" alt="test2.PNG" width="800" height="44"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, let’s look at how that is configured in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layout
&lt;/h2&gt;

&lt;p&gt;Layout component from &lt;code&gt;src/layout/Layout&lt;/code&gt; has the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MantineProvider&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;@mantine/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThemeProvider&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;styled-components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lightTheme&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;src/constants/theme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Navbar&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;../Navbar&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;StyledLayoutWrapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="s2"&gt;`
  padding-bottom: 48px;
`&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;Layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MantineProvider&lt;/span&gt; &lt;span class="na"&gt;forceColorScheme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"light"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lightTheme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StyledLayoutWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Navbar&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StyledLayoutWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MantineProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, there are lot of unknowns at this point in time in the above code. You could be wondering what is &lt;code&gt;MantineProvider&lt;/code&gt; or &lt;code&gt;ThemeProvider&lt;/code&gt; but focus on what you are interested to find out, i.e., header component. You can tell &lt;code&gt;Navbar&lt;/code&gt; is coming from &lt;code&gt;src/layout/Navbar/index.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Navbar&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;isAuthenticated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAuthenticated&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StyledNavbarWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StyledNavbar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;JSONCrackLogo&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Middle&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hide-mobile"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/pricing"&lt;/span&gt; &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"subtle"&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt; &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Pricing
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
            &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://marketplace.visualstudio.com/items?itemName=AykutSarac.jsoncrack-vscode"&lt;/span&gt;
            &lt;span class="na"&gt;prefetch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"subtle"&lt;/span&gt;
            &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt;
            &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            VS Code
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
            &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/docs"&lt;/span&gt;
            &lt;span class="na"&gt;prefetch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"subtle"&lt;/span&gt;
            &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt;
            &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Docs
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt; &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hover"&lt;/span&gt; &lt;span class="na"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;withArrow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Target&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
                &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"subtle"&lt;/span&gt;
                &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt;
                &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;
                &lt;span class="na"&gt;rightSection&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BiChevronDown&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"18"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Legal
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Target&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/legal/privacy"&lt;/span&gt; &lt;span class="na"&gt;prefetch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Privacy Policy
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/legal/terms"&lt;/span&gt; &lt;span class="na"&gt;prefetch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Terms and Conditions
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/legal/subscription-refund"&lt;/span&gt; &lt;span class="na"&gt;prefetch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Subscription
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Divider&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mailto:contact@jsoncrack.com"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                contact@jsoncrack.com
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt; &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hover"&lt;/span&gt; &lt;span class="na"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;withArrow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Target&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
                &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"subtle"&lt;/span&gt;
                &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt;
                &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;
                &lt;span class="na"&gt;rightSection&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BiChevronDown&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"18"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Social
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Target&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://twitter.com/jsoncrack"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                𝕏 (Twitter)
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://discord.gg/yVyTtCRueq"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Discord
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://www.linkedin.com/company/herowand"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                LinkedIn
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://github.com/AykutSarac/jsoncrack.com"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                GitHub
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Dropdown&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Middle&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
              &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/sign-in"&lt;/span&gt;
              &lt;span class="na"&gt;prefetch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"outline"&lt;/span&gt;
              &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"grape.9"&lt;/span&gt;
              &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hide-mobile"&lt;/span&gt;
            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              Login
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"grape.9"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/editor"&lt;/span&gt; &lt;span class="na"&gt;prefetch&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Editor
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StyledNavbar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StyledNavbarWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing fancy going on in the above code, just a simple navbar with links pointing to different pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We started off with &lt;code&gt;src/pages/index.tsx&lt;/code&gt; as this is the code responsible to load what you see when you visit &lt;a href="https://jsoncrack.com/"&gt;jsoncrack.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, &lt;code&gt;HeroSection&lt;/code&gt; and &lt;code&gt;Layout&lt;/code&gt; are used as main components. There is &lt;a href="https://mantine.dev/"&gt;Mantine&lt;/a&gt; configuration involved in &lt;code&gt;Layout&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>nextjs</category>
      <category>opensource</category>
    </item>
    <item>
      <title>JSONCrack Codebase Analysis - Part 1. File Structure</title>
      <dc:creator>TThroo-Dev</dc:creator>
      <pubDate>Mon, 01 Jan 2024 18:07:42 +0000</pubDate>
      <link>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-1-file-structure-11c2</link>
      <guid>https://forem.com/tthroo/jsoncrack-codebase-analysis-part-1-file-structure-11c2</guid>
      <description>&lt;p&gt;&lt;a href="https://jsoncrack.com/"&gt;jsoncrack.com&lt;/a&gt; is a popular opensource tool used to visualise json into a mindmap. It is built using Next.js. &lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://tthroo.com/"&gt;TThroo&lt;/a&gt;, love open source and perform codebase analysis on popular repositories, document, and provide a detailed explanation of the codebase. This enables OSS enthusiasts to learn and contribute to open source projects, and we also apply these learnings in our projects.&lt;/p&gt;

&lt;p&gt;Let's get started with File structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QO8ZWbRE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6djrjd91f6lbcbglbx19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QO8ZWbRE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6djrjd91f6lbcbglbx19.png" alt="File structure" width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/tree/main/.github"&gt;.github&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;This folder is used for Github actions and workflow. Resources: &lt;a href="https://stackoverflow.com/questions/60507097/is-there-an-overview-of-what-can-go-into-a-github-dot-github-directory"&gt;GitHub .github directory overview&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/tree/main/public"&gt;public&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Static assets like images are served using this public directory. Resources: &lt;a href="https://nextjs.org/learn-pages-router/basics/assets-metadata-css/assets"&gt;Next.js assets, metadata, and CSS&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/tree/main/src"&gt;src&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;src&lt;/code&gt; folder is a convention used to organize your source code. It stands for "source" and typically contains the main codebase of your Next.js application. Resources: &lt;a href="https://nextjs.org/docs/pages/building-your-application/configuring/src-directory"&gt;Next.js src directory&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/.dockerignore"&gt;.dockerignore&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Add a list of files to be ignored when building your app using DockerFile. Resources: &lt;a href="https://stackoverflow.com/questions/31789770/what-are-the-files-that-the-dockerignore-works-on"&gt;Docker .dockerignore files&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/.env.development"&gt;.env.development&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Set defaults/environment variables for the development environment. Resources: &lt;a href="https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables"&gt;Next.js environment variables&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/.env.production"&gt;.env.production&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Set defaults/environment variables for the production environment. Resources: &lt;a href="https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables"&gt;Next.js environment variables&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/.eslintrc.json"&gt;.eslintrc.json&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Configuration to identify and report on patterns found in JavaScript, to avoid bugs and maintain code consistency. Resources: &lt;a href="https://eslint.org/docs/latest/use/getting-started"&gt;ESLint documentation&lt;/a&gt; and &lt;a href="https://eslint.org/docs/latest/use/configure/configuration-files#:~:text=JSON%20%2D%20use%20.eslintrc.json,and%20define%20your%20configuration%20there"&gt;ESLint configuration files&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/.gitignore"&gt;.gitignore&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Use this file to ignore files, folders that you do not wish to see in your Github repo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/.prettierignore"&gt;.prettierignore&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;.prettierignore can be used to ignore files or folders of your choice. Resources: &lt;a href="https://prettier.io/docs/en/ignore.html"&gt;Prettier ignore files&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/.prettierrc"&gt;.prettierrc&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Format your code on save using Prettier. Resources: &lt;a href="https://prettier.io/docs/en/configuration.html"&gt;Prettier configuration&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/CODE_OF_CONDUCT.md"&gt;CODE_OF_CONDUCT.md&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Define standards for your community engagement. Resources: &lt;a href="https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/adding-a-code-of-conduct-to-your-project"&gt;GitHub code of conduct&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/CONTRIBUTING.md"&gt;CONTRIBUTING.md&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Contribution guide to follow, should you decide to contribute to this project. Resources: &lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/CONTRIBUTING.md"&gt;Contribution guide&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/Dockerfile"&gt;Dockerfile&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Provide instructions to build your docker image using this file. Resources: &lt;a href="https://docs.docker.com/engine/reference/builder/"&gt;Dockerfile reference&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/LICENSE"&gt;LICENSE&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/LICENSE"&gt;License&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/README.md"&gt;README.md&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Provides project set up instructions, features supported, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/default.conf"&gt;default.conf&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Nginx configuration file. Resources: &lt;a href="https://gist.github.com/xameeramir/a5cb675fb6a6a64098365e89a239541d"&gt;Nginx configuration&lt;/a&gt; and &lt;a href="https://nginx.org/en/docs/beginners_guide.html"&gt;Nginx beginners guide&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/docker-compose.yml"&gt;docker-compose.yml&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;A YAML configuration for Docker. Resources: &lt;a href="https://docs.docker.com/compose/compose-file/03-compose-file/"&gt;Docker Compose file reference&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/next-env.d.ts"&gt;next-env.d.ts&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;This file should not be edited, generated with Next.js project set up. Resources: &lt;a href="https://stackoverflow.com/questions/61420392/how-do-i-use-the-next-env-d-ts-file-in-next-js#:~:text=This%20file%20ensures%20Next.,you%20want%20in%20your%20code."&gt;Use of next-env.d.ts in Next.js&lt;/a&gt; and &lt;a href="https://nextjs.org/docs/pages/building-your-application/configuring/typescript"&gt;Next.js TypeScript configuration&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/next.config.js"&gt;next.config.js&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Next.js project configuration file. Resources: &lt;a href="https://nextjs.org/docs/pages/api-reference/next-config-js"&gt;Next.js configuration&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/AykutSarac/jsoncrack.com/blob/main/package.json"&gt;package.json&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Manage project’s metadata and dependencies. Node.js project set up adds this file when a new project is initialized with &lt;code&gt;npm init&lt;/code&gt;. Resources: [npm package.json configuration](&lt;a href="https://docs.npmjs.com/cli"&gt;https://docs.npmjs.com/cli&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>nextjs</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
