<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ian Kamau</title>
    <description>The latest articles on DEV Community by Ian Kamau (@iankcode).</description>
    <link>https://dev.to/iankcode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1006590%2F0a94a63a-1fb0-44fa-ad19-34ba77aeaed3.png</url>
      <title>DEV Community: Ian Kamau</title>
      <link>https://dev.to/iankcode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iankcode"/>
    <language>en</language>
    <item>
      <title>Building a multi-step form in Ruby on Rails</title>
      <dc:creator>Ian Kamau</dc:creator>
      <pubDate>Wed, 14 May 2025 21:52:30 +0000</pubDate>
      <link>https://dev.to/iankcode/building-a-multi-step-form-in-ruby-on-rails-1kme</link>
      <guid>https://dev.to/iankcode/building-a-multi-step-form-in-ruby-on-rails-1kme</guid>
      <description>&lt;p&gt;Many web applications require you to build a multi step form especially for things like user registration or checkout flow.&lt;br&gt;
In this blog, we will walk through how to create a multi-step form in Ruby on Rails.&lt;/p&gt;
&lt;h2&gt;
  
  
  🧩 Why Use a Multi-Step Form?
&lt;/h2&gt;

&lt;p&gt;Let’s quickly look at why you might want a multi-step form:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Increases completion rates as users are more likely to finish shorter steps than one long form.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improves UX: Long forms can overwhelm users. Breaking them into steps makes the process feel lighter.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  🛠️ What We’re Building
&lt;/h2&gt;

&lt;p&gt;We’ll build a multi-step form for creating a user profile with the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Personal Info (name, email)&lt;/li&gt;
&lt;li&gt;Address Info (street, city, state)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll implement this using only core Rails features — leveraging Turbo Frames and Turbo Streams from the Hotwire stack — to create dynamic, multi-step forms without full page reloads or third-party gems.&lt;/p&gt;
&lt;h2&gt;
  
  
  📦 Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of Rails controllers, views, models, and forms&lt;/li&gt;
&lt;li&gt;Basic knowledge of &lt;code&gt;turbo_frame_tag&lt;/code&gt; and &lt;code&gt;turbo_stream&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🚀 Step-by-Step Implementation
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Create a new app
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new multistep_form_app
cd multistep_form_app
rails db:create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Scaffold User
&lt;/h3&gt;

&lt;p&gt;This will create the controller, views, model, migration and also update the routes file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails generate scaffold User name:string email:string street:string city:string state:string
rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update root route to &lt;code&gt;root "users#index"&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;And your page should look like this&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Multi step logic
&lt;/h2&gt;

&lt;p&gt;Now we want the new.html.erb view file on &lt;code&gt;app/views/users/&lt;/code&gt; to be a multi form.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Split the form partial
&lt;/h3&gt;

&lt;p&gt;In the form partial, update the route and wrap both the name and email fields in a &lt;code&gt;turbo_frame_tag "step1"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It should be like this&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Step 2 - Create step2 partial
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;app/views/users&lt;/code&gt; create a new partial file and name it &lt;code&gt;_step2.html.erb&lt;/code&gt;. This is where we will have  Address information and submit button.&lt;/p&gt;

&lt;p&gt;Add the following code to it&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Step 3 - Create collection route on user resource
&lt;/h3&gt;

&lt;p&gt;Add a collection to the users resource route.&lt;br&gt;
This route will be used when submitting each step of the form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources :users do
    collection do
      post "next_step"
    end
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Step 4 - Create next_step method on users_controller.rb
&lt;/h3&gt;

&lt;p&gt;Add this method to users_controller.rb&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def next_step
    @name, @email, @next_step = params.values_at(:name, :email, :step)
    respond_to do |format|
      format.html
      format.turbo_stream
    end
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the next_step method, we will grab and save both name and email and also the current step.&lt;br&gt;
We will be using turbo_stream to replace step1 contents with step2 contents&lt;/p&gt;
&lt;h3&gt;
  
  
  Final step
