<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: GraphQL Editor</title>
    <description>The latest articles on DEV Community by GraphQL Editor (@graphqleditor).</description>
    <link>https://dev.to/graphqleditor</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%2Forganization%2Fprofile_image%2F1229%2Ff2693e73-4ca3-497c-9eeb-01c24ff59ed9.png</url>
      <title>DEV Community: GraphQL Editor</title>
      <link>https://dev.to/graphqleditor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/graphqleditor"/>
    <language>en</language>
    <item>
      <title>GraphQL benefits and why you should adopt it in 2024</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Fri, 19 Jan 2024 17:10:51 +0000</pubDate>
      <link>https://dev.to/graphqleditor/graphql-benefits-and-why-you-should-adopt-it-in-2024-4d2c</link>
      <guid>https://dev.to/graphqleditor/graphql-benefits-and-why-you-should-adopt-it-in-2024-4d2c</guid>
      <description>&lt;p&gt;The digital world is changing faster than ever. In an environment where new frameworks, technologies and tools are coming out almost every minute, scalability is not just an empty phrase, but the bare minimum to allow the development of an IT project. In this busy and ever-changing landscape, GraphQL architecture is steadily gaining popularity. Why? Thanks to its flexibility and precise data fetching mechanism. However as applications grow in scale and gain more users, the efficient scaling of GraphQL APIs becomes not only important, but actually crucial to ensure consistent performance and reliability.&lt;/p&gt;

&lt;p&gt;In this short blog, we'll explore a variety of practices that allow you to smoothly adapt to the rapidly changing digital environment. From leveraging caching mechanisms and query optimization, to exploring advanced tools that allow you to expand your infrastructure as your applications grow - all to show how important it is to ensure the consistency, performance and reliability of your GraphQL API.&lt;/p&gt;

&lt;p&gt;Let's start with the topic closest to my heart, due to the fact that our tool is used mainly (but not only) for designing GraphQL schemas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Efficiently designed schema is the key
&lt;/h2&gt;

&lt;p&gt;The foundation of a performant GraphQL API lies in its schema design*. When thinking of your schema there are a lot of things you need to cover (or at least be aware of), but to fully enjoy the DX and the speed of working with GraphQL lest start with data fetching. The main points I want to cover here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;over-fetching &amp;amp; under-fetching&lt;/strong&gt;: which is handled out of the box with the GraphQL queries system which enables retrieving only the required data, preventing unnecessary data retrieval or messing up your network bandwidth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and its biggest nightmare which is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;deep nesting&lt;/strong&gt;: when planing your GraphQL schema avoid going to deep or your will bury yourself with nested queries that can lead to performance bottlenecks and may nullify the highly optimized fetching system which you're getting for free in GraphQL! Keeping query depth shallow will let you enjoy faster query execution and reduce logic complexity for your team.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;*&lt;em&gt;if following the schema first path; schema first is our preferred approach here at GraphQL Editor &amp;amp; the entire blog post may be seen as biased in favor of schema first&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Data fetching, batching &amp;amp; caching
&lt;/h2&gt;

&lt;p&gt;When we talk about making things run faster, getting data quickly is super important. Using some basic data caching &amp;amp; batching techniques you can really amp up how well your API works, giving it a serious speed boost without much hassle.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;use DataLoader&lt;/strong&gt;: DataLoader is a utility that can be used as part of an application's data fetching layer to provide a simplistic and consistent API for different remote data sources (web services, databases etc.) through batching and caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;implement layered caching&lt;/strong&gt;: Using caching in different places, like on the client's side, the server's side or CDN (if used) can really help as it stops things from being fetched over and over and makes the general server response time way faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pick right cache eviction policy&lt;/strong&gt;: Once again caching is critical for any high-performance system so make sure to use a cache eviction policy (when things which are not needed anymore are kicked out of the cache) that fits your project. Keep in mind you need to figure out how to keep all the different caches in sync so they have the same information. This way, you make sure everything stays up-to-date and works smoothly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;batch your data&lt;/strong&gt;: Merge multiple data requests into a single query to minimize round trips and improve efficiency, leveraging GraphQL's ability to fetch multiple resources in a single request.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Monitoring, optimization, load balancing &amp;amp; horizontal scaling
&lt;/h2&gt;

&lt;p&gt;Continuous monitoring and optimization are required to keep your app running fast and smooth. Good monitoring tools, load balancing and horizontal scaling are your pals when it comes to handling peak traffic... and it also helps to retain customers as bad latency can wreck customer experience even for the best designed, shiny app. Keep your eyes on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;profiling &amp;amp; monitoring&lt;/strong&gt;: regularly check and analyze query execution times using monitoring tools to pinpoint and address performance issues effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;resolver optimization&lt;/strong&gt;: always aim to improve the efficiency of resolver functions to boost query performance. Don't wait and try to immediately address any issues with slow-performing queries for better overall system responsiveness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;load balancing&lt;/strong&gt;: most cloud infrastructures have a load balancing feature available out of the box, but if you're working on your own infrastructure (which is becoming a new trend after the "serverless hype" era), make every effort to evenly distribute incoming requests across multiple servers to prevent overload, ensuring a balanced workload and maintaining system responsiveness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;horizontal scaling&lt;/strong&gt;: scale your application by adding more server instances to handle increased demands and manage them efficiently through tools which help achieve seamless orchestration like K8s the &lt;a href="https://kubernetes.io/"&gt;open-source system for automating deployment, scaling, and management of containerized applications&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Don't rush with GraphQL adoption
&lt;/h2&gt;

&lt;p&gt;As always, the old saying that haste makes waste rings true. Rather than rush, take your time to give yourself and your users peace of mind. Transitioning from REST to GraphQL is one thing, overcoming obstacles that you didn't foresee at the beginning (let's not kid ourselves, there is no such thing as smooth transition and if there's even a small chance that something might go wrong you can be sure it will) so be prepared to handle one of the greatest scalability challenges which is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;backward compatibility:&lt;/strong&gt; with GraphQL you get backward compatibility out of the box and new fields can be added to the schema without impacting existing queries. This is in contrast to REST, where changes to the API may disrupt existing clients. So when you finally decide to transition from REST to GraphQL remember to ensure backward compatibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Teamwork makes the dream work - collaborate!
&lt;/h2&gt;

&lt;p&gt;Having effective communication and maintaining detailed documentation - these are the two keys for ensuring your team enjoys effective collaboration and is working effectively. Find a platform that can streamline and simplify communication over your schema (the most important piece of your GraphQL project) leave no room for understatement as the key to your project's success is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;teamwork&lt;/strong&gt;: GraphQL is all about collaboration between frontend and backend teams, helping develop a common understanding and an efficient query optimization approach. This is where our &lt;a href="https://graphqleditor.com/docs/"&gt;GraphQL Editor&lt;/a&gt; can help increase the work effectiveness of teams through such features as Live Collaboration that allows multiple team members to work on a GraphQL schema &amp;amp; in general through its visual features that provide a better picture of the schema overall.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  From niche to mainstream
&lt;/h2&gt;

&lt;p&gt;It's been 8 years since Facebook released GraphQL and the days when it was some fresh, niche technology are long gone. By now it has moved way past the hype phase, and has easily maintained its status as the main competitor to the steadily declining REST over the past few years. Hardly surprising taking into account the various GraphQL benefits mentioned above, especially with the schema-first approach I've recommended earlier. So while rushing into adoption isn't a good idea, considering it definitely is!&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>backenddevelopment</category>
      <category>webdev</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Conditional rendering in React</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Sun, 05 Nov 2023 16:46:05 +0000</pubDate>
      <link>https://dev.to/graphqleditor/conditional-rendering-in-react-35p</link>
      <guid>https://dev.to/graphqleditor/conditional-rendering-in-react-35p</guid>
      <description>&lt;p&gt;I recently saw some posts and comments about conditional rendering in React and to my surprise some of them stated &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; was outdated and should be dropped in favor of using &lt;code&gt;if/else&lt;/code&gt;, &lt;code&gt;: ?&lt;/code&gt; and &lt;code&gt;||&lt;/code&gt; conditions. It struck me as odd as from what (admittedly little) I have learned so far AND is fine and in some cases simply more straightforward. Especially when compared with sticking nulls everywhere just to avoid using it. Far be it from me to criticize anyone but I decided this would be a good idea to elaborate more on conditional rendering in React.&lt;/p&gt;

&lt;h2&gt;
  
  
  if/else and ternary operator :?
&lt;/h2&gt;

