<?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: Santhanam Elumalai</title>
    <description>The latest articles on DEV Community by Santhanam Elumalai (@santhanam87).</description>
    <link>https://dev.to/santhanam87</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1031325%2F13ee911d-c821-4fd3-9dea-c5c77727ebc7.png</url>
      <title>DEV Community: Santhanam Elumalai</title>
      <link>https://dev.to/santhanam87</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/santhanam87"/>
    <language>en</language>
    <item>
      <title>Building a Robust API Layer - `api-def` Package Integration with React (NextJs) app</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Sat, 28 Sep 2024 23:26:21 +0000</pubDate>
      <link>https://dev.to/santhanam87/building-a-robust-api-layer-api-def-package-integration-with-react-nextjs-app-3ai5</link>
      <guid>https://dev.to/santhanam87/building-a-robust-api-layer-api-def-package-integration-with-react-nextjs-app-3ai5</guid>
      <description>&lt;p&gt;&lt;strong&gt;Welcome back! In this part, we'll demonstrate how to integrate the &lt;code&gt;api-def&lt;/code&gt; package with a Next.js application for client-side and server-side API fetching using Tanstack Query.&lt;/strong&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;We explored the concept and implementation of the &lt;code&gt;api-def&lt;/code&gt; package.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration with Tanstack Query:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configure Tanstack Client:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Create a &lt;code&gt;Providers&lt;/code&gt; component to manage the QueryClient instance.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;isServer&lt;/code&gt; from &lt;code&gt;@tanstack/react-query&lt;/code&gt; to create separate clients for server and client.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeQueryClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;defaultOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="na"&gt;staleTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Cache timeout in milliseconds&lt;/span&gt;
              &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;browserQueryClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryClient&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getQueryClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isServer&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="nf"&gt;makeQueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="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;browserQueryClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;browserQueryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeQueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;browserQueryClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Providers&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="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Node&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getQueryClient&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;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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;/QueryClientProvider&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Provider Placement:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Wrap your application with the &lt;code&gt;Providers&lt;/code&gt; component at the root level (e.g., in &lt;code&gt;layout.tsx&lt;/code&gt;) to make the QueryClient context globally accessible.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&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="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&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;body&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;Providers&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;/Providers&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;/body&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;/html&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;ol&gt;
&lt;li&gt;
&lt;strong&gt;Client-Side Fetching:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Create a component (e.g., &lt;code&gt;Users&lt;/code&gt; component) that utilizes the &lt;code&gt;useQuery&lt;/code&gt; hook from Tanstack Query.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;GetUserKeys&lt;/code&gt; function from &lt;code&gt;api-def&lt;/code&gt; to define the query key for caching and invalidation.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;ApiClient&lt;/code&gt; from &lt;code&gt;api-def&lt;/code&gt; within the &lt;code&gt;queryFn&lt;/code&gt; to fetch data from the API.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GetUserKeys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@repo/api-definitions&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;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tanstack/react-query&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;function&lt;/span&gt; &lt;span class="nf"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetUserKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;({}),&lt;/span&gt;
          &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;queryKey&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;queries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;requestBody&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;ApiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queries&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="p"&gt;});&lt;/span&gt;

      &lt;span class="k"&gt;return&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Server-Side Prefetching:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Within a server component (e.g., in &lt;code&gt;page.tsx&lt;/code&gt;), prefetch the data using &lt;code&gt;queryClient.prefetchQuery&lt;/code&gt; before rendering the component.&lt;/li&gt;
&lt;li&gt;Use the same &lt;code&gt;GetUserKeys&lt;/code&gt; and &lt;code&gt;ApiClient&lt;/code&gt; from &lt;code&gt;api-def&lt;/code&gt; within the &lt;code&gt;queryFn&lt;/code&gt; for consistency.&lt;/li&gt;
&lt;li&gt;Wrap the component with a &lt;code&gt;HydrationBoundary&lt;/code&gt; from Tanstack Query to hydrate the prefetched data on the client.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dehydrate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HydrationBoundary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tanstack/react-query&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;GetUserKeys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@repo/api-definitions&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;Users&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@app/user/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PostsPage&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prefetchQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetUserKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;({}),&lt;/span&gt;
          &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;requestBody&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ApiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestBody&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;requestBody&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="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;HydrationBoundary&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;dehydrate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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;Users&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;/HydrationBoundary&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;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type safety:&lt;/strong&gt; Zod ensures type safety throughout the API interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralized definitions:&lt;/strong&gt; &lt;code&gt;api-def&lt;/code&gt; offers a single source for API definitions and endpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient caching:&lt;/strong&gt; Tanstack Query manages caching and invalidation for optimized performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Next Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the upcoming post, we'll delve into the integration of another powerful tool: &lt;strong&gt;React Hook Form&lt;/strong&gt;. This library will help us streamline form handling, validation, and submission processes within our React applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stay tuned!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/santhanam87/react-jam-stack/pull/2" rel="noopener noreferrer"&gt;Github PR Location&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Footnote:&lt;/strong&gt; This implementation is inspired by the Tanstack Query documentation on Advanced Server-Side Rendering: &lt;a href="https://tanstack.com/query/latest/docs/framework/react/guides/ssr" rel="noopener noreferrer"&gt;Advanced Server Rendering&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Building a Robust API Layer - Implementation with `api-def` Package</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Thu, 26 Sep 2024 01:38:37 +0000</pubDate>
      <link>https://dev.to/santhanam87/building-a-robust-api-layer-implementation-with-api-def-package-37cj</link>
      <guid>https://dev.to/santhanam87/building-a-robust-api-layer-implementation-with-api-def-package-37cj</guid>
      <description>&lt;p&gt;&lt;strong&gt;Continuing our series, let's delve into the practical implementation using the &lt;code&gt;api-def&lt;/code&gt; package.&lt;/strong&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;We explored the concept of the &lt;code&gt;api-def&lt;/code&gt; package in the previous post.&lt;/li&gt;