&lt;/h3&gt;

&lt;p&gt;On &lt;code&gt;app/views/users&lt;/code&gt; create a file &lt;code&gt;next_step.turbo_stream.erb&lt;/code&gt; and add the following code to it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%= turbo_stream.replace "step#{@next_step.to_i}" do %&amp;gt;
  &amp;lt;%= render partial: "step#{@next_step.to_i + 1}", locals: { name: @name, email: @email } %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above basically replaces anything with turbo frame tag &lt;code&gt;"step#{@next_step.to_i}"&lt;/code&gt; which in our case is &lt;code&gt;step1&lt;/code&gt;with the partial file we created earlier &lt;code&gt;step2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It also passes the 2 variable (name &amp;amp; email) to the partial.&lt;/p&gt;

&lt;p&gt;Now with that, you can create a new user.&lt;/p&gt;

&lt;p&gt;Your final form should look like this&lt;/p&gt;

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

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

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

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

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

&lt;h2&gt;
  
  
  ✅ Optional Enhancements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add validation logic before proceeding to the next step&lt;/li&gt;
&lt;li&gt;Allow users to go back to previous steps&lt;/li&gt;
&lt;li&gt;Style the form with Tailwind or Bootstrap&lt;/li&gt;
&lt;li&gt;Add a progress indicator&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Access Source Code here &lt;a href="https://github.com/Iank-code/multi_step_form_rails" rel="noopener noreferrer"&gt;https://github.com/Iank-code/multi_step_form_rails&lt;/a&gt;
&lt;/h4&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to define and use Rails Concerns</title>
      <dc:creator>Ian Kamau</dc:creator>
      <pubDate>Wed, 09 Oct 2024 06:40:03 +0000</pubDate>
      <link>https://dev.to/iankcode/how-to-define-and-use-rails-concerns-j96</link>
      <guid>https://dev.to/iankcode/how-to-define-and-use-rails-concerns-j96</guid>
      <description>&lt;p&gt;A &lt;strong&gt;Concern&lt;/strong&gt; is a module that you extract to split the implementation of a class or module instead of having a big class body.&lt;br&gt;
A Rails concern is just a plain Ruby module that extends the &lt;code&gt;ActiveSupport::Concern&lt;/code&gt; module provided by Rails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Characteristics of Concerns:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modularity&lt;/strong&gt;: Concerns break down complex classes into similar, more focused units, improving code readability and understanding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reusability&lt;/strong&gt;: A concern can be reused across multiple classes, reducing code duplication and promoting DRY principle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;: Concerns can be easily extended or customized to fit specific use cases, offering flexibility and adaptability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing: Concerns can be tested independently, ensuring their correctness and reliability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Creating a concern:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a new Ruby module file in your &lt;code&gt;app/controllers/concerns&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend the &lt;code&gt;ActiveSupport::Concern&lt;/code&gt; module to make it a Rails concern.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define methods or class methods that encapsulates the desired functionality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the &lt;code&gt;included&lt;/code&gt; block to automatically include the concern's methods in classes that include it. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/concerns/searchable.rb
module Searchable
  extend ActiveSupport::Concern

  included do
    scope :search, -&amp;gt;(query) { where("name ILIKE ?", "%#{query}%") }
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example using a Concern:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Product &amp;lt; ApplicationRecord
  include Searchable
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Mastering Next-Auth: Your Comprehensive Guide to Next.js Authentication</title>
      <dc:creator>Ian Kamau</dc:creator>
      <pubDate>Fri, 31 May 2024 15:16:14 +0000</pubDate>
      <link>https://dev.to/iankcode/mastering-next-auth-your-comprehensive-guide-to-nextjs-authentication-4kok</link>
      <guid>https://dev.to/iankcode/mastering-next-auth-your-comprehensive-guide-to-nextjs-authentication-4kok</guid>
      <description>&lt;p&gt;&lt;strong&gt;NextAuth.js&lt;/strong&gt; is a complete open-source authentication solution for Next.js applications. It is designed from the ground up to support Next.js and Serverless&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NextAuth&lt;/strong&gt; has authentication providers that allow your users to sign in with their favorite preexisting logins. You can use any of our many predefined providers, or write your own custom OAuth configuration.&lt;/p&gt;