&lt;p&gt;This is most likely the first type of conditional you’ve learned, honestly I didn't even know it was called a ternary operator until writing this as I’ve heard our devs simply call it an ‘if’ or ‘conditional’. Both are very straightforward and work pretty much the same although with a slightly different syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;PowerLevel&lt;/span&gt;  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt; 
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Its&lt;/span&gt; &lt;span class="nx"&gt;over&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="o"&gt;!!!&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PowerLevel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PowerLevel&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Its&lt;/span&gt; &lt;span class="nx"&gt;over&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="o"&gt;!!!&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PowerLevel&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both of these will do exactly the same thing but the syntax is slightly different. For a simple thing like this the ternary operator is just more succinct and makes more sense to use. It's obviously down to personal preference but from what I’ve heard from devs the rule of thumb is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;code&gt;:?&lt;/code&gt; for smaller things that can fit in one line or two (eg. for registered users show a button with “Log in” and for unregistered show it with “Register”)&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;if/else&lt;/code&gt; statements for executing bigger segments of code (like say a different navbar for desktop and mobile versions of a website)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just to give you a real example this is a simple code snippet from our language switcher:&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="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[locale]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newLang&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&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="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newLang&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's pretty simple - when the user selects a language from the dropdown it pushes the user to the selected language version of the page adding the locale tag to the url address, but omitting it if it's the default language ie. English. (sidenote here: this is actually very important for SEO as I’ve had multiple issues with language selectors adding a default locale tag to the url which caused example.com and example.com/en to be flagged as duplicate pages)&lt;/p&gt;

&lt;p&gt;While using ternary and if/else is the go-to it can be overused because of that, as sometimes other conditionals make more sense. Take this simple snippet for a metaDescription meta tag in my custom helmet - it uses the provided metaDescription if there is one and a fallback value if it is not provided:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;metaDescription&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;metaDescription&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;defaultDescription&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  OR (||) condition
&lt;/h2&gt;

&lt;p&gt;While that works fine I’ve actually started using OR conditions for cases like this since they are simpler and quicker to write. From my experience this is used way too little since you get tons of situations like this (especially when dealing with websites) where you just need one value and a default fallback just in case. Following the above metaDescription example we can just use this to get the exact same result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;metaDescription&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;defaultDescription&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will simply always use a metaDescription if one is provided, and fallback to the default one if it is not, which is perfect for use cases like this. Yes you can use multiple || and it will simply always render the first one that is true, but I think that’s overusing it since you can't specify different conditions for each one anyway and at that point using a ternary condition or if/else makes more sense anyway. You can also use || with a null for an element you only want to render under certain conditions, but for that case &amp;amp;&amp;amp; actually makes more sense in my opinion.&lt;/p&gt;

&lt;h2&gt;
  
  
  AND (&amp;amp;&amp;amp;) condition
&lt;/h2&gt;

&lt;p&gt;Like I said before I have seen some claims &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; is outdated, which surprised me since I consider it by far the cleanest to use when I want to render an element only under certain conditions. It works the simplest of all of the ones I mentioned here as it just does nothing if the condition is not fulfilled. Yeah you can do that with the others - just use a null and you’ll likely get the same result - though writing nulls everywhere just for the sake of avoiding &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; seems pointless.&lt;/p&gt;

&lt;p&gt;Sure you can get a displayed 0 error like the one on the screen below:&lt;/p&gt;

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

&lt;p&gt;Obviously if you’re afraid you might get one for something like &lt;code&gt;products.length&lt;/code&gt; on your ecommerce store it's also pointless to force yourself to use &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; just for the sake of it - it's way better to go with what you feel more comfortable with. That said, this particular error was solved by simply using &lt;code&gt;!!&lt;/code&gt; to force a boolean representation and the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; was left untouched - which goes to show once again that all this comes down to what you're most comfortable using.&lt;/p&gt;

&lt;p&gt;For me I can say that on the SEO side I’ve fixed enough bugs and issues where someone forgot to add a null and I had off-screen or hidden elements picked up by crawlers. If you like the seo guys in your workplace you can be nice and save them an hour or so which they might otherwise spend looking for a mobile langSwitcher with a 404 link which was hidden somewhere on the desktop version of the page. So for a simple component that you want rendered only if a certain condition is fulfilled &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; is still perfectly fine in my opinion. Here's an example case of where I use it in my custom helmet element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;LocalizedPage&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="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hrefLangs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;
          &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alternate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;hrefLang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://example.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;
        &lt;span class="nx"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alternate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;hrefLang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;defaultLang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://example.com&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;
        &lt;span class="nx"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alternate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;hrefLang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-default&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://example.com&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see that is even simpler than the others - only render this code if the page is localized. I don't have to specify the outcome for false or a fallback null value - I just say this is solely for that condition and that's it. This is a simple way of ensuring I have alternate links included in the head for pages which are translated into other languages, while making sure they won't appear in the dom for those which aren't translated (like say blogposts) which would be flagged as a SEO error. I think it's also a good approach to keep things as simple as possible when it comes to seo so if I go into someone’s frontend code to add this little element they figure out exactly what this is intended for at a glance.&lt;/p&gt;

&lt;p&gt;Obviously if you’re comfortable with using if/else everywhere and that works for you there's no reason to force yourself to use something else, even if it can make more sense in certain situations. But as you can see in using OR or AND can be handier so it's perfectly fine to use those as well, they are in no means outdated or wrong if used correctly.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I18next translations inside maps &amp; React dynamic import</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Thu, 19 Oct 2023 09:32:33 +0000</pubDate>
      <link>https://dev.to/graphqleditor/i18next-translations-inside-maps-react-dynamic-import-4kha</link>
      <guid>https://dev.to/graphqleditor/i18next-translations-inside-maps-react-dynamic-import-4kha</guid>
      <description>&lt;p&gt;Recently while browsing through one of our projects I found some atrocious piece of code I wrote a few months back. As ugly as it looks I think it can serve as a decent example of how much you can progress in a short time, even as a ‘copywriter-turned-not-really-a-dev’ like myself, and also how much you can do wrong in just one simple component.&lt;/p&gt;

&lt;p&gt;While the code here serves as an example for the sake of the blogpost, it is an actual piece of my code from one of our websites. It's a simple component with four tiles with an image, some text and icons that illustrate the features of one of our applications. In case you're wondering why fixing it matters, I can tell you that if there's one thing that impacts SEO - it's poorly written code. It can worsen performance causing our website to work too slow and incur something Google calls Cumulative Layout Shift. It's basically a measurement of how much crawlers see your website's layout change as components or elements are loading in, which may happen if your code is bloated. Google considers that bad for user experience and can penalize your website's positioning for it. Aside from that obviously fixing bad code just for the sake of it is reason enough (especially if you don't want to get yelled at during code review). So here's the code for the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useTranslation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-i18next&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;AutomationIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FastIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ProcessorIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AccurateIcon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FeaturesSection&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;t&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;landing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FeatureSectionWrapper&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;FeatureText&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;h2&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;"header"&lt;/span&gt; &lt;span class="na"&gt;dangerouslySetInnerHTML&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;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"desc"&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;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.description&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AccurateIcon&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;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.features.accurate&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.features.accurateText&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FastIcon&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;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.features.fast&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.features.fastText&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProcessorIcon&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;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.features.ai&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.features.aiText&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AutomationIcon&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;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.features.automated&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.features.automatedText&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&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;ul&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;FeatureText&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;FeatureImg&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;"/images/results.png"&lt;/span&gt;
                &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"feature image"&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;FeatureSectionWrapper&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;As you can see even though I had some basic understanding of html and the useTranslation hook, but I made a mess of it because I didn't do any mapping and just wrote out every segment of the component as a list item. The component is rather simple, it has two columns - one is an image and the other has a header, description and four smaller tiles with titles, descriptions and icons. First we need to properly map the translated text and for that we have to restructure the json file with the translations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"featuresSection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lorem ipsum header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lorem ipsum desc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"features"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"fast"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fast"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lorem ipsum dolor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FastIcon"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"accurate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Accurate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lorem ipsum dolor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AccurateIcon"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"ai"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AI powered"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lorem ipsum dolor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ProcessorIcon"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"automated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fully automated"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lorem ipsum dolor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AutomationIcon"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have everything neatly organized in our json files it's time to map it using the i18next useTranslation hook. Lets use a const for the section of the landing json file we're using so that we can then access it via just curly braces like in the h2 and desc div here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useTranslation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-i18next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;landing&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;featSection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;featuresSection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;featSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;featSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively you can use the built-in i18next attribute &lt;code&gt;KeyPrefix&lt;/code&gt;. I think this works the same way regardless (unless there's some key difference I’m unaware of) but I just like using the const as that way I can access every translation string by just calling the const name in curly braces &lt;code&gt;{featSection.whatever}&lt;/code&gt; instead of doing &lt;code&gt;{t(‘whatever’)}&lt;/code&gt; but that’s just personal preference and you can do it like this as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;landing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;keyPrefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;featuresSection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that done let's change the html code for the list items. We can simplify it since all the list items are structured the same way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;{key}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;IconComponent&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    {name}
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{text}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the whole list we still need to map these elements, at first I went with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iconComponents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;AutomationIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;FastIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;ProcessorIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;AccurateIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;featSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;features&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&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;icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&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="o"&gt;=&lt;/span&gt;
            &lt;span class="nx"&gt;featSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;features&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;featSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;features&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;IconComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;iconComponents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;iconComponents&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{key}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IconComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While that worked it required an extra const and a somewhat hacky workaround for a TypeScript type error via &lt;code&gt;as keyof typeof&lt;/code&gt; and pointing it to &lt;code&gt;featSection.features&lt;/code&gt;. We can definitely do better! In general there’s three methods of mapping objects: keys, values and entries (which contain both keys and values). As you can see at first I went with keys, but using values makes more sense since that way TypeScript can infer the type values and we can just use idx which will also let it identify the key values. That approach lets us get rid of the const and simplify the code again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iconComponents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;AutomationIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;FastIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;ProcessorIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;AccurateIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;featSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;features&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&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="nx"&gt;idx&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;IconComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;iconComponents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;iconComponents&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IconComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's nice and simple but as you can see I'm still defining the icon types and values via an extra const and the hacky &lt;code&gt;as keyof typeof&lt;/code&gt; workaround. To get rid of that we can use React's dynamic imports. Since the json file already defines what icon should be in each component we can use that to import the icons dynamically. So now instead of using import for each icon individually we can import them dynamically by using this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Icons&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;featSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;features&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&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="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Icons&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Icons&lt;/span&gt;&lt;span class="p"&gt;]()}&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can even use different icons for different language versions if we want to, by simply specifying their names in that language json file. Let's look at the whole component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useTranslation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-i18next&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Icons&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FeaturesSection&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;t&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTranslation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;landing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FeatureSectionWrapper&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FeatureText&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;features.description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;featSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;features&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&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="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Icons&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Icons&lt;/span&gt;&lt;span class="p"&gt;]()}&lt;/span&gt;
                                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                        &lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;})}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FeatureText&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FeatureImg&lt;/span&gt;
                &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/images/results.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;feature image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FeatureSectionWrapper&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a lot cleaner and less painful to look at, and it only took a couple simple changes. Obviously it's a reach to call this a refactor or really anything but a small fix, but going over earlier mistakes makes things easier to remember (at least for me). It's also a small step towards writing cleaner and simpler code which is a good thing to keep in mind. It's also the best route to take especially in regards to SEO where better safe than sorry is the only correct approach. You can be sure that it's a whole lot easier than figuring out which piece of code on your website is causing the dreaded layout shifts Google has flagged you for.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>html</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Eleventy components woes</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Tue, 03 Oct 2023 15:27:55 +0000</pubDate>
      <link>https://dev.to/graphqleditor/eleventy-components-woes-3nap</link>
      <guid>https://dev.to/graphqleditor/eleventy-components-woes-3nap</guid>
      <description>&lt;p&gt;So far so good, in part one we managed to do a very basic setup of a blog website sticking to just markdown and html (with a little bit of Nunjucks admittedly). If that's all you wanted from &lt;a href="https://www.11ty.dev/"&gt;Eleventy&lt;/a&gt; then you're good to go and you'll find a lot of possible improvements and additions if needed. If you wanted to build a more complex website, well... this is where things get a bit tougher as modern websites use components and for Eleventy those are a bit of a touchy subject.&lt;/p&gt;

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