&lt;li&gt;It centralizes API definitions and provides a consistent interface for making API requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implementation Breakdown (Part 1: &lt;code&gt;api-def-package&lt;/code&gt; Setup)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Existing Project:&lt;/strong&gt; Assuming you've bootstrapped your application based on the previous post &lt;a href="https://dev.to/santhanam87/building-a-solid-foundation-bootstrapping-with-turbo-repo-29mm"&gt;Bootstrapping With Turbo Repo&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dependencies:&lt;/strong&gt; Install the required packages using npm or yarn:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt; @zodios/core zod typescript axios eslint
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;&lt;strong&gt;API Definition:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a folder named &lt;code&gt;user&lt;/code&gt; under &lt;code&gt;src&lt;/code&gt; to store API definitions specific to user data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Define the API schema using Zod:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&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;UserProfileSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
   &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
   &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;

 &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UserProfileSchema&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;UserSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;UserProfileSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nx"&gt;Users&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;/li&gt;
&lt;li&gt;&lt;p&gt;Create separate files for types and query keys for better organization.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;API Endpoint:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use Zodios to create the API endpoint for fetching users:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;makeEndpoint&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@zodios/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserSchema&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./user-schema&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;getUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeEndpoint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user/search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getUsers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getUsersPayload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UserProfileSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Users&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;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Query Key:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Define a method to generate query keys for caching and invalidation:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./user-type&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;GetUserKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;requestBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UserProfile&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;requestBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;];&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;&lt;strong&gt;API Client:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Create an API client using Zodios to make API calls based on the defined endpoint:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Zodios&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;makeApi&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@zodios/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUsers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./user/user-endpoint&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;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeApi&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;getUsers&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;ApiClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Zodios&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3000/api/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

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

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

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Export all the components (schemas, types, query keys, API client) from a central index file:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./queryKey&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./schemas&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./types&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./apiclient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;&lt;strong&gt;This completes the implementation of the &lt;code&gt;api-def&lt;/code&gt; package. In the next part, we'll demonstrate how to integrate this package with a Next.js application for client-side and server-side API fetching.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/santhanam87/react-jam-stack/pull/2" rel="noopener noreferrer"&gt;Github PR Location&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stay tuned for the next post!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>zod</category>
      <category>zodios</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a Robust API Layer with TypeScript, Tanstack Query, Zod, and Zodios</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Tue, 17 Sep 2024 00:57:21 +0000</pubDate>
      <link>https://dev.to/santhanam87/building-a-robust-api-layer-with-typescript-tanstack-query-zod-and-zodios-1jg</link>
      <guid>https://dev.to/santhanam87/building-a-robust-api-layer-with-typescript-tanstack-query-zod-and-zodios-1jg</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Welcome back! In this part of our series, we'll dive deeper into the api-def package and its benefits. &lt;/p&gt;

&lt;p&gt;In today's data-intensive applications, ensuring seamless communication between the frontend and backend is paramount. This blog post will delve into how we can establish a robust API layer using TypeScript, Tanstack Query, Zod, and Zodios. By leveraging these powerful tools, we can achieve type safety, efficient data management, and a centralized approach to API interactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Problem:&lt;/strong&gt; Inconsistency and Errors
&lt;/h3&gt;

