<?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: Tribal Chief</title>
    <description>The latest articles on DEV Community by Tribal Chief (@tribalchiefjj).</description>
    <link>https://dev.to/tribalchiefjj</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%2F2080173%2F241e3a2d-80b0-48bb-81c9-4c1f8c4edae8.png</url>
      <title>DEV Community: Tribal Chief</title>
      <link>https://dev.to/tribalchiefjj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tribalchiefjj"/>
    <language>en</language>
    <item>
      <title>Nextjs-Dashboard Project .</title>
      <dc:creator>Tribal Chief</dc:creator>
      <pubDate>Tue, 17 Sep 2024 11:21:36 +0000</pubDate>
      <link>https://dev.to/swahilipotdevs/nextjs-dashboard-project--2h91</link>
      <guid>https://dev.to/swahilipotdevs/nextjs-dashboard-project--2h91</guid>
      <description>&lt;p&gt;In the past two weeks, I have embarked on an intensive development journey, creating a sophisticated dashboard application using the Next.js framework along with Typescript, React, and various other technologies. This article delves into the specific tasks I tackled, the technologies I employed, and the insights I gained.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;here is a look at the dashboard app&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

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

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

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

&lt;h2&gt;
  
  
  setting up the project
&lt;/h2&gt;

&lt;p&gt;i used pnpm package manager as it is fast than npm or yarn  i installed it globally bz running&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 -g pnpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;creating a nextjs app i used 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;npx create-next-app@latest nextjs-dashboard --example "https://github.com/vercel/next-learn/tree/main/dashboard/starter-example" --use-pnpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command uses create-next-app, a Command Line Interface (CLI) tool that sets up a Next.js application. In the command above, it  also using the --example flag with the starter example for this project &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;1. Global Styles and Tailwind CSS&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the initial steps in my project was to set up global styles using Tailwind CSS. Tailwind CSS is a utility-first CSS framework that facilitates rapid UI development by allowing developers to apply pre-defined classes directly in the markup. I integrated Tailwind CSS by configuring the tailwind.config.js file and incorporating the necessary CSS imports into the global stylesheet. This setup streamlined the design process and ensured consistent styling across the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding Global Styles&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To apply global styles across the application, i used a global CSS file. In a Next.js project, i import this CSS file in the root layout.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// /app/layout.tsx

import '@/app/ui/global.css';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    &amp;lt;html lang="en"&amp;gt;
      &amp;lt;body&amp;gt;{children}&amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;p&gt;This approach ensures that the styles defined in global.css are applied throughout your app.&lt;/p&gt;

&lt;p&gt;and in   &lt;code&gt;/* /app/ui/global.css */&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;`/* /app/ui/global.css */`
@tailwind base;
@tailwind components;
@tailwind utilities;

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

&lt;/div&gt;



&lt;p&gt;These directives set up Tailwind's base styles, components, and utility classes, providing a foundation for the design&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;&lt;strong&gt;2. CSS Modules&lt;/strong&gt;&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;For more component-specific styling, I employed CSS Modules. CSS Modules offer a scoped approach to CSS, ensuring that styles are applied only to the component they are defined in. This modularity prevents style conflicts and enhances maintainability. I utilized CSS Modules by creating .module.css files and importing them into React components, thereby achieving encapsulated and reusable styles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conditionally Adding Class Names with &lt;code&gt;clsx&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For dynamic styling, i used the clsx utility package. This package helps conditionally apply class names based on certain conditions.&lt;/p&gt;

&lt;p&gt;for instance you will first need to install &lt;code&gt;clsx&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;npm install clsx

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

&lt;/div&gt;



&lt;p&gt;then use in the component&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import clsx from 'clsx';