&lt;p&gt;Components are used almost universally now so it's hard to imagine web dev without them. At first glance everything looks really promising - not only does Eleventy support components but since it will compile them to static html and CSS we're getting a true server-side component system! While that sounds great in theory, sadly things aren't as simple as that. To get to know why first let's look at the numerous methods of creating components in Eleventy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Liquid Render/Include&lt;/li&gt;
&lt;li&gt;Nunjucks Include &amp;amp; Macro&lt;/li&gt;
&lt;li&gt;Eleventy Render Plugin&lt;/li&gt;
&lt;li&gt;Eleventy Vue Plugin (soon to be archived)&lt;/li&gt;
&lt;li&gt;Eleventy Shortcodes&lt;/li&gt;
&lt;li&gt;WebC Plugin (new!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Templating
&lt;/h3&gt;

&lt;p&gt;We've done a bit of that already with collections and this approach follows the same logic. Since we already have our blog posts now we need a bit of navigation, let's add a go-back button for users, letting them return to the index page after they're done reading a post. For that we need a button component in our &lt;code&gt;_includes&lt;/code&gt; folder which will have typical button props like label and URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Go back&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to include it in our layout template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;include&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That works, but it isn't really fair, is it? We simply imported a static piece of html. If we want a real button component it should have props and to do that with Eleventy we need to use Nunjucks and create a button.njk component with those props:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ url }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with that we can go to our template and specify what that url and label for the included button will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Go Back&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;include&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button.njk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  No thanks
&lt;/h3&gt;

&lt;p&gt;So we managed to create the simplest button component with props. The downside is that not only is this very similar to React and importing components - it's also more boilerplate compared to something like a simple import statement and &lt;code&gt;&amp;lt;Button href="/"&amp;gt;Go Back&amp;lt;/Button&amp;gt;&lt;/code&gt;. Just to hammer this point home, this button was the simplest example. Let's imagine some standard website component which will have not only a button but also localized text, which will vary depending on which language the user selects and styling which will vary if a different theme is selected.&lt;/p&gt;

&lt;p&gt;Liquid includes/render works basically the same - you can include a global reusable component like &lt;code&gt;button.liquid&lt;/code&gt; in your &lt;code&gt;_includes&lt;/code&gt; folder and render it in a template or page as &lt;code&gt;{% render 'button' %}&lt;/code&gt;. It does have additional options but since we're looking for simplicity and this method has already soured us on that, I won't be going over them in more detail here.&lt;/p&gt;

&lt;p&gt;Similarly there's also an option of using Nunjucks Macros for larger components like a pricing card:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;macro&lt;/span&gt; &lt;span class="nf"&gt;pricingCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pricing-card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;endmacro&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pricingCard.njk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pricingCard&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;pricingCard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pricingCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Basic Plan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Includes essential features&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$1.99/month&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;endblock&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue with all these methods is they are doing something similar to React, but in a more complicated way. What about conditional props which in React are as simple as a single &lt;code&gt;?&lt;/code&gt;, well for those you'll have to do even more javascript boilerplate and use if/else conditions. It's pretty apparent that neither of these approaches fits our simplicity requirement, so that's 0-2 for Eleventy and let’s proceed to the others.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Template Shortcodes
&lt;/h3&gt;

&lt;p&gt;The Render Plugin I mentioned before is a little addon which gives you two shortcodes for quick and easy use, so let’s go over shortcodes in general. You might be wondering why there’s a plugin with just two shortcodes when Eleventy supports them out of the box. The answer is very simple - adding them is even more of a hassle and even more boilerplate code.&lt;/p&gt;

&lt;p&gt;Going back to our button example, let’s say we want to get closer to React and use something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Go Back&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is doable, but for that we need to tell Eleventy what this button is and this is done via a function in the main eleventy config file. I don't think I need to go over this step by step because a quick look at the code will tell you everything you need to know:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&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;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&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;nunjucks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nunjucks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addNunjucksShortcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_includes/button.njk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;missing file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nunjucks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renderString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="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;Holy boilerplate, this just looks terrible and remember this is all for &lt;strong&gt;just one basic button component&lt;/strong&gt;. I guess I get the idea, but I shudder to think how that config file would look for some of our websites. Now I have seen some example of getting around that using functions to loop over a directory with components, but that's just digging a deeper hole with even more js code. Even if you make that work it's just another makeshift solution which will then run into the fact that most websites use nested components as organisms, atoms, sections etc. which you'll have to do even more clunky workarounds to handle. Once again we were looking for simplicity - and we arrived at the opposite end of the spectrum - tedious boilerplate code shoved into a bloated config file. I mean just compare the atrocity above with a simple export like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;href&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&amp;gt;&lt;/span&gt;&lt;span class="err"&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;Button&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Vue woes
&lt;/h2&gt;

&lt;p&gt;So with that we're down to 0-4, not great to put it mildly. Eleventy has also cooperated with Vue on a specific Eleventy Vue Plugin. This approach had its benefits as it used Vue components out of the box rendering them to plain html providing you with a very nice base. The issue here is that after a while Eleventy ran into the &lt;a href="https://graphqleditor.com/blog/eleventy/"&gt;same problem I mentioned in the first blogpost&lt;/a&gt; - maintenance. Maintaining a plugin like this requires cooperation on all the connected things and long story short that has broken down and the Eleventy Vue plugin is on its way to being archived after VUE shut it down on their end.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebC to the rescue?
&lt;/h2&gt;

&lt;p&gt;Now being completely honest I'm probably a bit too harsh on Eleventy as it did its job as a SSG wonderfully as I outlined in the first post. It's just a bummer that we got into this roadblock with components and looking at the various methods has put me off trying it for even a simple landing page. Just to make it perfectly clear I'm not comparing Eleventy with React because I want it to be React - far from it! We were looking for something that isn't React and thats why wrapping components in boilerplate js code to get them to work kinda like React is missing the point entirely.&lt;/p&gt;