&lt;p&gt;Traditional JavaScript-based applications often suffer from inconsistencies between frontend and backend data structures. This can lead to unexpected errors and difficulties in maintaining code quality. To address these challenges, we need a more structured and type-safe approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Solution: TypeScript and Zod&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;TypeScript:&lt;/strong&gt; By adopting TypeScript, we can introduce strong typing to our codebase. This ensures that data structures are defined precisely, reducing the likelihood of runtime errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zod:&lt;/strong&gt; Zod is a powerful schema validation library for TypeScript. It allows us to define the structure and validation rules for our data. This ensures that data entering our application adheres to the expected format, preventing invalid input from reaching the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;API Requests with Tanstack Query&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Tanstack Query is a popular library for managing asynchronous data fetching in React applications. It provides features like caching, invalidation, and query management, making it ideal for handling API requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Centralized API Management with Zodios&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To maintain a consistent approach to API interactions, we can use Zodios. It acts as a factory for creating API query functions based on specified parameters. This allows us to centralize common logic, such as middleware, interceptors, and error handling, in one place.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Asynchronous Events and State Management in React&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In React, asynchronous operations are typically handled using state management mechanisms. Instead of using traditional event-based callbacks, we watch for changes in the state to trigger updates in the UI. This approach ensures a more declarative and predictable way of handling asynchronous data.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Query Key Invalidation and Caching&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Tanstack Query introduces the concept of query keys. These keys are used to identify cached responses. By invalidating query keys, we can trigger refetches of data when necessary, ensuring that our application always displays the most up-to-date information.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The &lt;code&gt;api-def&lt;/code&gt; Package&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To encapsulate the API-related logic and definitions, we can create a separate package named &lt;code&gt;api-def&lt;/code&gt;. This package will contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API keys:&lt;/strong&gt; Unique identifiers for different API endpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API methods:&lt;/strong&gt; Functions that define how to interact with the corresponding API endpoints, including request parameters, response handling, and error management.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to &lt;a href="https://www.linkedin.com/in/tim-hazlett-02aa95190" rel="noopener noreferrer"&gt;Tim Hazlett&lt;/a&gt; who proposed and bootstrapped the api-def layer. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By adopting TypeScript, Zod, Tanstack Query, and Zodios, we can create a robust and maintainable API layer for our React applications. This approach ensures type safety, efficient data management, and a centralized approach to API interactions, leading to improved code quality and reduced errors.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>typescript</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Building a Solid Foundation: Bootstrapping with Turbo Repo</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Mon, 02 Sep 2024 20:01:14 +0000</pubDate>
      <link>https://dev.to/santhanam87/building-a-solid-foundation-bootstrapping-with-turbo-repo-29mm</link>
      <guid>https://dev.to/santhanam87/building-a-solid-foundation-bootstrapping-with-turbo-repo-29mm</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In today's complex web applications, creating a well-organized and maintainable codebase is crucial. Enter Turbo Repo, a powerful tool that streamlines project management and accelerates build times for JavaScript and TypeScript projects. This post will guide you through bootstrapping a robust front-end ecosystem using Turbo Repo. We'll establish the foundation for your application by setting up the folder structure, enabling inter-package connectivity, and ensuring a clean environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting Up a Solid Structure&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Turbo Repo Initialization:&lt;/strong&gt;  We'll follow the official Turbo Repo getting started guide for a smooth setup: &lt;a href="https://turbo.build/repo/docs/getting-started/installation" rel="noopener noreferrer"&gt;Link to Turbo Repo getting started documentation&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web App Refactoring and Cleanup:&lt;/strong&gt;  The default Turbo Repo setup includes a landing page and associated assets. Since these are unnecessary for our project, we'll remove them, leaving a clean &lt;code&gt;src&lt;/code&gt; folder.  To establish a consistent styling foundation, we'll incorporate a global CSS reset using Meyerweb's handy reset tool: &lt;a href="https://meyerweb.com/eric/tools/css/reset/" rel="noopener noreferrer"&gt;Link to Meyerweb CSS reset&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Introducing the &lt;code&gt;api-definition&lt;/code&gt; Package:&lt;/strong&gt;  Next, we'll introduce a new package named &lt;code&gt;api-definition&lt;/code&gt; within &lt;code&gt;package.json&lt;/code&gt;. This package will act as the central hub for defining all our API request structures, ensuring consistency and maintainability. We'll delve deeper into its functionalities in the next post.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UI Package Setup:&lt;/strong&gt;  The default setup includes a UI library package named &lt;code&gt;UI&lt;/code&gt;. We'll rename it to &lt;code&gt;ui-components&lt;/code&gt; and remove any unnecessary sample components.  An &lt;code&gt;index&lt;/code&gt; file will be added to the &lt;code&gt;src&lt;/code&gt; folder to export all essential UI components.  Furthermore, we'll include the &lt;code&gt;api-def&lt;/code&gt; package as a dependency for &lt;code&gt;ui-components&lt;/code&gt;, given its extensive usage within the UI components themselves.  Finally, to streamline import paths within the package, we'll create a global alias name.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This post has established a solid foundation for your Turbo Repo project. We've set up the essential folder structure, configured inter-package connectivity, ensured a clean environment, and introduced the &lt;code&gt;api-definition&lt;/code&gt; package.  In the next post, we'll delve deeper into setting up and utilizing this crucial package – the backbone of well-defined API interactions within your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Throughout this process, we've referred to existing configuration files like &lt;code&gt;tsconfig.json&lt;/code&gt; and &lt;code&gt;.eslintrc.js&lt;/code&gt; for clarity. The code snippets for these files are intentionally omitted to avoid overloading this post. However, future posts may provide detailed explanations of these configurations for a comprehensive understanding.&lt;/p&gt;

&lt;p&gt;By following these steps and exploring the functionalities of Turbo Repo, you'll be well on your way to developing a robust and well-structured front-end ecosystem. Stay tuned for the next post where we'll dive into the &lt;code&gt;api-definition&lt;/code&gt; package!&lt;/p&gt;

&lt;p&gt;Below is the implementation Pull Request:&lt;br&gt;
&lt;a href="https://github.com/santhanam87/react-jam-stack/pull/1" rel="noopener noreferrer"&gt;https://github.com/santhanam87/react-jam-stack/pull/1&lt;/a&gt;&lt;/p&gt;