&lt;p&gt;In this blog, we will use &lt;strong&gt;NextAuth&lt;/strong&gt; to authenticate using &lt;strong&gt;Google&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To begin, you need to have already set up a Nextjs application.&lt;br&gt;
First thing to do is to install &lt;strong&gt;next-auth&lt;/strong&gt; using this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install next-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add API route
&lt;/h2&gt;

&lt;p&gt;To add NextAuth.js to a project create a file called &lt;strong&gt;route.ts&lt;/strong&gt; in &lt;strong&gt;/app/api/auth/[...nextauth]/&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/app/api/auth/[...nextauth]/route.ts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We want all routes pointing to &lt;strong&gt;app/api/auth/&lt;/strong&gt; to be caught that is why we use &lt;strong&gt;[...nextauth]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;/app/api/auth/[...nextauth]/route.ts&lt;/code&gt;, add the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// src/app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";

// Define your NextAuth options
const authOptions = {
  // Configure one or more authentication providers
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_API_SECRET!,
      authorization: {
        params: {
          prompt: "consent",
          access_type: "offline",
          response_type: "code",
        },
      },
    }),
  ],
  // ...add more providers here
};

// Create the NextAuth handler
const handler = NextAuth(authOptions);

// Export the handler for both GET and POST requests
export const GET = handler;
export const POST = handler;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create &lt;strong&gt;.env.local&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You can get both &lt;strong&gt;GOOGLE_CLIENT_ID&lt;/strong&gt; and &lt;strong&gt;GOOGLE_API_SECRET&lt;/strong&gt; in &lt;a href="https://console.cloud.google.com/apis/dashboard"&gt;https://console.cloud.google.com/apis/dashboard&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GOOGLE_CLIENT_ID="&amp;lt;YOUR GOOGLE CLIENT ID&amp;gt;"
GOOGLE_API_SECRET="&amp;lt;YOUR GOOGLE API SECRET&amp;gt;"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure Shared session state
&lt;/h2&gt;

&lt;p&gt;You will need your &lt;strong&gt;children&lt;/strong&gt; in &lt;strong&gt;app/layout.tsx&lt;/strong&gt; with &lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It should look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client"
import { Inter } from "next/font/google";
import "./globals.css";
import { SessionProvider } from "next-auth/react";

const inter = Inter({ subsets: ["latin"] });
import "./globals.css";