&lt;p&gt;But thankfully from what I've read there's a light in the tunnel in the shape of a new WebC Plugin. I have to say I am a bit skeptical after going through the sad tale of the Vue plugin, but from what I've seen this looks a lot more promising. Which is great because Eleventy really is promising and solves a lot of the basic problems. All that's missing is some less hacky way to do components and it can be truly great. So thanks for reading and see you in part three where we look at the new WebC plugin and if that solves our component issues.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Making a simple Eleventy blog template</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Sun, 01 Oct 2023 16:16:22 +0000</pubDate>
      <link>https://dev.to/graphqleditor/making-a-simple-eleventy-blog-template-3558</link>
      <guid>https://dev.to/graphqleditor/making-a-simple-eleventy-blog-template-3558</guid>
      <description>&lt;p&gt;If you’ve worked with TypeScript, React or Next odds are you’ve encountered an update that broke a number of features on your page. When that happens you’re left wondering if there’s some simpler or older technology you could use that would just be less hassle. Well at least that’s what we were talking about at the office after the last Next update with translations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to the past
&lt;/h2&gt;

&lt;p&gt;Thinking about simplicity the things that come to mind are languages like css, html or even markdown. Simple is one thing and stability is another, there's zero chance we’ll get a groundbreaking markdown update next year, which will break our projects. That’s why we looked at some frameworks that could work with something as simple as that, going in the complete opposite from our usual TS, Next &amp;amp; React stack. That’s how I stumbled upon &lt;a href="https://www.11ty.dev/" rel="noopener noreferrer"&gt;Eleventy&lt;/a&gt;, a versatile SSG which works with a number of file formats - among them Markdown which is exactly what we were looking for and as simple as it gets.&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%2Fgraphqleditor.com%2Farticles%2Feleventy%2Fspeed.webp" 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%2Fgraphqleditor.com%2Farticles%2Feleventy%2Fspeed.webp" alt="11ty performance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a simple blog page
&lt;/h2&gt;

&lt;p&gt;So the next question was could we actually create a page using only simple languages like markdown? The answer is Eleventy and it's really simple to use just like we wanted. Obviously you’ll need to npm install the run it and since we’re already on a blog page let's use that for our example.&lt;/p&gt;

&lt;p&gt;First we’ll need a &lt;code&gt;index.html&lt;/code&gt; page from which we will be able to access our content and a posts folder for our blogposts in markdown. We can add an example post in markdown and run localhost to see eleventy will automatically render it to html (neat and simple just like we wanted)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;├── posts
│   ├── my-first-post.md
│   ├── my-second-post.md
├── index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll also need to do some layout for our blog, this is by default kept in a &lt;code&gt;_includes&lt;/code&gt; folder, but it's easy to rename it in the settings if you want to call it layouts or whatever.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;├── posts
│   ├── my-first-post.md
│   ├── my-second-post.md
├── _includes
│   ├── layout.html
├── index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use the layout for our index page we need to include it in a front matter section at the top of the page like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;layout.html&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="s"&gt;the content of our page&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to tell the layout file where the content will go and for that we use double curly braces, reminiscent of liquid or nunjucks (more on that later btw.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Our blog&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to our blog&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;{{ content }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviously our blogposts will also need a layout and Eleventy has a neat trick to do it for all of them with just one line. We simply need to go to our posts folder, create a json file with the matching name (ie. posts.json) and point it to our layout file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;layout'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;layout.html'&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Front Matter
&lt;/h2&gt;

&lt;p&gt;The fact we're using a json file to import the layout into our blog pages doesn't mean we can't also use front matter there. For example we'll definitely want to use different titles for our posts so we need to add them to the front matter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;the title of our post&lt;/span&gt;
&lt;span class="na"&gt;cover&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/images/FirstPostCover.png&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then import them in the layout&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;{{ title | default: "Our blog"}}&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;cover&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="na"&gt;default:&lt;/span&gt; &lt;span class="err"&gt;"/&lt;/span&gt;&lt;span class="na"&gt;images&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;default.png&lt;/span&gt;&lt;span class="err"&gt;"}}&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="na"&gt;default:&lt;/span&gt;
    &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;Our&lt;/span&gt; &lt;span class="na"&gt;blog&lt;/span&gt;&lt;span class="err"&gt;"}}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;{{ title | default: "Welcome to our blog"}}&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;{{ content }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is best suited for simple SEO tags like titles, meta descriptions, open graph tags etc. which we can now make sure will use dynamic titles, descriptions or images that we will specify in the front matter. For other things we can use something called collections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collections
&lt;/h2&gt;

&lt;p&gt;Collections let us iterate over a group of files, like our posts. To do so we need to set a tag in that same json file we created and set a tag for them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;layout"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;layout.html"&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tags"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;post"&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now we can for example list our blogposts on our index page. To do so we need to iterate over the post collection in the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;---&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;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;
&lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;endfor&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the syntax looks weird to you it's Liquid - or Nunjucks here specifically, a simple templating language used for static site generators. If you don't like it you can also achieve the same result using JavaScript as Eleventy does support that as well but it would kinda defeat the whole purpose of going away from React.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static Site Generator
&lt;/h2&gt;

&lt;p&gt;That said with these few simple steps we can get our blog page running in no time at all, which is exactly what we were looking for - quick and easy! I should say it's hardly a surprise that a static site generator works well for generating a pretty straightforward static site. I might've painted a too rosy a picture with this simple overview so I promise I'll go over some of the downsides of Eleventy in part 2 (where we'll get into components!)&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>css</category>
      <category>html</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>AI-Generated GraphQL Schema and Fake backend</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Fri, 29 Sep 2023 15:10:58 +0000</pubDate>
      <link>https://dev.to/graphqleditor/ai-generated-graphql-schema-and-fake-backend-2hg0</link>
      <guid>https://dev.to/graphqleditor/ai-generated-graphql-schema-and-fake-backend-2hg0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;if you want to check it out without reading &lt;a href="https://graphqleditor.com/"&gt;just click here&lt;/a&gt; and go test it out yourself&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Looking for a springboard
&lt;/h3&gt;

&lt;p&gt;For a while now we have seen data from both analytics and community feedback that &lt;a href="https://graphqleditor.com/"&gt;GraphQL Editor&lt;/a&gt; has a pretty steep learning curve and a lot of users have trouble getting their projects off the ground. We've tried pretty much everything to remedy that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;youtube tutorials&lt;/li&gt;
&lt;li&gt;detailed documentation with gifs&lt;/li&gt;
&lt;li&gt;step-by-step guides&lt;/li&gt;
&lt;li&gt;pop-up onboardings&lt;/li&gt;
&lt;li&gt;interactive in-app tutorials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While that has had positive effects it still didn't satisfy a lot of users who wanted to get going right away without following tutorials or guides. While brainstorming someone floated the idea of creating an example project that would give users some basic view of what they can do. This made a lot of sense, but why stop at a generic project when we can use AI to tailor it to what the user needs?&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-generated Docs
&lt;/h3&gt;

&lt;p&gt;We actually were already working on utilizing &lt;a href="https://chat.openai.com/"&gt;Chat-GPT&lt;/a&gt; for generating documentation. While that will be a sweet feature (as nobody likes writing documentation) it's a bit more complicated and we're still working on it. That said, we have decided that giving new users a jumping-off point was a priority and more importantly a lot easier to implement. So while ai-generated docs are coming soon, we do have two new AI features to show off!&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-generated schema
&lt;/h3&gt;

&lt;p&gt;From now on, when starting a new &lt;a href="https://graphqleditor.com/"&gt;GraphQL Editor&lt;/a&gt; project you will notice a new field with some sparkles. This is where you can enter your prompt and the AI will then generate a schema for your project based on what you have entered. It can be anything - a food delivery app or a twitter clone and the AI should give you a nice base schema to play around with.&lt;/p&gt;

&lt;p&gt;Here's what I got after typing 'schema for a twitter-like app':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;followers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;following&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;tweets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;retweets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;replies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;getTweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;searchUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;searchTweets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createTweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;deleteTweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;likeTweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tweetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;retweetTweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tweetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;replyTweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tweetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Tweet&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;scalar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;schema&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ai-powered fake backend
&lt;/h3&gt;

&lt;p&gt;Additionally you can now go to the API section and test out your queries and mutations against a fake backend with AI-generated field values! The AI will provide mock responses automatically based on the information it can gather - so if your query is something like &lt;code&gt;getUsers&lt;/code&gt; with fields of usernames and email addresses the mock backend will return faked responses for those fields with random names and emails and the same for anything from &lt;code&gt;listMovies&lt;/code&gt; to &lt;code&gt;getListofPizzaToppings&lt;/code&gt; and the like. We had used the popular FakerJS database for this for years but that had its limitations and more importantly, required the user to choose and click the type of value they wanted faked for each field. While handy that was only a small step from writing them in yourself in an array. Now all that happens automatically without requiring the user to do anything!&lt;/p&gt;