</description>
      <category>monorepo</category>
      <category>vercel</category>
      <category>turborepo</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Introducing: A Frontend Architect's Journey</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Sun, 01 Sep 2024 01:19:07 +0000</pubDate>
      <link>https://dev.to/santhanam87/introducing-a-frontend-architects-journey-51fc</link>
      <guid>https://dev.to/santhanam87/introducing-a-frontend-architects-journey-51fc</guid>
      <description>&lt;p&gt;&lt;strong&gt;Welcome to my blog!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm excited to share my experiences and insights as a Frontend Architect at my current company. In this series, I'll delve into the challenges, triumphs, and lessons learned while building a robust frontend ecosystem for our flagship product.&lt;/p&gt;

&lt;p&gt;One of the most significant challenges I've faced in this role has been &lt;strong&gt;balancing the need for innovation with the constraints of an established enterprise application&lt;/strong&gt;. As a frontend architect, I'm tasked with modernizing our technology stack and improving developer productivity, while also ensuring that our application meets the stringent requirements of our business. &lt;/p&gt;

&lt;p&gt;This has often meant striking a delicate balance between adopting cutting-edge technologies and maintaining compatibility with existing systems. Additionally, I've had to navigate the complexities of working with large, distributed teams and coordinating efforts across multiple geographical locations.&lt;/p&gt;

&lt;p&gt;Despite these challenges, I've found this role incredibly rewarding. I've had the opportunity to work with talented developers, solve complex technical problems, and contribute to the success of our organization. &lt;/p&gt;

&lt;p&gt;In the coming weeks and months, I'll be sharing more details about the specific challenges I've encountered, as well as the strategies I've used to overcome them. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Technology Stack Selection: A Balancing Act</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Sun, 01 Sep 2024 01:17:27 +0000</pubDate>
      <link>https://dev.to/santhanam87/technology-stack-selection-a-balancing-act-45gi</link>
      <guid>https://dev.to/santhanam87/technology-stack-selection-a-balancing-act-45gi</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this post, I'll discuss the factors that influenced our decision to choose Next.js as the primary framework for our frontend ecosystem. Given the limitations of the legacy system, it was essential to select a framework that could address our specific needs and challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Considerations&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before making a decision, we carefully considered the following factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; We needed a framework that could handle large-scale applications without sacrificing performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community support:&lt;/strong&gt; A strong community ensures access to resources, libraries, and solutions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modularity:&lt;/strong&gt; We wanted a framework that allowed us to include necessary libraries on-demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid approach:&lt;/strong&gt; We sought a framework that supported both server-side rendering (SSR) and client-side rendering (CSR).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typesafety:&lt;/strong&gt; We prioritized a framework that enforced strong typing to prevent errors and improve maintainability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API contracts:&lt;/strong&gt; We needed a way to define clear API contracts between the frontend and backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing:&lt;/strong&gt; We wanted a framework that supported unit testing and other testing methodologies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; Comprehensive documentation is essential for knowledge sharing and onboarding new team members.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Next.js?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After careful evaluation, we decided to go with Next.js for the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSR and CSR:&lt;/strong&gt; Next.js provides a flexible environment for combining SSR and CSR, allowing us to optimize performance based on specific use cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in API server:&lt;/strong&gt; The built-in API server simplifies the development process and provides a convenient way to mock data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static site generation:&lt;/strong&gt; Next.js generates pre-rendered static pages, improving initial load times and SEO.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; The framework's modular architecture makes it easier to scale the application as needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;TypeScript and Typesafety&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To ensure strong typing and prevent errors, we enforced the use of TypeScript as our primary coding language. TypeScript provides static type checking during the build process, helping to identify potential issues early on.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;API Management&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We used Tanstack Query, Zod, and Zodios to manage API requests, responses, and validation. Additionally, we leveraged OpenAPI specifications to generate types for our APIs, ensuring consistency between the frontend and backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Unit Testing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While we initially considered Vitest, we ultimately chose Jest with React Testing Library (RTL) for unit testing. Although we didn't achieve 100% code coverage, we aimed for at least 80% to ensure adequate test coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Documentation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To avoid the documentation challenges of the legacy system, we planned to create extensive documentation covering key implementations and processes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By carefully considering our requirements and evaluating available options, we selected Next.js as the ideal framework for our frontend ecosystem. In the next post, I'll discuss the process of bootstrapping the application with a GitHub repository.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>typescript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Laying the Foundation: Bootstrapping a New Frontend Ecosystem</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Sun, 01 Sep 2024 01:15:37 +0000</pubDate>
      <link>https://dev.to/santhanam87/laying-the-foundation-bootstrapping-a-new-frontend-ecosystem-3k21</link>
      <guid>https://dev.to/santhanam87/laying-the-foundation-bootstrapping-a-new-frontend-ecosystem-3k21</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this post, I'll delve into my initial task: bootstrapping the application with a robust frontend ecosystem. Given the challenges of the legacy system, my goal was to establish a more efficient and maintainable development environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Legacy Landscape&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The legacy system, built on Angular 1.x, suffered from several critical issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inflexible component library:&lt;/strong&gt; The existing component library, xLib, was difficult to modify or extend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lack of API contracts:&lt;/strong&gt; Frontend and backend communication was inconsistent and error-prone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inconsistent design:&lt;/strong&gt; The absence of design standards led to a fragmented and visually unappealing interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lack of typesafety:&lt;/strong&gt; Untyped data access made it difficult to prevent errors and ensure data integrity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited design patterns:&lt;/strong&gt; The development team was constrained by legacy design decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Absence of testing:&lt;/strong&gt; No unit or end-to-end tests were in place.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A Process-Oriented Approach&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To address these challenges, we adopted a process-oriented approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Standardized design:&lt;/strong&gt; We implemented a design system with predefined templates to ensure consistency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component-based development:&lt;/strong&gt; We created a reusable component library to streamline development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turbo monorepo:&lt;/strong&gt; We used a monorepo structure to manage our project and its dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js and TypeScript:&lt;/strong&gt; We chose Next.js for its server-side rendering capabilities and TypeScript for strong typing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Additional libraries:&lt;/strong&gt; We selected Tanstack Query for data fetching, React Hook Form for form handling, Zod for schema validation, and Voided for error handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Building a Reusable Component Library&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rather than building the entire component library at once, I focused on creating a complete profile screen with mock data. This approach allowed me to identify the essential components needed for the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bootstrapping the Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To provide a solid foundation for future development, I bootstrapped the application using a Turbo monorepo. This structure allowed us to organize our code into separate packages, including the component library and the main application.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By carefully considering the legacy system's limitations and adopting a process-oriented approach, we were able to establish a more efficient and maintainable frontend ecosystem. In the next post, I'll discuss the reasons behind our choice of Next.js and other key libraries.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>Beyond the Code: A Guide to Effective Code Reviews as a Front-End Engineer</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Wed, 17 Apr 2024 00:02:58 +0000</pubDate>
      <link>https://dev.to/santhanam87/from-functionality-to-finesse-mastering-code-reviews-for-front-end-developers-2ko7</link>
      <guid>https://dev.to/santhanam87/from-functionality-to-finesse-mastering-code-reviews-for-front-end-developers-2ko7</guid>
      <description>&lt;h2&gt;
  
  
  Beyond the Code: A Guide to Effective Code Reviews as a Front-End Engineer
