<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Shahmir Faisal - Web Developer]]></title><description><![CDATA[I am a web developer with experience in react, nextjs, node and express. I have experience creating web apps from scratch as well as refactoring existing ones. I enjoy learning new technologies.]]></description><link>https://blog.shahmirfaisal.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 11:50:01 GMT</lastBuildDate><atom:link href="https://blog.shahmirfaisal.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The Power of a Standout Portfolio for Software Developers]]></title><description><![CDATA[In the fast-paced world of software development, where competition is fierce and innovation is key, having a standout portfolio is not just an advantage—it's a necessity. Your portfolio is more than a collection of projects; it's a visual narrative t...]]></description><link>https://blog.shahmirfaisal.com/the-power-of-a-standout-portfolio-for-software-developers</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/the-power-of-a-standout-portfolio-for-software-developers</guid><category><![CDATA[portfolio]]></category><category><![CDATA[portfoliowebsite]]></category><category><![CDATA[Portfolio Project]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Sun, 21 Jan 2024 12:56:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705840349391/23de576c-cc1e-4b56-a84b-0b9d61535a60.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the fast-paced world of software development, where competition is fierce and innovation is key, having a standout portfolio is not just an advantage—it's a necessity. Your portfolio is more than a collection of projects; it's a visual narrative that can leave a lasting impression on potential employers, collaborators, and clients. Here's how you can make your portfolio compelling and truly stand out:</p>
<h2 id="heading-crafting-a-visual-narrative">Crafting a Visual Narrative</h2>
<h3 id="heading-homepage-design">Homepage Design</h3>
<ul>
<li><p><strong>Eye-catching Introduction:</strong> Capture attention with a visually appealing homepage that provides a snapshot of your skills and experience.</p>
</li>
<li><p><strong>Testimonials:</strong> Consider featuring brief testimonials or endorsements from colleagues, clients, or mentors to build credibility.</p>
</li>
</ul>
<h3 id="heading-technology-highlights">Technology Highlights</h3>
<ul>
<li><p><strong>Skill Cloud:</strong> Showcase your proficiency in key technologies through an engaging visual representation, such as a skill cloud or tag cloud.</p>
</li>
<li><p><strong>Achievement Showcase:</strong> Highlight notable achievements and milestones prominently on your homepage.</p>
</li>
</ul>
<h3 id="heading-visual-appeal">Visual Appeal</h3>
<ul>
<li><p><strong>Interactive Elements:</strong> Incorporate interactive elements, such as animations or dynamic graphics, to enhance visual appeal and user engagement.</p>
</li>
<li><p><strong>Portfolio Timeline:</strong> Create a visual timeline showcasing the evolution of your skills and major projects over time.</p>
</li>
</ul>
<h2 id="heading-showcasing-diverse-projects">Showcasing Diverse Projects</h2>
<h3 id="heading-versatility-is-key">Versatility is Key</h3>
<ul>
<li><p><strong>Project Categories:</strong> Organize your projects into categories, highlighting diverse skills and areas of expertise.</p>
</li>
<li><p><strong>Impact Metrics:</strong> Include quantifiable metrics showcasing the impact of your projects, such as improved efficiency or increased user engagement.</p>
</li>
</ul>
<h3 id="heading-provide-context">Provide Context</h3>
<ul>
<li><p><strong>Problem-Solution Overview:</strong> Clearly articulate the problem each project aimed to solve and how your solution addressed it.</p>
</li>
<li><p><strong>User Stories:</strong> Integrate user stories or testimonials to provide a human perspective on the impact of your work.</p>
</li>
<li><p><strong>Project Challenges Blog:</strong> Dedicate a section to blog about the challenges faced in various projects and the innovative solutions implemented.</p>
</li>
</ul>
<h3 id="heading-visuals-matter">Visuals Matter</h3>
<ul>
<li><p><strong>Interactive Demos:</strong> If applicable, include interactive demos or walkthroughs to allow visitors to experience your projects firsthand.</p>
</li>
<li><p><strong>Before-and-After Visuals:</strong> Include visuals illustrating the challenges faced, emphasizing the transformation achieved through your solutions.</p>
</li>
</ul>
<h2 id="heading-highlighting-problem-solving-skills">Highlighting Problem-Solving Skills</h2>
<h3 id="heading-core-of-development">Core of Development</h3>
<ul>
<li><p><strong>Scenario-Based Solutions:</strong> Describe real-world scenarios where your problem-solving skills made a significant impact.</p>
</li>
<li><p><strong>Interactive Challenges:</strong> Integrate coding challenges or puzzles that demonstrate your approach to problem-solving.</p>
</li>
<li><p><strong>Problem-Solving Blog Series:</strong> Develop a blog series focusing on different aspects of problem-solving in software development.</p>
</li>
</ul>
<h3 id="heading-discuss-challenges">Discuss Challenges</h3>
<ul>
<li><p><strong>Technical Deep Dives:</strong> Provide in-depth technical analyses of specific challenges encountered in your projects and the innovative solutions devised.</p>
</li>
<li><p><strong>Lessons Learned Section:</strong> Dedicate a section to reflect on lessons learned from challenges and how they shaped your growth.</p>
</li>
</ul>
<h3 id="heading-case-studies">Case Studies</h3>
<ul>
<li><p><strong>In-Depth Analysis:</strong> Expand on specific projects with comprehensive case studies, detailing decision-making processes, challenges, and iterative improvements.</p>
</li>
<li><p><strong>Problem-Solving Frameworks:</strong> Illustrate the frameworks or methodologies you employ when tackling complex problems.</p>
</li>
</ul>
<h2 id="heading-providing-code-samples">Providing Code Samples</h2>
<h3 id="heading-transparency-through-code">Transparency Through Code</h3>
<ul>
<li><p><strong>GitHub Integration:</strong> Showcase your commitment to transparency by seamlessly integrating links to your GitHub repositories or specific code samples.</p>
</li>
<li><p><strong>Coding Style Guide:</strong> Provide a coding style guide within your portfolio, showcasing your commitment to clean and maintainable code.</p>
</li>
</ul>
<h3 id="heading-organized-code">Organized Code</h3>
<ul>
<li><p><strong>Code Documentation:</strong> Emphasize well-documented code with comments, explaining key sections and providing insights into your coding practices.</p>
</li>
<li><p><strong>Interactive Code Demos:</strong> Embed interactive code demos to allow visitors to explore your coding skills in real-time.</p>
</li>
</ul>
<h3 id="heading-github-contributions">GitHub Contributions</h3>
<ul>
<li><p><strong>Open Source Involvement:</strong> If relevant, highlight your contributions to open-source projects, demonstrating collaboration and community engagement.</p>
</li>
<li><p><strong>Code Review Highlights:</strong> Showcase instances where you contributed to or received positive feedback on code reviews.</p>
</li>
</ul>
<h2 id="heading-incorporating-feedback-and-iteration">Incorporating Feedback and Iteration</h2>
<h3 id="heading-dynamic-portfolio">Dynamic Portfolio</h3>
<ul>
<li><p><strong>Evolution Timeline:</strong> Showcase the evolution of your skills and projects over time, emphasizing continuous learning and improvement.</p>
</li>
<li><p><strong>Feedback Integration:</strong> Feature instances where you received feedback and how you incorporated it into your work, demonstrating adaptability.</p>
</li>
</ul>
<h3 id="heading-show-growth">Show Growth</h3>
<ul>
<li><p><strong>Learning Journey Blog:</strong> Include a blog section discussing your learning journey, documenting challenges faced, and lessons learned.</p>
</li>
<li><p><strong>Continuous Improvement Metrics:</strong> Highlight metrics that demonstrate your commitment to continuous improvement, such as certifications, courses, or new skills acquired.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, a standout portfolio is not merely a compilation of projects; it's a holistic representation of your skills, problem-solving prowess, and growth as a developer. By incorporating testimonials, interactive elements, diverse project displays, and transparent code samples, you transform your portfolio into a compelling narrative that resonates with potential employers.</p>
<h2 id="heading-mydevpagehttpsmydevpage-create-a-portfolio-website-instantly"><a target="_blank" href="https://mydevpa.ge/">MyDevPage</a>: Create a Portfolio Website Instantly</h2>
<p><a target="_blank" href="https://mydevpa.ge/">MyDevPage</a> allows you to build a portfolio website in minutes. Focus on building great projects and enhancing your skills rather than wasting your time building a portfolio website from scratch or customizing expensive templates.</p>
<p>MyDevPage handles everything:</p>
<ul>
<li><p>Portfolio Creation</p>
</li>
<li><p>SEO</p>
</li>
<li><p>Analytics</p>
</li>
<li><p>Customization</p>
</li>
<li><p>Custom Domain</p>
</li>
<li><p>Contact Form</p>
</li>
</ul>
<p><img src="//images.ctfassets.net/vlpuprt2y2ne/RalPofpnXi1BMHbiMzhRE/48e605e0533cb0e5daeb85f06dbd007f/pawelzmarlak-2024-01-21T12_47_19.081Z.png" alt="My Dev Page" /></p>
]]></content:encoded></item><item><title><![CDATA[How to use Next.Js 14 Server Actions]]></title><description><![CDATA[Next.Js 14 has added a lot of cool features that make development so much easier like:

App Router

Server Actions

Route Handlers

Client and Server Components


In this article, we will be covering Server Actions.
What are Server Actions
A Server A...]]></description><link>https://blog.shahmirfaisal.com/how-to-use-next-js-14-server-actions</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/how-to-use-next-js-14-server-actions</guid><category><![CDATA[Next.js]]></category><category><![CDATA[nextjs 14]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Wed, 10 Jan 2024 08:58:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1704876038220/c19465f1-6cf6-4e08-8e4c-62ed14e9ed01.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Next.Js 14 has added a lot of cool features that make development so much easier like:</p>
<ul>
<li><p>App Router</p>
</li>
<li><p>Server Actions</p>
</li>
<li><p>Route Handlers</p>
</li>
<li><p>Client and Server Components</p>
</li>
</ul>
<p>In this article, we will be covering Server Actions.</p>
<h2 id="heading-what-are-server-actions">What are Server Actions</h2>
<p>A Server Action is simply an asynchronous function that runs on the server whenever a form is submitted. It allows you to run the code directly on the server. This way, you don't have to make a separate backend or API and don't need to send requests to the API. You can communicate with a database directly in a Server Action.</p>
<p>You can use it in both client and server components.</p>
<h2 id="heading-using-server-actions">Using Server Actions</h2>
<h3 id="heading-using-server-actions-in-server-components">Using Server Actions in Server Components</h3>
<p>Simply make an asynchronous function inside a server component. Add the <strong>"use server"</strong> directive inside the function (at the top). Then attach an <strong>action</strong> property to the form element.</p>
<p>The Server Action receives a <strong>formData</strong> object as an argument that lets you access the values of the input fields. After this, you can perform validation and store information directly in a database. No need to create an API endpoint.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// server component</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Form = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> createPost = <span class="hljs-keyword">async</span> (formData) =&gt; {
    <span class="hljs-string">"use server"</span>
    <span class="hljs-keyword">const</span> title = formData.get(<span class="hljs-string">"title"</span>)
    <span class="hljs-keyword">const</span> description = formData.get(<span class="hljs-string">"description"</span>)

    <span class="hljs-comment">// store the post in the database directly</span>
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{createPost}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"title"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}
</code></pre>
<h3 id="heading-using-server-actions-in-client-components">Using Server Actions in Client Components</h3>
<p>Since a client component is rendered on the client, you cannot create Server Actions in a client component. But what you can do is, you can create a new file and add the <strong>use server</strong> directive at the top of the file. Now any function you create inside of that file will be considered a Server Action. Then you can import those Server Actions into a client component.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> createPost = <span class="hljs-keyword">async</span> (formData) =&gt; {
  <span class="hljs-keyword">const</span> title = formData.get(<span class="hljs-string">"title"</span>)
  <span class="hljs-keyword">const</span> description = formData.get(<span class="hljs-string">"description"</span>)

  <span class="hljs-comment">// store the post in the database directly</span>
}
</code></pre>
<p>Now you can import this Server Action in a client component.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// client component</span>
<span class="hljs-string">"use client"</span>

<span class="hljs-keyword">import</span> { createPost } <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Form = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{createPost}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"title"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}
</code></pre>
<h3 id="heading-showing-a-loading-state">Showing a Loading State</h3>
<p>Now you might be wondering, how can we show a loading state because the function is being executed on the server.</p>
<p>To do this you can create a separate client component for your button. Inside of this component, you can use the <strong>useFormStatus</strong> hook. It tells you whether the Server Action has finished executing or is still being executed.</p>
<p><strong>Note:</strong> You can only use the <strong>useFormStatus</strong> hook inside of a form. That's why you have to create a separate component for your button and place it inside the form.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use client"</span>

<span class="hljs-keyword">import</span> { useFormStatus } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Button = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> { pending } = useFormStatus()

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">{pending}</span>&gt;</span>
      {children} {pending &amp;&amp; "Loading..."}
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  )
}
</code></pre>
<p>Now we can use it inside the form.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// client component</span>
<span class="hljs-string">"use client"</span>

<span class="hljs-keyword">import</span> { createPost } <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'./Button'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Form = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{createPost}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"title"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}
</code></pre>
<h3 id="heading-handling-errors-and-success-state">Handling Errors and Success State</h3>
<p>Now to show errors and success messages to the user, we can make use of the <strong>useFormState</strong> hook. It accepts a <strong>Server Action</strong> and an <strong>Initial State</strong> as an argument. It returns the <strong>New State</strong> and <strong>a copy of the Server action</strong>.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// client component</span>
<span class="hljs-string">"use client"</span>