&lt;p&gt;Here's the result I got for the &lt;code&gt;searchUsers&lt;/code&gt; query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"searchUsers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wed, 27 Sep 2023 18:42:23 GMT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Santos_Murray@yahoo.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Chanel.Cummings"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thu, 28 Sep 2023 07:48:07 GMT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Howard_Romaguera30@yahoo.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lexie.Langosh"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wed, 27 Sep 2023 22:31:15 GMT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ulices.Brown@yahoo.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Johnathon_Krajcik"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wed, 27 Sep 2023 20:31:03 GMT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bart_Emmerich97@hotmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Scot20"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thu, 28 Sep 2023 00:13:46 GMT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jaylin_Marvin@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Loren.Harris65"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wed, 27 Sep 2023 23:01:56 GMT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rylan3@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alysson.Heaney88"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wed, 27 Sep 2023 16:35:04 GMT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Angelo81@yahoo.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Katheryn.Bednar0"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thu, 28 Sep 2023 05:54:44 GMT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nichole_Schamberger@yahoo.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lottie.Fay63"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For fun or as POC
&lt;/h3&gt;

&lt;p&gt;As you can see it's very easy to play around with. Our main hope is that with this users (especially new ones) will have a way easier time getting acquainted with the basic possibilities of the tool. Obviously that's just one use, it can also be pretty handy to show proof of concept for an app showing both the overall structure and possible query and mutation results. It also serves as a nice starting point as you can easily edit all the fields the AI has created for you - changing the schema to whatever fits your needs. The whole process is so simple it requires only a few clicks without writing or even knowing any code - so even non-coders can easily do it and show their idea for an application!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Apollo Supergraph: A GraphQL stack for everything</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Thu, 23 Jun 2022 09:51:34 +0000</pubDate>
      <link>https://dev.to/graphqleditor/apollo-supergraph-a-graphql-stack-for-everything-4id9</link>
      <guid>https://dev.to/graphqleditor/apollo-supergraph-a-graphql-stack-for-everything-4id9</guid>
      <description>&lt;p&gt;The folks at Apollo have been working with GraphQL since 2016, back when they were still Meteor Software. Versatility has always been at the core of Apollo, when they released their GraphQL-based datastack in 2016 its calling card was ‘any backend, any language, any client’. The idea was clear, to have one tool for building a GraphQL client and server which can then be used to either build a new app from scratch or fit into an existing project, so that it can take full advantage of the perks of GraphQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apollo Server and Apollo Client
&lt;/h2&gt;

&lt;p&gt;At the core of the stack were Apollo Server and Apollo Client and both became popular tools in the community in their own right. Apollo Server ran as a GraphQL translation layer on top of the existing backend and Apollo Client was a Relay-like client that could be adopted in any application. The same flexible approach was clearly apparent in both. Apollo Server works with a wide range of different data sources via open-source implementations (HTTP/REST APIs, SQL databases, MongoDb and others) and Apollo Client is view-layer agnostic and works with a number of frameworks like React, Angular, Vue or even vanilla JS.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Supergraph
&lt;/h2&gt;

&lt;p&gt;The versatile approach, started with those two tools, has now produced a new stack called Apollo Supergraph. It's a single solution for bringing together data from a wide variety of sources into a single Supergraph, a unified layer made from modules interacting with each other. Apollo has always worked according to their &lt;a href="https://principledgraphql.com/" rel="noopener noreferrer"&gt;principled GraphQL approach&lt;/a&gt;, inspired by the Twelve-Factor App methodology. It's easy to see here as well as the entire Supergraph concept is based around three core principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;a unified composition layer&lt;/strong&gt;: Supergraph is meant to be a graph of graphs, connecting all of the company’s data, microservices and digital capabilities into a new unified composition layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;modular architecture&lt;/strong&gt;: Supergraph’s modular and declarative architecture lets teams quickly integrate modular data, services and business logic into that unified layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;agile approach&lt;/strong&gt;: Taking a bottom-up instead of a top-down approach makes for faster and more involved development. Every dev and team is encouraged to publish changes into the schema on their end, and the actual use of schema is what pushes development forward, by having everyone focus on decisions and improvement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Three building blocks
&lt;/h2&gt;

&lt;p&gt;So everything is about making a unified layer by using modules and focusing on constant improvement. While that gives us some indication of what were the main ideas behind creating the stack, we still need some more specific information to get the full picture. Similarly to the three principles the Supergraph also has three core components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Apollo Federation&lt;/strong&gt; is what is actually responsible for building the Supergraph, by composing a number of subgraphs (GraphQL services) into a supergraph. Following the modular principle each subgraph is an independent self-contained component with its own schema, which can be worked on and deployed individually. Subgraphs can be written in 20 different programming languages so the bottom-up, flexible approach is also evident here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apollo Router&lt;/strong&gt; is what is responsible for running the Supergraph. The runtime is a successor to the previously used Apollo Gateway: it boasts 10x lower latency, 10x higher throughput and 12x lower variance compared to its JavaScript predecessor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apollo Studio&lt;/strong&gt; is what delivers the Supergraph. Validation, automation, observability, all that good stuff you need to make delivering changes quickly and safely possible. It's even more true in the rapidly evolving environment of the Supergraph where devs and teams are encouraged to work on each other's contributions. Schema Checks and Launches automatically validate the schema in development, which helps prevent breaking changes before they occur and makes past and ongoing changes easily visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Spread the word
&lt;/h2&gt;

&lt;p&gt;I think it's safe to say Supergraph aims very high. It wants to be a true enterprise stack that you can adopt and work on company-wide regardless of what languages the programmers use and what types of services and data sources need to be integrated. If the hype is real it can really become a catch all solution that will streamline work and make full use of the advantages of GraphQL along the way. The Apollo team has been very reliable so far so if you’re a GraphQL enthusiast it's definitely something you want to keep an eye on and tell others about. After all wide adoption is key if we ever want to start working together using the Supergraph.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;A guest blog post for &lt;a href="https://blog.graphqleditor.com/" rel="noopener noreferrer"&gt;GraphQL Editor blog&lt;/a&gt; by Michał Tyszkiewicz&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Speed up your GraphQL API development
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GraphQL Editor&lt;/strong&gt; is a supportive tool for both advanced GraphQL users as well as those taking their first steps with GraphQL APIs. Our all-in-one development environment for GraphQL will help you build, manage &amp;amp; deploy your GraphQL API much faster. &lt;strong&gt;&lt;a href="https://graphqleditor.com" rel="noopener noreferrer"&gt;Try GraphQL Editor for free!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://graphqleditor.com" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fur7var8ljvdb5tzhyjz9.png" alt="Try GraphQL Editor"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>GraphQL Yoga 2.0 - a light but fully-featured GraphQL Server</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Thu, 05 May 2022 08:03:23 +0000</pubDate>
      <link>https://dev.to/graphqleditor/graphql-yoga-20-a-light-but-fully-featured-graphql-server-210l</link>
      <guid>https://dev.to/graphqleditor/graphql-yoga-20-a-light-but-fully-featured-graphql-server-210l</guid>
      <description>&lt;p&gt;Everyone including beginners who are just getting into GraphQL sooner rather than later arrives at what you can call the server question. In GraphQL everything is basically dealt with in two parts, the schema (type definitions and resolvers) and the HTTP server. On the client side you can find many useful libraries that will help you build your schema and everything is in SDL which is a pretty transparent language that isn't too hard to get a hang of. The server side might be a bit tougher to handle, but there’s also a number of options that can help you with that as well. One particular library just got a big revamp so it's a good idea to check it out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Yoga 1.0 - quick and easy
&lt;/h2&gt;

&lt;p&gt;Graphql-yoga has been around since 2017 and while not nearly as popular as Apollo-server it did have a lot of advantages. Its documentation described it as ‘create-react-app for building GraphQL servers’ and it's hard to argue with that. It required minimal setup, kept most of the boilerplate code you usually get when starting a server hidden and handled much of the initial project setup for you. Together this made it the easiest server option for beginners to get into as well as a useful tool for experienced users looking for a way to make a quick NodeJS GraphQL server. Down the line if your project grew too large for Yoga you could’ve simply swapped it out for a more complex tool like the above mentioned Apollo-server. All wasn't rosy though as by 2019 the project stopped getting updates and was basically abandoned. This resigned it to the role of a learning tool with some uses in case you need to get up a server quickly, but pretty much ensured you wouldn't ever use it for a fully fledged project. The fate of the Yoga library might’ve been a bit of a bummer considering the lack of an alternative lightweight and versatile GraphQL server option.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Guild comes to the rescue
&lt;/h2&gt;