&lt;/h2&gt;

&lt;p&gt;Code review is a cornerstone of software development, and as an experienced front-end engineer, you understand it's more than just checking for syntax errors. It's a collaborative effort to ensure clean, maintainable, and well-structured code. Here's a breakdown of my approach to code reviews, focusing on both general aspects and front-end specific considerations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting the Stage for Success&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before hitting that "submit PR" button, I make sure my code is deployment-ready. This involves running tasks like linting, testing, and building locally. This proactive approach minimizes the chances of your PR getting rejected due to basic issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;General Code Review Principles&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Business Requirements:&lt;/strong&gt; Every PR should demonstrably fulfill a specific business need. New features, especially, require clear alignment with core functionalities. Missing functionality triggers a change request to ensure proper coverage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beyond Requirements:&lt;/strong&gt;  While requirements are crucial, consider additional factors that enhance user experience. These might include internationalization, feature access controls, informative help text, progress bars, and well-crafted alert messages. These elements, while not explicitly stated, contribute to a polished user experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Naming Conventions:&lt;/strong&gt; Readable code is self-explanatory. Meaningful variable names act like a mini-narrative, eliminating the need for lengthy comments. If the programmer grasps their code's purpose, the variable names should reflect that intention.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency is Key:&lt;/strong&gt; When building similar screens with minor variations, I recommend enforcing a common pattern to streamline the development flow. This promotes predictability and makes variations readily apparent during review. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Cases and Coverage:&lt;/strong&gt;  While achieving 100% coverage can be tempting, it's essential to consider edge cases and ensure they're adequately addressed in your tests. Aim to think critically about potential corner cases and write tests that effectively handle them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Double-Edged Sword of Reusability:&lt;/strong&gt;  Reusability is valuable, promoting abstraction and modularity. However, over-abstraction can create complex layers that become difficult to maintain in the long run. I strive for a balance, considering both the "why not reuse" and "why reuse" arguments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constants in their Place:&lt;/strong&gt;  Proper placement and definition of constants are essential. This ensures consistency and maintainability throughout the codebase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Front-End Specific Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Holy Trinity:&lt;/strong&gt; As a front-end engineer, a well-structured PR should present the code in three distinct parts: HTML, CSS, and JavaScript (or TypeScript).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Valid HTML:&lt;/strong&gt; While I may not be overly stringent on specific markup standards, there are certain practices to avoid.  Examples include nesting divs within anchor tags or adding inline &lt;code&gt;onclick&lt;/code&gt; events to paragraph tags. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS - There's No Silver Bullet:&lt;/strong&gt;  CSS offers multiple paths to achieving the same layout. However, practices like using tag selectors excessively, non-standard ID-based selectors, or overriding library CSS classes are generally discouraged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript Efficiency:&lt;/strong&gt;  Nested loops can be performance bottlenecks. If unavoidable, ensure they are optimized and called only when necessary. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Transformation Magic:&lt;/strong&gt;  When dealing with large datasets for searching, filtering, or other transformations, consider creating JavaScript object mappings for future reference. This improves code readability and maintainability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pixel Perfection:&lt;/strong&gt;  A keen eye for layout is essential. Even minor inconsistencies can disrupt the user experience.  If I notice such issues, I'll clearly communicate them to the reviewer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typescript Power:&lt;/strong&gt;  In today's world, TypeScript reigns supreme. I avoid using &lt;code&gt;any&lt;/code&gt; or &lt;code&gt;unknown&lt;/code&gt; types at all costs. Their presence often indicates hidden complexities within the code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Providing Constructive Feedback&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Focus on Functionality:&lt;/strong&gt;  If the core functionality is implemented correctly, I'll typically approve the PR with comments outlining any desired changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Positive Reinforcement:&lt;/strong&gt;  Harsh criticism is counterproductive. I focus on providing clear and actionable feedback that fosters a collaborative environment. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pair Programming for the Win:&lt;/strong&gt;  For complex issues, I suggest pair programming sessions to address them efficiently in a single sitting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following these guidelines, you can approach code reviews not just as a task, but as an opportunity to improve code quality, maintainability, and foster a positive development culture within your team.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Beyond SPAs and SSR: Why a Hybrid Approach Might Be Your Web App's Perfect Match</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Tue, 16 Apr 2024 14:08:15 +0000</pubDate>
      <link>https://dev.to/santhanam87/beyond-spas-and-ssr-why-a-hybrid-approach-might-be-your-web-apps-perfect-match-2ijo</link>
      <guid>https://dev.to/santhanam87/beyond-spas-and-ssr-why-a-hybrid-approach-might-be-your-web-apps-perfect-match-2ijo</guid>
      <description>&lt;h2&gt;
  
  
  Not Quite SSR, Not Quite SPA: Why I Chose a Hybrid Approach