<span class="hljs-keyword">import</span> { createPost } <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'./Button'</span>
<span class="hljs-keyword">import</span> { useFormState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom"</span>
<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Form = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [createPostState, createPostAction] = useFormState(createPost, {
    <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>
  })

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (createPostState.success) {
      alert(<span class="hljs-string">"Post created!"</span>)
    }

    <span class="hljs-keyword">if</span> (createPostState.error) {
      alert(createPostState.error)
    }
  }, [createPostState])

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{createPostAction}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"title"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}
</code></pre>
<p>When using the <strong>useFormState</strong> hook. Your Server Action will receive an extra argument <strong>prevState</strong>. So you can modify your server action like this:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> createPost = <span class="hljs-keyword">async</span> (prevState, formData) =&gt; {
  <span class="hljs-keyword">const</span> title = formData.get(<span class="hljs-string">"title"</span>)
  <span class="hljs-keyword">const</span> description = formData.get(<span class="hljs-string">"description"</span>)

  <span class="hljs-keyword">if</span> (!title) {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">error</span>: <span class="hljs-string">"Enter the title!"</span>, <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span> }
  }

  <span class="hljs-keyword">if</span> (!description) {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">error</span>: <span class="hljs-string">"Enter the description!"</span>, <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span> }
  }

  <span class="hljs-comment">// store the post in the database directly</span>
  <span class="hljs-keyword">return</span> { <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>, <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span> }
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Server Actions in Next.Js 14 is an amazing feature. It makes development faster since you don't need a separate backend or API. From creating Server Actions to using them in different scenarios, this guide has provided a comprehensive overview of using Next.Js 14 Server Actions. To learn more about Next.Js 14 and Server Actions, read their official documentation.</p>
<ul>
<li><p><a target="_blank" href="https://nextjs.org/docs">Next.Js 14 Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations">Server Actions Documentation</a></p>
</li>
</ul>
<h2 id="heading-mydevpagehttpsmydevpage-create-a-portfolio-website-instantly"><a target="_blank" href="https://mydevpa.ge/">MyDevPage</a>: Create a Portfolio Website Instantly</h2>
<p><a target="_blank" href="https://mydevpa.ge/">MyDevPage</a> allows you to build a portfolio website in minutes. Focus on building great projects and enhancing your skills rather than wasting your time building a portfolio website from scratch or customizing expensive templates.</p>
<p>MyDevPage handles everything:</p>
<ul>
<li><p>Portfolio Creation</p>
</li>
<li><p>SEO</p>
</li>
<li><p>Analytics</p>
</li>
<li><p>Customization</p>
</li>
<li><p>Custom Domain</p>
</li>
<li><p>Contact Form</p>
</li>
</ul>
<p><img src="//images.ctfassets.net/vlpuprt2y2ne/6oOJjFtSMHjgeoNhDW1IOm/4a4cb3c8f946e7e8056c8ee122c406a4/image.png" alt="MyDevPa.ge" /></p>
]]></content:encoded></item><item><title><![CDATA[How to use Next.Js 14 with Supabase]]></title><description><![CDATA[Next.js provides a solid foundation for building React applications with server-side rendering, while Supabase offers a scalable and easy-to-use backend-as-a-service with PostgreSQL as the database.
Since the release of Next.js 13 and then Next.js 14...]]></description><link>https://blog.shahmirfaisal.com/how-to-use-next-14-with-supabase</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/how-to-use-next-14-with-supabase</guid><category><![CDATA[Next.js]]></category><category><![CDATA[supabase]]></category><category><![CDATA[nextjs 14]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Thu, 04 Jan 2024 13:40:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1704374609385/bf5e0046-8281-4c11-a7d0-ac18df686103.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Next.js provides a solid foundation for building React applications with server-side rendering, while Supabase offers a scalable and easy-to-use backend-as-a-service with PostgreSQL as the database.</p>
<p>Since the release of Next.js 13 and then Next.js 14, there have been a lot of changes. We now have the:</p>
<ul>
<li><p>App Router</p>
</li>
<li><p>Client and Server components</p>
</li>
<li><p>Route Handlers</p>
</li>
<li><p>Server Actions</p>
</li>
</ul>
<p>Combining these new features with Supabase will speed up the development process and will help you build things faster. So in this article, we will learn how to integrate Supabase with your Next.Js 14 project.</p>
<h2 id="heading-setting-up-a-nextjs-project">Setting up a Next.Js Project</h2>
<pre><code class="lang-powershell">npx create<span class="hljs-literal">-next</span><span class="hljs-literal">-app</span>@latest
</code></pre>
<p>On installation, you'll see the following prompts:</p>
<pre><code class="lang-powershell">What is your project named? my<span class="hljs-literal">-app</span>
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias (<span class="hljs-selector-tag">@</span>/*)? No / Yes
What import alias would you like configured? <span class="hljs-selector-tag">@</span>/*
</code></pre>
<p>After the prompts, create-next-app will create a folder with your project name and install the required dependencies.</p>
<h2 id="heading-using-supabase-in-the-project">Using Supabase in the Project</h2>
<p>Now to use Supabase in the project we have to follow the following steps:</p>
<h3 id="heading-installing-the-supabase-libraries">Installing the Supabase Libraries</h3>
<p>Next, we have to install the required libraries to work with Supabase.</p>
<pre><code class="lang-powershell">npm install @supabase/auth<span class="hljs-literal">-helpers</span><span class="hljs-literal">-nextjs</span> @supabase/supabase<span class="hljs-literal">-js</span>
</code></pre>
<h3 id="heading-setting-the-environment-variables">Setting the Environment Variables</h3>
<p>Create a new file named <strong>.env.local</strong> in the root of your project and paste your Supabase <strong>Project URL</strong> and <strong>Anon Key</strong>.</p>
<p>You can get this information by going to the supabase project dashboard then on the left side click settings and then click on API.</p>
<p><img src="//images.ctfassets.net/vlpuprt2y2ne/5f8gf8vtS3KVFrJ2bEJBY8/a3c3071b2ed642c142be785072a934d0/pawelzmarlak-2024-01-04T12_46_20.703Z.png" alt="Supabase URL and Anon Key" /></p>
<pre><code class="lang-javascript">NEXT_PUBLIC_SUPABASE_URL=PROJECT_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY=ANON_KEY
</code></pre>
<h3 id="heading-using-supabase-in-client-components">Using Supabase in Client Components</h3>
<p>To use Supabase in client components, call the <strong>createClientComponentClient</strong> function to create a Supabase client. You can then use this client to perform operations.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use client"</span>

<span class="hljs-keyword">import</span> { createClientComponentClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/auth-helpers-nextjs"</span>
<span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ClientComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> supabase = createClientComponentClient()
  <span class="hljs-keyword">const</span> [users, setUsers] = useState([])

  <span class="hljs-keyword">const</span> getUsers = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.from(<span class="hljs-string">"users"</span>).select(<span class="hljs-string">"*"</span>)
    setUsers(data)
  }

  useEffect(<span class="hljs-function">() =&gt;</span> {
    getUsers()
  }, [])

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>This is a client component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
}
</code></pre>
<h3 id="heading-using-supabase-in-server-components">Using Supabase in Server Components</h3>
<p>To use Supabase in server components, call the <strong>cookies</strong> function and then call the <strong>createServerComponentClient</strong> function and pass the cookies object to create a Supabase client. You can then use this client to perform operations.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createServerComponentClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/auth-helpers-nextjs"</span>
<span class="hljs-keyword">import</span> { cookies } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/headers"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ServerComponent = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> cookieStore = cookies()
  <span class="hljs-keyword">const</span> supabase = createServerComponentClient({
    <span class="hljs-attr">cookies</span>: <span class="hljs-function">() =&gt;</span> cookieStore
  })

  <span class="hljs-keyword">const</span> { data, error} = <span class="hljs-keyword">await</span> supabase.from(<span class="hljs-string">"users"</span>).select(<span class="hljs-string">"*"</span>);

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>This is a server component<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
}
</code></pre>
<h3 id="heading-using-supabase-in-server-actions">Using Supabase in Server Actions</h3>
<p>To use Supabase in server actions, call the <strong>createServerActionClient</strong> function and pass the <strong>cookies</strong> function to create a Supabase client. You can then use this client to perform operations.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createServerActionClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/auth-helpers-nextjs"</span>
<span class="hljs-keyword">import</span> { cookies } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/headers"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Form = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> addPost = <span class="hljs-keyword">async</span> (formData: FormData) =&gt; {
    <span class="hljs-string">"use server"</span>

    <span class="hljs-keyword">const</span> title = formData.get(<span class="hljs-string">"title"</span>) <span class="hljs-keyword">as</span> string
    <span class="hljs-keyword">const</span> description = formData.get(<span class="hljs-string">"description"</span>) <span class="hljs-keyword">as</span> string

    <span class="hljs-keyword">const</span> supabase = createServerActionClient({
      cookies
    })

    <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.from(<span class="hljs-string">"posts"</span>).insert({
      title,
      description
    })
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{addPost}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"title"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}
</code></pre>
<h3 id="heading-using-supabase-in-route-handlers">Using Supabase in Route Handlers</h3>
<p>To use Supabase in route handlers, call the <strong>cookies</strong> function and then call the <strong>createRouteHandlerClient</strong> function and pass the cookies object to create a Supabase client. You can then use this client to perform operations.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createRouteHandlerClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/auth-helpers-nextjs"</span>
<span class="hljs-keyword">import</span> { cookies } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/headers"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> GET = <span class="hljs-keyword">async</span> (request: Request) =&gt; {
  <span class="hljs-keyword">const</span> cookieStore = cookies()
  <span class="hljs-keyword">const</span> supabase = createRouteHandlerClient({ <span class="hljs-attr">cookies</span>: <span class="hljs-function">() =&gt;</span> cookieStore })

  <span class="hljs-keyword">const</span> { data, error} = <span class="hljs-keyword">await</span> supabase.from(<span class="hljs-string">"users"</span>).select(<span class="hljs-string">"*"</span>)

  <span class="hljs-keyword">return</span> Response.json(data)
}
</code></pre>
<h3 id="heading-supabase-authentication">Supabase Authentication</h3>
<p>Next, we will learn how to authenticate users and add authorization using Supabase.</p>
<h4 id="heading-creating-a-middleware">Creating a Middleware</h4>
<p>When using the Supabase client on the server, you must perform extra steps to ensure the user's auth session remains active. Since the user's session is tracked in a cookie, we need to read this cookie and update it if necessary.</p>
<p>Next.js Server Components allow us to read a cookie but not write back to it. Middleware on the other hand allows us to both read and write to cookies.</p>
<p>Create a new file named <strong>middleware.ts</strong> in the <strong>src</strong> folder (if you have one) or in the root of your project. And paste the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createMiddlewareClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/auth-helpers-nextjs'</span>
<span class="hljs-keyword">import</span> { NextResponse } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/server'</span>

<span class="hljs-keyword">import</span> type { NextRequest } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/server'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">middleware</span>(<span class="hljs-params">req: NextRequest</span>) </span>{
  <span class="hljs-keyword">const</span> res = NextResponse.next()

  <span class="hljs-keyword">const</span> supabase = createMiddlewareClient({ req, res })

  <span class="hljs-comment">// Refresh session if expired - required for Server Components</span>
  <span class="hljs-keyword">await</span> supabase.auth.getSession()

  <span class="hljs-keyword">return</span> res
}
</code></pre>
<h4 id="heading-api-route-for-code-exchange">API Route for Code Exchange</h4>
<p>Supabase requires us to set up a <strong>Code Exchange</strong> route, to exchange an auth code for the user's session, which is set as a cookie for future requests made to Supabase.</p>
<p>Create a new folder named <strong>auth</strong> inside the app folder, inside of this create another folder <strong>callback</strong> and then create a <strong>route.ts</strong> file and paste the following code</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createRouteHandlerClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/auth-helpers-nextjs"</span>
<span class="hljs-keyword">import</span> { cookies } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/headers"</span>
<span class="hljs-keyword">import</span> { NextResponse } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/server"</span>

<span class="hljs-keyword">import</span> type { NextRequest } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">GET</span>(<span class="hljs-params">request: NextRequest</span>) </span>{
  <span class="hljs-keyword">const</span> requestUrl = <span class="hljs-keyword">new</span> URL(request.url)
  <span class="hljs-keyword">const</span> code = requestUrl.searchParams.get(<span class="hljs-string">"code"</span>)

  <span class="hljs-keyword">if</span> (code) {
    <span class="hljs-keyword">const</span> cookieStore = cookies()
    <span class="hljs-keyword">const</span> supabase = createRouteHandlerClient({
      <span class="hljs-attr">cookies</span>: <span class="hljs-function">() =&gt;</span> cookieStore
    })
    <span class="hljs-keyword">await</span> supabase.auth.exchangeCodeForSession(code)
  }

  <span class="hljs-comment">// URL to redirect to after sign in process completes</span>
  <span class="hljs-keyword">return</span> NextResponse.redirect(<span class="hljs-string">`http://localhost:3000/`</span>)
}
</code></pre>
<h4 id="heading-sign-up-a-user">Sign Up a User</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createServerActionClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/auth-helpers-nextjs"</span>
<span class="hljs-keyword">import</span> { cookies } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/headers"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> SignUp = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> signUp = <span class="hljs-keyword">async</span> (formData: FormData) =&gt; {
    <span class="hljs-string">"use server"</span>

    <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">"name"</span>) <span class="hljs-keyword">as</span> string
    <span class="hljs-keyword">const</span> email = formData.get(<span class="hljs-string">"email"</span>) <span class="hljs-keyword">as</span> string
    <span class="hljs-keyword">const</span> password = formData.get(<span class="hljs-string">"password"</span>) <span class="hljs-keyword">as</span> string

    <span class="hljs-keyword">const</span> supabase = createServerActionClient({
      cookies
    })

    <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.auth.signUp({
      email,
      password,
      <span class="hljs-attr">options</span>: {
        <span class="hljs-attr">data</span>: {
          name
        },
        <span class="hljs-attr">emailRedirectTo</span>: <span class="hljs-string">`http://localhost:3000/auth/callback`</span>
      }
    })
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{signUp}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}
</code></pre>
<h4 id="heading-log-in-a-user">Log In a User</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createServerActionClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/auth-helpers-nextjs"</span>
<span class="hljs-keyword">import</span> { cookies } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/headers"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> LogIn = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> logIn = <span class="hljs-keyword">async</span> (formData: FormData) =&gt; {
    <span class="hljs-string">"use server"</span>

    <span class="hljs-keyword">const</span> email = formData.get(<span class="hljs-string">"email"</span>) <span class="hljs-keyword">as</span> string
    <span class="hljs-keyword">const</span> password = formData.get(<span class="hljs-string">"password"</span>) <span class="hljs-keyword">as</span> string

    <span class="hljs-keyword">const</span> supabase = createServerActionClient({
      cookies
    })

    <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.auth.signInWithPassword({
      email,
      password
    })
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{logIn}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}
</code></pre>
<h4 id="heading-log-out-a-user">Log Out a User</h4>
<pre><code class="lang-javascript"><span class="hljs-string">"use client"</span>

<span class="hljs-keyword">import</span> { createClientComponentClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/auth-helpers-nextjs"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> LogOut = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> supabase = createClientComponentClient()

  <span class="hljs-keyword">const</span> logOut = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">await</span> supabase.auth.signOut()
  }

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{logOut}</span>&gt;</span>LogOut<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
}
</code></pre>
<h4 id="heading-get-the-logged-in-user">Get the Logged In User</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createServerComponentClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/auth-helpers-nextjs"</span>
<span class="hljs-keyword">import</span> { cookies } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/headers"</span>
<span class="hljs-keyword">import</span> { redirect } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/navigation"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Profile = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> cookieStore = cookies()
  <span class="hljs-keyword">const</span> supabase = createServerComponentClient({
    <span class="hljs-attr">cookies</span>: <span class="hljs-function">() =&gt;</span> cookieStore
  })

  <span class="hljs-keyword">const</span> {
    <span class="hljs-attr">data</span>: { session }
  } = <span class="hljs-keyword">await</span> supabase.auth.getSession()  

  <span class="hljs-keyword">if</span> (!session) {
    redirect(<span class="hljs-string">"/login"</span>)
  }

  <span class="hljs-keyword">const</span> user = session.user

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>User Profile<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Next.Js 14 and Supabase is a powerful combination and it allows us to build things faster. From setting up a Next.js project to initializing the Supabase client, fetching data, and implementing user authentication, this guide has provided a comprehensive overview of using Supabase with Next.Js 14. To learn more about Next.Js 14 and Supabase, read their official documentation.</p>
<ul>
<li><p><a target="_blank" href="https://nextjs.org/docs">Next.Js 14 Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://supabase.com/docs/reference/javascript/introduction">Supabase Documentation</a></p>
</li>
</ul>
<h2 id="heading-mydevpagehttpsmydevpage-create-a-portfolio-website-in-minutes"><a target="_blank" href="https://mydevpa.ge/">MyDevPage</a>: Create a Portfolio Website in Minutes</h2>
<p><a target="_blank" href="https://mydevpa.ge/">MyDevPage</a> allows you to build a portfolio website in minutes. Focus on building great projects and enhancing your skills rather than wasting your time in building a portfolio website from scratch or customizing expensive templates.</p>
<p>MyDevPage handles everything:</p>
<ul>
<li><p>Creating a portfolio</p>
</li>
<li><p>SEO</p>
</li>
<li><p>Analytics</p>
</li>
<li><p>Customization</p>
</li>
<li><p>Custom Domain</p>
</li>
<li><p>Contact Form</p>
</li>
</ul>
<p><img src="//images.ctfassets.net/vlpuprt2y2ne/6oOJjFtSMHjgeoNhDW1IOm/4a4cb3c8f946e7e8056c8ee122c406a4/image.png" alt="MyDevPa.ge" /></p>
]]></content:encoded></item><item><title><![CDATA[How to send emails using Next.js 14, Resend and React-Email]]></title><description><![CDATA[Communication with your users is really important and emails are one of the means of communication. Sending emails is really important for applications. These are some of the reasons:

User Onboarding and Account Verification

Password Resets and Acc...]]></description><link>https://blog.shahmirfaisal.com/how-to-send-emails-using-next-14-resend-and-react-email</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/how-to-send-emails-using-next-14-resend-and-react-email</guid><category><![CDATA[Next.js]]></category><category><![CDATA[email marketing]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Tue, 19 Dec 2023 19:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1703930439671/9620b885-86ad-4aca-8cef-7bba8d921d28.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Communication with your users is really important and emails are one of the means of communication. Sending emails is really important for applications. These are some of the reasons:</p>
<ol>
<li><p>User Onboarding and Account Verification</p>
</li>
<li><p>Password Resets and Account Recovery</p>
</li>
<li><p>Notification and Alerts</p>
</li>
<li><p>Communication and Updates</p>
</li>
<li><p>Marketing and Promotions</p>
</li>
<li><p>Support and Customer Service</p>
</li>
</ol>
<p>In this article, we will dive into sending emails using Next.js 14, Resend and React-Email. We will leverage the latest Next.js features, such as the app directory and server actions.</p>
<h2 id="heading-setting-up-resend">Setting up Resend</h2>
<p>Before we can start using Resend in our app, first you have to create an account on <a target="_blank" href="https://resend.com">Resend</a>. After creating the account, you have to verify your domain name and the email address you will be using to send emails.<br />Once that's done, go to the <a target="_blank" href="https://resend.com/api-keys">API Keys</a> page and create a new api key.</p>
<p><img src="//images.ctfassets.net/vlpuprt2y2ne/7hMmozVIMnypwof8X1skPc/3f28a786b7553e054b8e3738436272f2/image.png" alt="Resend Api keys" /></p>
<p>Copy an existing API key or click <strong>Create Api Key</strong> to create a new one.</p>
<h2 id="heading-setting-up-your-nextjs-project">Setting Up Your Next.js Project</h2>
<pre><code class="lang-powershell">npx create<span class="hljs-literal">-next</span><span class="hljs-literal">-app</span>@latest
</code></pre>
<p>On installation, you'll see the following prompts:</p>
<pre><code class="lang-powershell">What is your project named? my<span class="hljs-literal">-app</span>
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias (<span class="hljs-selector-tag">@</span>/*)? No / Yes
What import alias would you like configured? <span class="hljs-selector-tag">@</span>/*
</code></pre>
<p>After the prompts, create-next-app will create a folder with your project name and install the required dependencies. Next, we have to install the packages for sending emails.</p>
<pre><code class="lang-powershell">npm i resend react<span class="hljs-literal">-email</span> @react<span class="hljs-literal">-email</span>/components @react<span class="hljs-literal">-email</span>/render
</code></pre>
<p>Let's talk about the packages we just installed:</p>
<ul>
<li><p><strong>resend:</strong> It is the service that we will be using to send emails</p>
</li>
<li><p><strong>react-email:</strong> It allows us to create email templates using React Js.</p>
</li>
<li><p><strong>@react-email/render:</strong> For converting react js based templates to an html string.</p>
</li>
</ul>
<h2 id="heading-creating-a-simple-form">Creating a Simple Form</h2>
<p>Let's now create a simple form where the user can enter his name, email and message. And when it is submitted we will send the detail to the entered email.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Form</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"name"</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"message"</span>&gt;</span>Message<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">cols</span>=<span class="hljs-string">{30}</span> <span class="hljs-attr">rows</span>=<span class="hljs-string">{10}</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Send<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}
</code></pre>
<h2 id="heading-creating-an-email-template">Creating an Email Template</h2>
<p>Now let's create an email template using React Js.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Html, Heading, Text } <span class="hljs-keyword">from</span> <span class="hljs-string">"@react-email/components"</span>
<span class="hljs-keyword">const</span> EmailTemplate = <span class="hljs-function">(<span class="hljs-params">{
  name,
  email,
  message
}: {
  name: string
  email: string
  message: string
}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h1"</span>&gt;</span>New Form Submission<span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>You just submitted a form. Here are the details:<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Name: {name}<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Email: {email}<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Message: {message}<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Html</span>&gt;</span></span>
  )
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> EmailTemplate
</code></pre>
<h2 id="heading-creating-server-action">Creating Server Action</h2>
<p>Server action is the latest feature of Next.js 14. It is an asynchronous function that runs on the server. We can use it to handle form submissions and to handle email logic on the server. So when you submit a form the function will start running on a server. In this case, you don't have to create API routes to handle any sensitive logic, like communicating with the database.<br />Create a file named <strong>actions.ts</strong> in the src folder (if you have) or the root of your project.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>
<span class="hljs-keyword">import</span> { Resend } <span class="hljs-keyword">from</span> <span class="hljs-string">"resend"</span>
<span class="hljs-keyword">import</span> EmailTemplate <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/EmailTemplate"</span>
interface State {
  <span class="hljs-attr">error</span>: string | <span class="hljs-literal">null</span>
  <span class="hljs-attr">success</span>: boolean
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> sendEmail = <span class="hljs-keyword">async</span> (prevState: State, <span class="hljs-attr">formData</span>: FormData) =&gt; {
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">"name"</span>) <span class="hljs-keyword">as</span> string
  <span class="hljs-keyword">const</span> email = formData.get(<span class="hljs-string">"email"</span>) <span class="hljs-keyword">as</span> string
  <span class="hljs-keyword">const</span> message = formData.get(<span class="hljs-string">"message"</span>) <span class="hljs-keyword">as</span> string
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> resend = <span class="hljs-keyword">new</span> Resend(process.env.RESEND_API_KEY)
    <span class="hljs-keyword">await</span> resend.emails.send({
      <span class="hljs-attr">from</span>: <span class="hljs-string">"Shahmir &lt;shahmir@mydevpa.ge&gt;"</span>,
      <span class="hljs-attr">to</span>: email,
      <span class="hljs-attr">subject</span>: <span class="hljs-string">"Form Submission"</span>,
      <span class="hljs-attr">react</span>: EmailTemplate({ name, email, message })
    })
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,
      <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>
    }
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error)
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">error</span>: (error <span class="hljs-keyword">as</span> <span class="hljs-built_in">Error</span>).message,
      <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>
    }
  }
}
</code></pre>
<p>Create a <strong>.env.local</strong> file in the root of your project and paste the Resend API key you created earlier.<br />The <strong>sendEmail</strong> function is a server action. It receives the <strong>previous state</strong> and the <strong>formData</strong>, that gives you access to the values of the form. Then it uses <strong>resend</strong> to send the email to the provided email address. In the <strong>from</strong> field, make sure to use an email that you verified on your Resend account.<br />In some cases, the <strong>react</strong> property might not work and you might receive an error while sending emails. In that case you can convert the React component into an HTML string.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>
<span class="hljs-keyword">import</span> { Resend } <span class="hljs-keyword">from</span> <span class="hljs-string">"resend"</span>
<span class="hljs-keyword">import</span> EmailTemplate <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/EmailTemplate"</span>
<span class="hljs-keyword">import</span> { render } <span class="hljs-keyword">from</span> <span class="hljs-string">"@react-email/render"</span>
interface State {
  <span class="hljs-attr">error</span>: string | <span class="hljs-literal">null</span>
  <span class="hljs-attr">success</span>: boolean
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> sendEmail = <span class="hljs-keyword">async</span> (prevState: State, <span class="hljs-attr">formData</span>: FormData) =&gt; {
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">"name"</span>) <span class="hljs-keyword">as</span> string
  <span class="hljs-keyword">const</span> email = formData.get(<span class="hljs-string">"email"</span>) <span class="hljs-keyword">as</span> string
  <span class="hljs-keyword">const</span> message = formData.get(<span class="hljs-string">"message"</span>) <span class="hljs-keyword">as</span> string
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> resend = <span class="hljs-keyword">new</span> Resend(process.env.RESEND_API_KEY)
    <span class="hljs-keyword">await</span> resend.emails.send({
      <span class="hljs-attr">from</span>: <span class="hljs-string">"Shahmir &lt;shahmir@mydevpa.ge&gt;"</span>,
      <span class="hljs-attr">to</span>: email,
      <span class="hljs-attr">subject</span>: <span class="hljs-string">"Form Submission"</span>,
      <span class="hljs-attr">html</span>: render(EmailTemplate({ name, email, message }))
    })
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,
      <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>
    }
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error)
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">error</span>: (error <span class="hljs-keyword">as</span> <span class="hljs-built_in">Error</span>).message,
      <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>
    }
  }
}
</code></pre>
<h2 id="heading-using-server-action-with-the-form">Using Server Action with the Form</h2>
<p>Now let's use the server action we created above with our form component.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use client"</span>
<span class="hljs-keyword">import</span> { sendEmail } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/actions"</span>
<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { useFormState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom"</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Form</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [sendEmailState, sendEmailAction] = useFormState(sendEmail, {
    <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>
  })
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (sendEmailState.success) {
      alert(<span class="hljs-string">"Email sent!"</span>)
    }
    <span class="hljs-keyword">if</span> (sendEmailState.error) {
      alert(<span class="hljs-string">"Error sending email!"</span>)
    }
  }, [sendEmailState])
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{sendEmailAction}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"name"</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"message"</span>&gt;</span>Message<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">cols</span>=<span class="hljs-string">{30}</span> <span class="hljs-attr">rows</span>=<span class="hljs-string">{10}</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Send<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}
</code></pre>
<p>We are using the <strong>useFormState</strong> hook. It accepts the action and the initial state and returns the new state and the action function that we can attach with our form.<br />In the end we added an <strong>action</strong> property to our form and gave it the server action function.<br />Now when you submit the form you should receive an email.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article aimed to help you quickly get started with sending emails. The Resend and React-Email libraries make it so easy to achieve this. To learn more about Resend and React-Email read their official documentation.</p>
<ul>
<li><p><a target="_blank" href="https://resend.com/docs/introduction">Resend Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://react.email/docs/introduction">React-Email Documentation</a></p>
</li>
</ul>
<h2 id="heading-mydevpagehttpmydevpage-create-a-portfolio-website-instantly"><a target="_blank" href="http://mydevpa.ge/">MyDevPage</a>: Create a Portfolio Website Instantly</h2>
<p><a target="_blank" href="http://MyDevPa.ge">MyDevPa.ge</a> allows you to build a portfolio website in minutes. Focus on building great projects and enhancing your skills rather than wasting your time in building a portfolio website from scratch or customizing expensive templates.<br /><a target="_blank" href="http://MyDevPa.ge">MyDevPa.ge</a> handles everything:</p>
<ul>
<li><p>Creating a portfolio</p>
</li>
<li><p>SEO</p>
</li>
<li><p>Analytics</p>
</li>
<li><p>Customization</p>
</li>
<li><p>Custom Domain</p>
</li>
<li><p>Contact Form</p>
</li>
</ul>
<p><img src="//images.ctfassets.net/vlpuprt2y2ne/6oOJjFtSMHjgeoNhDW1IOm/4a4cb3c8f946e7e8056c8ee122c406a4/image.png" alt="MyDevPa.ge" /></p>
]]></content:encoded></item><item><title><![CDATA[Singly Linked List - Data Structures and Algorithms in Javascript]]></title><description><![CDATA[This is our first article in the series of Data Structures and Algorithms. In this article, we will discuss the ins and outs of a Singly Linked List.
What is a Singly Linked List?
A Singly Linked List is a linear data structure that allows us to stor...]]></description><link>https://blog.shahmirfaisal.com/singly-linked-list-data-structures-and-algorithms-in-javascript</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/singly-linked-list-data-structures-and-algorithms-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[linked list]]></category><category><![CDATA[data structures]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Mon, 20 Nov 2023 07:42:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1700422199791/84ed1c5a-f761-4b57-93e9-661d067b0472.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is our first article in the series of <a target="_blank" href="https://blog.shahmirfaisal.com/series/data-structure-algorithm">Data Structures and Algorithms</a>. In this article, we will discuss the ins and outs of a Singly Linked List.</p>
<h1 id="heading-what-is-a-singly-linked-list">What is a Singly Linked List?</h1>
<p>A Singly Linked List is a linear data structure that allows us to store data in a linear way. It is a collection of nodes where each node points to the next node.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700385399671/1d700a18-10e0-4d05-b3b3-e0383be42590.png" alt="A Singly Linked List from VisuAlgo.net" class="image--center mx-auto" /></p>
<p>Every node contains two crucial things:</p>
<ol>
<li><p>Data (integer, string, boolean, etc)</p>
</li>
<li><p>Pointer (points to the next node)</p>
</li>
</ol>
<p>A singly linked list has two pointers of its own:</p>
<ol>
<li><p>head (points to the first node)</p>
</li>
<li><p>tail (points to the last node)</p>
</li>
</ol>
<p>The pointer of the last node always points to null since there is no node after it.</p>
<h1 id="heading-implementation-in-javascript">Implementation in Javascript</h1>
<p>Now that we know what is a singly linked list and what it looks like, let's code it using JavaScript. We will be using object-oriented programming to implement it and we will use the ES6 Class syntax.</p>
<p>We will need two classes:</p>
<ol>
<li><p>Node (represents the structure of the node)</p>
</li>
<li><p>SinglyLinkedList (represents the structure and also includes the major operations)</p>
</li>
</ol>
<h2 id="heading-node-class">Node Class</h2>
<p>As we discussed above, a node contains two things:</p>
<ul>
<li><p>Data (number, string, boolean, etc)</p>
</li>
<li><p>Pointer (points to the next node)</p>
</li>
</ul>
<p>The pointer initially points to null.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Node</span> </span>{
  <span class="hljs-keyword">constructor</span>(value) {
    <span class="hljs-built_in">this</span>.value = value
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>
  }
}
</code></pre>
<h2 id="heading-singly-linked-list-class">Singly Linked List Class</h2>
<p>A singly linked list will have:</p>
<ol>
<li><p>head pointer (points to the first node)</p>
</li>
<li><p>tail pointer (points to the last node)</p>
</li>
<li><p>length (number of nodes in the list)</p>
</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SinglyLinkedList</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>
    <span class="hljs-built_in">this</span>.length = <span class="hljs-number">0</span>
  }
}
</code></pre>
<h2 id="heading-basic-operations">Basic Operations</h2>
<p>A singly linked list can perform the following operations:</p>
<ul>
<li><p>push (insert at the end)</p>
</li>
<li><p>pop (remove from the end)</p>
</li>
<li><p>shift (remove from the start)</p>
</li>
<li><p>unshift (insert at the start)</p>
</li>
<li><p>get (get a node at a particular index)</p>
</li>
<li><p>set (change the value of a node at a particular index)</p>
</li>
<li><p>insert (insert at a particular index)</p>
</li>
<li><p>remove (remove from a particular index)</p>
</li>
</ul>
<p>Now we will implement all these operations into the SinglyLinkedList class.</p>
<h3 id="heading-push">Push</h3>
<p>Push will insert a new node at the end.</p>
<pre><code class="lang-javascript">  push(value) {
    <span class="hljs-keyword">const</span> node = <span class="hljs-keyword">new</span> Node(value)

    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.length) {
      <span class="hljs-built_in">this</span>.head = node
      <span class="hljs-built_in">this</span>.tail = node
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.tail.next = node
      <span class="hljs-built_in">this</span>.tail = node
    }
    <span class="hljs-built_in">this</span>.length++
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>
  }
</code></pre>
<h3 id="heading-pop">Pop</h3>
<p>Pop will remove a node from the end.</p>
<pre><code class="lang-javascript">  pop() {
    <span class="hljs-keyword">let</span> currentNode = <span class="hljs-built_in">this</span>.head
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.length &lt;= <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">while</span> (!currentNode?.next?.next) {
        currentNode = currentNode.next
      }
      currentNode.next = <span class="hljs-literal">null</span>
      <span class="hljs-built_in">this</span>.tail = currentNode
    }
    <span class="hljs-built_in">this</span>.length--
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>
  }
</code></pre>
<h3 id="heading-shift">Shift</h3>
<p>Shift will remove a node from the start.</p>
<pre><code class="lang-javascript">  shift() {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.length &lt;= <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-built_in">this</span>.head.next
    }
    <span class="hljs-built_in">this</span>.length--
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>
  }
</code></pre>
<h3 id="heading-unshift">Unshift</h3>
<p>Unshift will insert a new node at the start</p>
<pre><code class="lang-javascript">  unshift(value) {
    <span class="hljs-keyword">const</span> node = <span class="hljs-keyword">new</span> Node(value)
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.length) {
      <span class="hljs-built_in">this</span>.tail = node
    } <span class="hljs-keyword">else</span> {
      node.next = <span class="hljs-built_in">this</span>.head
    }
    <span class="hljs-built_in">this</span>.head = node

    <span class="hljs-built_in">this</span>.length++
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>
  }
</code></pre>
<h3 id="heading-get">Get</h3>
<p>Get a node's value from a particular index.</p>
<pre><code class="lang-javascript">  get(index) {
    <span class="hljs-keyword">if</span> (index &lt; <span class="hljs-number">0</span> || index &gt;= <span class="hljs-built_in">this</span>.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>
    <span class="hljs-keyword">let</span> currentNode = <span class="hljs-built_in">this</span>.head
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i &lt;= index; i++) {
      currentNode = currentNode.next
    }
    <span class="hljs-keyword">return</span> currentNode.value
  }
</code></pre>
<h3 id="heading-set">Set</h3>
<p>Change the node's value at a particular index.</p>
<pre><code class="lang-javascript">  set(index, value) {
    <span class="hljs-keyword">if</span> (index &lt; <span class="hljs-number">0</span> || index &gt;= <span class="hljs-built_in">this</span>.length) <span class="hljs-keyword">return</span>
    <span class="hljs-keyword">let</span> currentNode = <span class="hljs-built_in">this</span>.head
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i &lt;= index; i++) {
      currentNode = currentNode.next
    }
    currentNode.value = value
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>
  }
</code></pre>
<h3 id="heading-insert">Insert</h3>
<p>Insert a new node at a particular index.</p>
<pre><code class="lang-javascript">  insert(index, value) {
    <span class="hljs-keyword">if</span> (index &lt; <span class="hljs-number">0</span> || index &gt; <span class="hljs-built_in">this</span>.length) <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>
    <span class="hljs-keyword">const</span> node = <span class="hljs-keyword">new</span> Node(value)
    <span class="hljs-keyword">if</span> (index === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.unshift(value)
    <span class="hljs-keyword">if</span> (index === <span class="hljs-built_in">this</span>.length) <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.push(value)
    <span class="hljs-keyword">let</span> currentNode = <span class="hljs-built_in">this</span>.head
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i &lt;= index - <span class="hljs-number">1</span>; i++) {
      currentNode = currentNode.next
    }
    <span class="hljs-keyword">const</span> nextNode = currentNode.next
    currentNode.next = node
    node.next = nextNode
    <span class="hljs-built_in">this</span>.length++
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>
  }
</code></pre>
<h3 id="heading-remove">Remove</h3>
<p>Remove a node at a particular index.</p>
<pre><code class="lang-javascript">  remove(index) {
    <span class="hljs-keyword">if</span> (index &lt; <span class="hljs-number">0</span> || index &gt;= <span class="hljs-built_in">this</span>.length) <span class="hljs-keyword">return</span>
    <span class="hljs-keyword">if</span> (index === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.shift()
    <span class="hljs-keyword">if</span> (index === <span class="hljs-built_in">this</span>.length - <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.pop()
    <span class="hljs-keyword">let</span> currentNode = <span class="hljs-built_in">this</span>.head
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i &lt;= index - <span class="hljs-number">1</span>; i++) {
      currentNode = currentNode.next
    }
    currentNode.next = currentNode.next.next
    <span class="hljs-built_in">this</span>.length--
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>
  }
</code></pre>
<h1 id="heading-time-complexity">Time Complexity</h1>
<p>Now that we have implemented all the basic operations that a singly linked list can perform, let's talk about the time complexity of each of them:</p>
<ul>
<li><p>push: <strong>O(1)</strong></p>
</li>
<li><p>pop: <strong>O(n)</strong></p>
</li>
<li><p>shift: <strong>O(1)</strong></p>
</li>
<li><p>unshift: <strong>O(1)</strong></p>
</li>
<li><p>get: <strong>O(n)</strong></p>
</li>
<li><p>set: <strong>O(n)</strong></p>
</li>
<li><p>insert: <strong>O(n)</strong></p>
</li>
<li><p>remove: <strong>O(n)</strong></p>
</li>
</ul>
<h1 id="heading-pros-and-cons-of-a-singly-linked-list">Pros and Cons of a Singly Linked List</h1>
<h2 id="heading-pros">Pros</h2>
<p>A singly linked list is useful when you want to frequently insert or remove elements because it takes constant time.</p>
<h2 id="heading-cons">Cons</h2>
<p>A singly linked list is not efficient when it comes to accessing the elements because there are no indices assigned to the elements. So you have to visit each node starting from the first node until you find the target node.</p>
]]></content:encoded></item><item><title><![CDATA[Introducing RepairRadar - Discover Trusted Mechanics Near You]]></title><description><![CDATA[About RepairRadar
RepairRadar is an open-source platform that connects mechanics with vehicle owners. Mechanics can register themselves and set up their profiles. Customers can sign in and find nearby mechanics through an interactive map. Customers c...]]></description><link>https://blog.shahmirfaisal.com/introducing-repairradar-discover-trusted-mechanics-near-you</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/introducing-repairradar-discover-trusted-mechanics-near-you</guid><category><![CDATA[AWS Amplify]]></category><category><![CDATA[AWS Amplify Hackathon]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Mon, 31 Jul 2023 19:25:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1690830690632/bd529721-8919-4967-b6fa-69e5522c72f6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-about-repairradar">About RepairRadar</h1>
<p>RepairRadar is an open-source platform that connects mechanics with vehicle owners. Mechanics can register themselves and set up their profiles. Customers can sign in and find nearby mechanics through an interactive map. Customers can contact different mechanics and request appointments. Mechanics can approve or reject those appointments depending on their schedule. Customers can also leave ratings and review once their work is done.</p>
<h1 id="heading-problem"><strong>🚩</strong>Problem</h1>
<p>A lot of times when people are traveling and they face vehicle problems. It's hard to find a mechanic nearby. The shops are far away or people don't know where the shops are and they don't know how to contact a mechanic. Even if they do find a mechanic, the mechanic might be quite busy with other vehicles and people will have to wait hours for their turn.</p>
<h1 id="heading-solution"><strong>💡</strong>Solution</h1>
<p>This is where I came up with the idea of RepairRadar. A way to connect mechanics with customers. Both can communicate easily and schedule appointments. Leave reviews and ratings so other customers can have a better idea of which mechanic to choose.</p>
<h1 id="heading-reason-for-building-repairradar">👷Reason for Building RepairRadar</h1>
<ul>
<li><p><strong>To complete the project</strong>. I leave most of the projects incomplete.</p>
</li>
<li><p><strong>To learn AWS Amplify.</strong> I was looking to learn a new technology.</p>
</li>
<li><p><strong>To improve my portfolio.</strong></p>
</li>
<li><p><strong>Of course for the swags and prizes</strong> .🤣</p>
</li>
</ul>
<h1 id="heading-features"><strong>🔥</strong>Features</h1>
<h2 id="heading-authentication">Authentication</h2>
<p>Customers and Mechanics can register themselves.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690823184961/7b708a90-97f9-410c-8160-1c1be890a4ef.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-customer-features">Customer Features</h2>
<h3 id="heading-find-mechanics">Find Mechanics</h3>
<p>Customers can find mechanics through the map and visit their profiles.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690823340184/53b925d1-549a-4bf0-abef-902d8f05da9b.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-book-appointment">Book Appointment</h3>
<p>Customers can choose a time and write a description to request an appointment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690823282041/56380228-6fc4-4349-adea-16f0171f0111.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-add-review">Add Review</h3>
<p>Once the work is done and marked as completed by the mechanic, the customer can add a review.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690823470132/edb2a1b4-80fb-44d9-9dbb-5dd32e9b6aa3.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-chat">Chat</h3>
<p>Customer can start a chat with the mechanic.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690823650845/1810175c-d0cb-4c04-b429-09944e9ad3ed.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-mechanic-features">Mechanic Features</h2>
<h3 id="heading-onboarding">Onboarding</h3>
<p>Mechanics will set up their profiles by uploading a profile picture and giving their shop location.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690823778309/494ecb21-3721-436b-a7a9-45b5f9ce257e.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-profile">Profile</h3>
<p>Mechanics can view their profiles.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690823911476/58f0854e-a5e0-4c19-9e6e-6462a2252b28.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-edit-profile">Edit Profile</h3>
<p>Mechanics can edit their profiles.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690823914410/85c4e581-e918-436b-b660-bd4ef02ca7ab.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-appointments">Appointments</h3>
<p>Mechanics can accept or reject the appointments requested by different customers. Once the work is done, the mechanics can also mark the appointments as completed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690823960220/917d5940-ea66-44ff-b92d-50b24323f9d8.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-tech-stack"><strong>👨‍💻</strong>Tech Stack</h1>
<ol>
<li><p>ReactJs - For building the Frontend.</p>
</li>
<li><p>Amplify UI - For building the UI.</p>
</li>
<li><p>Typescript - For type checking and writing better code.</p>
</li>
<li><p>Leaflet - For adding maps.</p>
</li>
<li><p>AWS Amplify - For the backend (Authentication, Database, File Storage, UI Components).</p>
</li>
<li><p>Vercel - For deployment.</p>
</li>
</ol>
<h1 id="heading-folder-structure"><strong>🧱</strong>Folder Structure</h1>
<pre><code class="lang-plaintext">-- components
    -- Chat
        -- ChatItem.tsx
        -- Message.tsx
    -- LocationPickerMap
        -- index.tsx
        -- LocationMarker.tsx
    -- Sidebar
        -- index.tsx
        -- SidebarItem.tsx
    -- AddReviewModal.tsx
    -- AppointmentItem.tsx
    -- AppointmentRequestModal.tsx
    -- AppointmentsSection.tsx
    -- Header.tsx
    -- LayoutItem.tsx
    -- Map.tsx
    -- Review.tsx
    -- ReviewViewModal.tsx
-- context
    -- AuthContext.tsx
-- hooks
    -- useImagePicker.tsx
    -- usePickLocation.tsx
-- hoc
    -- withAuth.tsx
    -- withNoAuth.tsx
-- layouts
    -- AuthLayout.tsx
    -- ChatLayout.tsx
    -- CustomerLayout.tsx
    -- Layout.tsx
    -- MechanicLayout.tsx
    -- UserLayout.tsx
-- pages
    -- customer
        -- FindMechanicsPage
        -- AppointmentsPage.tsx
        -- CustomerProfilePage.tsx
        -- MechanicProfilePage.tsx
    -- mechanic
        -- AppointmentsPage.tsx
        -- DashboardPage.tsx
        -- MechanicProfilePage.tsx
        -- MechanicProfileEditPage.tsx
    -- ChatPage.tsx
    -- EmailVerificationPage.tsx
    -- LandingPage.tsx
    -- LogInPage.tsx
    -- OnboardingPage.tsx
    -- SignUpPage.tsx
-- routes
    -- authRoutes.tsx
    -- customerRoutes.tsx
    -- index.tsx
    -- mechanicRoutes.tsx
-- types
    -- error.types.ts
    -- map.types.ts
    -- user.types.ts
-- utils
    -- user.utils.ts
-- index.css
-- main.tsx
</code></pre>
<h1 id="heading-usage-of-aws-amplify">❤️Usage of AWS Amplify</h1>
<p>I used <a target="_blank" href="https://aws.amazon.com/pm/amplify/">AWS Amplify</a> for the following features:</p>
<ol>
<li><p>Authentication</p>
</li>
<li><p>Database</p>
</li>
<li><p>File Storage</p>
</li>
<li><p>Generating UI Components</p>
</li>
</ol>
<h2 id="heading-1-authentication">1- Authentication</h2>
<p>I set up authentication using aws cognito and also set up some additional attributes as they were needed for this kind of multi-role application where we have mechanics and customers.</p>
<h2 id="heading-2-database">2- Database</h2>
<p>I set up different Data Models for the storage of Users, Appointments, Reviews, Chats, and Messages.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690826680143/f3115391-6919-4b7f-ba47-5c4282fcb43b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690826725004/8226e3f4-8c7b-4667-9236-4807bf5d9c54.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690826757290/f0c65859-1ace-48b5-beb0-98f0a0307f5e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-3-storage">3- Storage</h2>
<p>I made a public S3 bucket for storing profile pictures of mechanics.</p>
<h2 id="heading-4-ui-components">4- UI Components</h2>
<p>I also used <a target="_blank" href="https://aws.amazon.com/pm/amplify/">AWS Amplify</a> for generating ReactJs UI components from a Figma file.</p>
<h1 id="heading-difficulties"><strong>😕</strong>Difficulties</h1>
<ol>
<li><p>I was new to AWS Amplify so it took me around 10 days to learn and experiment with the different services of AWS Amplify.</p>
</li>
<li><p>I am not good at design. So I had to search a lot to find design inspirations.</p>
</li>
<li><p>Lack of time. I work as a freelancer so managing the time was a bit hard for me.</p>
</li>
</ol>
<h1 id="heading-future-enhancement"><strong>🤖</strong>Future Enhancement</h1>
<p>These are some features that I was looking to add but did not get enough time. But these can definitely be added in the future.</p>
<ol>
<li><p>Dark Mode.</p>
</li>
<li><p>Mechanics can add services and Customers can choose a particular service while booking an appointment.</p>
</li>
<li><p>In-app payments. Customers can pay directly through the app.</p>
</li>
<li><p>Analytics and Reporting.</p>
</li>
</ol>
<h1 id="heading-useful-links"><strong>🔗</strong>Useful Links</h1>
<p>Live Preview: <a target="_blank" href="https://repairradar.shahmirfaisal.com/">https://repairradar.shahmirfaisal.com/</a></p>
<p>Github Repo: <a target="_blank" href="https://github.com/shahmirfaisal/RepairRadar">https://github.com/shahmirfaisal/RepairRadar</a></p>
<h1 id="heading-about-me"><strong>🧑</strong>About Me</h1>
<p>I'm Shahmir Faisal, currently pursuing my Bachelor's in Computer Engineering. I've been in the world of coding for 4 years now. I'm a web developer and my current stack consists of React, React Native, Next, Node, Express, and MongoDB. But now I will also include AWS Amplify🔥.</p>
<p>Sorry, but I thought I should do some promotion as well :(</p>
<p>I work as a web developer tutor and have taught a lot of students in the past year on <a target="_blank" href="https://www.fiverr.com/shahmirfaisal">Fiverr</a>. Feel free to reach out to me.</p>
<h1 id="heading-conclusion"><strong>🎇</strong>Conclusion</h1>
<p>I have learned a lot of things by participating in this hackathon. It was a bit tough for me but still made an amazing app. Thank you <a target="_blank" href="https://hashnode.com/">Hashnode</a> and <a target="_blank" href="https://aws.amazon.com/pm/amplify/">AWS Amplify</a> for organizing this amazing hackathon.</p>
]]></content:encoded></item><item><title><![CDATA[Interface Segregation Principle - SOLID Principles in Javascript]]></title><description><![CDATA[This is the 3rd article in our series of articles covering the SOLID Design Principles.
If you are unaware of SOLID, you can read the first article where I gave a brief introduction to SOLID. In this article, we will be covering the Interface Segrega...]]></description><link>https://blog.shahmirfaisal.com/interface-segregation-principle-solid-principles-in-javascript</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/interface-segregation-principle-solid-principles-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[SOLID principles]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Sun, 14 Aug 2022 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660395991349/uB6k0GyC7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the 3rd article in our <a target="_blank" href="https://shahmir.me/series/solid-design-principles">series of articles</a> covering the SOLID Design Principles.</p>
<p>If you are unaware of SOLID, you can read the <a target="_blank" href="https://shahmir.me/single-responsibility-principle-solid-principles-in-javascript#heading-what-are-the-solid-design-principles">first article</a> where I gave a brief introduction to SOLID. In this article, we will be covering the Interface Segregation Principle.</p>
<h2 id="heading-what-is-interface-segregation-principle">What is Interface Segregation Principle?</h2>
<p>It states that the client should not be forced to implement an interface that it doesn't use.</p>
<p>Now, this definition doesn't really make any sense. So let's simplify this.</p>
<p>In simple words, the classes in your code or any other entity in your code should not be dependent on methods that they cannot use.</p>
<h2 id="heading-example">Example</h2>
<p>Let's clear the concept with the help of an example.</p>
<p>Consider you are building a movie streaming app and you have 2 kinds of users: free users and premium users.</p>
<p>Premium users can watch both the trailer as well as the movie. However, free users can only watch the trailer. </p>
<h3 id="heading-naive-solution">Naive Solution</h3>
<p>We can code this app something like this:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
  <span class="hljs-keyword">constructor</span>(name) {
    <span class="hljs-built_in">this</span>.name = name;
  }

  watchTrailer() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Watching trailer..."</span>);
  }

  watchMovie() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Watching movie..."</span>);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PremiumUser</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">User</span> </span>{}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FreeUser</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">User</span> </span>{
  watchMovie() {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }
}
</code></pre>
<p>Here, we created a <strong>User</strong> class with a <strong>name</strong> property and <strong>watchTrailer</strong> and <strong>watchMovie</strong> methods. Then we have 2 children: <strong>PremiumUser</strong> and <strong>FreeUser</strong>.</p>
<p>Inside of <strong>FreeUser</strong>, we override the <strong>watchMovie</strong> method and here it returns null which means it does nothing so free users cannot watch a movie. </p>
<h4 id="heading-whats-wrong-with-this-solution">What's wrong with this solution?</h4>
<p>In our solution, <strong>FreeUser</strong> is depending on the <strong>watchMovie</strong> method but it cannot use that method because we are returning null. We can still call that method but it does nothing meaningful.</p>
<p>And here we are violating the Interface Segregation Principle because our <strong>FreeUser</strong> class is depending on a method that it doesn't use.</p>
<h3 id="heading-better-solution">Better Solution</h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
  <span class="hljs-keyword">constructor</span>(name) {
    <span class="hljs-built_in">this</span>.name = name;
  }

  watchTrailer() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Watching trailer..."</span>);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PremiumUser</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">User</span> </span>{
  watchMovie() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Watching movie..."</span>);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FreeUser</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">User</span> </span>{}
</code></pre>
<p>In this solution, we only put the common methods in the parent class, in our case it is just the <strong>watchTrailer</strong> method because every user can watch the trailer. And then <strong>PremiumUser</strong> has its own <strong>watchMovie</strong> method. Now any of our class is not depending on any method that it cannot use. <strong>FreeUser</strong> is now independent of the <strong>watchMovie</strong> method.</p>
<p>Hence, we are not violating the principle anymore because each of the class only has those things that it can use.</p>
<p>So that's it. Comment below if you have any questions. Will see you in the next article covering the Dependency Inversion Principle.</p>
<p>Follow me on:<br /><a target="_blank" href="https://twitter.com/codewithshahmir">Twitter</a><br /><a target="_blank" href="https://www.linkedin.com/in/shahmir-faisal-17978616a/">LinkedIn</a><br /><a target="_blank" href="https://github.com/shahmirfaisal">Github</a></p>
]]></content:encoded></item><item><title><![CDATA[Liskov Substitution Principle - SOLID Principles in Javascript]]></title><description><![CDATA[This is the 3rd article in our series of articles covering the SOLID Design Principles.
If you are unaware of SOLID, you can read the first article where I gave a brief introduction to SOLID. In this article, we will be covering the Liskov Substituti...]]></description><link>https://blog.shahmirfaisal.com/liskov-substitution-principle-solid-principles-in-javascript</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/liskov-substitution-principle-solid-principles-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[clean code]]></category><category><![CDATA[SOLID principles]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Sat, 13 Aug 2022 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660315334706/NntXlgA0v.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the 3rd article in our <a target="_blank" href="https://shahmir.me/series/solid-design-principles">series of articles</a> covering the SOLID Design Principles.</p>
<p>If you are unaware of SOLID, you can read the <a target="_blank" href="https://shahmir.me/single-responsibility-principle-solid-principles-in-javascript#heading-what-are-the-solid-design-principles">first article</a> where I gave a brief introduction to SOLID. In this article, we will be covering the Liskov Substitution Principle.</p>
<h2 id="heading-what-is-liskov-substitution-principle">What is Liskov Substitution Principle?</h2>
<p>It states that an object of the parent class should be replaceable with the object of the child class without breaking the application. </p>
<p>You might have heard this definition in some other places or maybe it's your first time but anyways, it sounds confusing.</p>
<p>In simple words, if you have a parent and a child class and you are using an object of parent class somewhere in your code. If you replace that object of the parent class with the object of the child class, everything should still work the same without giving any errors or unexpected output.</p>
<h2 id="heading-example">Example</h2>
<p>Let's clear this concept with the help of an example.</p>
<p>Consider we have a Rectangle class as a parent and a Square class as the child.</p>
<h3 id="heading-naive-solution">Naive Solution</h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> </span>{
  <span class="hljs-keyword">constructor</span>(width, height) {
    <span class="hljs-built_in">this</span>._width = width;
    <span class="hljs-built_in">this</span>._height = height;
  }

  <span class="hljs-keyword">set</span> <span class="hljs-title">width</span>(<span class="hljs-params">value</span>) {
    <span class="hljs-built_in">this</span>._width = value;
  }
  <span class="hljs-keyword">set</span> <span class="hljs-title">height</span>(<span class="hljs-params">value</span>) {
    <span class="hljs-built_in">this</span>._height = value;
  }

  <span class="hljs-keyword">get</span> <span class="hljs-title">width</span>() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._width;
  }
  <span class="hljs-keyword">get</span> <span class="hljs-title">height</span>() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._height;
  }

  <span class="hljs-keyword">get</span> <span class="hljs-title">area</span>() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._width * <span class="hljs-built_in">this</span>._height;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Square</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Rectangle</span> </span>{
  <span class="hljs-keyword">constructor</span>(width, height) {
    <span class="hljs-keyword">if</span> (width !== height) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Width and Height should be same!"</span>);
    }

    <span class="hljs-built_in">super</span>(width, height);
  }

  <span class="hljs-keyword">set</span> <span class="hljs-title">width</span>(<span class="hljs-params">value</span>) {
    <span class="hljs-built_in">this</span>._width = value;
    <span class="hljs-built_in">this</span>._height = value;
  }
  <span class="hljs-keyword">set</span> <span class="hljs-title">height</span>(<span class="hljs-params">value</span>) {
    <span class="hljs-built_in">this</span>._width = value;
    <span class="hljs-built_in">this</span>._height = value;
  }
}
</code></pre>
<p>Here we have 2 properties <strong>_width</strong> and <strong>_height</strong> and we are using getters and setters for accessing and modifying the values. Now in the <strong>Square</strong> class, we are overriding the setters because we want to have the same width and height. </p>
<p>Now if we try to use them:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> calculateObjectArea = <span class="hljs-function">(<span class="hljs-params">object</span>) =&gt;</span> {
  object.height = <span class="hljs-number">20</span>;
  <span class="hljs-keyword">return</span> object.area;
};

<span class="hljs-keyword">const</span> rc = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">10</span>, <span class="hljs-number">10</span>);

<span class="hljs-built_in">console</span>.log(calculateObjectArea(rc));
<span class="hljs-comment">// Output: 200</span>
</code></pre>
<p>Here, we have a function <strong>calculateObjectArea</strong> that changes the height to 20 and then calculates the area. So basically in our case, the output will be 200 (10 * 20).</p>
<p>Now, what if we pass a square to that function instead of a rectangle with the same width and height?</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> calculateObjectArea = <span class="hljs-function">(<span class="hljs-params">object</span>) =&gt;</span> {
  object.height = <span class="hljs-number">20</span>;
  <span class="hljs-keyword">return</span> object.area;
};

<span class="hljs-keyword">const</span> rc = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">10</span>, <span class="hljs-number">10</span>);
<span class="hljs-keyword">const</span> sq = <span class="hljs-keyword">new</span> Square(<span class="hljs-number">10</span>, <span class="hljs-number">10</span>);

<span class="hljs-built_in">console</span>.log(calculateObjectArea(sq));
<span class="hljs-comment">// Output: 400</span>
</code></pre>
<p>According to the principle, if we replace the object of the parent class with the object of the child class we should still get the expected output. But here we will get 400 instead of 200. It means we are violating the Liskov Substitution Principle.</p>
<h3 id="heading-better-solution">Better Solution</h3>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
  <span class="hljs-keyword">get</span> <span class="hljs-title">area</span>() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._width * <span class="hljs-built_in">this</span>._height;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
  <span class="hljs-keyword">constructor</span>(width, height) {
    <span class="hljs-built_in">super</span>();
    <span class="hljs-built_in">this</span>._width = width;
    <span class="hljs-built_in">this</span>._height = height;
  }

  <span class="hljs-keyword">get</span> <span class="hljs-title">width</span>() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._width;
  }
  <span class="hljs-keyword">get</span> <span class="hljs-title">height</span>() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._height;
  }

  <span class="hljs-keyword">set</span> <span class="hljs-title">width</span>(<span class="hljs-params">value</span>) {
    <span class="hljs-built_in">this</span>._width = value;
  }
  <span class="hljs-keyword">set</span> <span class="hljs-title">height</span>(<span class="hljs-params">value</span>) {
    <span class="hljs-built_in">this</span>._height = value;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Square</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
  <span class="hljs-keyword">constructor</span>(width, height) {
    <span class="hljs-keyword">if</span> (width !== height) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Width and Height should be same!"</span>);
    }
    <span class="hljs-built_in">super</span>();
    <span class="hljs-built_in">this</span>._width = width;
    <span class="hljs-built_in">this</span>._height = height;
  }

  <span class="hljs-keyword">get</span> <span class="hljs-title">width</span>() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._width;
  }
  <span class="hljs-keyword">get</span> <span class="hljs-title">height</span>() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._height;
  }

  <span class="hljs-keyword">set</span> <span class="hljs-title">width</span>(<span class="hljs-params">value</span>) {
    <span class="hljs-built_in">this</span>._width = value;
    <span class="hljs-built_in">this</span>._height = value;
  }
  <span class="hljs-keyword">set</span> <span class="hljs-title">height</span>(<span class="hljs-params">value</span>) {
    <span class="hljs-built_in">this</span>._width = value;
    <span class="hljs-built_in">this</span>._height = value;
  }
}
</code></pre>
<p>Here we put all the common things in one base class <strong>Shape</strong> (in our case it is just the area). And then in <strong>Rectangle</strong> and <strong>Square</strong> we are having different setters and getters. Now the <strong>Square</strong> class is completely independent of the <strong>Rectangle</strong> class.</p>
<p>So whenever you are using inheritance and when you replace one object with another one and your code behaves unexpectedly, try to split your code into multiple classes and put only common things in the base class.</p>
<p>So that's it. Comment below if you have any questions. Will see you in the next article covering the Interface Segregation Principle.</p>
<p>Follow me on:<br /><a target="_blank" href="https://twitter.com/codewithshahmir">Twitter</a><br /><a target="_blank" href="https://www.linkedin.com/in/shahmir-faisal-17978616a/">LinkedIn</a><br /><a target="_blank" href="https://github.com/shahmirfaisal">Github</a></p>
]]></content:encoded></item><item><title><![CDATA[Introducing Polle - Create, Distribute and Analyze Polls.]]></title><description><![CDATA[About Polle
Polle is an open-source platform where you can create polls, share them to get votes, and finally analyze them in the dashboard. See the number of votes on each answer, votes on each day, votes from different devices, and much more!
🚩 Th...]]></description><link>https://blog.shahmirfaisal.com/introducing-polle-create-distribute-and-analyze-polls</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/introducing-polle-create-distribute-and-analyze-polls</guid><category><![CDATA[PlanetScale]]></category><category><![CDATA[PlanetScaleHackathon]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Thu, 28 Jul 2022 17:51:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659003937389/Minv_tk4h.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-about-polle">About Polle</h2>
<p>Polle is an open-source platform where you can create polls, share them to get votes, and finally analyze them in the dashboard. See the number of votes on each answer, votes on each day, votes from different devices, and much more!</p>
<h2 id="heading-the-problem">🚩 The Problem</h2>
<p>Now, we know there are already a lot of <strong>poll makers</strong> in the market. They lack in one big thing, analytics and that's where <strong>Polle</strong> can help you. I used some of the poll makers out there and came to know that they don't have great analytics like we don't know from where the votes are coming, when are we getting the most votes, how many votes we got today, yesterday, or the day before yesterday, are we getting votes from mobile, desktop or tablet.</p>
<h2 id="heading-the-idea">💡 The Idea</h2>
<p>That's where I came up with the idea of <strong>Polle</strong>. It not only lets you build and share polls but also provides user-friendly charts for analyzing the polls. I was thinking to build such kind of app way before this hackathon. But when I heard about this hackathon, I was very motivated to build it.  </p>
<p>Here are some reasons why I built <strong>Polle</strong> for this hackathon:</p>
<ul>
<li>To complete the entire project. I usually leave my projects incomplete in the middle. This hackathon really pushed me towards completing the entire project.</li>
<li>To learn something new. This project helped me learn some new technologies like PlanetScale and Prisma.</li>
<li>And of course for the swags and prizes 🤣.</li>
</ul>
<h2 id="heading-features">🔥 Features</h2>
<h3 id="heading-1-landing-page">1. Landing Page</h3>
<p>Not a feature though. But tried my best to build a nice-looking landing page.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658944219483/b9mwMgjPo.png" alt="Landing Page" /></p>
<h3 id="heading-2-authentication">2. Authentication</h3>
<p>I added authentication using JWT and Cookies.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658944187130/T8hRZSO3Q.png" alt="Signup Page" /></p>
<h3 id="heading-3-dashboard">3. Dashboard</h3>
<p>The dashboard shows an overview of the polls, votes and votes on the current day.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658944137653/kp4er1lJJ.png" alt="Dashboard" /></p>
<h3 id="heading-4-poll-creation">4. Poll Creation</h3>
<p>Users can not only create polls, but they can also customize and configure them. Users can:</p>
<ol>
<li>Add a question and multiple answers. Also added drag/drop functionality to change the position of answers.</li>
<li>Pick a theme color for the poll.</li>
<li>Show a custom "thanks message" that the audience will see after submitting the vote.</li>
<li>Show or hide results. If results are hidden, the audience can't see the results after voting.</li>
<li>Enable or disable the poll anytime. The audience can't vote if the poll is disabled.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658944088199/oEage-OFb.png" alt="Create New Poll" /></li>
</ol>
<h3 id="heading-5-polls-page">5. Polls Page</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658992768663/o3woFnh2w.png" alt="Poll Page" /></p>
<h3 id="heading-6-analytics">6. Analytics</h3>
<p>The analytics page shows:</p>
<ol>
<li>Number of votes on each answer.</li>
<li>Number of notes on each day.</li>
<li>Votes from different devices like desktop, mobile, and tablet.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658944437007/pn9HtFmd8.png" alt="Analytics" /></li>
</ol>
<h3 id="heading-7-the-poll">7. The Poll</h3>
<p>This is the Poll page where users can vote and can also see the results if allowed by the creator.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658945036252/Z2yjgoggB.png" alt="Poll" /></p>
<p>There are some other features and pages as well. Make sure to explore them.</p>
<h2 id="heading-tech-stack">👨‍💻 Tech Stack</h2>
<ol>
<li><strong>Next.js</strong> - For building the entire App.</li>
<li><strong>Material-UI</strong> - For building the UI.</li>
<li><strong>SASS</strong> - CSS preprocessor.</li>
<li><strong>Chart.js</strong> - For adding charts to the dashboard.</li>
<li><strong>Context API</strong> - For managing state.</li>
<li><strong>Prisma</strong> - For working with the database.</li>
<li><strong>PlanetScale</strong> - As a database.</li>
<li><strong>JWT</strong> - For authentication.</li>
<li><strong>Axios</strong> - For consuming the API.</li>
<li><strong>Bcrypt</strong> - For hashing passwords.</li>
<li><strong>React-Beautiful-DnD</strong> - For drag/drop feature.</li>
<li><strong>Vercel</strong> - For deployment.</li>
</ol>
<p>I built the entire app using <strong>Next.js</strong> along with some other packages and deployed the app on <strong>Vercel</strong>.</p>
<h2 id="heading-project-structure">🧱 Project Structure</h2>
<pre><code><span class="hljs-operator">-</span><span class="hljs-operator">-</span> components
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> AnalyticsBox
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> DashboardLayout
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> Features
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> Footer
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> Header
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> Hero
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> HomeLayout
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> Navbar
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> Poll
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> PollCustomize
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> PollItem
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> PollMaker
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> PollManager
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> PollSettings
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> Seo
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> SharePoll
<span class="hljs-operator">-</span><span class="hljs-operator">-</span> context
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> PollContext
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> UserContext
<span class="hljs-operator">-</span><span class="hljs-operator">-</span> lib
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> getUser
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> prisma
<span class="hljs-operator">-</span><span class="hljs-operator">-</span> pages
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> api
        <span class="hljs-operator">-</span><span class="hljs-operator">-</span> auth
        <span class="hljs-operator">-</span><span class="hljs-operator">-</span> polls
        <span class="hljs-operator">-</span><span class="hljs-operator">-</span> votes
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> dashboard
        <span class="hljs-operator">-</span><span class="hljs-operator">-</span> analytics
        <span class="hljs-operator">-</span><span class="hljs-operator">-</span> edit<span class="hljs-operator">-</span>poll
        <span class="hljs-operator">-</span><span class="hljs-operator">-</span> create<span class="hljs-operator">-</span>poll
        <span class="hljs-operator">-</span><span class="hljs-operator">-</span> index
        <span class="hljs-operator">-</span><span class="hljs-operator">-</span> polls
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> poll
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> _app
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> _document
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> index
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> login
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> signup
<span class="hljs-operator">-</span><span class="hljs-operator">-</span> prisma
    <span class="hljs-operator">-</span><span class="hljs-operator">-</span> schema.prisma
<span class="hljs-operator">-</span><span class="hljs-operator">-</span> src
<span class="hljs-operator">-</span><span class="hljs-operator">-</span> styles
<span class="hljs-operator">-</span><span class="hljs-operator">-</span> utils
</code></pre><h2 id="heading-process-of-creation">😵‍💫 Process of Creation</h2>
<p>As this was the first time I was working with PlanetScale and Prisma, so I had to cover some basic stuff before creating the project. I read this <a target="_blank" href="https://planetscale.com/blog/how-to-setup-next-js-with-prisma-and-planetscale">blog post on PlanetScale by Camila Ramos</a> which gave me an overview of Prisma and PlanetScale. Then started reading the official docs of Prisma and PlanetScale. Once I covered the basics, then the next step:</p>
<pre><code class="lang-npm">npx create-next-app polle
</code></pre>
<p>Installed Prisma, set up PlanetScale, and created the schema. I started off by implementing authentication, then CRUD operations on the poll, then implemented analytics by using chart.js, and at the end built this cool logo:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658988177554/aEo74q9wz.png" alt="Logo" />
Which is nothing but a copy of an emoji from Notion 🤣. I just changed its color using Figma 😊. I'm not a designer so I had to do this 😔.  I also created an open-graph image using Canva:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658988466883/_a6AC9uT8.png" alt="Open Graph Image" /></p>
<h2 id="heading-difficulties">😕 Difficulties</h2>
<p>Here are some difficulties that I faced during the development process:</p>
<ol>
<li>As I'm not a designer, It was a bit hard for me to come up with a nice-looking UI.</li>
<li>I struggled with the analytics part. As I had never worked with charts before so adding charts and gathering data for them was hard for me.</li>
</ol>
<h2 id="heading-future-enhancements">🤖 Future Enhancements</h2>
<p>These are some features that I thought of adding but was unable to do so. However, I will definitely add them in the future:</p>
<ol>
<li>Dark mode.</li>
<li>Add images in the poll.</li>
<li>Add a description in the poll.</li>
<li>Ability to embed the polls in websites using iframe or some other technique.</li>
</ol>
<h2 id="heading-links">🔗 Links</h2>
<p>Live Preview: <a target="_blank" href="https://polle.shahmir.me/">polle.shahmir.me</a><br />Github Repo: <a target="_blank" href="https://github.com/shahmirfaisal/polle">github.com/shahmirfaisal/polle</a></p>
<h2 id="heading-about-me">🧑 About Me</h2>
<p>I'm Shahmir Faisal, currently pursuing my Bachelor's in Computer Engineering. I've been in the world of coding for 3 years now. I'm a web developer and my current stack consists of React, Next, Node, Express, and MongoDB. But now I will also include Prisma and PlanetScale 🔥.</p>
<h2 id="heading-conclusion">🎇 Conclusion</h2>
<p>In the end, I want to say thanks to Hashnode and PlanetScale for organizing such a great hackathon where we can learn and show our skills by building cool projects.</p>
]]></content:encoded></item><item><title><![CDATA[Open-Closed Principle - SOLID Principles in Javascript]]></title><description><![CDATA[This is the second article in our series of articles covering the SOLID Design Principles.  
If you are unaware of SOLID, you can read the first article where I gave a brief introduction to SOLID. In this article, we will be covering the Open-Closed ...]]></description><link>https://blog.shahmirfaisal.com/open-closed-principle-solid-principles-in-javascript</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/open-closed-principle-solid-principles-in-javascript</guid><category><![CDATA[SOLID principles]]></category><category><![CDATA[clean code]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Open Closed Principle]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Wed, 20 Jul 2022 11:38:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658315202107/laFdW-e0s.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the second article in our <a target="_blank" href="https://shahmir.me/series/solid-design-principles">series of articles</a> covering the SOLID Design Principles.  </p>
<p>If you are unaware of SOLID, you can read the <a target="_blank" href="https://shahmir.me/single-responsibility-principle-solid-principles-in-javascript#heading-what-are-the-solid-design-principles">first article</a> where I gave a brief introduction to SOLID. In this article, we will be covering the Open-Closed Principle.</p>
<h2 id="heading-what-is-the-open-closed-principle">What is the Open-Closed Principle?</h2>
<p>The Open-Closed principle states that entities are open for extension but closed for modifications. Now, this definition obviously doesn't make sense to anyone. So let's understand it by some alternative and simpler definitions:</p>
<ul>
<li>You can create new entities but you cannot change the existing ones.</li>
<li>You can add new code (that will work with the old code) but you cannot change the old code.</li>
</ul>
<p>Here, the word <strong><em>entity</em></strong> refers to an object, class, or function or in other words a set of instructions grouped together. So basically, you cannot change the existing set of instructions but you can add new ones. Let's understand it with an example:</p>
<h2 id="heading-example">Example</h2>
<p>Consider we have a set of users and we want to sort them in different ways and in different orders.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> users = [
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Shahmir"</span>,
    <span class="hljs-attr">age</span>: <span class="hljs-number">19</span>,
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Faisal"</span>,
    <span class="hljs-attr">age</span>: <span class="hljs-number">18</span>,
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Usman"</span>,
    <span class="hljs-attr">age</span>: <span class="hljs-number">20</span>,
  },
];
</code></pre>
<p>Here each user has a <strong><em>name</em></strong> and an <strong><em>age</em></strong> property and we want to sort these using name and age and in ascending and descending order.</p>
<h3 id="heading-naive-solution">Naive Solution</h3>
<p>We can sort them using a function like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> sortUsers = <span class="hljs-function">(<span class="hljs-params">users, sortBy, order</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (sortBy) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"name"</span>:
      <span class="hljs-keyword">switch</span> (order) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"asc"</span>:
          users = users.sort(<span class="hljs-function">(<span class="hljs-params">user1, user2</span>) =&gt;</span>
            user1.name &lt; user2.name ? <span class="hljs-number">-1</span> : <span class="hljs-number">1</span>
          );
          <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> <span class="hljs-string">"desc"</span>:
          users = users.sort(<span class="hljs-function">(<span class="hljs-params">user1, user2</span>) =&gt;</span>
            user1.name &gt; user2.name ? <span class="hljs-number">-1</span> : <span class="hljs-number">1</span>
          );
          <span class="hljs-keyword">break</span>;
      }
      <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">case</span> <span class="hljs-string">"age"</span>:
      <span class="hljs-keyword">switch</span> (order) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"asc"</span>:
          users = users.sort(<span class="hljs-function">(<span class="hljs-params">user1, user2</span>) =&gt;</span> user1.age - user2.age);
          <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> <span class="hljs-string">"desc"</span>:
          users = users.sort(<span class="hljs-function">(<span class="hljs-params">user1, user2</span>) =&gt;</span> user2.age - user1.age);
          <span class="hljs-keyword">break</span>;
      }
      <span class="hljs-keyword">break</span>;
  }

  <span class="hljs-keyword">return</span> users;
};
</code></pre>
<p>This function takes the users, orderBy(name/age) and order(ascending/descending) as arguments. And uses a bunch of switch statements to sort them in different ways using the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort">sort function</a>. Now, this solution works but it's violating the Open-Closed principle.</p>
<h4 id="heading-why-is-it-violating-the-open-closed-principle">Why is it Violating the Open-Closed Principle?</h4>
<p>The above solution is violating the Open-Closed principle and it is not the best way to perform this task. What if we have <strong><em>first name</em></strong> and <strong><em>last name</em></strong> and we want to sort using these in ascending/descending order. We need to modify our existing entity(sortUsers function) and add more switch statements to make it work and the principle states that we should not modify existing entities.</p>
<h3 id="heading-better-solution">Better Solution</h3>
<p>Instead of changing the existing entity, we want to be able to add new ones. So let's change the above code to make it work better.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SortUserName</span> </span>{
  constructors(users) {
    <span class="hljs-built_in">this</span>.users = users;
  }

  ascending() {
    <span class="hljs-keyword">return</span> users.sort(<span class="hljs-function">(<span class="hljs-params">user1, user2</span>) =&gt;</span> (user1.name &lt; user2.name ? <span class="hljs-number">-1</span> : <span class="hljs-number">1</span>));
  }

  descending() {
    <span class="hljs-keyword">return</span> users.sort(<span class="hljs-function">(<span class="hljs-params">user1, user2</span>) =&gt;</span> (user1.name &gt; user2.name ? <span class="hljs-number">-1</span> : <span class="hljs-number">1</span>));
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SortUserAge</span> </span>{
  constructors(users) {
    <span class="hljs-built_in">this</span>.users = users;
  }

  ascending() {
    <span class="hljs-keyword">return</span> users.sort(<span class="hljs-function">(<span class="hljs-params">user1, user2</span>) =&gt;</span> user1.age - user2.age);
  }

  descending() {
    <span class="hljs-keyword">return</span> users.sort(<span class="hljs-function">(<span class="hljs-params">user1, user2</span>) =&gt;</span> user2.age - user1.age);
  }
}
</code></pre>
<p> In the above code, we created 2 classes one for sorting through name and the other for sorting through age. And both of them have <strong><em>ascending</em></strong> and <strong><em>descending</em></strong> functions for sorting in different orders. Now, this code is a lot better than the previous one.</p>
<h4 id="heading-why-is-it-a-better-solution">Why is it a Better Solution?</h4>
<p>If we want to sort them using <strong><em>first name</em></strong> or <strong><em>last name</em></strong>, all we need to do is to create new classes for them and this is what Open-Closed principle says(create new entities).  </p>
<p>Here's how we can use the newly created classes:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> sort = <span class="hljs-keyword">new</span> SortUserAge(users);
<span class="hljs-built_in">console</span>.log(sort.ascending());
</code></pre>
<p>Now, we don't need to modify any existing code. Whenever we need to change how we are sorting the users, we can just create a new class for it without changing any existing classes.  </p>
<p>So that's it. Comment below if you have any questions. Will see you in the next article covering the Liskov Substitution principle.  </p>
<p>Follow me on:<br /><a target="_blank" href="https://twitter.com/codewithshahmir">Twitter</a><br /><a target="_blank" href="https://www.linkedin.com/in/shahmir-faisal-17978616a/">LinkedIn</a><br /><a target="_blank" href="https://github.com/shahmirfaisal">Github</a></p>
]]></content:encoded></item><item><title><![CDATA[Single Responsibility Principle - SOLID Principles in Javascript]]></title><description><![CDATA[This is the first article in our series of articles covering the SOLID Design Principles.
What are the SOLID Design Principles?
SOLID is a set of object-oriented design principles allowing you to write understandable and maintainable code. It makes s...]]></description><link>https://blog.shahmirfaisal.com/single-responsibility-principle-solid-principles-in-javascript</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/single-responsibility-principle-solid-principles-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[SOLID principles]]></category><category><![CDATA[clean code]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Sat, 23 Apr 2022 14:29:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1650723061965/4RiUHJbxx.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the first article in our series of articles covering the SOLID Design Principles.</p>
<h2 id="heading-what-are-the-solid-design-principles">What are the SOLID Design Principles?</h2>
<p>SOLID is a set of object-oriented design principles allowing you to write understandable and maintainable code. It makes sure that changing one part of your code doesn't impact other parts. SOLID is an acronym for 5 key design principles:</p>
<ol>
<li>S - Single Responsibility principle</li>
<li>O - Open-Closed principle</li>
<li>L - Liskov Substitution principle</li>
<li>I - Interface Segregation principle</li>
<li>D - Dependency Inversion principle</li>
</ol>
<p>In this series, we will cover all these 5 principles. We will cover the first one in this article.</p>
<h2 id="heading-single-responsibility-principle">Single Responsibility principle</h2>
<p>The Single Responsibility Principle states that a class should have only one responsibility means that it should have only one reason to change or in other words, it should have only one job.<br />If your class has multiple responsibilities, it's better to split it into multiple classes to avoid the violation of single responsibility.</p>
<h2 id="heading-example">Example</h2>
<p>Consider we're building an application to manage the students and their courses.</p>
<h3 id="heading-naive-solution">Naive Solution</h3>
<p>We might have a class like this:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> </span>{
  <span class="hljs-keyword">constructor</span>(name) {
    <span class="hljs-built_in">this</span>.name = name;
    <span class="hljs-built_in">this</span>.courses = [];
  }

  enrollCourse(course) {
    <span class="hljs-built_in">this</span>.courses.push(course);
    <span class="hljs-built_in">this</span>.notify(course);
  }

  notify(course) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span>, you have successfully enrolled <span class="hljs-subst">${course}</span>.`</span>);
  }
}

<span class="hljs-keyword">const</span> Shahmir = <span class="hljs-keyword">new</span> Student(<span class="hljs-string">"Shahmir"</span>);
Shahmir.enrollCourse(<span class="hljs-string">"Physics"</span>);

<span class="hljs-comment">// Output</span>
<span class="hljs-comment">// Shahmir, you have successfully enrolled Physics.</span>
</code></pre>
<p>Here we have 2 properties, the name, and courses of the student. Then a function <strong><em>enrollCourse</em></strong> for adding courses and uses the <strong><em>notify</em></strong> function to notify the student about that course.<br />Now the solution looks good, isn't it? However, it's violating the single responsibility principle.</p>
<h3 id="heading-whys-it-violating-the-single-responsibility">Why's it Violating the Single Responsibility?</h3>
<p>If you carefully look at the above example, it has 2 responsibilities:</p>
<ol>
<li>Enrolling Courses</li>
<li>Notifying Students about the new enrolled course</li>
</ol>
<p>The class has 2 reasons to change: </p>
<ol>
<li>if we want to change how we're enrolling in the course</li>
<li>if we want to change how we notify the user</li>
</ol>
<p>Here are the problems with the <strong><em>notify</em></strong> function:</p>
<ol>
<li>What if we want to send an email or a push notification to notify the student instead of just printing the message in the console? We need to come back and make changes to the class.</li>
<li>What if we have 10 different classes and we want the notify functionality in them? We need to write the function 10 times.</li>
<li>And what if we want to change the function again? We need to make changes in 10 different places.</li>
</ol>
<h3 id="heading-better-solution">Better Solution</h3>
<p>Why not just take that function out of the class? This will make the class use the single responsibility principle and we will be able to use that function wherever we want. And whenever we want to make changes, we will only change one part of the code without affecting the other parts.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">notify</span>(<span class="hljs-params">message</span>) </span>{
  <span class="hljs-built_in">console</span>.log(message);
  <span class="hljs-comment">// we can also email or send a push notification</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> </span>{
  <span class="hljs-keyword">constructor</span>(name) {
    <span class="hljs-built_in">this</span>.name = name;
    <span class="hljs-built_in">this</span>.courses = [];
  }

  enrollCourse(course) {
    <span class="hljs-built_in">this</span>.courses.push(course);
    notify(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span>, you have successfully enrolled <span class="hljs-subst">${course}</span>.`</span>);
  }
}

<span class="hljs-keyword">const</span> Shahmir = <span class="hljs-keyword">new</span> Student(<span class="hljs-string">"Shahmir"</span>);
Shahmir.enrollCourse(<span class="hljs-string">"Physics"</span>);

<span class="hljs-comment">// Output</span>
<span class="hljs-comment">// Shahmir, you have successfully enrolled Physics.</span>
</code></pre>
<p>Now the class has only one responsibility and that is to enroll the courses. The <strong><em>notify</em></strong> function is separate from the class.<br />So that's it. Will see you in the next article covering the open-closed principle.</p>
<p>Follow me on:<br /><a target="_blank" href="https://twitter.com/codewithshahmir">Twitter</a><br /><a target="_blank" href="https://www.linkedin.com/in/shahmir-faisal-17978616a/">LinkedIn</a><br /><a target="_blank" href="https://github.com/shahmirfaisal">Github</a></p>
]]></content:encoded></item><item><title><![CDATA[Scope in JavaScript and How the Lexical Environment Works]]></title><description><![CDATA[Scope in Javascript
Scope determines the accessibility of variables in JavaScript. It means where you can access a particular variable in your code. In Javascript, we have 2 types of scope:

Global Scope
Local Scope

Global Scope
Whenever you declare...]]></description><link>https://blog.shahmirfaisal.com/scope-in-javascript-and-how-the-lexical-environment-works</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/scope-in-javascript-and-how-the-lexical-environment-works</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Sat, 09 Apr 2022 14:58:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649515489894/B1j2f2ar8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-scope-in-javascript">Scope in Javascript</h2>
<p>Scope determines the accessibility of variables in JavaScript. It means where you can access a particular variable in your code. In Javascript, we have 2 types of scope:</p>
<ol>
<li>Global Scope</li>
<li>Local Scope</li>
</ol>
<h3 id="heading-global-scope">Global Scope</h3>
<p>Whenever you declare a variable outside of any function, then it is in the global scope and the variable is called <strong>global variable</strong>. Global variables can be accessed from anywhere in the code.
Example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> x = <span class="hljs-number">10</span>;
</code></pre>
<h3 id="heading-local-scope">Local Scope</h3>
<p>Whenever you declare a variable inside of a function, then it is in the local scope and the variable is called <strong>local variable</strong>. Local variables can only be accessed inside of the function they are declared in.
Example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">localScope</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> x = <span class="hljs-number">10</span>;
}

localScope();
</code></pre>
<p>But how does javascript allow global variables to be accessed from anywhere and restrict local variables from getting access outside of the function they are declared in? It happens because of <strong>Lexical Environment</strong>.</p>
<h2 id="heading-what-is-lexical-environment">What is Lexical Environment?</h2>
<p>A lexical environment consists of 2 things:</p>
<ol>
<li>Local Memory Space</li>
<li>A reference to the Lexical Environment of parent</li>
</ol>
<p>Local Memory Space means the memory space (where variables are stored) of a function or global scope if you are outside of any function. Reference means it has access to the lexical environment of the parent. </p>
<p>Let's understand it with some simple examples.</p>
<h3 id="heading-example-1">Example 1</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> x = <span class="hljs-number">10</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printX</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(x);
}

printX();
</code></pre>
<pre><code><span class="hljs-comment">// Output</span>
<span class="hljs-selector-tag">10</span>
</code></pre><p>Here, we created a variable x and assigned 10 to it then we are calling a function that prints the value of x. Now, when we call the function it outputs 10 but we don't actually have x inside the function, we have it in the global scope. How does it access x from the global scope?  </p>
<p>The answer is simple, it's because of the lexical environment.  </p>
<p>When we try to print x inside of the function, the javascript engine tries to find it in the lexical environment of the function which consists of local memory and a reference to the lexical environment of the parent. When it fails to find it in the local memory of function then it will move to the lexical environment of the parent (global scope in this case) using the reference. Which again consists of local memory and a reference to the lexical environment of its parent. The engine will find x in the memory of the global scope and will print it.  </p>
<h3 id="heading-example-2">Example 2</h3>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createX</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> x = <span class="hljs-number">10</span>;
}
createX();
<span class="hljs-built_in">console</span>.log(x);
</code></pre>
<pre><code>Uncaught ReferenceError: x <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> defined
</code></pre><p>We get an error, but why?<br />When we try to access x in the global scope, the javascript engine tries to find it in the lexical environment. X is not defined in the memory space of global scope (it is actually in the local memory space of createX). So it moves to the lexical environment of its parent. We don't have any parent of global scope, so it means x does not exist. That's why we get that error.  </p>
<h3 id="heading-example-3">Example 3</h3>
<pre><code class="lang-javscript">var x = 10;

function outer() {
  function inner() {
    console.log(x);
  }
  inner();
}

outer();
</code></pre>
<pre><code><span class="hljs-comment">// Output</span>
<span class="hljs-selector-tag">10</span>
</code></pre><p>Here we have an outer function and then an inner function inside of it which tries to access x. When we call inner, the javascript engine tries to find x in its lexical environment. It fails to find it in the local memory space of inner, so using the reference to the lexical environment of the parent, it moves to the lexical environment of outer, still, x is not in the local memory space of outer, again using the reference, the engine moves to the lexical environment of its parent (global scope). And there we have x in the memory. So it prints the value x in the console.</p>
<h2 id="heading-scope-chain">Scope Chain</h2>
<p>The way Javascript Engine moves from one lexical environment to another to find the variable is called scope chain.</p>
<h2 id="heading-helpful-resources">Helpful Resources</h2>
<ul>
<li>https://youtu.be/uH-tVP8MUs8</li>
<li>https://amnsingh.medium.com/lexical-environment-the-hidden-part-to-understand-closures-71d60efac0e0</li>
<li>https://dev.to/abdulazizcode/scope-lexical-environment-4pdd</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Adding Lottie Animations to Your Website]]></title><description><![CDATA[What are Lottie animations?
Lottie is a JSON-file format for adding animations to your web and mobile applications. Lottie animations are eye-catching and can communicate messages more effectively than images and text. They make the overall user expe...]]></description><link>https://blog.shahmirfaisal.com/adding-lottie-animations-to-your-website</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/adding-lottie-animations-to-your-website</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[animation]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Sat, 02 Apr 2022 14:22:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648109114395/sMQiV_w00.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-are-lottie-animations">What are Lottie animations?</h2>
<p>Lottie is a JSON-file format for adding animations to your web and mobile applications. Lottie animations are eye-catching and can communicate messages more effectively than images and text. They make the overall user experience a lot more enjoyable. Lottie animations work on the web, iOS, Android, Windows, and React Native, so no matter what device or browser your audience uses, they'll be able to view them.<br />Examples:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648105406055/xouzcIusl.gif" alt="Store Animation" />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648105488673/kkQ8_J860.gif" alt="Coding Animation" /></p>
<h2 id="heading-lottiefiles">LottieFiles</h2>
<p><a target="_blank" href="https://lottiefiles.com/">LottieFiles</a> is an amazing website where you will find tons of free animations created by designers. And we'll be using their animations for our project. Head over to <a target="_blank" href="https://lottiefiles.com/featured">this page</a> where you will find all the amazing animations. Pick any animation. For our purpose, we'll be using this one: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648106566167/1xafImAIo.png" alt="Coding Animation" /></p>
<p>Below you will find the ''Lottie Animation URL". This is the URL of the JSON file of this animation. Copy it. But how can we use it?</p>
<h2 id="heading-using-lottie-animations">Using Lottie Animations</h2>
<p>LottiFiles has an <a target="_blank" href="https://www.npmjs.com/">npm</a> package named as <a target="_blank" href="https://www.npmjs.com/package/@lottiefiles/lottie-player">@lottiefiles/lottie-player</a>. You can either import it from CDN or can install it.</p>
<h3 id="heading-cdn">CDN</h3>
<pre><code><span class="hljs-operator">&lt;</span>script src<span class="hljs-operator">=</span><span class="hljs-string">"https://unpkg.com/@lottiefiles/lottie-player@0.4.0/dist/tgs-player.js"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>script<span class="hljs-operator">&gt;</span>
</code></pre><h3 id="heading-npm">NPM</h3>
<pre><code><span class="hljs-built_in">npm</span> i @lottiefiles/lottie-player
</code></pre><pre><code><span class="hljs-attribute">import</span> <span class="hljs-string">"<span class="hljs-variable">@lottiefiles</span>/lottie-player"</span>;
</code></pre><h3 id="heading-usage">Usage</h3>
<p>Add the element <strong><em>lottie-player</em></strong> and set the <strong><em>src</em></strong> property to a URL pointing to the JSON file which you copied earlier.</p>
<pre><code><span class="hljs-operator">&lt;</span>lottie<span class="hljs-operator">-</span>player src<span class="hljs-operator">=</span><span class="hljs-string">"https://assets4.lottiefiles.com/packages/lf20_l3sfdi9x.json"</span> <span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>lottie<span class="hljs-operator">-</span>player<span class="hljs-operator">&gt;</span>
</code></pre><p>It accepts some other properties as well which you can use to control the behaviour of the animation:</p>
<pre><code><span class="hljs-operator">&lt;</span>lottie<span class="hljs-operator">-</span>player src<span class="hljs-operator">=</span><span class="hljs-string">"https://assets4.lottiefiles.com/packages/lf20_l3sfdi9x.json"</span> autoplay loop controls background<span class="hljs-operator">=</span><span class="hljs-string">"transparent"</span> speed<span class="hljs-operator">=</span><span class="hljs-string">"1"</span> <span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>lottie<span class="hljs-operator">-</span>player<span class="hljs-operator">&gt;</span>
</code></pre><p>You can play around with these properties <a target="_blank" href="https://lottiefiles.com/web-player">here</a>.<br />That's it!  </p>
]]></content:encoded></item><item><title><![CDATA[Building Custom Authentication for Your Next.js Apps]]></title><description><![CDATA[Next.js is an open-source web development framework built on top of Node.js enabling you to build SEO-friendly React-based web apps by utilizing its features like server-side rendering and static-site generation.
Authentication
Handling authenticatio...]]></description><link>https://blog.shahmirfaisal.com/building-custom-authentication-for-your-nextjs-apps</link><guid isPermaLink="true">https://blog.shahmirfaisal.com/building-custom-authentication-for-your-nextjs-apps</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[authentication]]></category><dc:creator><![CDATA[Shahmir Faisal]]></dc:creator><pubDate>Sat, 26 Mar 2022 04:53:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648109296132/tbaICKHyl.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://nextjs.org/">Next.js</a> is an open-source web development framework built on top of Node.js enabling you to build SEO-friendly React-based web apps by utilizing its features like server-side rendering and static-site generation.</p>
<h2 id="heading-authentication">Authentication</h2>
<p>Handling authentication and authorization in your next.js app can be a bit tricky. There are so many options when it comes to adding auth like <a target="_blank" href="https://next-auth.js.org/">NextAuth</a>, <a target="_blank" href="https://auth0.com/">Auth0</a>, <a target="_blank" href="https://firebase.google.com/">Firebase</a>, etc. And these are pretty easy to start with. But sometimes you might need to build your own authentication feature to suit our web app needs rather than using these pre-built solutions. So in this article, we'll be building our own authentication feature using jwt, cookies, and mongodb.</p>
<h2 id="heading-lets-get-started">Let's Get Started</h2>
<p>First, you need to have node.js installed on your machine. You can get it from <a target="_blank" href="https://nodejs.org/">their official website</a>.
Next, create an empty next.js project by running the following command:</p>
<pre><code>npx create<span class="hljs-operator">-</span>next<span class="hljs-operator">-</span>app next<span class="hljs-operator">-</span>custom<span class="hljs-operator">-</span>auth <span class="hljs-operator">-</span><span class="hljs-operator">-</span>example <span class="hljs-string">"https://github.com/vercel/next-learn/tree/master/basics/learn-starter"</span>
</code></pre><p>Now we need the following packages for our app:</p>
<ul>
<li><p><a target="_blank" href="https://www.npmjs.com/package/axios">axios</a></p>
</li>
<li><p><a target="_blank" href="https://www.npmjs.com/package/cookies-next">cookies-next</a></p>
</li>
<li><p><a target="_blank" href="https://www.npmjs.com/package/jsonwebtoken">jsonwebtoken</a></p>
</li>
<li><p><a target="_blank" href="https://www.npmjs.com/package/mongoose">mongoose</a></p>
</li>
</ul>
<p>Install the packages:</p>
<pre><code>npm i axios cookies-<span class="hljs-keyword">next</span> jsonwebtoken mongoose
</code></pre><h2 id="heading-setting-up-mongodb">Setting Up MongoDB</h2>
<p>Create a '.env.local' file in the root of your project and add the environment variable for mongodb uri.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647854536993/H4D-WBPlk.png" alt=".env.local file" /></p>
<p>Now create a 'lib' folder in the root of your project, inside of that create a 'dbConnect.js'. Add the following code in it:</p>
<pre><code><span class="hljs-comment">// lib/dbConnect.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-title">mongoose</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"mongoose"</span>;

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">dbConnect</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> await mongoose.connect(process.env.MONGODB_URI);
}

export default dbConnect;
</code></pre><p>Here, we're creating an asynchronous function that uses mongoose to connect to the MongoDB database. We will call this function whenever we need to perform database operations.</p>
<h2 id="heading-building-the-ui">Building the UI</h2>
<p>Now let's build the UI for the home, signup, and signin page.</p>
<h3 id="heading-layout-component">Layout Component</h3>
<p>Create a 'components' directory in the root of the project and then add a 'Layout.js' file.</p>
<pre><code><span class="hljs-comment">// components/Layout.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-title">Link</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"next/link"</span>;

export default <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Layout</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>nav<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>Link href<span class="hljs-operator">=</span><span class="hljs-string">"/"</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-operator">&lt;</span>a<span class="hljs-operator">&gt;</span>Home Page<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>a<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>Link<span class="hljs-operator">&gt;</span>

        <span class="hljs-operator">&lt;</span>Link href<span class="hljs-operator">=</span><span class="hljs-string">"/signup"</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-operator">&lt;</span>a<span class="hljs-operator">&gt;</span>SignUp<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>a<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>Link<span class="hljs-operator">&gt;</span>

        <span class="hljs-operator">&lt;</span>Link href<span class="hljs-operator">=</span><span class="hljs-string">"/signin"</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-operator">&lt;</span>a<span class="hljs-operator">&gt;</span>SignIn<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>a<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>Link<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>nav<span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span>section<span class="hljs-operator">&gt;</span>{children}<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>section<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
  );
}
</code></pre><p>We will use this component for all of our pages. It adds a navigation bar and renders its children.</p>
<h3 id="heading-home-page">Home Page</h3>
<p>Inside of your 'index.js' file in the pages directory add the following code:</p>
<pre><code><span class="hljs-comment">// pages/index.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-title">Layout</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../components/Layout"</span>;

export default <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">HomePage</span>(<span class="hljs-params">props</span>) </span>{

  const signoutHandler <span class="hljs-operator">=</span> () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
      <span class="hljs-comment">// logic for signout</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="hljs-operator">&lt;</span>Layout<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>h1<span class="hljs-operator">&gt;</span>Home Page<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>h1<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>p<span class="hljs-operator">&gt;</span>
        This <span class="hljs-keyword">is</span> the home page and it <span class="hljs-keyword">is</span> protected. Only authenticated users can
        access <span class="hljs-built_in">this</span> page.
      &lt;<span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span>p<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>strong<span class="hljs-operator">&gt;</span>Name<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>strong<span class="hljs-operator">&gt;</span>: name
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>p<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>strong<span class="hljs-operator">&gt;</span>Email<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>strong<span class="hljs-operator">&gt;</span>: email
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span>button onClick<span class="hljs-operator">=</span>{signoutHandler}<span class="hljs-operator">&gt;</span>Sign out<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>button<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>Layout<span class="hljs-operator">&gt;</span>
  );
}
</code></pre><p>It will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647860176838/jP19KDPX5.png" alt="home page" /></p>
<h3 id="heading-signup-page">SignUp Page</h3>
<p>Create a 'signup.js' file in the 'pages' directory and add the following code:</p>
<pre><code><span class="hljs-comment">// pages/signup.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-title">Layout</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../components/Layout"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">useState</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"react"</span>;

export default <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SignupPage</span>(<span class="hljs-params"></span>) </span>{
  const [name, setName] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [email, setEmail] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [password, setPassword] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);

  const signupHandler <span class="hljs-operator">=</span> async (e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    e.preventDefault();
    <span class="hljs-comment">// signup logic</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="hljs-operator">&lt;</span>Layout<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>h1<span class="hljs-operator">&gt;</span>SignUp<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>h1<span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span>p<span class="hljs-operator">&gt;</span>Only unauthenticated users can access <span class="hljs-built_in">this</span> page.&lt;<span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span>form onSubmit<span class="hljs-operator">=</span>{signupHandler}<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input
          <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"text"</span>
          placeholder<span class="hljs-operator">=</span><span class="hljs-string">"Name"</span>
          onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> setName(e.target.<span class="hljs-built_in">value</span>)}
          value<span class="hljs-operator">=</span>{name}
        <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input
          <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"email"</span>
          placeholder<span class="hljs-operator">=</span><span class="hljs-string">"Email"</span>
          onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> setEmail(e.target.<span class="hljs-built_in">value</span>)}
          value<span class="hljs-operator">=</span>{email}
        <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input
          <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"password"</span>
          placeholder<span class="hljs-operator">=</span><span class="hljs-string">"Password"</span>
          onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> setPassword(e.target.<span class="hljs-built_in">value</span>)}
          value<span class="hljs-operator">=</span>{password}
        <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>button<span class="hljs-operator">&gt;</span>SignUp<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>button<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>form<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>Layout<span class="hljs-operator">&gt;</span>
  );
}
</code></pre><p>It will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647861470300/5uTANGWPc.png" alt="signup paqe" /></p>
<h3 id="heading-signin-page">SignIn Page</h3>
<p>Create a 'signin.js' file in the pages directory and add the following code:</p>
<pre><code><span class="hljs-comment">// pages/signin.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-title">Layout</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../components/Layout"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">useState</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"react"</span>;

export default <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SigninPage</span>(<span class="hljs-params"></span>) </span>{
  const [email, setEmail] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);
  const [password, setPassword] <span class="hljs-operator">=</span> useState(<span class="hljs-string">""</span>);

  const signinHandler <span class="hljs-operator">=</span> async (e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    e.preventDefault();
    <span class="hljs-comment">// Signin logic</span>
  };

  <span class="hljs-keyword">return</span> (
    <span class="hljs-operator">&lt;</span>Layout<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>h1<span class="hljs-operator">&gt;</span>SignIn<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>h1<span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span>p<span class="hljs-operator">&gt;</span>Only unauthenticated users can access <span class="hljs-built_in">this</span> page.&lt;<span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span>form onSubmit<span class="hljs-operator">=</span>{signinHandler}<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input
          <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"email"</span>
          placeholder<span class="hljs-operator">=</span><span class="hljs-string">"Email"</span>
          onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> setEmail(e.target.<span class="hljs-built_in">value</span>)}
          value<span class="hljs-operator">=</span>{email}
        <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input
          <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"password"</span>
          placeholder<span class="hljs-operator">=</span><span class="hljs-string">"Password"</span>
          onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> setPassword(e.target.<span class="hljs-built_in">value</span>)}
          value<span class="hljs-operator">=</span>{password}
        <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>button<span class="hljs-operator">&gt;</span>SignIn<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>button<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>form<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>Layout<span class="hljs-operator">&gt;</span>
  );
}
</code></pre><p>It will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647861789388/zx_qz8_p4.png" alt="signin page" />
I've added some CSS but I'm not going to show it here because styling isn't the focus of this article.</p>
<h2 id="heading-creating-the-user-model">Creating the User Model</h2>
<p>Create a 'models' directory at the root of the project. Inside, add a 'user.js' file and add the following code:</p>
<pre><code><span class="hljs-comment">// models/user.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-title">mongoose</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"mongoose"</span>;

const UserSchema <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> mongoose.Schema({
  name: String,
  email: String,
  password: String,
});

export default mongoose.models.User <span class="hljs-operator">|</span><span class="hljs-operator">|</span> mongoose.model(<span class="hljs-string">"User"</span>, UserSchema);
</code></pre><p>Here, we're creating a <strong><em>User</em></strong> schema using mongoose. It has the name, email, and password properties. Finally, we're creating a model and exporting it.</p>
<h2 id="heading-building-the-api">Building the API</h2>
<p>Now we will work on the API. To begin, first, let's create a directory name 'api' in the 'pages' directory where we will add all of our endpoints.</p>
<h3 id="heading-signup-endpoint">Signup Endpoint</h3>
<p>Create a 'signup.js' file in the 'api' directory and add the following code:</p>
<pre><code><span class="hljs-comment">// pages/api/signup.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-title">dbConnect</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../../lib/dbConnect"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">User</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../../models/user"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">jwt</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"jsonwebtoken"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">setCookies</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"cookies-next"</span>;

export default async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
  await dbConnect();

  const { name, email, password } <span class="hljs-operator">=</span> req.body;

  <span class="hljs-keyword">if</span> (req.method <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">"POST"</span>) {
    const userExist <span class="hljs-operator">=</span> await User.findOne({ email });

    <span class="hljs-keyword">if</span> (userExist)
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">422</span>).json({ message: <span class="hljs-string">"Email already in use!"</span> });

    const user <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> User({ name, email, password });
    await user.save();

    const token <span class="hljs-operator">=</span> jwt.sign({ userId: user._id }, process.env.TOKEN_SECRET, {
      expiresIn: <span class="hljs-string">"1d"</span>,
    });

    setCookies(<span class="hljs-string">"token"</span>, token, {
      req,
      res,
      maxAge: <span class="hljs-number">60</span> <span class="hljs-operator">*</span> <span class="hljs-number">60</span> <span class="hljs-operator">*</span> <span class="hljs-number">24</span>, <span class="hljs-comment">// 1 day</span>
      path: <span class="hljs-string">"/"</span>,
    });

    res.status(<span class="hljs-number">201</span>).json(user);
  } <span class="hljs-keyword">else</span> {
    res.status(<span class="hljs-number">424</span>).json({ message: <span class="hljs-string">"Invalid method!"</span> });
  }
}
</code></pre><p>Here, we created a handler function. Inside, we're using the <strong><em>dbConnect</em></strong> function to connect the database and destructed the properties from <strong><em>req.body</em></strong>. After that, we're only accepting <strong><em>POST</em></strong> requests. Then, we're validating the <strong><em>email</em></strong> and saving the user. We're creating a <strong><em>jsonwebtoken</em></strong> and storing it in a cookie using the <strong><em>setCookies</em></strong> method. The <strong><em>maxAge</em></strong> means it will expire after 24 hours. Make sure to add the <strong><em>TOKEN_SECRET</em></strong> in your <strong><em>.env.local</em></strong> file that you can use for creating jwts.</p>
<p>You can learn more about <strong><em>cookies-next</em></strong> from <a target="_blank" href="https://github.com/andreizanik/cookies-next">here</a>.</p>
<h3 id="heading-signin-endpoint">SignIn Endpoint</h3>
<p>Create a 'signin.js' file in the 'api' directory and add the following code:</p>
<pre><code><span class="hljs-comment">// pages/api/signin.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-title">dbConnect</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../../lib/dbConnect"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">User</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../../models/user"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">jwt</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"jsonwebtoken"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">setCookies</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"cookies-next"</span>;

export default async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
  await dbConnect();

  const { email, password } <span class="hljs-operator">=</span> req.body;

  <span class="hljs-keyword">if</span> (req.method <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">"POST"</span>) {
    const user <span class="hljs-operator">=</span> await User.findOne({ email, password });

    <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>user)
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">422</span>).json({ message: <span class="hljs-string">"Wrong email or password!"</span> });

    const token <span class="hljs-operator">=</span> jwt.sign({ userId: user._id }, process.env.TOKEN_SECRET, {
      expiresIn: <span class="hljs-string">"1d"</span>,
    });

    setCookies(<span class="hljs-string">"token"</span>, token, {
      req,
      res,
      maxAge: <span class="hljs-number">60</span> <span class="hljs-operator">*</span> <span class="hljs-number">60</span> <span class="hljs-operator">*</span> <span class="hljs-number">24</span>, <span class="hljs-comment">// 1 day</span>
      path: <span class="hljs-string">"/"</span>,
    });

    res.status(<span class="hljs-number">200</span>).json(user);
  } <span class="hljs-keyword">else</span> {
    res.status(<span class="hljs-number">424</span>).json({ message: <span class="hljs-string">"Invalid method!"</span> });
  }
}
</code></pre><p>It is very similar to the <strong><em>signup</em></strong> endpoint. Here, we're accepting the email and password of a user and validating it before letting the user to signin.</p>
<h2 id="heading-connecting-the-api-with-frontend">Connecting the API with Frontend</h2>
<p>Now head over to the 'signup.js' file in the 'pages' directory and add the following code in the <strong><em>signupHandler</em></strong> function:</p>
<pre><code><span class="hljs-comment">// pages/signup.js</span>

const signupHandler <span class="hljs-operator">=</span> async (e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    e.preventDefault();

    <span class="hljs-keyword">try</span> {
      const res <span class="hljs-operator">=</span> await axios.post(<span class="hljs-string">"/api/signup"</span>, {
        name,
        email,
        password,
      });

      router.<span class="hljs-built_in">push</span>(<span class="hljs-string">"/"</span>);
    } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
      console.log(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
    }
  };
</code></pre><p>Here we're using <strong><em>axios</em></strong> to send an HTTP request to the <strong><em>signup</em></strong> endpoint along with the name, email, and password of the user. Once the user signs up, we're redirecting to the home page using the <strong><em>router</em></strong> object provided by next.js. </p>
<p>You can import router and axios like so:</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">axios</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"axios"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">useRouter</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"next/router"</span>;

<span class="hljs-comment">// inside of the component</span>
const router <span class="hljs-operator">=</span> useRouter();
</code></pre><p>Now head over to the 'signin.js' file in the 'pages' directory and add the following code in the <strong><em>signinHandler</em></strong> function:</p>
<pre><code><span class="hljs-comment">// pages/signin.js</span>

 const signinHandler <span class="hljs-operator">=</span> async (e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    e.preventDefault();

    <span class="hljs-keyword">try</span> {
      const res <span class="hljs-operator">=</span> await axios.post(<span class="hljs-string">"/api/signin"</span>, {
        email,
        password,
      });

      router.<span class="hljs-built_in">push</span>(<span class="hljs-string">"/"</span>);
    } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
      console.log(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
    }
  };
</code></pre><p>Here we're sending an HTTP request to the <strong><em>signin</em></strong> endpoint along with the email and password of the user. Once the user signs in, we're redirecting to the home page.</p>
<p>Now open the 'index.js' file in the 'pages' directory and add this code in <strong><em>signoutHandler</em></strong> function:</p>
<pre><code><span class="hljs-comment">// pages/index.js</span>

const signoutHandler <span class="hljs-operator">=</span> () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    removeCookies(<span class="hljs-string">"token"</span>);
    router.<span class="hljs-built_in">push</span>(<span class="hljs-string">"/signin"</span>);
  };
</code></pre><p>It removes the 'token' cookie to signout the user.</p>
<h2 id="heading-fetching-user-data">Fetching User Data</h2>
<p>Now we need to verify whether the user is signed in or not to restrict the home page from being accessed by an unauthenticated user.</p>
<p>Create a file 'getUser.js' in the 'lib' directory and add the following code:</p>
<pre><code><span class="hljs-comment">// lib/getUser.js</span>

<span class="hljs-keyword">import</span> { <span class="hljs-title">getCookie</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"cookies-next"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">jwt</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"jsonwebtoken"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">User</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../models/user"</span>;

export default async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUser</span>(<span class="hljs-params">req, res</span>) </span>{
  const token <span class="hljs-operator">=</span> getCookie(<span class="hljs-string">"token"</span>, { req, res });

  <span class="hljs-keyword">try</span> {
    const data <span class="hljs-operator">=</span> jwt.verify(token, process.env.TOKEN_SECRET);
    let user <span class="hljs-operator">=</span> await User.findById(data.userId);
    user <span class="hljs-operator">=</span> JSON.parse(JSON.stringify(user));
    <span class="hljs-keyword">return</span> user;
  } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
    <span class="hljs-keyword">return</span> null;
  }
}
</code></pre><p>We will use the <strong><em>getUser</em></strong> function to verify the user. It takes in the <strong><em>req</em></strong> and <strong><em>res</em></strong> object and fetches the cookie. Then it verifies the token using the <strong><em>jwt.verify</em></strong> method. Then it fetches the user from the database using its id.<br />Remember, we stored the user's id in the token early in our article.<br />Then there's some serializing and parsing. What's that? Here, we're serializing and parsing the user document, it's because the <strong><em>_id</em></strong> of a document is of type <strong><em>ObjectId</em></strong> and we need to convert it into a string. You can avoid it and run the code to see what's going to happen. After that, we finally returned the user. If we don't have any user we will simply return null.</p>
<p>Now add this code in the 'index.js' file in your 'pages' directory:</p>
<pre><code><span class="hljs-comment">// pages/index.js</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getServerSideProps</span>(<span class="hljs-params">{ req, res }</span>) </span>{
  <span class="hljs-keyword">await</span> dbConnect();
  <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> getUser(req, res);
  <span class="hljs-keyword">if</span> (!user) {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">redirect</span>: {
        <span class="hljs-attr">permanent</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">destination</span>: <span class="hljs-string">"/signin"</span>,
      },
      <span class="hljs-attr">props</span>: {},
    };
  }
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: {
      user,
    },
  };
}
</code></pre><p>Here we're using server-side rendering to fetch the user data. If there's no user, we'll simply redirect to the 'signin' page otherwise we're good to go. You can the user data that we're returning as props in your component.</p>
<p>Now we need to make sure that only unauthenticated users can access the signin and signup pages. For both of the pages add the following code:</p>
<pre><code><span class="hljs-comment">// pages/signup.js and pages/signin.js</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getServerSideProps</span>(<span class="hljs-params">{ req, res }</span>) </span>{
  <span class="hljs-keyword">await</span> dbConnect();

  <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> getUser(req, res);
  <span class="hljs-keyword">if</span> (user) {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">redirect</span>: {
        <span class="hljs-attr">permanent</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">destination</span>: <span class="hljs-string">"/"</span>,
      },
      <span class="hljs-attr">props</span>: {},
    };
  }
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: {},
  };
}
</code></pre><p>If the user is available we will redirect to the home page.<br />That's it!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Adding authentication from scratch can be a bit spiny but you can go through this article to quickly understand how to do it. One thing which we missed was password hashing. You can do that by using the <a target="_blank" href="https://www.npmjs.com/package/bcryptjs">bcrypt</a> package. The main goal was to build using jwt, cookies, and mongodb.</p>
<p>Here's the:<br /><a target="_blank" href="https://next-custom-auth.vercel.app/">Live version of the app.</a><br /><a target="_blank" href="https://github.com/shahmirfaisal/next-custom-auth">Source code.</a></p>
<p><a target="_blank" href="https://twitter.com/codewithshahmir">Follow me on twitter.</a></p>
]]></content:encoded></item></channel></rss>