&lt;p&gt;In late 2021 Yoga was taken over by The Guild and they decided to rewrite it from scratch. Their main focus was performance, flexibility, easy setup and improving overall developer experience, in other words a lot of what the old Yoga was about combined with new more comprehensive solutions. The key thing here is that The Guild promises to be here for the long run and not only update Yoga, but also keep working on improving it with new features. They can be trusted to uphold that as they have quite a bit of experience with GraphQL with a number of popular and still developed libraries like GraphQL Tools or Envelop. On GitHub you can already see Yoga has received hundreds of commits and lots of updates so the project is very much alive. In late March the big 2.0 update finally arrived so let’s check out what the key features are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;flexible:&lt;/strong&gt; Built around W3C Request/Response which is supported in all major serverless, worker and serverful JavaScript environments, Yoga is designed to run basically anywhere&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lean:&lt;/strong&gt; Yoga has a really light core and a small bundle size, three times smaller than Apollo-server, which can prove very significant for performance in serverless environments and make maintenance much easier in general&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;out of the box:&lt;/strong&gt; Some popular GraphQL API features like advanced error handling, file-uploads, subscription support or CORS come built-in with Yoga&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;easy to get a hang of:&lt;/strong&gt; Keeping up with the beginner firendly approach Yoga has robust documentation and comprehensive tutorials to help you get to know all the features and functionalities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;plugin system:&lt;/strong&gt; With Envelop The Guild has started a large plugin system for GraphQL, which Yoga has built-in and comes with a default preset enabled (which can be disabled or customized)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Beyond 2.0
&lt;/h2&gt;

&lt;p&gt;Yoga has been a useful tool for easily and quickly creating a GraphQL server, especially great if you just wanted to get a hang of it. Now though it looks like the aims are quite a bit larger and the team behind it wants to make it a viable or even superior alternative to other server options. It already had its niche and now fusing the old Yoga approach of getting started quickly with the rich ecosystem of Envelop can prove to be a powerful combination. The Guild know their way around GraphQL and have already created a number of very useful and popular tools so we pretty much know we can expect good things to happen to Yoga as well. With the development picking up speed so quickly additional new features will probably arrive soon, so even if you’re still not convinced it's a good idea to keep an eye out on the growth of Yoga and how it compares to other server options.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;A guest blog post for &lt;a href="https://blog.graphqleditor.com/"&gt;GraphQL Editor blog&lt;/a&gt; by Michał Tyszkiewicz&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Speed up your GraphQL API development
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GraphQL Editor&lt;/strong&gt; is a supportive tool for both advanced GraphQL users as well as those taking their first steps with GraphQL APIs. Our all-in-one development environment for GraphQL will help you build, manage &amp;amp; deploy your GraphQL API much faster. &lt;strong&gt;&lt;a href="https://graphqleditor.com"&gt;Try GraphQL Editor for free!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://graphqleditor.com"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yN5xB87j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ur7var8ljvdb5tzhyjz9.png" alt="Try GraphQL Editor" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Apollo Kotlin - getting started with GraphQL on Android</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Tue, 18 Jan 2022 07:49:58 +0000</pubDate>
      <link>https://dev.to/graphqleditor/apollo-kotlin-getting-started-with-graphql-on-android-2km1</link>
      <guid>https://dev.to/graphqleditor/apollo-kotlin-getting-started-with-graphql-on-android-2km1</guid>
      <description>&lt;p&gt;Using GraphQL on Android has been a niche topic for quite a while and that might be a bit surprising, especially considering the prevalence of Android devices and the steadily growing popularity of GraphQL. Still even a quick google search will show you REST still dominates in the Android community. That said, something not being popular isn't a reason to discount it out of hand and since it's a new year, why not check out something different instead of going with the flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who doesn't like GraphQL?!
&lt;/h2&gt;

&lt;p&gt;If you’re here you’re probably quite familiar with the advantages of GraphQL so you might be wondering why the Android community has been slow in getting on the GraphQL hypetrain. While there are a number of factors, one is pretty glaring, the number of available tools. Thankfully there are some new libraries popping up here and there, but it's safe to say that if you’re trying to work with GraphQL on Android right now, Apollo's Android library is the only way.&lt;/p&gt;

&lt;p&gt;So it looks like we’re stuck picking it, but what is it exactly? Well GraphQL was released publicly all the way back in 2015 and in early 2017 Apollo released Apollo Android v. 0.2 which provided some basic support for GraphQL model generation. It's been a few years since then and it has grown quite a bit larger, version 1.0 introduced Kotlin code generation and 2.0 introduced multiplatform query and subscription support. To get a better look at it's state let’s check out the main features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multiplatform: the library is designed with Android in mind, but can be used in any Java/Kotlin app&lt;/li&gt;
&lt;li&gt;makes full use of GraphQL: from basics like queries, mutations and subscriptions to more advanced stuff like query batching, persistent queries and an AST parser&lt;/li&gt;
&lt;li&gt;3 levels of catching: HTTP Response Cache (for caching raw http responses), Normalized Disk Cache (per node caching of responses in SQL) and Normalized InMemory Cache (Optimized Guava memory cache for in memory caching)&lt;/li&gt;
&lt;li&gt;RXJava support ...&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  RXJava
&lt;/h2&gt;

&lt;p&gt;On that last one if you’re familiar with Java you’ve probably heard about RXJava, if not it's an extremely useful implementation of Reactive Extensions that has been popularized by Netflix. While Android Apollo generates Kotlin/Java models from GraphQL queries, RXJava (to quote the official description here) is a library for composing asynchronous and event-based programs by using observable sequences. That’s just the technical terms, to use simpler language it reverses the usual process where you request data, to an event based process where you're notified about data in the stream. Since you’re using GraphQL for requests (or rather queries) anyway it's simply very handy for use with subscriptions. That’s obviously not the only advantage and you can find a ton of info on the uses of RXJava so let’s just say it's popular for a good reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apollo Android -&amp;gt; Apollo Kotlin
&lt;/h2&gt;

&lt;p&gt;That’s not all, about a month ago Apollo Android made version 3.0.0 public. While the most noticeable difference was clearly the name change from Apollo Android to Apollo Kotlin, the changelog was a bit longer than that. Aside from the usual bugfixes and an update to Kotlin version 1.6.10 we can see a few new features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;extended multiplatform support for Android, JS, iOS, MacOS and linux&lt;/li&gt;
&lt;li&gt;coroutine APIs for easier concurrency&lt;/li&gt;
&lt;li&gt;response based code generation engine&lt;/li&gt;
&lt;li&gt;SQLite batching&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  Your own niche
&lt;/h2&gt;

&lt;p&gt;I hope that gave you a somewhat decent overview of the Apollo Kotlin library and maybe piqued your interest at least a tiny bit. As I mentioned previously it's not a very popular topic, so if you’re looking for your own niche this might be it. If not, the growing popularity of GraphQL will certainly keep influencing the Android community anyway, so it might be a good idea to beat others to it and start early. While Apollo Kotlin is the go-to tool now, no one can say that has to be the case forever. Maybe it will soon face competition from some new libraries and who can say one of those libraries can't be created by you?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;A guest blog post for &lt;a href="https://blog.graphqleditor.com/"&gt;GraphQL Editor blog&lt;/a&gt; by Michał Tyszkiewicz&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Speed up your GraphQL API development
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GraphQL Editor&lt;/strong&gt; is a supportive tool for both advanced GraphQL users as well as those taking their first steps with GraphQL APIs. Our all-in-one development environment for GraphQL will help you build, manage &amp;amp; deploy your GraphQL API much faster. &lt;strong&gt;&lt;a href="https://graphqleditor.com"&gt;Try GraphQL Editor for free!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://graphqleditor.com"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yN5xB87j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ur7var8ljvdb5tzhyjz9.png" alt="Try GraphQL Editor" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Saleor - a GraphQL-first open-source e-Commerce platform</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Wed, 08 Dec 2021 09:57:47 +0000</pubDate>
      <link>https://dev.to/graphqleditor/saleor-a-graphql-first-open-source-e-commerce-platform-15a9</link>
      <guid>https://dev.to/graphqleditor/saleor-a-graphql-first-open-source-e-commerce-platform-15a9</guid>
      <description>&lt;p&gt;The pandemic has changed many aspects of our lives.  Because of the lockdowns, almost all of our activities have moved online. Work? Remote. Meetings? Zoom or Teams. Shopping? Ecommerce. One of the areas most impacted by the pandemic is the retail industry.&lt;/p&gt;

&lt;p&gt;The changes have caused a significant acceleration of e-commerce, but also increased competition in the field. With such rapid growth and the race for the biggest market share, keeping in touch with customers and making sure they get what they need has become a challenge. Just as Zoom, Teams and other apps have helped with conference calls as remote working has entered the lives of most people permanently, automation and tools that allow for better management of sales, customer service and customer relations has become essential for the ecommerce industry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customer Relationship &amp;amp; Process Management Platforms
&lt;/h2&gt;