&lt;/h2&gt;

&lt;p&gt;Building a web application involves trade-offs. There's the classic Single Page Application (SPA) approach, where everything runs in the browser, and then there's Server-Side Rendering (SSR), where the server generates the entire HTML page. But what if neither quite fits your needs? That's where a hybrid approach can be a game-changer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data-Heavy Screens:&lt;/strong&gt; Multiple dropdowns pulling data on load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Content:&lt;/strong&gt; Help text and error messages that change based on user interaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual Support:&lt;/strong&gt; All text needs to be available in multiple languages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Menus:&lt;/strong&gt; Menu structure changes based on user roles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role-Based Features:&lt;/strong&gt; Feature availability depends on user permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large Menu List:&lt;/strong&gt; A massive menu dependent on various factors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Many Screens:&lt;/strong&gt; Around 200 profiles and other screens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Not Pure SPA?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An SPA could handle everything, but there's a catch: the initial wait. Holding users hostage while all the services load isn't ideal. Sure, we could try Suspense components, but things like dynamic menus and help text would keep the entire app in limbo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Not Pure SSR?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Lazy-loading could help with a pure SSR approach, but for an application size like mine, I wasn't sure how well it would scale. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enter the Hybrid Approach:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I wanted a lean structure that loads essential information on the server first, with the rest loading asynchronously. This lets me prepare pages with heavy data (cached on the server) and keep the initial load light.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diving Deeper: Benefits and Drawbacks of the Hybrid Approach
&lt;/h2&gt;

&lt;p&gt;We explored the high-level advantages and disadvantages of a hybrid approach for web development. Now, let's delve deeper into each point:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lean Page Size &amp;amp; Faster Initial Load:&lt;/strong&gt;  Hybrid apps leverage the server to pre-render pages with essential data. This means less code for the browser to download initially, resulting in a quicker first impression for your users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Does the Heavy Lifting:&lt;/strong&gt; Complex data processing and calculations can be handled on the server-side, freeing up the user's device for a smoother experience. This is especially beneficial for users with less powerful devices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deployment Unit Size Freedom:&lt;/strong&gt; Unlike pure SPAs where the entire application resides in the browser, the hybrid approach separates code. This allows for larger applications without worrying about exceeding deployment unit size limitations on some platforms.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hydration Hurdles:&lt;/strong&gt;  Hydration refers to the process of turning the initial server-rendered HTML into a fully interactive client-side application.  Hybrid apps can face challenges when hydrating dynamic data like dates or user-specific information. Extra steps might be needed to ensure a seamless transition from server-rendered content to fully interactive elements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dev Watch Mode Delays:&lt;/strong&gt;  Development environments often use watch modes to automatically recompile code changes. In a hybrid approach, this process can be slower because it might involve communication between the server and client-side code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global State Management Maze:&lt;/strong&gt;  Maintaining a consistent state across the entire application, especially for complex data, can be tricky in a hybrid approach. Different solutions might be needed for server-side and client-side state management, adding complexity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tunneling Troubles:&lt;/strong&gt;  If your internal services (APIs) are separate from the application server, accessing them might require network tunneling during development and testing. This can introduce additional configuration steps and potential security considerations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Remember:&lt;/strong&gt; The hybrid approach isn't a one-size-fits-all solution. Carefully weigh the benefits and drawbacks against your specific project requirements before taking the plunge.&lt;/p&gt;

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

&lt;p&gt;Going hybrid is a bold move. My advice? Keep your application flexible enough to transition to a full SPA as a backup plan. With this compatibility in mind, you have the freedom to explore ways to improve your application's core functionalities within the hybrid approach.&lt;/p&gt;

&lt;p&gt;By considering both the advantages and challenges, you can decide if a hybrid approach might be the perfect fit for your next web application project.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>New Tech Job? Hit the Ground Running with These First-Week Wins</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Mon, 15 Apr 2024 01:28:14 +0000</pubDate>
      <link>https://dev.to/santhanam87/new-tech-job-hit-the-ground-running-with-these-first-week-wins-3f13</link>
      <guid>https://dev.to/santhanam87/new-tech-job-hit-the-ground-running-with-these-first-week-wins-3f13</guid>
      <description>&lt;h2&gt;
  
  
  Hitting the Ground Running: Your First Few Weeks at a New Tech Job