export default function RootLayout({
  children,
}: Readonly&amp;lt;{ children: React.ReactNode}&amp;gt;) {
  return (
    &amp;lt;html lang="en"&amp;gt;
      &amp;lt;body className={inter.className}&amp;gt;
          &amp;lt;SessionProvider refetchInterval={5 * 60}&amp;gt;
            {children}
          &amp;lt;/SessionProvider&amp;gt;
      &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;p&gt;By using &lt;strong&gt;refetchinterval&lt;/strong&gt; you ensure that the session data is refetched every 5 minutes, which helps in maintaining the accuracy and security of the session state in your Next.js application&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend - Add React Hook
&lt;/h2&gt;

&lt;p&gt;We have done with all the configurations, the only thing remaining is to add the &lt;strong&gt;sign up&lt;/strong&gt; and &lt;strong&gt;sign out&lt;/strong&gt; buttons&lt;/p&gt;

&lt;p&gt;We use the &lt;strong&gt;useSession()&lt;/strong&gt; React Hook in the NextAuth.js client to sign in, check if someone is signed in and sign out.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;components/navbar.tsx&lt;/strong&gt; import &lt;strong&gt;useSession()&lt;/strong&gt; and add the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useSession, signIn, signOut } from "next-auth/react"

export default function Navbar() {
  const { data: session } = useSession()
  if (session) {
    return (
      &amp;lt;&amp;gt;
        Signed in as {session.user.email} &amp;lt;br /&amp;gt;
        &amp;lt;button onClick={() =&amp;gt; signOut({callbackUrl: "/"})}&amp;gt;Sign out&amp;lt;/button&amp;gt;
      &amp;lt;/&amp;gt;
    )
  }
  return (
    &amp;lt;&amp;gt;
      Not signed in &amp;lt;br /&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; signIn("google")}&amp;gt;Sign in&amp;lt;/button&amp;gt;
    &amp;lt;/&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can get current user's information from the data provided here &lt;strong&gt;const { data: session } = useSession()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With that, you users can successfully login using their google accounts&lt;/p&gt;

</description>
      <category>authentication</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Creating a custom logger in Node JS using Winston</title>
      <dc:creator>Ian Kamau</dc:creator>
      <pubDate>Thu, 11 Apr 2024 14:02:57 +0000</pubDate>
      <link>https://dev.to/iankcode/crafting-custom-logger-solutions-in-nodejs-using-winston-56df</link>
      <guid>https://dev.to/iankcode/crafting-custom-logger-solutions-in-nodejs-using-winston-56df</guid>
      <description>&lt;p&gt;Hello fellow developers,&lt;/p&gt;

&lt;p&gt;I am excited to share with you how you can use winston to develop a custom logger for your node js application. This is beginner friendly and anyone can follow.&lt;/p&gt;

&lt;p&gt;Let's get started:&lt;br&gt;
Create an empty directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir node-logger
cd node-logger
code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the terminal inside the VS code &lt;br&gt;
Initialize package.json:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Install express, dotenv, winston and nodemon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev express dotenv winston nodemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;create the &lt;code&gt;index.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating &lt;code&gt;index.js&lt;/code&gt; go to &lt;code&gt;package.json&lt;/code&gt; and add the &lt;code&gt;start script&lt;/code&gt; inside &lt;code&gt;scripts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "start": "nodemon index.js",
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;index.js&lt;/code&gt; lets set up the basic server configuration using Express.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require("express");
const dotenv = require("dotenv");
dotenv.config();

const PORT = process.env.PORT || 8000;
const app = express();

app.listen(PORT, ()=&amp;gt;{
  console.log(`listening on http://localhost:${PORT}`)
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us now create the &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;code&gt;touch .env&lt;/code&gt;&lt;br&gt;
Now add your environment variables inside your &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PORT=8000
NODE_ENV=development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that done, in the terminal inside your VS code, create a folder &lt;code&gt;utils&lt;/code&gt; and inside &lt;code&gt;utils&lt;/code&gt; create a file called &lt;code&gt;logger.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir utils
cd utils
touch logger.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;logger.js&lt;/code&gt;, lets write the logging logic. First let us import winston and configure dotenv:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const winston = require("winston");
const dotenv = require("dotenv");
dotenv.config();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we will define our security levels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const levels = {
  error: 0,
  warn: 1,
  info: 2,
  http: 3,
  debug: 4,

}

const level = () =&amp;gt; {
  const isDevelopment = process.env.NODE_ENV || "development";
  return isDevelopment ? "debug" : "warn";
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will define different colors for each level and tell winston to use those colors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const colors = {
  error: "red",
  warn: "yellow",
  info: "green",
  http: "magenta",
  debug: "white",
};

winston.addColors(colors);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, select the aspect of our logging process to customize the log format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const format = winston.format.combine(
  winston.format.timestamp({
    format: "YYYY-MM-DDTHH:mm:ss",
  }),

  winston.format.colorize({ all: true }),

  winston.format.printf(
    (info) =&amp;gt; `${info.timestamp} ${info.level}: ${info.message}`
  )
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's define the transports that the logger must use for printing out messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const transports = [
  // Allow the user to console/print the message
  new winston.transports.Console(),
  // Allow to print all error level messages inside the all.log file
  new winston.transports.File({
    filename: "logs/error.log",
    level: "error",
  }),

  // Allow to print all messages inside the all.log file
  new winston.transports.File({
    filename: "logs/all.log",
  }),
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure the transports that the logger needs to employ for displaying messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Logger = winston.createLogger({
  level: level(),
  levels: levels,
  format: format,
  transports: transports,
  exitOnError: false,
});

module.exports = Logger;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your &lt;code&gt;index.js&lt;/code&gt; import &lt;code&gt;logger&lt;/code&gt; from &lt;code&gt;logger.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Logger = require("./utils/logger");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;replace &lt;code&gt;console.log&lt;/code&gt; with &lt;code&gt;Logger.http&lt;/code&gt;&lt;br&gt;
Finally, start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>node</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>winston</category>
    </item>
    <item>
      <title>Enhancing API Security: Best Practices for Developers</title>
      <dc:creator>Ian Kamau</dc:creator>
      <pubDate>Tue, 09 Apr 2024 14:07:12 +0000</pubDate>
      <link>https://dev.to/iankcode/enhancing-api-security-best-practices-for-developers-4m37</link>
      <guid>https://dev.to/iankcode/enhancing-api-security-best-practices-for-developers-4m37</guid>
      <description>&lt;p&gt;APIs (Application Programming Interfaces) have become a cornerstone of modern software development, enabling seamless communication and integration between different systems and services. However, with this increased connectivity comes the need for robust security measures to protect sensitive data and prevent unauthorized access. In this blog post, we'll explore various strategies and best practices for enhancing API security to ensure the integrity, confidentiality, and availability of your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understand the Risks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Begin by identifying potential security threats and vulnerabilities specific to your API. Common risks include injection attacks, authentication flaws, insufficient encryption, and improper error handling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conduct a thorough risk assessment to evaluate the potential impact of these threats and prioritize security measures accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implement Authentication and Authorization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Require strong authentication mechanisms such as API keys, OAuth tokens, or JWT (JSON Web Tokens) to verify the identity of clients accessing your API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement fine-grained authorization controls to restrict access to authorized users and limit privileges based on roles and permissions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Use HTTPS for Secure Communication
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Encrypt data transmitted between clients and the API server using HTTPS (HTTP Secure) protocol.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Utilize SSL/TLS certificates to establish a secure connection and prevent eavesdropping, man-in-the-middle attacks, and data tampering.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Apply Input Validation and Sanitization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Validate and sanitize all input received from clients to prevent injection attacks such as SQL injection, XSS (Cross-Site Scripting), and command injection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use parameterized queries, input validation libraries, and output encoding techniques to mitigate these vulnerabilities effectively.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Employ Rate Limiting and Throttling
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Implement rate limiting and throttling mechanisms to prevent abuse, DDoS (Distributed Denial of Service) attacks, and ensure the availability of your API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set appropriate limits on the number of requests per time interval and enforce usage quotas for individual clients or IP addresses.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Secure Data Storage and Transmission
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Encrypt sensitive data at rest using strong encryption algorithms and secure key management practices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement secure transmission protocols and avoid transmitting sensitive information, such as credentials or personal data, in plaintext.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Monitor and Log Activity
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Implement comprehensive logging mechanisms to record API activity, including requests, responses, errors, and security-related events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monitor logs regularly for suspicious or anomalous behavior, such as unusual traffic patterns, unauthorized access attempts, or error responses.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stay Updated and Patch Vulnerabilities
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Keep your API dependencies, frameworks, and libraries up-to-date to address known security vulnerabilities and mitigate emerging threats.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Subscribe to security advisories, follow best practices for secure coding, and proactively patch any identified vulnerabilities in a timely manner.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Unveiling the Power of React.js: A Comprehensive Guide</title>
      <dc:creator>Ian Kamau</dc:creator>
      <pubDate>Mon, 15 Jan 2024 16:21:50 +0000</pubDate>
      <link>https://dev.to/iankcode/unveiling-the-power-of-reactjs-a-comprehensive-guide-8ih</link>
      <guid>https://dev.to/iankcode/unveiling-the-power-of-reactjs-a-comprehensive-guide-8ih</guid>
      <description>&lt;p&gt;In the ever-evolving landscape of web development, React.js has emerged as a game-changer. Developed and maintained by Facebook, React.js, or simply React, is a JavaScript library for building user interfaces. Whether you're a seasoned developer or just starting your journey in the world of web development, understanding React.js is a valuable asset. In this comprehensive guide, we will explore the key concepts, advantages, and best practices that make React.js a top choice for building dynamic and responsive web applications.&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting Started with React.js
&lt;/h1&gt;

&lt;h2&gt;
  
  
  What is React.js?
&lt;/h2&gt;

&lt;p&gt;At its core, React.js is a declarative, efficient, and flexible JavaScript library for building user interfaces. It allows developers to create reusable UI components and manage the state of an application efficiently. React's component-based architecture promotes a modular and maintainable codebase, making it easier to build and scale complex applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Virtual DOM
&lt;/h2&gt;

&lt;p&gt;One of the standout features of React.js is the Virtual DOM. Instead of updating the entire DOM when changes occur, React uses a virtual representation of the DOM to identify the minimal changes required. This results in improved performance and a smoother user experience.&lt;/p&gt;

&lt;h1&gt;
  
  
  Core Concepts
&lt;/h1&gt;

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

&lt;p&gt;In React, everything is a component. Components are the building blocks of a React application, representing different parts of the user interface. Whether it's a button, form, or an entire page, each can be encapsulated within a reusable component.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSX - JavaScript Syntax Extension
&lt;/h2&gt;

&lt;p&gt;React utilizes JSX, a syntax extension for JavaScript that allows you to write HTML-like code within your JavaScript files. JSX makes it more intuitive to describe what the UI should look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const MyComponent = () =&amp;gt; {
  return &amp;lt;div&amp;gt;Hello, React!&amp;lt;/div&amp;gt;;
};

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  State and Props
&lt;/h2&gt;

&lt;p&gt;State and props are fundamental concepts in React. State represents the internal data of a component, while props are external inputs passed to a component. Understanding how to manage state and props is crucial for building dynamic and interactive applications.&lt;/p&gt;

&lt;h1&gt;
  
  
  Advantages of React.js
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Reusability
&lt;/h2&gt;

&lt;p&gt;With React, you can create reusable components, making it easier to maintain and scale your application. This reusability not only improves development speed but also ensures consistency across your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual DOM for Performance
&lt;/h2&gt;

&lt;p&gt;React's use of the Virtual DOM significantly improves performance by reducing the need for direct manipulation of the actual DOM. This results in faster rendering and a smoother user experience, particularly in complex applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strong Community Support
&lt;/h2&gt;

&lt;p&gt;React has a vast and active community, providing an abundance of resources, tutorials, and third-party libraries. Whether you're a beginner or an experienced developer, the React community is a valuable asset for learning and problem-solving.&lt;/p&gt;

&lt;h1&gt;
  
  
  Best Practices
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Component Lifecycle Methods
&lt;/h2&gt;

&lt;p&gt;Understanding the component lifecycle is crucial for managing side effects, fetching data, and optimizing performance. Familiarize yourself with methods like componentDidMount and componentWillUnmount to handle various stages of a component's life.&lt;/p&gt;

&lt;h2&gt;
  
  
  State Management with Hooks
&lt;/h2&gt;

&lt;p&gt;Introduced in React 16.8, hooks revolutionized state management in functional components. Embrace hooks like useState and useEffect to simplify state management and side effect handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component Organization
&lt;/h2&gt;

&lt;p&gt;Keep your components organized and modular. Follow a clear folder structure and naming conventions to enhance readability and maintainability.&lt;/p&gt;

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

&lt;p&gt;React.js has become a cornerstone in modern web development, empowering developers to build dynamic and efficient user interfaces. Whether you're creating a small project or a large-scale application, React's declarative syntax, component-based architecture, and vibrant community make it a powerful tool in your development arsenal.&lt;/p&gt;

&lt;p&gt;This guide has provided a glimpse into the world of React.js, but there's always more to explore. Dive into the official documentation, experiment with building projects, and leverage the wealth of resources available in the React community to enhance your skills. Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Understanding React Routing Using React Router</title>
      <dc:creator>Ian Kamau</dc:creator>
      <pubDate>Fri, 05 Jan 2024 22:55:10 +0000</pubDate>
      <link>https://dev.to/iankcode/understanding-react-routing-using-react-router-19dk</link>
      <guid>https://dev.to/iankcode/understanding-react-routing-using-react-router-19dk</guid>
      <description>&lt;p&gt;&lt;strong&gt;React Router&lt;/strong&gt;: React Router is a library for handling navigation in a React application. It enables the navigation of different components in a React application, making it possible to create a Single Page Application (SPA) where the page doesn't reload when navigating between different views.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring Page Navigation with React Router: A Practical Guide
&lt;/h2&gt;

&lt;p&gt;In this blog post, I'll guide you through the process of seamlessly navigating between pages using React Router.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: Setting up a React Application with Vite JS
&lt;/h2&gt;

&lt;p&gt;To begin your journey, let's create a new React application using Vite JS. Open your terminal and enter the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm create vite@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be prompted to choose a few things, make sure that you choose react and javascript.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The React Router Experience
&lt;/h2&gt;

&lt;p&gt;Once your React application is up and running, we'll dive into the world of React Router. Learn how to efficiently move between pages, enhancing the user experience of your application.&lt;/p&gt;

&lt;h1&gt;
  
  
  Ready to embark on this journey? Let's get started!
&lt;/h1&gt;

&lt;p&gt;After the project has been created, install the dependencies and open it on the vs code or the code editor of your choice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd react-navigation
npm install
code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the project is opened on your code editor, install react-router using the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-router-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When its completed, navigate to &lt;code&gt;App.jsx&lt;/code&gt; and write the code in this image.&lt;/p&gt;

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

&lt;p&gt;Here we are importing &lt;code&gt;Link&lt;/code&gt; from &lt;code&gt;react-router-dom&lt;/code&gt;. &lt;code&gt;Link&lt;/code&gt; is similar to an &lt;code&gt;a&lt;/code&gt; tag and is used in navigation.&lt;br&gt;
Then open the &lt;code&gt;src&lt;/code&gt; directory and create a folder and name it as &lt;code&gt;pages&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;src/pages&lt;/code&gt; create a file name it &lt;code&gt;About.jsx&lt;/code&gt; and write the code in this image.&lt;/p&gt;

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

&lt;p&gt;Navigate to &lt;code&gt;main.jsx&lt;/code&gt;. This is where we will set up our navigation.&lt;br&gt;
To start, we will have to&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;import &lt;code&gt;About&lt;/code&gt; from &lt;code&gt;./pages/About.jsx&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import About from "./pages/About.jsx";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;import &lt;code&gt;createBrowserRouter&lt;/code&gt; and &lt;code&gt;RouterProvider&lt;/code&gt; from &lt;code&gt;react-router-dom&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createBrowserRouter, RouterProvider } from "react-router-dom";
import About from "./pages/About.jsx";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create our router
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const router = createBrowserRouter([
  {
    path: "/",
    element: &amp;lt;App /&amp;gt;,
  },
  {
    path: "/about",
    element: &amp;lt;About /&amp;gt;,
  },
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use &lt;code&gt;createBrowserRouter&lt;/code&gt; to create our routes which accepts an array of objects each having a &lt;code&gt;path&lt;/code&gt; and an &lt;code&gt;element&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Replace &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; inside the &lt;code&gt;&amp;lt;React.StrictMode&amp;gt;&amp;lt;/React.StrictMode&amp;gt;&lt;/code&gt; with &lt;code&gt;RouterProvider&lt;/code&gt; and placing the &lt;code&gt;router&lt;/code&gt; inside it.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;React.StrictMode&amp;gt;
    &amp;lt;RouterProvider router={router} /&amp;gt;
&amp;lt;/React.StrictMode&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

</description>
    </item>
    <item>
      <title>Ruby on Rails Pagination</title>
      <dc:creator>Ian Kamau</dc:creator>
      <pubDate>Fri, 24 Nov 2023 21:48:45 +0000</pubDate>
      <link>https://dev.to/iankcode/ruby-on-rails-pagination-2fm5</link>
      <guid>https://dev.to/iankcode/ruby-on-rails-pagination-2fm5</guid>
      <description>&lt;p&gt;Hey Rubyist!&lt;/p&gt;

&lt;p&gt;I'm excited to share with you a streamlined approach to implementing pagination in your Ruby on Rails blog application. Pagination can be a bit tricky, but fear not! The Ruby community has gifted us with a gem that simplifies the process.&lt;/p&gt;

&lt;p&gt;Let's get started:&lt;/p&gt;

&lt;p&gt;Create a new Ruby on Rails application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   rails new &amp;lt;name_of_your_project&amp;gt;
   &lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;name_of_your_project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate a scaffold for your blog posts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails generate scaffold Post title:string content:text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using a scaffold is convenient as it creates everything from controllers to views to models, saving you time.&lt;/p&gt;

&lt;p&gt;Perform migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures your database is set up with the new Post model.&lt;/p&gt;

&lt;p&gt;Open &lt;strong&gt;&lt;em&gt;application_controller.rb&lt;/em&gt;&lt;/strong&gt; and include the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;include Pagy::Backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;&lt;em&gt;application_helper.rb&lt;/em&gt;&lt;/strong&gt;, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;include Pagy::Frontend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a file named &lt;strong&gt;pagy.rb&lt;/strong&gt; in the &lt;strong&gt;config/initializers&lt;/strong&gt; folder, and insert:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pagy::DEFAULT[:items] = 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we specify that we want 5 items/posts per page.&lt;/p&gt;

&lt;p&gt;Update the index method in &lt;strong&gt;&lt;em&gt;posts_controller.rb&lt;/em&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def index
  @pagy, @posts = pagy(Post.order(created_at: :desc))
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code fetches a paginated list of posts ordered by creation date in descending order, storing pagination information (&lt;strong&gt;@pagy&lt;/strong&gt;) and the posts (&lt;strong&gt;@posts&lt;/strong&gt;) in instance variables.&lt;/p&gt;

&lt;p&gt;In views/posts/index.html.erb, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;% @posts.each do |post| %&amp;gt;
        &amp;lt;h2&amp;gt;
            &amp;lt;%= link_to post.title, post %&amp;gt;
        &amp;lt;/h2&amp;gt;
    &amp;lt;% end %&amp;gt;

    &amp;lt;div&amp;gt;
        &amp;lt;%== pagy_nav(@pagy) if @pagy.pages &amp;gt; 1 %&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This template iterates through the collection of posts, displaying each post's title as a link. If pagination is necessary (more than one page), it displays the pagination navigation at the bottom.&lt;/p&gt;

&lt;p&gt;Now you have a robust pagination setup for your Ruby on Rails blog application! Remember to test thoroughly, consider alternative gems like kaminari if needed, and keep an eye on gem updates for any improvements or changes.&lt;/p&gt;

</description>
      <category>pagygem</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
  </channel>
</rss>