export default function Button({ isActive }: { isActive: boolean }) {
  return (
    &amp;lt;button className={clsx('p-2 rounded', { 'bg-blue-500': isActive, 'bg-gray-500': !isActive })}&amp;gt;
      Click me
    &amp;lt;/button&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;p&gt;In this example, the button's background color changes based on the isActive prop.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Setting Up and Seeding a PostgreSQL Database for Your Next.js Project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To effectively manage data in your Next.js application, setting up and seeding a PostgreSQL database is essential. This guide will walk you through the process of configuring a PostgreSQL database using Vercel's PostgreSQL service and seeding it with initial data. By the end of this guide, you'll have a fully functional database ready for your Next.js dashboard application.&lt;/p&gt;

&lt;p&gt;Table of Contents :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a GitHub Repository&lt;/li&gt;
&lt;li&gt;Create a Vercel Account and Deploy Your Project&lt;/li&gt;
&lt;li&gt;Create and Link Your PostgreSQL Database&lt;/li&gt;
&lt;li&gt;Seed Your Database&lt;/li&gt;
&lt;li&gt;Exploring and Querying Your Database
-Troubleshooting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a GitHub Repository
&lt;/h2&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;p&gt;If you haven’t set up a repository yet, follow this  &lt;a href="https://docs.github.com/en/get-started/quickstart/create-a-repo" rel="noopener noreferrer"&gt;GitHub guide&lt;/a&gt;.&lt;br&gt;
to get started. For a simplified workflow, consider using the GitHub Desktop App.&lt;/p&gt;

&lt;p&gt;Note: You can use other Git providers like GitLab or Bitbucket if preferred.&lt;/p&gt;

&lt;p&gt;**&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a Vercel Account and Deploy Your Project
&lt;/h2&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;p&gt;** Sign Up for Vercel:**&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Visit vercel.com/signup to create an account.
    Choose the free "Hobby" plan.
    Select "Continue with GitHub" to connect your GitHub and              Vercel accounts.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;** Import and Deploy Your Project:**&lt;br&gt;
        After signing up, you'll be redirected to the Vercel dashboard.&lt;br&gt;
        Click "Import Project" and select your GitHub repository.&lt;br&gt;
        Name your project and click "Deploy."&lt;/p&gt;

&lt;p&gt;boooom!!! there you go the project is now deployed. Vercel will automatically redeploy the application with each push to the main branch and provide instant previews for pull requests.&lt;/p&gt;

&lt;p&gt;Create and Link Your PostgreSQL Database&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Access Your Vercel Dashboard:&lt;br&gt;
    Navigate to your project’s dashboard on Vercel.&lt;br&gt;
    Click "Continue to Dashboard" and select the "Storage" tab.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a New Database:&lt;br&gt;
    Click "Connect Store" → "Create New" → "Postgres" → "Continue."&lt;br&gt;
    Accept the terms, name your database, and set the region to Washington D.C (iad1), which is the default for new Vercel projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy Database Secrets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the .env.local tab in Vercel, click "Show secret," and copy the snippet.

&lt;ul&gt;
&lt;li&gt;Rename the .env.example file in your project to .env and paste the copied contents from Vercel.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Important: Ensure .env is listed in your .gitignore file to prevent exposing your database secrets in version control.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install the Vercel Postgres SDK:&lt;/p&gt;

&lt;p&gt;Run the following command to install the Vercel Postgres SDK:&lt;br&gt;
&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm i @vercel/postgres

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Seed Your Database&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Seeding your database involves populating it with initial data to test your application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Prepare the Seed Script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inside the &lt;code&gt;/app&lt;/code&gt; directory, locate and uncomment the &lt;code&gt;seed&lt;/code&gt; folder. This folder contains &lt;code&gt;route.ts&lt;/code&gt;, a Next.js Route Handler used to seed your database.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the Seed Script:&lt;br&gt;
    Ensure your local development server is running with:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm run dev

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

&lt;/div&gt;



&lt;p&gt;after that you can Navigate to &lt;code&gt;http://localhost:3000/seed&lt;/code&gt; in your browser. You should see a message "Database seeded successfully."&lt;br&gt;
**&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;4. Adding Authentication to Your Next.js Dashboard Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I integrated authentication functionalities, including login and logout features. This process involved updating the login form, implementing secure authentication mechanisms, and ensuring proper session management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;here i will take you through :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting Up NextAuth.js&lt;/li&gt;
&lt;li&gt;Protecting Routes with Middleware&lt;/li&gt;
&lt;li&gt;Implementing Password Hashing&lt;/li&gt;
&lt;li&gt;Adding Authentication Providers&lt;/li&gt;
&lt;li&gt;Updating the Login Form&lt;/li&gt;
&lt;li&gt;Adding Logout Functionality&lt;/li&gt;
&lt;li&gt;Testing Your Implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setting Up NextAuth.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To add authentication to the application,i used NextAuth.js. This library simplifies session management, sign-ins, and sign-outs.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install NextAuth.js&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Run the following command to install the beta version compatible with Next.js 14:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm i next-auth@beta

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

&lt;/div&gt;



&lt;p&gt;2.Generate a Secret Key&lt;/p&gt;

&lt;p&gt;Generate a secret key for encrypting cookies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openssl rand -base64 32

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

&lt;/div&gt;



&lt;p&gt;Add this key to your .env file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AUTH_SECRET=your-secret-key

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Configure NextAuth.js&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create an auth.config.ts file in the root of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// auth.config.ts

import type { NextAuthConfig } from 'next-auth';

export const authConfig = {
  pages: {
    signIn: '/login',
  },
} satisfies NextAuthConfig;

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

&lt;/div&gt;



&lt;p&gt;This configuration sets the custom sign-in page route.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protecting Routes with Middleware&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To ensure only authenticated users can access specific routes, use Next.js Middleware.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create Middleware&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;middleware.ts&lt;/code&gt; file in the root of your project:&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

import NextAuth from 'next-auth';
import { authConfig } from './auth.config';

export default NextAuth(authConfig).auth;

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
};

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

&lt;/div&gt;



&lt;p&gt;This setup ensures that Middleware runs on the specified paths, protecting the routes by checking authentication before rendering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementing Password Hashing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hashing passwords adds an extra layer of security by transforming passwords into a fixed-length string.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create an Authentication Module&lt;/p&gt;

&lt;p&gt;Create an &lt;code&gt;auth.ts&lt;/code&gt; file for handling authentication logic:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;// auth.ts&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;

import NextAuth from 'next-auth';
import { authConfig } from './auth.config';
import Credentials from 'next-auth/providers/credentials';
import bcrypt from 'bcrypt';
import { sql } from '@vercel/postgres';
import type { User } from '@/app/lib/definitions';

async function getUser(email: string): Promise&amp;lt;User | undefined&amp;gt; {
  try {
    const user = await sql&amp;lt;User&amp;gt;`SELECT * FROM users WHERE email=${email}`;
    return user.rows[0];
  } catch (error) {
    console.error('Failed to fetch user:', error);
    throw new Error('Failed to fetch user.');
  }
}

export const { auth, signIn, signOut } = NextAuth({
  ...authConfig,
  providers: [
    Credentials({
      async authorize(credentials) {
        const parsedCredentials = z
          .object({ email: z.string().email(), password: z.string().min(6) })
          .safeParse(credentials);

        if (parsedCredentials.success) {
          const { email, password } = parsedCredentials.data;
          const user = await getUser(email);
          if (user &amp;amp;&amp;amp; await bcrypt.compare(password, user.password)) {
            return user;
          }
        }
        return null;
      },
    }),
  ],
});

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

&lt;/div&gt;



&lt;p&gt;This configuration sets up the Credentials provider and checks if the entered password matches the hashed password stored in the database&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding Authentication Providers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Credentials provider allows users to log in with a username and password. While other providers like Google or GitHub are available, i will focus on Credentials for simplicity.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Update the Authentication Configuration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;// auth.ts&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;

import NextAuth from 'next-auth';
import Credentials from 'next-auth/providers/credentials';
import { authConfig } from './auth.config';

export const { auth, signIn, signOut } = NextAuth({
  ...authConfig,
  providers: [
    Credentials({
      // Configuration for Credentials provider
    }),
  ],
});

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

&lt;/div&gt;



&lt;p&gt;Updating the Login Form&lt;/p&gt;

&lt;p&gt;To connect the authentication logic with the login form, i use React’s useActionState to handle form submissions and display errors.&lt;/p&gt;

&lt;p&gt;1.Create the Login Form&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// app/ui/login-form.tsx&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;'use client';

import { lusitana } from '@/app/ui/fonts';
import { AtSymbolIcon, KeyIcon, ExclamationCircleIcon } from '@heroicons/react/24/outline';
import { ArrowRightIcon } from '@heroicons/react/20/solid';
import { Button } from '@/app/ui/button';
import { useActionState } from 'react';
import { authenticate } from '@/app/lib/actions';

export default function LoginForm() {
  const [errorMessage, formAction, isPending] = useActionState(authenticate, undefined);

  return (
    &amp;lt;form action={formAction} className="space-y-3"&amp;gt;
      &amp;lt;div className="flex-1 rounded-lg bg-gray-50 px-6 pb-4 pt-8"&amp;gt;
        &amp;lt;h1 className={`${lusitana.className} mb-3 text-2xl`}&amp;gt;Please log in to continue.&amp;lt;/h1&amp;gt;
        &amp;lt;div className="w-full"&amp;gt;
          &amp;lt;div&amp;gt;
            &amp;lt;label className="mb-3 mt-5 block text-xs font-medium text-gray-900" htmlFor="email"&amp;gt;Email&amp;lt;/label&amp;gt;
            &amp;lt;div className="relative"&amp;gt;
              &amp;lt;input
                className="peer block w-full rounded-md border border-gray-200 py-[9px] pl-10 text-sm outline-2 placeholder:text-gray-500"
                id="email"
                type="email"
                name="email"
                placeholder="Enter your email address"
                required
              /&amp;gt;
              &amp;lt;AtSymbolIcon className="pointer-events-none absolute left-3 top-1/2 h-[18px] w-[18px] -translate-y-1/2 text-gray-500 peer-focus:text-gray-900" /&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="mt-4"&amp;gt;
            &amp;lt;label className="mb-3 mt-5 block text-xs font-medium text-gray-900" htmlFor="password"&amp;gt;Password&amp;lt;/label&amp;gt;
            &amp;lt;div className="relative"&amp;gt;
              &amp;lt;input
                className="peer block w-full rounded-md border border-gray-200 py-[9px] pl-10 text-sm outline-2 placeholder:text-gray-500"
                id="password"
                type="password"
                name="password"
                placeholder="Enter password"
                required
                minLength={6}
              /&amp;gt;
              &amp;lt;KeyIcon className="pointer-events-none absolute left-3 top-1/2 h-[18px] w-[18px] -translate-y-1/2 text-gray-500 peer-focus:text-gray-900" /&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;Button className="mt-4 w-full" aria-disabled={isPending}&amp;gt;
          Log in &amp;lt;ArrowRightIcon className="ml-auto h-5 w-5 text-gray-50" /&amp;gt;
        &amp;lt;/Button&amp;gt;
        &amp;lt;div className="flex h-8 items-end space-x-1" aria-live="polite" aria-atomic="true"&amp;gt;
          {errorMessage &amp;amp;&amp;amp; (
            &amp;lt;&amp;gt;
              &amp;lt;ExclamationCircleIcon className="h-5 w-5 text-red-500" /&amp;gt;
              &amp;lt;p className="text-sm text-red-500"&amp;gt;{errorMessage}&amp;lt;/p&amp;gt;
            &amp;lt;/&amp;gt;
          )}
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;p&gt;This form connects to the authenticate action, displays pending states, and handles error messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding Logout Functionality&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Adding a logout button to the side navigation to enable users to sign out.&lt;/p&gt;

&lt;p&gt;1.Update the SideNav Component&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// ui/dashboard/sidenav.tsx&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;
import Link from 'next/link';
import NavLinks from '@/app/ui/dashboard/nav-links';
import AcmeLogo from '@/app/ui/acme-logo';
import { PowerIcon } from '@heroicons/react/24/outline';
import { signOut } from '@/auth';

export default function SideNav() {
  return (
    &amp;lt;div className="flex h-full flex-col px-3 py-4 md:px-2"&amp;gt;
      &amp;lt;div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2"&amp;gt;
        &amp;lt;NavLinks /&amp;gt;
        &amp;lt;div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block"&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;form
          action={async () =&amp;gt; {
            'use server';
            await signOut();
          }}
        &amp;gt;
          &amp;lt;button className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"&amp;gt;
            &amp;lt;PowerIcon className="w-6" /&amp;gt;
            &amp;lt;div className="hidden md:block"&amp;gt;Sign Out&amp;lt;/div&amp;gt;
          &amp;lt;/button&amp;gt;
        &amp;lt;/form&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 button calls the &lt;code&gt;signOut&lt;/code&gt; function from &lt;code&gt;auth.ts&lt;/code&gt; to log the user out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing the Implementation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should now be able to log in and out of the application using the credentials:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Email: user@nextmail.com
Password: 123456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;5. Adding Metadata to the Next.js Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is Metadata?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Metadata provides additional details about a webpage that are not visible to users but are crucial for search engines and social media platforms. It resides in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of your HTML document and helps these systems understand and categorize your content more effectively.&lt;/p&gt;

&lt;p&gt;To improve SEO and enhance social media presence, I incorporated metadata into the application. Metadata, embedded within the &lt;/p&gt; element of HTML, provides search engines and social media platforms with additional information about the page. This included adding Open Graph tags to optimize link previews on social media.

&lt;p&gt;&lt;strong&gt;Adding Metadata in Next.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next.js provides a Metadata API that allows you to configure metadata in a flexible and organized manner. You can add metadata either through configuration files or dynamically within your components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Config-Based Metadata&lt;/strong&gt;&lt;br&gt;
 define static metadata in your layout.js or page.js files. Here’s how you can set up basic metadata:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Root Layout Metadata
In the root &lt;code&gt;layout.tsx&lt;/code&gt; file, define a metadata object:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;// app/layout.tsx&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;import { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Acme Dashboard',
  description: 'The official Next.js Course Dashboard, built with App Router.',
  metadataBase: new URL('https://next-learn-dashboard.vercel.sh'),
};

export default function RootLayout() {
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This metadata will be applied globally to all pages that use this layout.&lt;/p&gt;

&lt;p&gt;2.Page-Specific Metadata&lt;/p&gt;

&lt;p&gt;mmh, so To override or add metadata specific to a page, define the metadata object in the page file:&lt;br&gt;
&lt;code&gt;// app/dashboard/invoices/page.tsx&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;import { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Invoices | Acme Dashboard',
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This page-level metadata will override the global metadata for this specific page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dynamic Page Titles with Templates&lt;/strong&gt;&lt;br&gt;
To avoid repetitive metadata and manage dynamic titles more efficiently, i usedt the &lt;code&gt;title.template&lt;/code&gt; field:&lt;/p&gt;

&lt;p&gt;yeey !!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set Up a Template in the Root Layout
&lt;code&gt;// app/layout.tsx&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 { Metadata } from 'next';

export const metadata: Metadata = {
  title: {
    template: '%s | Acme Dashboard',
    default: 'Acme Dashboard',
  },
  description: 'The official Next.js Learn Dashboard built with App Router.',
  metadataBase: new URL('https://next-learn-dashboard.vercel.sh'),
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The %s placeholder will be replaced with the page-specific title.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the Template in a Page
&lt;code&gt;// app/dashboard/invoices/page.tsx&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;export const metadata: Metadata = {
  title: 'Invoices',
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup results in a page title like "Invoices | Acme Dashboard."&lt;/p&gt;

&lt;p&gt;The past two weeks have been a period of significant learning and development. By employing a range of technologies and best practices, I have built a robust and efficient Next.js dashboard application. From optimizing performance to implementing secure data handling, each task has contributed to a comprehensive and scalable solution. This project not only enhanced my technical skills but also provided practical experience in building modern web applications.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