&lt;/h2&gt;

&lt;p&gt;So you've landed the new gig – congratulations! But before you settle in with a cup of coffee and contemplate your desk chair feng shui, there are some key actions you can take to make a positive impact right away. Here are some tips I've learned to &lt;strong&gt;launch yourself&lt;/strong&gt; into a successful career path at your new tech company:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proactive Power Plays:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Be a Code Crusader:&lt;/strong&gt; Dive into code reviews! Don't just identify issues; suggest improvements that enhance the codebase. This showcases your technical skills and problem-solving abilities. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expectation Excavation:&lt;/strong&gt;  Get clear on your role expectations. Understand your responsibilities and how your work contributes to the bigger picture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quick Contribution Quest:&lt;/strong&gt; Assess the codebase and see where you can jump in and contribute – even small fixes demonstrate your understanding and willingness to help.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation Dynamo:&lt;/strong&gt;  Become a documentation champion! Start documenting processes, systems, and code. Clear documentation is invaluable for you and your team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Time Traveler:&lt;/strong&gt;  Get acquainted with the development tools and frameworks used by the team. Aim to reach a level where you can make your first contribution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project Management Master:&lt;/strong&gt;  Learn the project management tools used by the team and keep your assigned tasks updated. This demonstrates organization and accountability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Polishing Your Pull Requests:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code Chameleon:&lt;/strong&gt; When making your first pull request (code change submission), ensure it adheres to the existing code style. This includes code flow, variable naming conventions, and overall formatting. Consistency is key!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Building Confidence:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Work for You, Not Them:&lt;/strong&gt; Focus on your own development and learning. Don't get caught up in office politics or trying to please everyone. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stand Up for Your Code (Respectfully):&lt;/strong&gt;  Be prepared to defend your code during code reviews. Explain your decisions and be open to feedback. Remember, respect goes both ways.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Staying Aware:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep Your Ears to the Ground:&lt;/strong&gt;  Pay attention to what's happening around you. If you feel like you're being neglected, speak up politely to understand the situation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What &lt;em&gt;Not&lt;/em&gt; to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Forced Friendliness:&lt;/strong&gt;  Don't try to be best friends with everyone immediately. Genuine connections take time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trust Your Gut:&lt;/strong&gt;  While respecting others, trust your instincts about situations and colleagues. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settling In is Settling Out:&lt;/strong&gt;  &lt;a href="https://dev.to/santhanam87/new-job-heres-your-first-3-week-action-plan-n4g"&gt;Don't waste time getting comfortable. Take initiative and start contributing from day one.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Question Quandary:&lt;/strong&gt;  Do your research before asking questions. This shows you've put in the effort to learn independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Judgement Calls:&lt;/strong&gt;  Observe your colleagues, don't judge them. Focus on understanding team dynamics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Blame Game:&lt;/strong&gt;  If a task isn't yours, don't shy away from clarifying that. Be upfront about your responsibilities. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bragging Rights:&lt;/strong&gt;  Avoid boasting about your skills.  Let your work speak for itself. Build your momentum steadily.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Final Word: Resilience is Key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Remember, nothing is permanent.  Prepare yourself for unexpected situations.  This is just one step in your career journey. There will be other opportunities, so don't give up!&lt;/p&gt;

&lt;p&gt;By following these tips and staying focused, you can make a fantastic first impression and set yourself on the path to success in your new tech role.  &lt;/p&gt;

</description>
      <category>onboarding</category>
      <category>techjob</category>
      <category>careeradvice</category>
    </item>
    <item>
      <title>New Job? Here's Your First 3-Week Action Plan</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Mon, 15 Apr 2024 00:13:10 +0000</pubDate>
      <link>https://dev.to/santhanam87/new-job-heres-your-first-3-week-action-plan-n4g</link>
      <guid>https://dev.to/santhanam87/new-job-heres-your-first-3-week-action-plan-n4g</guid>
      <description>&lt;h2&gt;
  
  
  The First Three Weeks:  Make Your Mark or Move On
&lt;/h2&gt;

&lt;p&gt;One of the toughest lessons I've learned recently? Don't waste time settling in at a new company.  The first three weeks are absolutely &lt;strong&gt;critical&lt;/strong&gt;.  Here's why:&lt;/p&gt;

&lt;p&gt;During this initial period, you have the opportunity to establish yourself as a &lt;strong&gt;superhero&lt;/strong&gt;, an &lt;strong&gt;average contributor&lt;/strong&gt;, or someone who might not be the &lt;strong&gt;right fit&lt;/strong&gt; for the role. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The reality? If you can't land in the first two categories within those three weeks, it might be an uphill battle forever.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the honest recommendation:&lt;/strong&gt; Don't waste those precious first weeks! Be &lt;strong&gt;proactive&lt;/strong&gt; and make yourself as &lt;strong&gt;visible&lt;/strong&gt; as possible. &lt;/p&gt;