&lt;p&gt;The most basic customer relationship helpers are Customer Relationship Management (CRM) apps. CRMs are a sort of company archivists, keeping track of all matters related to its business operations in order to create a “company's memory" independent of the changing of its employees. The data gathered this way can be easily subjected to multidirectional analyses leading to more accurate business strategies.&lt;/p&gt;

&lt;p&gt;The above definition was valid 20 years ago, currently CRMs have transformed into something more than just company business data storage &amp;amp; there's a lot more to them than that. Modern CRMs track every interaction with every client, the chain of email conversations and the progress of each individual customer case. This can be anything from tracking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;potential leads,&lt;/li&gt;
&lt;li&gt;sales,&lt;/li&gt;
&lt;li&gt;purchases,&lt;/li&gt;
&lt;li&gt;customer support or complaints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The strength doesn't come from just having the data, but from being able to streamline the whole process through various automations and integrations, while still having everything in one place. This keeps the whole process and each case transparent and easy to analyze for the person handling it. CRMs evolved from a company archive into Business Process Management (BPM) platforms which, with a little of help from 3rd party tools, can be not only the company's archivist but also a sales and marketing person.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mix and match
&lt;/h2&gt;

&lt;p&gt;I said the strength comes from automations and integrations, because CRMs do not aim to be the be-all end-all. These platforms are aimed at keeping things tidy and easily accessible for non coders while most of the work happens in the background. Some of the more popular CRMs are Pipedrive and Pipefy, so let’s take a quick look at what they’re about.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;vertical platform developed with sales in mind&lt;/li&gt;
&lt;li&gt;batch processing&lt;/li&gt;
&lt;li&gt;sales force automation and sales tracking&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;horizontal platform developed to fit the needs of various businesses&lt;/li&gt;
&lt;li&gt;easy to learn automations to make personalization easier&lt;/li&gt;
&lt;li&gt;custom workflow management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--07Hta1aO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ojxs9kuvluaenvlfb6qa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--07Hta1aO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ojxs9kuvluaenvlfb6qa.png" alt="With Pipefy you can create &amp;amp; automate business workflows easily" width="518" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Source: &lt;a href="https://www.pipefy.com/"&gt;pipefy.com&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;As we can see here Pipedrive is focused on sales and Pipefy is geared towards a broader audience, still both use integrations to fill in the gaps, so if you need to hook them up with some other app, for example to import data, you’ll have to rely on those. They do have a bit of basic built in integrations with things like Slack, Zoom or Google Sheets etc. but if you need something else it's pretty likely you’ll have to use something like Zapier to bridge the gap. Alternatively you could also use web hooks or a little thing called GraphQL. While Pipedrive requires third party libraries, Pipefy does handle both GraphQL queries and mutations by design, so it is a lot more flexible in terms of what you can do with it using that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saleor
&lt;/h2&gt;

&lt;p&gt;Well if you’re a GraphQL enthusiast (and you probably wouldn't be here if you weren't one) this probably sounded like something right down your alley. After all, GraphQL is all about getting exactly what you want and not about jumping through hoops and integrations to get what you need. Well this is where Saleor comes in, a GraphQL-first headless sales platform. Most CRMs are geared towards non-coders, trying to keep everything simple by using tailored solutions and templates to make tracking everything easier. Saleor is a platform that helps connect that with both customers and developers, it’s aimed at providing maximum flexibility by giving them free reign over the platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;aimed at developers:&lt;/strong&gt; no proprietary templates, just GraphQL, JAMstack, Next.js and modern front-end tools, &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;simple integration:&lt;/strong&gt; teams don't need to focus on integrating various platforms (like CRMs) or tools and can just rely on the GraphQL API,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;frontend freedom:&lt;/strong&gt; it's entirely up to you how the frontend looks, you can write a client from scratch using the language or platform of your choosing or you can use use the default PWA storefront or JavaScript SDK,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;decoupled presentation layer:&lt;/strong&gt; the frontend is separate from your core business so you can manage any number of stores, apps, and devices from a single back-end.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h6&gt;
  
  
  Source: &lt;a href="https://saleor.io/"&gt;aleor.io&lt;/a&gt;
&lt;/h6&gt;

&lt;h2&gt;
  
  
  Is it for me though?
&lt;/h2&gt;

&lt;p&gt;As always choosing the right platform depends on your particular situation and needs. If you just want something, which will make working a bit easier for sales people with no knowledge of coding a CRM is still very useful. But things tend to pile up over time, so if it's a bigger project you might find yourself using a bunch of makeshift integrations down the line (of which not all are free). That might prove problematic in case something stops working and will take additional time to get a hang of in case you bring new people in. Saleor is a solution that can help you with that as it keeps everything decoupled. Sales people work on the CRM platform, devs work on the GraphQL API and customers just see the end result. The only drawback is you'll need someone who knows GraphQL to make use of it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;A guest blog post for &lt;a href="https://blog.graphqleditor.com/"&gt;GraphQL Editor blog&lt;/a&gt; by Michał Tyszkiewicz&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Speed up your GraphQL API development
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GraphQL Editor&lt;/strong&gt; is a supportive tool for both advanced GraphQL users as well as those taking their first steps with GraphQL APIs. Our all-in-one development environment for GraphQL will help you build, manage &amp;amp; deploy your GraphQL API much faster. &lt;strong&gt;&lt;a href="https://graphqleditor.com"&gt;Try GraphQL Editor for free!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://graphqleditor.com"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yN5xB87j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ur7var8ljvdb5tzhyjz9.png" alt="Try GraphQL Editor" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>GraphQL Editor - the journey from initial release to version 5.0</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Tue, 07 Dec 2021 11:57:24 +0000</pubDate>
      <link>https://dev.to/graphqleditor/graphql-editor-the-journey-from-initial-release-to-version-50-8k1</link>
      <guid>https://dev.to/graphqleditor/graphql-editor-the-journey-from-initial-release-to-version-50-8k1</guid>
      <description>&lt;p&gt;From the very beginning of our adventure with GraphQL, we were impressed by how great its community is. The amount of content, libraries and great tools generated by GraphQL users amazed us from the very start. The more time we spent working with GraphQL the more things we saw that could be improved to make working with it easier and better. We also knew that we wanted to give something back to its wonderful community.&lt;/p&gt;

&lt;h2&gt;
  
  
  The origins
&lt;/h2&gt;

&lt;p&gt;Three years ago we were working on quite a schema with a lot of complicated relationships, then a thought occurred to us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"It would be nice to be able to visualize it well enough to understand all the connections."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes there were several solutions on the market that would let us do that, but hey everyone knows how it works. The question always arises, why not do it differently, better, and most importantly in our own way. A few days after saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"OK, lets do it"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;came&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"What if we could build a GraphQL scheme out of visual blocks?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and that's how it all started. We begun with the PoC version, which included just these two functionalities, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GraphQL schema visualization,&lt;/li&gt;
&lt;li&gt;the ability to build it using viusal elements.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&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%2Fpxf3ptvt6s4i3jml1etq.png" alt="Old GraphQL Editor UI"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;The very first version of GraphQL Editor from 2018&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Our project has been very warmly received by the GraphQL community which resulted in quickly amassing &lt;a href="https://github.com/graphql-editor" rel="noopener noreferrer"&gt;3 000 stars on GitHub&lt;/a&gt;. Users were not only happy to use these two simple features but also started suggesting some cool new ones. Users were not only happy to use these two simple features but also started suggesting some cool features.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's new in GraphQL Editor 5.0
&lt;/h2&gt;

&lt;p&gt;When we started we had a roadmap in mind which we tried to stick to, as much as it was possible. But with all the additional feedback we also kept adding features suggested by the community, which after more than 2 years has led us to the point we are at now, namely the release of &lt;strong&gt;&lt;a href="https://graphqleditor.com/" rel="noopener noreferrer"&gt;GraphQL Editor 5.0&lt;/a&gt;&lt;/strong&gt;.  &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&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%2F6q5z9y3nsul6i9v9f1eu.png" alt="New GraphQL Editor UI"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Many graph improvements &amp;amp; various view modes&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So once again we would like to thank all our users for their valuable feedback, including those that were critical, it all really helped us improve. So without further ado, let's get into the new features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microservices
&lt;/h3&gt;