&lt;p&gt;Here are some ways to do that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Jump right in:&lt;/strong&gt; Ask questions, volunteer for projects, and show your eagerness to learn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network internally:&lt;/strong&gt; Meet your colleagues, understand their roles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't try to impress:&lt;/strong&gt; Don't show you are trying to impress, there is a difference between self promoting and self branding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliver early wins:&lt;/strong&gt; Look for opportunities to add immediate value, even if they seem small.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communicate effectively:&lt;/strong&gt; Keep your manager and team updated on your progress and ask for feedback. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;But what if you put in the hard work and still feel invisible?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;That's a sign you might need to consider if this is the right environment for you. Don't be afraid to have an honest conversation with your manager about your concerns. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember, your career path is yours to define. Don't be afraid to make the call that's best for you!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#careeradvice #newjob #firstimpressions&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>careeradvice</category>
      <category>newjob</category>
    </item>
    <item>
      <title>SSR vs SPA Showdown: Choosing the Right Rendering Approach for Your Web App</title>
      <dc:creator>Santhanam Elumalai</dc:creator>
      <pubDate>Fri, 12 Apr 2024 03:15:44 +0000</pubDate>
      <link>https://dev.to/santhanam87/ssr-vs-spa-showdown-choosing-the-right-rendering-approach-for-your-web-app-4439</link>
      <guid>https://dev.to/santhanam87/ssr-vs-spa-showdown-choosing-the-right-rendering-approach-for-your-web-app-4439</guid>
      <description>&lt;h2&gt;
  
  
  When to Choose SSR vs SPA
&lt;/h2&gt;

&lt;p&gt;Single Page Applications (SPAs) and Server-Side Rendering (SSR) are two titans in the web development world, each offering distinct advantages for building modern web experiences. But with great power comes a great choice: which one is right for your next project?&lt;/p&gt;

&lt;p&gt;This blog cuts through the jargon to help you pick the perfect rendering approach based on your specific needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  In the Corner of Content King: Enter SSR
&lt;/h3&gt;

&lt;p&gt;SSR shines when content reigns supreme. Here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SEO Champion:&lt;/strong&gt;  Search engines love pre-rendered HTML, and that's exactly what SSR delivers. Your content is readily available for crawlers to understand and index, boosting your SEO potential.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Speedy Initial Load:&lt;/strong&gt;  Users see content instantly, thanks to the server sending a fully-formed HTML page. This is especially crucial for users on slower connections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accessibility All-Star:&lt;/strong&gt;  SSR ensures your app is accessible to everyone, even those with JavaScript disabled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Social Sharing Savior:&lt;/strong&gt;  Sharing your app on social media is a breeze with SSR. The full content is there for platforms to preview, unlike SPAs that might show a blank page initially.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prime use cases for SSR include:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;E-commerce websites&lt;/li&gt;
&lt;li&gt;Blogs and news sites&lt;/li&gt;
&lt;li&gt;Marketing landing pages&lt;/li&gt;
&lt;li&gt;SEO-focused applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The SPA: Dynamic Dance Partner
&lt;/h3&gt;

&lt;p&gt;SPAs excel at creating dynamic and interactive user experiences. Here's how:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single Page Bliss:&lt;/strong&gt;  The user sees a single page throughout their interaction, leading to a smooth and seamless feel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Offline Functionality (maybe):&lt;/strong&gt;  With clever caching strategies, SPAs can potentially function even without an internet connection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-time Magic:&lt;/strong&gt;  SPAs can provide a more dynamic and real-time user experience, perfect for applications like chat or collaborative tools.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;SPAs are a great choice for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single-purpose web applications&lt;/li&gt;
&lt;li&gt;Dashboards and data visualization tools&lt;/li&gt;
&lt;li&gt;Social media platforms&lt;/li&gt;
&lt;li&gt;Real-time chat applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Champion You Choose
&lt;/h3&gt;

&lt;p&gt;So, which rendering approach wins? It depends! Here's a quick cheat sheet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Need top-notch SEO and fast initial load? Go SSR.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prioritizing a seamless, dynamic user experience? Choose SPA.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enter the Hybrid Hero: Combining the Best of Both Worlds
&lt;/h3&gt;

&lt;p&gt;The good news is, you're not limited to just one approach. Many frameworks, like Next.js and Nuxt.js, allow for a hybrid solution, where you leverage the strengths of both SSR and SPA. This can be particularly useful for content-heavy applications that also require a high degree of interactivity.&lt;/p&gt;

&lt;p&gt;Here's how a hybrid approach works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strategic SSR:&lt;/strong&gt;  Use SSR for critical pages or initial content loads to ensure SEO and fast initial rendering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SPA for Interaction:&lt;/strong&gt;  Once the initial content is loaded, switch to SPA mode for a smooth and dynamic user experience on subsequent interactions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach gives you the best of both worlds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Excellent SEO:&lt;/strong&gt;  Search engines can easily index your content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast Initial Load:&lt;/strong&gt;  Users see content quickly, even on slower connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seamless User Experience:&lt;/strong&gt;  The application feels smooth and responsive after the initial load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Consider a hybrid approach if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a content-heavy application with SEO requirements.&lt;/li&gt;
&lt;li&gt;Your application needs to be highly interactive after the initial load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By understanding the strengths and weaknesses of SSR, SPA, and the hybrid approach, you can make an informed decision about the best way to build your next web application. Remember, the ultimate goal is to create a user experience that is both functional and delightful.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