&lt;p&gt;It's the most exciting as well as the most requested feature. What's even more satisfying about it finally being released, is that, we've been trying to figure out how to tackle this one since the first release of GraphgQL Editor. &lt;strong&gt;GraphQL Microservices&lt;/strong&gt; allow users instantly deploy their GraphQL backend prototypes using JavaScript or TypeScript. What's worth mentioning is microservices is powered by our open-source library called Stucco.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/graphql-editor" rel="noopener noreferrer"&gt;Stucco&lt;/a&gt; is a backend engine for our microservices. Its main goal is to keep you in charge of your infrastructure decisions. No risk of vendor lock-in, no worries. With Stucco you can use TypeScript, JavaScript or Golang to create GraphQL backends &amp;amp; deploy them easily using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GraphQL Editor Shared worker&lt;/li&gt;
&lt;li&gt;Local environment&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Kubernetes &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can deploy microservices directly from our built-in Live Editor (similar to those you may know from Git-based platforms), but the recommended way is to do it using &lt;a href="https://github.com/graphql-editor/graphql-editor-cli" rel="noopener noreferrer"&gt;graphql-editor-cli&lt;/a&gt;. Although microservices are great for testing and development purposes, we do not recommend using them on production as they run on very small machines with rate limit of 200 requests per minute &amp;amp; 1 000 000 requests per month. Additionally this feature is very much work-in-progress and is being released mostly because we need live testers to iterate on it and improve it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&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%2F2o3u87fypvkix4q6t3ru.png" alt="Microservices"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;With Microservices you can deploy NodeJS GraphQL backends using JavaScript or TypeScript&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  JAMStack Engine
&lt;/h3&gt;

&lt;p&gt;Although JAMStack was introduced a couple versions back, in this one it received a significant update. We have added TypeScript and the most popular JS library for building user interfaces support - ReactJS. Among other notable features you can find:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;better ES modules support&lt;/strong&gt; - j just give our Live Service a CDN URL &amp;amp; it will fetch all types from your server and also look for typings,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;relative ES modules imports&lt;/strong&gt; -  now you can have user relative ES module imports inside our online code editor,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;deployment&lt;/strong&gt; - built-in static page deployment feature to easily show off your work to your team or a wider audience.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&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%2Fjqydfal3to1z1cysjzt1.png" alt="JAMStack engine"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;JAMStack with ReactJS, TS support &amp;amp; easy static deployment&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  GraphQL Cloud
&lt;/h3&gt;

&lt;p&gt;We want GraphQL Editor to become a self-sufficient IDE for GraphQL based project development. Following this goal we’re adding more and more "responsibilities" for our tools. Now you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create your own queries with ease,&lt;/li&gt;
&lt;li&gt;preview easily using built-in GraphiQL,&lt;/li&gt;
&lt;li&gt;save &amp;amp; access your work anytime you need from any device.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have also added a proxy to support every GraphQL URL &amp;amp; CORS issues which frequently appear during development.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&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%2Fohajo2qv4e08amw7l1yy.png" alt="GraphQL Cloud"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;GraphQL Cloud offers GraphiQL-like queries preview, configurable mock backend &amp;amp; CORS support&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Last but not least
&lt;/h2&gt;

&lt;p&gt;Aside from core features we have also been working on some quality of life improvements like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Graph improvements&lt;/strong&gt; - the graph module has been significantly improved:

&lt;ul&gt;
&lt;li&gt;node &amp;amp; fields creation is now much faster thanks to keyboard support,&lt;/li&gt;
&lt;li&gt;relation view includes all scalar fields,&lt;/li&gt;
&lt;li&gt;selected node state persists between view,&lt;/li&gt;
&lt;li&gt;code editor view can be toggled anytime now,&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Spotlight menu (CTRL/CMD + K)&lt;/strong&gt; - spotlight menu added for easier navigation,&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Color Themes&lt;/strong&gt; - we have added 4 new color themes,&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Learning center&lt;/strong&gt; - from now on every start, you will be welcomed with recent projects and a learning center to level up your editor skills,&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;as well as tons of bug fixes &amp;amp; minor UI improvements.&lt;/p&gt;




&lt;p&gt;So that's basically what we've been working on for the last 12 months. I must say it feels great to be able to finally share all these new features with a broader audience (thanks David!). If your are using GraphQL already I would love to hear your feedback, if not I hope GraphQL Editor would make working with it even more efficient as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If once you start down the GraphQL path, forever will it &lt;br&gt;
dominate your destiny.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Speed up your GraphQL API development
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GraphQL Editor&lt;/strong&gt; is a supportive tool for both advanced GraphQL users as well as those taking their first steps with GraphQL APIs. Our all-in-one development environment for GraphQL will help you build, manage &amp;amp; deploy your GraphQL API much faster. &lt;strong&gt;&lt;a href="https://graphqleditor.com" rel="noopener noreferrer"&gt;Try GraphQL Editor for free!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://graphqleditor.com" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fur7var8ljvdb5tzhyjz9.png" alt="Try GraphQL Editor"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>webdev</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Neo4j GraphQL Library 2.0.0</title>
      <dc:creator>Tomek Poniatowicz</dc:creator>
      <pubDate>Mon, 27 Sep 2021 11:03:20 +0000</pubDate>
      <link>https://dev.to/graphqleditor/neo4j-graphql-library-2-0-0-3cec</link>
      <guid>https://dev.to/graphqleditor/neo4j-graphql-library-2-0-0-3cec</guid>
      <description>&lt;p&gt;A while ago I wrote a bit about the GRAND stack, an integration of GraphQL, React, Apollo and the Neo4j Database. While working with the stack carries numerous benefits (and hey if you’re curious about those head on over and &lt;a href="https://blog.graphqleditor.com/grandstack"&gt;read about them here&lt;/a&gt;) it can be a bit overwhelming to get straight into it if you’re just starting out. So this time let's just look at the integration of the ‘G’ with the ‘N’ and with good reason as there is quite a bit of new stuff to check out there.&lt;/p&gt;

&lt;h2&gt;
  
  
  From GRAND to .js
&lt;/h2&gt;

&lt;p&gt;The GRAND stack has made use of combining the strengths of the Neo4j database with GraphQL for a while, but the team at Neo4j wasn't resting on their laurels and has been hard at work to improve on the benefits of combining the two technologies. In 2018 they released  a library neo4j-graphql.js, a GraphQL-to-Cypher based query execution layer for Neo4j and JavaScript GraphQL implementations. To put it short, something that gives you a fully functioning GraphQL API backed by Neo4j just by using type implementations from the GraphQL schema. The library was very useful and quite popular so it's not surprising they decided to build on that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beta and 1.0.0
&lt;/h2&gt;

&lt;p&gt;In early april of 2021 the Neo4j team announced that after a year of hard work they’re releasing a beta of the Neo4j GraphQL library. Since then they’ve only picked up the pace with the full stable 1.0.0 release coming in that very same month. Even at just a glance the features look pretty enticing&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic query and mutation generation for CRUD interactions&lt;/li&gt;
&lt;li&gt;Object Graph Mapper for programmatic interaction with your GraphQL API&lt;/li&gt;
&lt;li&gt;node and relationship properties support&lt;/li&gt;
&lt;li&gt;custom resolver support&lt;/li&gt;
&lt;li&gt;multiple pagination options&lt;/li&gt;
&lt;li&gt;authentication and authorisation options with additional access control options&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Onto 2.0.0
&lt;/h2&gt;

&lt;p&gt;Continuing with their blistering pace, neo4j dropped version 2.0.0 of their library on august tenth. While you could say that on the whole this library is a replacement or rather a continuation of the neo4j-graphql.js library with the sheer number of features it has far surpassed it. Aside from the usual stuff you can expect from a 2.0 update like bug fixes or performance improvements we have a few completely new features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;relationship properties&lt;/strong&gt;: This is the star of the show, adding relationships to your type definitions provides way more context for your data. This way when fetching data you will have a much clearer picture than you would with just disconnected nodes. This solution combines rich and interconnected data with the transparency of GraphQL letting you easily build apps even when using quite complex data sets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cursor-based pagination&lt;/strong&gt;: on relationship connected fields in your schema you’re able to use cursor-based pagination which is especially handy for infinitely scrolling apps&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Count queries&lt;/strong&gt;: if cursor based pagination is not your thing you can now use a simple query for counting all user nodes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GraphQL = easy on the eye
&lt;/h2&gt;

&lt;p&gt;That’s not all, the update also provides improvements to union relationship fields, more comprehensive validation of type definitions and various bug fixes. On the whole the key thing is still utilizing how good GraphQL is at displaying even complex data and relationships is probably the best way to take full advantage of that. Even if that doesn't convince you, with how quickly the development is going on this particular library, you can be sure a lot of additional features will be added very soon.&lt;/p&gt;

&lt;p&gt;Oh and make sure to check this video presenting Neo4j GraphQL Library in action:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Ww3XclhuaaU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;&lt;em&gt;A guest blog post for &lt;a href="https://blog.graphqleditor.com/"&gt;GraphQL Editor blog&lt;/a&gt; by Michał Tyszkiewicz&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Speed up your GraphQL API development
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GraphQL Editor&lt;/strong&gt; is a supportive tool for both advanced GraphQL users as well as those taking their first steps with GraphQL APIs. Our all-in-one development environment for GraphQL will help you build, manage &amp;amp; deploy your GraphQL API much faster. &lt;strong&gt;&lt;a href="https://graphqleditor.com"&gt;Try GraphQL Editor for free!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

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

</description>
      <category>graphql</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
