diff --git a/app/(content)/(community)/communities/page.tsx b/app/(content)/(community)/communities/page.tsx
deleted file mode 100644
index 7a1e2cfa04c7c5585326afa281e80d9b89cc765d..0000000000000000000000000000000000000000
--- a/app/(content)/(community)/communities/page.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-export default function CommunitiesPage() {
-    return (
-        <div>
-            <h1>Community WIP</h1>
-        </div>
-    )
-}
\ No newline at end of file
diff --git a/app/(content)/(search)/search/page.tsx b/app/(content)/(search)/search/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..cb8d68edd738d54202a2ea8066adcaf25b04772a
--- /dev/null
+++ b/app/(content)/(search)/search/page.tsx
@@ -0,0 +1,19 @@
+import { GlobalLayout } from "@/components/global-layout"
+
+export default async function SearchPage() {
+    return (
+        <GlobalLayout
+            mainContent={
+                <>
+                    Search Page
+                </>
+            }
+
+            sideContent={
+                <>
+
+                </>
+            }
+        />
+    )
+}
\ No newline at end of file
diff --git a/app/(content)/(user)/[userid]/(profile)/followers/page.tsx b/app/(content)/(user)/[userid]/(profile)/followers/page.tsx
deleted file mode 100644
index 4c4cc4597bb4c954f24bb86c4cb6a19a8f08dd35..0000000000000000000000000000000000000000
--- a/app/(content)/(user)/[userid]/(profile)/followers/page.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-
-import { GlobalLayout } from "@/components/global-layout"
-import { UserAvatar } from "@/components/user-avatar"
-import { db } from "@/lib/db"
-import { User } from "@prisma/client"
-import Link from "next/link"
-
-export default async function UserFollowers({ params }: { params: { userid: string } }) {
-
-    const fullUser = await db.user.findFirst({
-        where: {
-            username: params.userid
-        },
-        include: {
-            following: true,
-            followers: true
-        }
-    })
-
-    const followers = await db.user.findMany({
-        where: {
-            following: {
-                every: {
-                    followerId: { not: undefined }
-                }
-            },
-            followers: {
-                every: {
-                    followingId: fullUser?.id
-                }
-            }
-        }
-    })
-
-    return (
-        <GlobalLayout
-            mainContent={
-                <div className="flex flex-col w-full">
-                    {followers?.map((follower: User) => (
-                        <div className="flex items-center space-y-6" key={follower.id}>
-                            <Link href={`/${follower.username}`} className="flex flex-row">
-                                <UserAvatar
-                                    user={{ username: follower.username, image: follower.image }}
-                                    className="h-10 w-10"
-                                />
-
-                                <div className="flex flex-col ml-3">
-                                    <span className="font-bold">{follower.name}</span>
-                                    <span className="text-sky-500 text-sm">@{follower.username}</span>
-                                </div>
-                            </Link>
-
-                            <div className="ml-auto">
-                                {/* Followbutton */}
-                            </div>
-                        </div>
-                    ))}
-                </div>
-            }
-        />
-    )
-}
\ No newline at end of file
diff --git a/app/(content)/(user)/[userid]/(profile)/likes/page.tsx b/app/(content)/(user)/[userid]/(profile)/likes/page.tsx
deleted file mode 100644
index d1050ff370eab7ae89abaf9012a3c9d499129093..0000000000000000000000000000000000000000
--- a/app/(content)/(user)/[userid]/(profile)/likes/page.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-export default async function Likes() {
-    return (
-        <div>
-            <h1>Likes Page WIP</h1>
-        </div>
-    )
-}
\ No newline at end of file
diff --git a/app/(content)/(user)/[userid]/(profile)/page.tsx b/app/(content)/(user)/[userid]/(profile)/page.tsx
deleted file mode 100644
index d60b12fe5162b14c03e21f932c9902ad9170be22..0000000000000000000000000000000000000000
--- a/app/(content)/(user)/[userid]/(profile)/page.tsx
+++ /dev/null
@@ -1,157 +0,0 @@
-import FollowButton from "@/components/following-button"
-import GameItem from "@/components/game-item"
-import { GlobalLayout } from "@/components/global-layout"
-import { AspectRatio } from "@/components/ui/aspect-ratio"
-import { Card } from "@/components/ui/card"
-import { Skeleton } from "@/components/ui/skeleton"
-import { UserAvatar } from "@/components/user-avatar"
-import { db } from "@/lib/db"
-import { getFavoriteGames } from "@/lib/igdb"
-import { getCurrentUser } from "@/lib/session"
-import { IGame } from "@/types/igdb-types"
-import { redirect } from "next/navigation"
-
-
-export default async function User({ params }: { params: { userid: string } }) {
-    const user = await getCurrentUser()
-
-    const sessionUser = await db.user.findFirst({
-        where: {
-            id: user?.id
-        },
-        include: {
-            following: true,
-            followers: true
-        }
-    })
-
-    const fullUser = await db.user.findFirst({
-        where: {
-            username: params.userid
-        },
-        include: {
-            following: true,
-            followers: true
-        }
-    })
-
-    if (!fullUser) {
-        redirect('/home')
-    }
-
-    let favoritegames = undefined
-    let playingGames = undefined
-    let finishedGames = undefined
-    let planningGames = undefined
-
-    if (fullUser?.favGameList?.length !== 0 && fullUser?.favGameList?.length != undefined) {
-        favoritegames = await getFavoriteGames(fullUser?.favGameList!)
-    }
-    if (fullUser?.playingGameList?.length !== 0) {
-        playingGames = await getFavoriteGames(fullUser?.playingGameList!)
-    }
-    if (fullUser?.finishedGameList?.length !== 0) {
-        finishedGames = await getFavoriteGames(fullUser?.finishedGameList!)
-    }
-    if (fullUser?.planningGameList?.length !== 0) {
-        planningGames = await getFavoriteGames(fullUser?.planningGameList!)
-    }
-
-    return (
-        <GlobalLayout
-            mainContent={
-                <div className="space-y-6 w-full">
-                    <Card className="overflow-hidden">
-                        <div className="h-64 overflow-hidden">
-                            <AspectRatio ratio={889 / 500} className="bg-slate-600  dark:bg-slate-400">
-                                {/* profile banner */}
-                                {/* <Image
-                                    src={ }
-                                    alt={ }
-                                    fill
-                                    priority
-                                    className="object-center" /> */}
-                            </AspectRatio>
-                        </div>
-                        <div className="p-6 md:p-12 ss:flex">
-                            <UserAvatar
-                                user={{ username: fullUser.username, image: fullUser.image || null }}
-                                className="h-52 w-52 -mt-36"
-                            />
-                            <div className="ml-6 md:ml-12 space-y-3">
-                                <h1 className="text-2xl font-bold">{fullUser.name}</h1>
-                                <h1 className="text-md text-sky-500">@{fullUser.username}</h1>
-                                {/* <h1 className="pt-3">{fullUser.bio}</h1> */}
-                            </div>
-                            <div className="flex justify-start ml-6 md:ml-12 space-y-3">
-                                <FollowButton user={sessionUser!} followingId={fullUser?.id!} />
-                            </div>
-                        </div>
-
-                        <div className="px-6 md:px-12">
-                            {/* <div className="border-b border-gray-400 dark:border-gray-200" /> */}
-                            {/* gweets */}
-                        </div>
-                    </Card >
-
-                    <Card className="overflow-hidden p-6 md:p-12" >
-                        <h1 className="text-2xl font-bold pb-3">Favorite Games</h1>
-                        <div className="grid grid-cols-1 ss:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8 items-center">
-                            {favoritegames ? favoritegames.map((game: IGame) => (
-                                <GameItem id={game.id} name={game.name} cover={game.cover} key={game.id} />
-                            ))
-                                :
-                                <p>No favorites currently...</p>}
-                        </div>
-                    </Card>
-
-                    <Card className="overflow-hidden p-6 md:p-12" >
-                        <h1 className="text-2xl font-bold pb-3">Currently playing</h1>
-                        <div className="grid grid-cols-1 ss:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8 items-center">
-                            {playingGames ? playingGames.map((game: IGame) => (
-                                <GameItem id={game.id} name={game.name} cover={game.cover} key={game.id} />
-                            ))
-                                :
-                                <p>Currently not playing any games...</p>}
-                        </div>
-                    </Card>
-
-                    <Card className="overflow-hidden p-6 md:p-12" >
-                        <h1 className="text-2xl font-bold pb-3">Planning to play</h1>
-                        <div className="grid grid-cols-1 ss:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8 items-center">
-                            {planningGames ? planningGames.map((game: IGame) => (
-                                <GameItem id={game.id} name={game.name} cover={game.cover} key={game.id} />
-                            ))
-                                :
-                                <p>Currently not planning to play any games...</p>}
-                        </div>
-                    </Card>
-
-                    <Card className="overflow-hidden p-6 md:p-12" >
-                        <h1 className="text-2xl font-bold pb-3">Finished Games</h1>
-                        <div className="grid grid-cols-1 ss:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8 items-center">
-                            {finishedGames ? finishedGames.map((game: IGame) => (
-                                <GameItem id={game.id} name={game.name} cover={game.cover} key={game.id} />
-                            ))
-                                :
-                                <p>No finished games...</p>}
-                        </div>
-                    </Card>
-                </div>
-            }
-
-            sideContent={
-                <Card className="p-6 grid items-start gap-2 bg-secondary">
-                    <h1>Media</h1>
-                    <div className="grid grid-cols-1 gap-4">
-                        {Array.from({ length: 2 }, (_, i) => i + 1).map((i) => {
-                            return (
-                                <Skeleton key={i} className="aspect-[264/374] bg-gray-300" />
-                            )
-                        })}
-                    </div>
-                </Card>
-            }
-        />
-    )
-}
\ No newline at end of file
diff --git a/app/(content)/(user)/[username]/(profile)/games/page.tsx b/app/(content)/(user)/[username]/(profile)/games/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..802d5a5df55780ae74012fc3bb61b173eb9fe3e6
--- /dev/null
+++ b/app/(content)/(user)/[username]/(profile)/games/page.tsx
@@ -0,0 +1,10 @@
+import { UserGames } from "@/components/profile/components/user-games"
+import { TabsContent } from "@/components/ui/tabs"
+
+export default async function Games({ params }: { params: { username: string } }) {
+    return (
+        <TabsContent value="games">
+            <UserGames username={params.username} />
+        </TabsContent>
+    )
+}
\ No newline at end of file
diff --git a/app/(content)/(user)/[username]/(profile)/layout.tsx b/app/(content)/(user)/[username]/(profile)/layout.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f79ac51af8414f111f180c3ba913c54d01be8dbe
--- /dev/null
+++ b/app/(content)/(user)/[username]/(profile)/layout.tsx
@@ -0,0 +1,40 @@
+import { GlobalLayout } from "@/components/global-layout"
+import { ProfileNavbar } from "@/components/profile/components/profile-navbar"
+import { ProfileSideContent } from "@/components/profile/components/profile-side-content"
+import { ProfileUserInfo } from "@/components/profile/components/profile-user-info"
+import { Card } from "@/components/ui/card"
+import { UserNotFound } from "@/components/user-not-found"
+import getURL from "@/lib/utils"
+
+// export const dynamic = 'force-dynamic'
+// export const fetchCache = 'force-no-store'
+
+export default async function ProfileLayout({
+    params,
+    children,
+}: {
+    params: { username: string }
+    children: React.ReactNode
+}) {
+    const user = await fetch(getURL(`/api/users/${params.username}`)).then((result) => result.json())
+
+    return (
+        <GlobalLayout
+            mainContent={
+                <Card className="overflow-hidden h-full w-full">
+                    {!user ?
+                        <UserNotFound />
+                        :
+                        <>
+                            <ProfileUserInfo user={user} />
+                            <ProfileNavbar param={params.username}>
+                                {children}
+                            </ProfileNavbar>
+                        </>
+                    }
+                </Card>
+            }
+            sideContent={<ProfileSideContent />}
+        />
+    )
+}
\ No newline at end of file
diff --git a/app/(content)/(user)/[username]/(profile)/likes/page.tsx b/app/(content)/(user)/[username]/(profile)/likes/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4d506758e5217df9ca8db3d7605187210576891e
--- /dev/null
+++ b/app/(content)/(user)/[username]/(profile)/likes/page.tsx
@@ -0,0 +1,13 @@
+import { UserGweets } from "@/components/profile/components/user-gweets"
+import { TabsContent } from "@/components/ui/tabs"
+import { getCurrentUser } from "@/lib/session"
+
+export default async function Likes({ params }: { params: { username: string } }) {
+    const session = await getCurrentUser()
+
+    return (
+        <TabsContent value="likes">
+            <UserGweets username={params.username} sessionname={session?.username as string} />
+        </TabsContent>
+    )
+}
\ No newline at end of file
diff --git a/app/(content)/(user)/[username]/(profile)/media/page.tsx b/app/(content)/(user)/[username]/(profile)/media/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..05724bd0ad11312382de9dd368b7fa59e7b61c81
--- /dev/null
+++ b/app/(content)/(user)/[username]/(profile)/media/page.tsx
@@ -0,0 +1,13 @@
+import { UserGweets } from "@/components/profile/components/user-gweets"
+import { TabsContent } from "@/components/ui/tabs"
+import { getCurrentUser } from "@/lib/session"
+
+export default async function Media({ params }: { params: { username: string } }) {
+    const session = await getCurrentUser()
+
+    return (
+        <TabsContent value="media">
+            <UserGweets username={params.username} sessionname={session?.username as string} />
+        </TabsContent>
+    )
+}
\ No newline at end of file
diff --git a/app/(content)/(user)/[username]/(profile)/page.tsx b/app/(content)/(user)/[username]/(profile)/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..35111b1f5f4208ad3223b38a8fce56d510054e8f
--- /dev/null
+++ b/app/(content)/(user)/[username]/(profile)/page.tsx
@@ -0,0 +1,13 @@
+import { UserGweets } from "@/components/profile/components/user-gweets"
+import { TabsContent } from "@/components/ui/tabs"
+import { getCurrentUser } from "@/lib/session"
+
+export default async function Gweets({ params }: { params: { username: string } }) {
+    const session = await getCurrentUser()
+
+    return (
+        <TabsContent value="gweets">
+            <UserGweets username={params.username} sessionname={session?.username as string} />
+        </TabsContent>
+    )
+}
\ No newline at end of file
diff --git a/app/(content)/(user)/[userid]/(profile)/following/page.tsx b/app/(content)/(user)/[username]/followers/page.tsx
similarity index 100%
rename from app/(content)/(user)/[userid]/(profile)/following/page.tsx
rename to app/(content)/(user)/[username]/followers/page.tsx
diff --git a/app/(content)/(user)/[username]/following/page.tsx b/app/(content)/(user)/[username]/following/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..5ea8f4daa5c5fef29b079a07c60284b12ab27cba
--- /dev/null
+++ b/app/(content)/(user)/[username]/following/page.tsx
@@ -0,0 +1,7 @@
+export default async function Following() {
+    return (
+        <div>
+            <h1>Following Page WIP</h1>
+        </div>
+    )
+}
\ No newline at end of file
diff --git a/app/(content)/(user)/[userid]/status/[id]/page.tsx b/app/(content)/(user)/[username]/status/[id]/page.tsx
similarity index 100%
rename from app/(content)/(user)/[userid]/status/[id]/page.tsx
rename to app/(content)/(user)/[username]/status/[id]/page.tsx
diff --git a/app/(content)/layout.tsx b/app/(content)/layout.tsx
index 9f3fedee59a59c10d952f8fde755d0f6d05d2e98..a868a706afdb2837acc0b38966bae28a5ec8f559 100644
--- a/app/(content)/layout.tsx
+++ b/app/(content)/layout.tsx
@@ -3,12 +3,11 @@ import { Sidebar } from "@/components/nav-sidebar"
 import { dashboardConfig } from "@/lib/config/dashboard"
 import { getCurrentUser } from "@/lib/session"
 
-interface DashboardLayoutProps {
-    children?: React.ReactNode
-}
 export default async function ContentLayout({
     children,
-}: DashboardLayoutProps) {
+}: {
+    children: React.ReactNode
+}) {
     const user = await getCurrentUser()
 
     return (
diff --git a/app/api/followers/route.ts b/app/api/followers/route.ts
deleted file mode 100644
index cc327201fc2833606e01beb869bff9515f15ddb7..0000000000000000000000000000000000000000
--- a/app/api/followers/route.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import { db } from "@/lib/db"
-import { getCurrentUser } from "@/lib/session"
-import { revalidatePath } from "next/cache"
-import { NextRequest, NextResponse } from "next/server"
-
-export async function GET(req: NextRequest) {
-    const sessionUser = await getCurrentUser()
-
-    if (!sessionUser) {
-        return NextResponse.json({ status: 401, message: 'Unauthorized' })
-    }
-    let follows = undefined
-
-    try {
-        follows = await db.follows.findMany({
-            where: {
-                followerId: sessionUser.id
-            }
-        })
-    } catch (error) {
-        console.log("error", error)
-    }
-
-    return NextResponse.json({ status: 200, message: "fetched follows", follows })
-}
-
-export async function PUT(req: NextRequest) {
-    const sessionUser = await getCurrentUser()
-
-    const data = await req.json()
-
-    if (!sessionUser) {
-        return NextResponse.json({ status: 401, message: 'Unauthorized' })
-    }
-
-    try {
-        const dbUser = await db.user.findFirst({
-            where: {
-                id: sessionUser.id
-            }
-        })
-
-        const follow = await db.follows.findFirst({
-            where: {
-                followerId: sessionUser.id,
-                followingId: data.followingId
-            }
-        })
-        console.log("follow", follow)
-
-        if (follow) {
-            // User is already following, so unfollow
-            console.log("delete follow")
-            const delfollow = await db.follows.delete({
-                where: {
-                    followerId_followingId: {
-                        followerId: sessionUser.id,
-                        followingId: data.followingId
-                    }
-
-                }
-            })
-            console.log("del follow:", delfollow)
-        } else {
-            // User is not following, so follow
-            console.log("create follow")
-            await db.follows.create({
-                data: {
-                    followerId: sessionUser.id,
-                    followingId: data.followingId
-                },
-            })
-
-        }
-    } catch (error) {
-        console.log("err", error)
-    }
-    const path = req.nextUrl.searchParams.get('path') || '/'
-    revalidatePath(path)
-
-    return NextResponse.json({ status: 200, message: 'Follow handled' })
-}
\ No newline at end of file
diff --git a/app/api/games/route.ts b/app/api/games/route.ts
index 04d0ee92cb77c31e5331e1d5a346d4e8d440e681..8af8dfb2cf1203f6092531762fdc32620b6532aa 100644
--- a/app/api/games/route.ts
+++ b/app/api/games/route.ts
@@ -37,7 +37,7 @@ export async function GET(req: NextRequest) {
             sortby ? sortby : undefined,
             order ? order : undefined
         )
-        return NextResponse.json(games)
+        return NextResponse.json(games, { status: 200 })
     } catch (error) {
         return NextResponse.json(error, { status: 500 })
     }
diff --git a/app/api/gweets/[id]/route.ts b/app/api/gweets/[id]/route.ts
index a9c706539844ac3becd0dc6549fb977d1e65391d..13408317200201894c5654d6d433ed0068268005 100644
--- a/app/api/gweets/[id]/route.ts
+++ b/app/api/gweets/[id]/route.ts
@@ -3,7 +3,6 @@ import { z } from "zod"
 
 import { db } from "@/lib/db"
 
-// get a single gweet
 export async function GET(request: Request, { params }: { params: { id: string } }) {
     const { id } = params
 
@@ -12,12 +11,10 @@ export async function GET(request: Request, { params }: { params: { id: string }
     const zod = gweetIdSchema.safeParse(id)
 
     if (!zod.success) {
-        return NextResponse.json(
-            {
-                message: "Invalid request body",
-                error: zod.error.formErrors,
-            }, { status: 400 },
-        )
+        return NextResponse.json({
+            message: "Invalid request body",
+            error: zod.error.formErrors,
+        }, { status: 400 })
     }
 
     try {
@@ -96,20 +93,16 @@ export async function GET(request: Request, { params }: { params: { id: string }
         })
 
         if (!gweet) {
-            return NextResponse.json(
-                {
-                    message: "Gweet not found",
-                }, { status: 404 },
-            )
+            return NextResponse.json({
+                message: "Gweet not found",
+            }, { status: 404 })
         }
 
         return NextResponse.json(gweet, { status: 200 })
     } catch (error) {
-        return NextResponse.json(
-            {
-                message: "Something went wrong",
-                error,
-            }, { status: 500 },
-        )
+        return NextResponse.json({
+            message: "Something went wrong",
+            error,
+        }, { status: 500 })
     }
 }
\ No newline at end of file
diff --git a/app/api/gweets/likes/route.ts b/app/api/gweets/likes/route.ts
index 6c298fed796a99885baa5826724286a7097b2550..f560fe5e44116dc9eea9244939c704be0534ef07 100644
--- a/app/api/gweets/likes/route.ts
+++ b/app/api/gweets/likes/route.ts
@@ -3,7 +3,6 @@ import { z } from "zod"
 
 import { db } from "@/lib/db"
 
-// get likes from user
 export async function GET(request: Request) {
     const { searchParams } = new URL(request.url)
     const user_id = searchParams.get("user_id") || undefined
@@ -41,16 +40,13 @@ export async function GET(request: Request) {
 
         return NextResponse.json(gweets, { status: 200 })
     } catch (error: any) {
-        return NextResponse.json(
-            {
-                message: "Something went wrong",
-                error: error.message,
-            }, { status: error.errorCode || 500 },
-        )
+        return NextResponse.json({
+            message: "Something went wrong",
+            error: error.message,
+        }, { status: error.errorCode || 500 })
     }
 }
 
-// like and dislike
 export async function POST(request: Request) {
     const { gweet_id, user_id } = await request.json()
 
@@ -64,12 +60,10 @@ export async function POST(request: Request) {
     const zod = likeSchema.safeParse({ gweet_id, user_id })
 
     if (!zod.success) {
-        return NextResponse.json(
-            {
-                message: "Invalid request body",
-                error: zod.error.formErrors,
-            }, { status: 400 },
-        )
+        return NextResponse.json({
+            message: "Invalid request body",
+            error: zod.error.formErrors,
+        }, { status: 400 })
     }
 
     try {
@@ -87,7 +81,7 @@ export async function POST(request: Request) {
                 },
             })
 
-            return NextResponse.json({ message: "Gweet unliked" })
+            return NextResponse.json({ message: "Gweet unliked" }, { status: 200 })
         } else {
             await db.like.create({
                 data: {
@@ -96,12 +90,12 @@ export async function POST(request: Request) {
                 },
             })
 
-            return NextResponse.json({ message: "Gweet liked" })
+            return NextResponse.json({ message: "Gweet liked" }, { status: 201 })
         }
     } catch (error: any) {
         return NextResponse.json({
             message: "Something went wrong",
             error: error.message,
-        })
+        }, { status: 500 })
     }
 }
\ No newline at end of file
diff --git a/app/api/gweets/regweets/route.ts b/app/api/gweets/regweets/route.ts
index 1cc824193d6af5d418bb82692d660f6a01f709f8..00a446ef38a0c9d8c1c309c4bc75fc2027e96783 100644
--- a/app/api/gweets/regweets/route.ts
+++ b/app/api/gweets/regweets/route.ts
@@ -16,12 +16,10 @@ export async function POST(request: Request) {
     const zod = regweetSchema.safeParse({ gweet_id, user_id })
 
     if (!zod.success) {
-        return NextResponse.json(
-            {
-                message: "Invalid request body",
-                error: zod.error.formErrors,
-            }, { status: 400 },
-        )
+        return NextResponse.json({
+            message: "Invalid request body",
+            error: zod.error.formErrors,
+        }, { status: 400 })
     }
 
     try {
@@ -39,7 +37,7 @@ export async function POST(request: Request) {
                 },
             })
 
-            return NextResponse.json({ message: "Deleted gweet regweet" })
+            return NextResponse.json({ message: "Deleted gweet regweet" }, { status: 200 })
         } else {
             await db.regweet.create({
                 data: {
@@ -48,7 +46,7 @@ export async function POST(request: Request) {
                 },
             })
 
-            return NextResponse.json({ message: "Gweet regweeted" })
+            return NextResponse.json({ message: "Gweet regweeted" }, { status: 201 })
         }
     } catch (error: any) {
         return NextResponse.json({ error: error.message }, { status: 500 })
diff --git a/app/api/gweets/route.ts b/app/api/gweets/route.ts
index cf5ae7257c9c264516e04c3eb90afe5d57ace20a..4f5903d9bf64f21bf738dc71399fe9f920160cc0 100644
--- a/app/api/gweets/route.ts
+++ b/app/api/gweets/route.ts
@@ -4,7 +4,6 @@ import { z } from "zod"
 import { db } from "@/lib/db"
 import { utapi } from "uploadthing/server"
 
-// get gweets
 export async function GET(request: Request) {
     const { searchParams } = new URL(request.url)
 
@@ -30,9 +29,9 @@ export async function GET(request: Request) {
         //         if (gweet && gweet.replyToGweetId) thread = await fetchThread(gweet.replyToGweetId)
         //     }
 
-        //     // logic correct TODO
+        //     // logic correct TODO get all gweets above comment
         //     const prevId = thread.length < 4 ? undefined : thread[thread.length - 1].id
-        //     return NextResponse.json({ gweets: thread, prevId })
+        //     return NextResponse.json({ gweets: thread, prevId }, { status: 200 })
         // }
 
         const gweets = await db.gweet.findMany({
@@ -53,20 +52,35 @@ export async function GET(request: Request) {
                 }),
 
                 ...(type === "user_gweets" && {
-                    authorId: id,
+                    author: {
+                        username: id,
+                    },
                 }),
 
                 ...(type === "user_replies" && {
-                    authorId: id,
+                    author: {
+                        username: id,
+                    },
                     NOT: {
                         replyToGweetId: null,
                     },
                 }),
 
+                ...(type === "user_media" && {
+                    author: {
+                        username: id,
+                    },
+                    media: {
+                        some: {},
+                    },
+                }),
+
                 ...(type === "user_likes" && {
                     likes: {
                         some: {
-                            userId: id,
+                            user: {
+                                username: id,
+                            },
                         },
                     },
                 }),
@@ -113,13 +127,12 @@ export async function GET(request: Request) {
 
         const nextId = gweets.length < take ? undefined : gweets[gweets.length - 1].id
 
-        return NextResponse.json({ gweets, nextId })
+        return NextResponse.json({ gweets, nextId }, { status: 200 })
     } catch (error) {
-        return NextResponse.error()
+        return NextResponse.json(error, { status: 500 })
     }
 }
 
-// create gweet
 export async function POST(request: Request) {
     const { gweet, fileprops } = await request.json()
 
@@ -144,12 +157,10 @@ export async function POST(request: Request) {
     )
 
     if (!zodGweet.success) {
-        return NextResponse.json(
-            {
-                message: "Invalid request body",
-                error: zodGweet.error.formErrors,
-            }, { status: 400 },
-        )
+        return NextResponse.json({
+            message: "Invalid request body",
+            error: zodGweet.error.formErrors,
+        }, { status: 400 })
     }
 
     try {
@@ -174,12 +185,10 @@ export async function POST(request: Request) {
             const zodMedia = mediaSchema.safeParse(mediaArray)
 
             if (!zodMedia.success) {
-                return NextResponse.json(
-                    {
-                        message: "Invalid media body",
-                        error: zodMedia.error.formErrors,
-                    }, { status: 400 },
-                )
+                return NextResponse.json({
+                    message: "Invalid media body",
+                    error: zodMedia.error.formErrors,
+                }, { status: 400 })
             }
 
             await db.media.createMany({
@@ -187,18 +196,15 @@ export async function POST(request: Request) {
             })
         }
 
-        return NextResponse.json(created_gweet, { status: 200 })
+        return NextResponse.json(created_gweet, { status: 201 })
     } catch (error: any) {
-        return NextResponse.json(
-            {
-                message: "Something went wrong",
-                error: error.message,
-            }, { status: error.errorCode || 500 },
-        )
+        return NextResponse.json({
+            message: "Something went wrong",
+            error: error.message,
+        }, { status: error.errorCode || 500 })
     }
 }
 
-// delete gweet
 export async function DELETE(request: Request) {
     const { searchParams } = new URL(request.url)
     const id = searchParams.get("id") as string
@@ -232,14 +238,12 @@ export async function DELETE(request: Request) {
             },
         })
 
-        return NextResponse.json({ message: "Gweet deleted successfully", })
+        return NextResponse.json({ message: "Gweet deleted" }, { status: 200 })
     } catch (error: any) {
-        return NextResponse.json(
-            {
-                message: "Something went wrong",
-                error: error.message,
-            }, { status: error.errorCode || 500 },
-        )
+        return NextResponse.json({
+            message: "Something went wrong",
+            error: error.message,
+        }, { status: error.errorCode || 500 })
     }
 }
 
diff --git a/app/api/hashtags/route.ts b/app/api/hashtags/route.ts
index b4ffb8ef97ebee57128b889e83ab2264d6c5aefe..58ee86ebdecd344bc86dd8d6a5d028eb0c72438b 100644
--- a/app/api/hashtags/route.ts
+++ b/app/api/hashtags/route.ts
@@ -57,18 +57,8 @@ export async function POST(request: Request) {
             }
         }
 
-        return NextResponse.json(
-            {
-                message: "Hashtag(s) created",
-            },
-            { status: 200 },
-        )
+        return NextResponse.json({ message: "Hashtag(s) created", }, { status: 201 })
     } catch (error: any) {
-        return NextResponse.json(
-            {
-                error: error.message,
-            },
-            { status: 500 },
-        )
+        return NextResponse.json({ error: error.message, }, { status: 500 },)
     }
 }
\ No newline at end of file
diff --git a/app/api/route.ts b/app/api/route.ts
index ae6ece829b02260a63fbd9add4bcd171f9e5a215..8672d2778c10343280dc3f6d89d28c530136c270 100644
--- a/app/api/route.ts
+++ b/app/api/route.ts
@@ -9,5 +9,5 @@ export async function GET() {
         return new NextResponse(JSON.stringify({ error: 'unauthorized' }), { status: 401 })
     }
 
-    return NextResponse.json({ authenticated: !!session })
+    return NextResponse.json({ authenticated: !!session }, { status: 200 })
 }
\ No newline at end of file
diff --git a/app/api/signup/route.ts b/app/api/signup/route.ts
index ffb9dbaa646337cc621f18ecf6cd6a80ce49d71b..d754d92b38ce52c4fbd73c70a34a6baa07b9d891 100644
--- a/app/api/signup/route.ts
+++ b/app/api/signup/route.ts
@@ -19,7 +19,7 @@ export async function POST(req: Request) {
         })
 
         if (existingUser) {
-            throw new Error('email already exists')
+            return NextResponse.json({ error: 'Email already exists' }, { status: 422 })
         }
 
         let isUnique = false
@@ -46,21 +46,11 @@ export async function POST(req: Request) {
             }
         })
 
+        return NextResponse.json({ usernameOrEmail: user.email })
+    } catch (error) {
         return NextResponse.json({
-            usernameOrEmail: user.email
-        })
-    } catch (err: any) {
-        if (err.message === 'email already exists') {
-            return new NextResponse(JSON.stringify({
-                error: err.message
-            }), { status: 422 }
-            )
-        }
-
-        return new NextResponse(
-            JSON.stringify({
-                error: err.message
-            }), { status: 500 }
-        )
+            message: "Something went wrong",
+            error,
+        }, { status: 500 })
     }
 }
\ No newline at end of file
diff --git a/app/api/uploadthing/core.ts b/app/api/uploadthing/core.ts
index 3652b13a059642ebb2aca3d32ea7e3ccf7d15291..fbb5b7f38f093a56544208c9935e4c0a846011ec 100644
--- a/app/api/uploadthing/core.ts
+++ b/app/api/uploadthing/core.ts
@@ -4,7 +4,27 @@ import { createUploadthing, type FileRouter } from "uploadthing/next"
 const f = createUploadthing()
 
 export const ourFileRouter = {
-    imageUploader: f({ image: { maxFileSize: "4MB", maxFileCount: 4 } })
+    mediaUploader: f({ image: { maxFileSize: "4MB", maxFileCount: 4 } })
+        .middleware(async ({ req }) => {
+            const user = await getCurrentUser()
+
+            if (!user) throw new Error("Unauthorized")
+
+            return { userId: user.id }
+        })
+        .onUploadComplete(async ({ metadata, file }) => { }),
+
+    imageUploader: f({ image: { maxFileSize: "4MB", maxFileCount: 1 } })
+        .middleware(async ({ req }) => {
+            const user = await getCurrentUser()
+
+            if (!user) throw new Error("Unauthorized")
+
+            return { userId: user.id }
+        })
+        .onUploadComplete(async ({ metadata, file }) => { }),
+
+    bannerUploader: f({ image: { maxFileSize: "4MB", maxFileCount: 1 } })
         .middleware(async ({ req }) => {
             const user = await getCurrentUser()
 
diff --git a/app/api/users/[username]/route.ts b/app/api/users/[username]/route.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e089b9b7276365c1e9cc1d0131039894fc72fe11
--- /dev/null
+++ b/app/api/users/[username]/route.ts
@@ -0,0 +1,107 @@
+import { db } from "@/lib/db"
+import { NextResponse } from "next/server"
+import { z } from "zod"
+
+export async function GET(request: Request, context: { params: { username: string } }) {
+    const { username } = context.params
+
+    const idSchema = z.string()
+    const zod = idSchema.safeParse(username)
+
+    if (!zod.success) {
+        return NextResponse.json(zod.error, { status: 400 })
+    }
+
+    try {
+        const user = await db.user.findUnique({
+            where: {
+                username,
+            },
+
+            select: {
+                id: true,
+                name: true,
+                username: true,
+                email: true,
+                image: true,
+                banner: true,
+
+                createdAt: true,
+                bio: true,
+                location: true,
+                website: true,
+                followers: true,
+                following: true,
+
+                _count: {
+                    select: {
+                        followers: true,
+                        following: true,
+                    },
+                },
+            },
+        })
+
+        return NextResponse.json(user, { status: 200 })
+    } catch (error: any) {
+        return NextResponse.json(error.message, { status: 500 })
+    }
+}
+
+export async function PUT(request: Request) {
+    const {
+        userId,
+        name,
+        bio,
+        location,
+        website,
+        banner,
+        image,
+    } = await request.json()
+
+    const userSchema = z
+        .object({
+            userId: z.string().cuid(),
+            name: z.string().min(1).max(50),
+            bio: z.string().max(160).optional(),
+            location: z.string().max(30).optional(),
+            website: z.string().max(100).optional(),
+            banner: z.string().optional(),
+            image: z.string().optional(),
+        })
+        .strict()
+
+    const zod = userSchema.safeParse({
+        userId,
+        name,
+        bio,
+        location,
+        website,
+        banner,
+        image,
+    })
+
+    if (!zod.success) {
+        return NextResponse.json(zod.error, { status: 400 })
+    }
+
+    try {
+        const user = await db.user.update({
+            where: {
+                id: userId,
+            },
+            data: {
+                name,
+                bio,
+                location,
+                website,
+                banner,
+                image,
+            },
+        })
+
+        return NextResponse.json(user, { status: 200 })
+    } catch (error: any) {
+        return NextResponse.json(error.message, { status: 500 })
+    }
+}
\ No newline at end of file
diff --git a/app/api/users/favgameslist/route.ts b/app/api/users/favgameslist/route.ts
index 7b06bead77749d765ee284b985b0063922027025..67bd79f2c75a37bc649488a92df2e41cefd8d826 100644
--- a/app/api/users/favgameslist/route.ts
+++ b/app/api/users/favgameslist/route.ts
@@ -4,13 +4,13 @@ import { revalidatePath } from "next/cache"
 import { NextRequest, NextResponse } from "next/server"
 
 export async function PUT(req: NextRequest) {
-    const user = await getCurrentUser()
+    const session = await getCurrentUser()
 
-    if (!user) {
+    if (!session) {
         return NextResponse.json({ status: 401, message: 'Unauthorized' })
     }
 
-    const userId = user.id
+    const userId = session.id
     const data = await req.json()
     data.gameId = parseInt(data.gameId)
 
@@ -51,9 +51,9 @@ export async function PUT(req: NextRequest) {
         const path = req.nextUrl.searchParams.get('path') || '/'
         revalidatePath(path)
 
-        return NextResponse.json({ status: 201, message: 'Game Hinzugefügt' })
+        return NextResponse.json({ message: 'Game added' }, { status: 201 })
 
     } catch (error: any) {
-        return NextResponse.json({ status: 500, message: error.message })
+        return NextResponse.json({ message: error.message }, { status: 500 })
     }
 }
\ No newline at end of file
diff --git a/app/api/users/follow/route.ts b/app/api/users/follow/route.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7e36eb5c10dac51dd32462b4c50a6f88623a9e27
--- /dev/null
+++ b/app/api/users/follow/route.ts
@@ -0,0 +1,127 @@
+import { db } from "@/lib/db"
+import { getCurrentUser } from "@/lib/session"
+import { NextResponse } from "next/server"
+import { z } from "zod"
+
+// get following or followers information
+export async function GET(request: Request) {
+    const { searchParams } = new URL(request.url)
+    const userId = searchParams.get("userId") || undefined
+    const type = searchParams.get("type") || undefined
+
+    const userIdSchema = z.string().cuid().optional()
+    const zod = userIdSchema.safeParse(userId)
+
+    if (!zod.success) {
+        return NextResponse.json(zod.error, { status: 400 })
+    }
+
+    try {
+        if (type === "followers") {
+            const followers = await db.user
+                .findUnique({
+                    where: {
+                        id: userId,
+                    },
+                })
+                .followers()
+            return NextResponse.json(followers, { status: 200 })
+        } else if (type === "following") {
+            const following = await db.user
+                .findUnique({
+                    where: {
+                        id: userId,
+                    },
+                })
+                .following()
+
+            return NextResponse.json(following, { status: 200 })
+        }
+    } catch (error: any) {
+        return NextResponse.json(error.message, { status: 500 })
+    }
+}
+
+// follow a user
+export async function PUT(request: Request) {
+    const session = await getCurrentUser()
+    const { userId } = await request.json()
+
+    const followerIdSchema = z
+        .object({
+            userId: z.string().cuid(),
+        })
+        .strict()
+
+    const zod = followerIdSchema.safeParse({ userId })
+
+    if (!zod.success) {
+        return NextResponse.json(zod.error, { status: 400 })
+    }
+
+    try {
+        await db.user.update({
+            where: {
+                id: userId,
+            },
+
+            data: {
+                followers: {
+                    connect: {
+                        id: session?.id,
+                    },
+                },
+            },
+        })
+
+        return NextResponse.json(
+            {
+                message: "followed",
+            }, { status: 200 }
+        )
+    } catch (error: any) {
+        return NextResponse.json(error.message, { status: 500 })
+    }
+}
+
+// unfollow a user
+export async function DELETE(request: Request) {
+    const session = await getCurrentUser()
+    const { userId } = await request.json()
+
+    const followerIdSchema = z
+        .object({
+            userId: z.string().cuid(),
+        })
+        .strict()
+
+    const zod = followerIdSchema.safeParse({ userId })
+
+    if (!zod.success) {
+        return NextResponse.json(zod.error, { status: 400 })
+    }
+
+    try {
+        await db.user.update({
+            where: {
+                id: userId,
+            },
+
+            data: {
+                followers: {
+                    disconnect: {
+                        id: session?.id,
+                    },
+                },
+            },
+        })
+
+        return NextResponse.json(
+            {
+                message: "unfollowed",
+            }, { status: 200 },
+        )
+    } catch (error: any) {
+        return NextResponse.json(error.message, { status: 500 })
+    }
+}
\ No newline at end of file
diff --git a/app/api/gamelists/route.ts b/app/api/users/gamelists/route.ts
similarity index 79%
rename from app/api/gamelists/route.ts
rename to app/api/users/gamelists/route.ts
index 7c578b3ef8e25ba5431237bbfe24b459b46b5dd6..629f995d73d5ada83642ee9c5079cb9e421aed31 100644
--- a/app/api/gamelists/route.ts
+++ b/app/api/users/gamelists/route.ts
@@ -8,11 +8,11 @@ export async function PUT(req: NextRequest) {
     const sessionUser = await getCurrentUser()
 
     const data: User = await req.json()
-    console.log("userid", sessionUser!.id, "formdataid", data.id)
+
     if (!sessionUser || sessionUser.id != data.id) {
-        return NextResponse.json({ status: 401, message: 'Unauthorized' })
+        return NextResponse.json({ message: 'Unauthorized' }, { status: 401 })
     }
-    console.log("put list")
+
     try {
         const dbUser = await db.user.findFirst({
             where: {
@@ -41,11 +41,12 @@ export async function PUT(req: NextRequest) {
                 }
             })
         }
-    } catch (error) {
 
-    }
-    const path = req.nextUrl.searchParams.get('path') || '/'
-    revalidatePath(path)
+        const path = req.nextUrl.searchParams.get('path') || '/'
+        revalidatePath(path)
 
-    return NextResponse.json({ status: 201, message: 'Game Hinzugefügt' })
+        return NextResponse.json({ message: 'Game added' }, { status: 201 })
+    } catch (error: any) {
+        return NextResponse.json({ message: error.message }, { status: 500 })
+    }
 }
\ No newline at end of file
diff --git a/app/api/users/route.ts b/app/api/users/route.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7f3814a20547512e139f8877290c2d958691fed8
--- /dev/null
+++ b/app/api/users/route.ts
@@ -0,0 +1,43 @@
+import { db } from "@/lib/db"
+import { NextResponse } from "next/server"
+import { z } from "zod"
+
+export async function GET(request: Request) {
+    const { searchParams } = new URL(request.url)
+    const id = searchParams.get("id") || undefined
+    const idSchema = z.string().cuid().optional()
+
+    const zod = idSchema.safeParse(id)
+
+    if (!zod.success) {
+        return NextResponse.json(zod.error, { status: 400 })
+    }
+
+    try {
+        const users = await db.user.findMany({
+            where: {
+                NOT: {
+                    id,
+                },
+            },
+
+            orderBy: {
+                createdAt: "desc",
+            },
+
+            select: {
+                id: true,
+                name: true,
+                username: true,
+                email: true,
+                image: true,
+                following: true,
+                followers: true,
+            },
+        })
+
+        return NextResponse.json(users, { status: 200 })
+    } catch (error: any) {
+        return NextResponse.json(error.message, { status: 500 })
+    }
+}
\ No newline at end of file
diff --git a/components/add-game-to-finished-list.tsx b/components/add-game-to-finished-list.tsx
index bc37572a92fb214c02fa29e9ac094296782b856e..6f8ec4fec6592b7d0ef72a7b9c7fb5e990d99822 100644
--- a/components/add-game-to-finished-list.tsx
+++ b/components/add-game-to-finished-list.tsx
@@ -33,7 +33,7 @@ export default function AddGameToFinishedList(props: { gameId: string, user: Use
         formData.id = user.id
         formData.finishedGameList = props.user.finishedGameList.filter((id) => id !== gameId)
         console.log(formData.finishedGameList)
-        const response = await fetch('/api/gamelists', {
+        const response = await fetch('/api/users/gamelists', {
             method: 'PUT',
             body: JSON.stringify(formData)
         })
@@ -52,7 +52,7 @@ export default function AddGameToFinishedList(props: { gameId: string, user: Use
         formData.id = user.id
         props.user.finishedGameList.push(gameId)
         formData.finishedGameList = props.user.finishedGameList
-        const response = await fetch('/api/gamelists', {
+        const response = await fetch('/api/users/gamelists', {
             method: 'PUT',
             body: JSON.stringify(formData)
         })
diff --git a/components/add-game-to-plan-list.tsx b/components/add-game-to-plan-list.tsx
index 61f62e85fa0c4ad352a0b7b680769904b34c91d4..9de2099cfc9a791adeeb582fa51f2951246130ea 100644
--- a/components/add-game-to-plan-list.tsx
+++ b/components/add-game-to-plan-list.tsx
@@ -33,7 +33,7 @@ export default function AddGameToPlanList(props: { gameId: string, user: User })
         formData.id = user.id
         formData.planningGameList = props.user.planningGameList.filter((id) => id !== gameId)
         console.log(formData.planningGameList)
-        const response = await fetch('/api/gamelists', {
+        const response = await fetch('/api/users/gamelists', {
             method: 'PUT',
             body: JSON.stringify(formData)
         })
@@ -52,7 +52,7 @@ export default function AddGameToPlanList(props: { gameId: string, user: User })
         formData.id = user.id
         props.user.planningGameList.push(gameId)
         formData.planningGameList = props.user.planningGameList
-        const response = await fetch('/api/gamelists', {
+        const response = await fetch('/api/users/gamelists', {
             method: 'PUT',
             body: JSON.stringify(formData)
         })
diff --git a/components/add-game-to-playing-list.tsx b/components/add-game-to-playing-list.tsx
index 73e8067728687051a7b63e67640a5a5c014238d7..81232c6e72774bc9e86d07f90d7970f1fc070fd0 100644
--- a/components/add-game-to-playing-list.tsx
+++ b/components/add-game-to-playing-list.tsx
@@ -33,7 +33,7 @@ export default function AddGameToPlayingList(props: { gameId: string, user: User
         formData.id = user.id
         formData.playingGameList = props.user.playingGameList.filter((id) => id !== gameId)
         console.log(formData.playingGameList)
-        const response = await fetch('/api/gamelists', {
+        const response = await fetch('/api/users/gamelists', {
             method: 'PUT',
             body: JSON.stringify(formData)
         })
@@ -52,7 +52,7 @@ export default function AddGameToPlayingList(props: { gameId: string, user: User
         formData.id = user.id
         props.user.playingGameList.push(gameId)
         formData.playingGameList = props.user.playingGameList
-        const response = await fetch('/api/gamelists', {
+        const response = await fetch('/api/users/gamelists', {
             method: 'PUT',
             body: JSON.stringify(formData)
         })
diff --git a/components/create-gweet/api/post-gweet.ts b/components/create-gweet/api/post-gweet.ts
index 76c02d36fcbeb61b585fa643da4bcb8bf334dc7e..9f10a8dce0a6907e68aa6d33c80f4b31b607b70c 100644
--- a/components/create-gweet/api/post-gweet.ts
+++ b/components/create-gweet/api/post-gweet.ts
@@ -25,7 +25,7 @@ export const postGweet = async ({
     try {
         let fileprops: { fileUrl: string; fileKey: string }[] = []
         if (files.length > 0) {
-            fileprops = await uploadFiles({ files, endpoint: 'imageUploader' })
+            fileprops = await uploadFiles({ files, endpoint: 'mediaUploader' })
         }
 
         const data = await fetch('/api/gweets', {
diff --git a/components/follow-button.tsx b/components/follow-button.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..294bf2700fc7194870e5a28903a44378897ee6e3
--- /dev/null
+++ b/components/follow-button.tsx
@@ -0,0 +1,78 @@
+"use client"
+
+import { useRouter } from "next/navigation"
+import { useEffect, useState } from "react"
+import { Icons } from "./icons"
+import { useFollow } from "./profile/hooks/use-follow"
+import { Button } from "./ui/button"
+import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./ui/dialog"
+
+export const FollowButton = ({
+    userId,
+    username,
+    isFollowing = false,
+}: {
+    userId: string
+    username: string
+    isFollowing?: boolean
+}) => {
+    const followMutation = useFollow("follow")
+    const unfollowMutation = useFollow("unfollow")
+
+    const [text, setText] = useState<"Following" | "Unfollow">("Following")
+    const [isHovered, setIsHovered] = useState(false)
+    const [open, setOpen] = useState(false)
+
+    const router = useRouter()
+
+    useEffect(() => {
+        if (followMutation.isSuccess) {
+            router.refresh()
+        }
+        if (unfollowMutation.isSuccess) {
+            setOpen(false)
+            router.refresh()
+        }
+    }, [router, followMutation.isSuccess, unfollowMutation.isSuccess])
+
+    return (
+        <Dialog open={open} onOpenChange={setOpen}>
+            {isFollowing ? (
+                <DialogTrigger asChild>
+                    <Button variant={`${isHovered ? "destructive" : "outline"}`} size="lg"
+                        className="w-24"
+                        onMouseEnter={() => {
+                            setText("Unfollow")
+                            setIsHovered(true)
+                        }}
+                        onMouseOut={() => {
+                            setText("Following")
+                            setIsHovered(false)
+                        }}>
+                        {text}
+                    </Button>
+                </DialogTrigger>
+            ) : (
+                <Button size="lg" onClick={() => followMutation.mutate({ userId })}>
+                    Follow
+                </Button>
+            )}
+            <DialogContent>
+                <DialogHeader>
+                    <DialogTitle>Unfollow @{username}?</DialogTitle>
+                    <DialogDescription>
+                        You can still view their profile, unless their Gweets are protected.
+                    </DialogDescription>
+                </DialogHeader>
+                <DialogFooter>
+                    <Button type="submit" onClick={() => unfollowMutation.mutate({ userId })} disabled={unfollowMutation.isLoading}>
+                        {unfollowMutation.isLoading && (
+                            <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
+                        )}
+                        Unfollow
+                    </Button>
+                </DialogFooter>
+            </DialogContent>
+        </Dialog>
+    )
+}
\ No newline at end of file
diff --git a/components/following-button.tsx b/components/following-button.tsx
deleted file mode 100644
index b5eb3f4e51b564dad1cd30b38b77fecce04e4dd7..0000000000000000000000000000000000000000
--- a/components/following-button.tsx
+++ /dev/null
@@ -1,75 +0,0 @@
-"use client"
-
-import { Follows, Prisma } from '@prisma/client'
-import { useSession } from 'next-auth/react'
-import { usePathname } from "next/navigation"
-import { useEffect, useState } from 'react'
-import { Button } from './ui/button'
-
-// 1: Define a type that includes the relation to `Post`
-const userWithFollows = Prisma.validator<Prisma.UserArgs>()({
-    include: { followers: true, following: true },
-})
-
-// 2: Define a type that only contains a subset of the scalar fields
-const userPersonalData = Prisma.validator<Prisma.UserArgs>()({
-    select: { email: true, name: true },
-})
-
-// 3: This type will include a user and all their posts
-type UserWithFollows = Prisma.UserGetPayload<typeof userWithFollows>
-
-
-export default function FollowButton({ user, followingId }: { user: UserWithFollows; followingId: string }) {
-    const [isFollowing, setIsFollowing] = useState(false)
-    const [follows, setFollows] = useState([])
-    const [buttonPressed, setButtonPress] = useState(false)
-
-    const pathname = usePathname()
-    const { data: session } = useSession()
-
-    async function fetchFollows() {
-
-        try {
-            const response = await fetch('/api/followers')
-
-            const data = await response.json()
-            setFollows(data.follows)
-            setIsFollowing(false)
-            data.follows?.forEach((f: Follows) => {
-
-                if (f.followerId == user.id && f.followingId == followingId) {
-                    setIsFollowing(true)
-                    return
-                }
-            })
-        } catch (error) {
-
-        }
-    }
-    useEffect(() => {
-        fetchFollows()
-        // TODO: fix this warning
-        // eslint-disable-next-line react-hooks/exhaustive-deps
-    }, [buttonPressed])
-
-    async function handleFollow(e: any) {
-        e.preventDefault()
-
-        const response = await fetch('/api/followers', {
-            method: 'PUT',
-            body: JSON.stringify({ user, followingId })
-        })
-
-        setButtonPress(!buttonPressed)
-    }
-
-    return (
-        <>
-            {pathname !== `/${session?.user.username}` &&
-                <Button onClick={handleFollow}>
-                    {isFollowing ? 'Unfollow' : 'Follow'}
-                </Button>}
-        </>
-    )
-}
\ No newline at end of file
diff --git a/components/gweets/components/infinite-gweets.tsx b/components/gweets/components/infinite-gweets.tsx
index 2e8f73dd51094bb4dec000cd790196a93c6f4341..8952722cfe4c7ae68dcd00d6fd62dc4fb3d69d0c 100644
--- a/components/gweets/components/infinite-gweets.tsx
+++ b/components/gweets/components/infinite-gweets.tsx
@@ -49,9 +49,11 @@ export const InfiniteGweets = ({
                             key={gweet.id}
                         >
                             <Gweet gweet={gweet} />
-                            <div className="px-6">
-                                <Separator className="my-3" />
-                            </div>
+                            {index !== page.gweets.length - 1 && (
+                                <div className="px-6">
+                                    <Separator className="my-3" />
+                                </div>
+                            )}
                         </div>
                     ))
                 })}
diff --git a/components/icons.tsx b/components/icons.tsx
index 52f4a7e8c3ba0bc159f46798508a44b08580c2be..4c26e62a29788efefa0d39f372ab75225caaf343 100644
--- a/components/icons.tsx
+++ b/components/icons.tsx
@@ -4,6 +4,7 @@ import {
     ArrowRight,
     ArrowUpToLine,
     BellRing,
+    CalendarRange,
     Check,
     ChevronLeft,
     ChevronRight,
@@ -18,8 +19,10 @@ import {
     Image,
     Laptop,
     Link,
+    Link2,
     Loader2,
     LucideProps,
+    MapPin,
     MessageCircle,
     Moon,
     MoreHorizontal,
@@ -29,6 +32,7 @@ import {
     Repeat2,
     Settings,
     SunMedium,
+    SwitchCamera,
     Trash,
     User,
     Users,
@@ -87,6 +91,10 @@ export const Icons: IconsType = {
     trash: Trash, // Delete Button
     link: Link, // Link Button
     regweet: Repeat2, // Regweet Button
+    location: MapPin, // Location Button
+    website: Link2, // Website Button
+    calendar: CalendarRange, // Calendar Button
+    camera: SwitchCamera, // Change Image Button
     post: FileText,
     page: File,
     media: Image,
diff --git a/components/nav-sidebar.tsx b/components/nav-sidebar.tsx
index 7d5808ab9c5a591ec5d9da89f0b49989c0c9d604..b8f579a029ec8e3811f75d96b540622a023f136e 100644
--- a/components/nav-sidebar.tsx
+++ b/components/nav-sidebar.tsx
@@ -31,7 +31,7 @@ export const Sidebar = ({ items, user }: { items: SidebarNavItem[], user: User |
                             <span
                                 className={cn(
                                     "group flex items-center rounded-md px-3 py-2 font-medium hover:bg-accent hover:text-accent-foreground",
-                                    path === item.href ? "bg-accent" : "transparent",
+                                    path.startsWith(item.href) ? "bg-accent" : "transparent",
                                     item.disabled && "cursor-not-allowed opacity-80"
                                 )}
                             >
diff --git a/components/profile/api/follow-user.ts b/components/profile/api/follow-user.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bfa5bf2593a412d570c745dcbf6e2ac3f5027886
--- /dev/null
+++ b/components/profile/api/follow-user.ts
@@ -0,0 +1,12 @@
+export const followUser = async (userId: string) => {
+    try {
+        const data = await fetch("/api/users/follow", {
+            method: "PUT",
+            body: JSON.stringify({ userId }),
+        }).then((result) => result.json())
+
+        return data
+    } catch (error: any) {
+        return error.message
+    }
+}
\ No newline at end of file
diff --git a/components/profile/api/get-follows.ts b/components/profile/api/get-follows.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dc83afb8de3fc7b2dc5c40f80186464b3f0ad418
--- /dev/null
+++ b/components/profile/api/get-follows.ts
@@ -0,0 +1,10 @@
+export const getFollows = async (id: string | undefined, type: string | undefined) => {
+    try {
+        const data = await fetch(`/api/users/follow?type=${type}&user_id=${id}`)
+            .then((result) => result.json())
+
+        return data
+    } catch (error: any) {
+        return error.message
+    }
+}
\ No newline at end of file
diff --git a/components/profile/api/get-user-likes.ts b/components/profile/api/get-user-likes.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1a1ebd4dd3a14dfa0d5bf18823a772543771c8b4
--- /dev/null
+++ b/components/profile/api/get-user-likes.ts
@@ -0,0 +1,10 @@
+export const getUserLikes = async (id: string | undefined) => {
+    try {
+        const data = await fetch(`/api/tweets/likes?user_id=${id}`)
+            .then((result) => result.json())
+
+        return data
+    } catch (error: any) {
+        return error.message
+    }
+}
\ No newline at end of file
diff --git a/components/profile/api/get-user.ts b/components/profile/api/get-user.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7942e09c24179c36a5b0f26146d34552920e20b7
--- /dev/null
+++ b/components/profile/api/get-user.ts
@@ -0,0 +1,25 @@
+export const getUser = async (username: string | undefined) => {
+    try {
+        const user = await fetch(`/api/users/${username}`)
+            .then((result) => result.json())
+
+        return user
+    } catch (error: any) {
+        if (error.response) {
+            // The request was made and the server responded with a status code
+            // that falls out of the range of 2xx
+            console.log(error.response.data)
+            console.log(error.response.status)
+            console.log(error.response.headers)
+        } else if (error.request) {
+            // The request was made but no response was received
+            // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
+            // http.ClientRequest in node.js
+            console.log(error.request)
+        } else {
+            // Something happened in setting up the request that triggered an Error
+            console.log("Error", error.message)
+        }
+        console.log(error.config)
+    }
+}
\ No newline at end of file
diff --git a/components/profile/api/get-users.ts b/components/profile/api/get-users.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5456b72d31a767f8a14246df0635d68ad20fdc21
--- /dev/null
+++ b/components/profile/api/get-users.ts
@@ -0,0 +1,10 @@
+export const getUsers = async (id?: string) => {
+    try {
+        const data = await fetch(`/api/users${id ? `?id=${id}` : ""}`)
+            .then((result) => result.json())
+
+        return data
+    } catch (error: any) {
+        return error.response.data
+    }
+}
\ No newline at end of file
diff --git a/components/profile/api/unfollow-user.ts b/components/profile/api/unfollow-user.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1d23d10d70f67484e60bdaf1f8ef8f59f48bf422
--- /dev/null
+++ b/components/profile/api/unfollow-user.ts
@@ -0,0 +1,12 @@
+export const unfollowUser = async (userId: string) => {
+    try {
+        const data = await fetch(`/api/users/follow`, {
+            method: "DELETE",
+            body: JSON.stringify({ userId }),
+        }).then((result) => result.json())
+
+        return data
+    } catch (error: any) {
+        return error.message
+    }
+}
\ No newline at end of file
diff --git a/components/profile/api/update-profile.ts b/components/profile/api/update-profile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..861e2c8125f87632faf323aee9d929a97e6f4ecb
--- /dev/null
+++ b/components/profile/api/update-profile.ts
@@ -0,0 +1,42 @@
+import { uploadFiles } from "@/lib/uploadthing"
+import { IProfile } from "./../types/index"
+
+export const updateProfile = async ({
+    profile,
+    userId,
+}: {
+    profile: IProfile
+    userId: string
+}) => {
+    if (!profile) return
+
+    try {
+        let bannerfileprops: { fileUrl: string; fileKey: string } = { fileUrl: '', fileKey: '' }
+        let imagefileprops: { fileUrl: string; fileKey: string } = { fileUrl: '', fileKey: '' }
+
+        if (profile.banner.file) {
+            [bannerfileprops] = await uploadFiles({ files: [profile.banner.file], endpoint: 'mediaUploader' })
+        }
+
+        if (profile.image.file) {
+            [imagefileprops] = await uploadFiles({ files: [profile.image.file], endpoint: 'imageUploader' })
+        }
+        console.log('bannerfileprops', profile.banner.removed)
+        const data = await fetch(`/api/users/${userId}`, {
+            method: 'PUT',
+            body: JSON.stringify({
+                userId,
+                name: profile.name,
+                bio: profile.bio,
+                location: profile.location,
+                website: profile.website,
+                banner: profile.banner.removed ? "" : bannerfileprops.fileUrl !== "" ? bannerfileprops.fileUrl : undefined,
+                image: imagefileprops.fileUrl !== "" ? imagefileprops.fileUrl : undefined,
+            })
+        }).then((result) => result.json())
+
+        return data
+    } catch (error: any) {
+        return error.Message
+    }
+}
\ No newline at end of file
diff --git a/components/profile/components/edit-profile-modal.tsx b/components/profile/components/edit-profile-modal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..bf4dbc6b54919ed0a4591bcea1404d6151da6591
--- /dev/null
+++ b/components/profile/components/edit-profile-modal.tsx
@@ -0,0 +1,359 @@
+"use client"
+
+import { Icons } from "@/components/icons"
+import { AspectRatio } from "@/components/ui/aspect-ratio"
+import { Button } from "@/components/ui/button"
+import { Card } from "@/components/ui/card"
+import {
+    Dialog,
+    DialogContent,
+    DialogDescription,
+    DialogFooter,
+    DialogHeader,
+    DialogTitle,
+    DialogTrigger,
+} from "@/components/ui/dialog"
+import { Form, FormControl, FormField, FormItem, FormMessage } from "@/components/ui/form"
+import { Input } from "@/components/ui/input"
+import { Label } from "@/components/ui/label"
+import { Textarea } from "@/components/ui/textarea"
+import { toast } from "@/components/ui/use-toast"
+import { UserAvatar } from "@/components/user-avatar"
+import { zodResolver } from "@hookform/resolvers/zod"
+import Image from "next/image"
+import { useRouter } from "next/navigation"
+import { use, useEffect, useRef, useState } from "react"
+import { useForm } from "react-hook-form"
+import { z } from "zod"
+import { useUpdateProfile } from "../hooks/use-update-profile"
+import { IProfile, IUser } from "../types"
+
+const FormSchema = z.object({
+    name: z.string().min(1, "Name can't be blank").max(50, "Name can't be more than 50 characters"),
+    bio: z.string().max(160, "Bio can't be more than 160 characters").optional(),
+    location: z.string().max(30, "Location can't be more than 30 characters").optional(),
+    website: z.string().max(100, "Website can't be more than 100 characters").optional(),
+})
+
+const ImagesSchema = z.custom<File>().refine((file) => file instanceof File, { message: "Expected a file" })
+    .refine((file) => file?.size < 4000000, { message: "Images must be less than 4MB" })
+    .optional()
+
+export const EditProfileModal = ({ user }: { user: IUser }) => {
+    const { isLoading, isSuccess, mutate } = useUpdateProfile()
+
+    const form = useForm<z.infer<typeof FormSchema>>({
+        resolver: zodResolver(FormSchema),
+        defaultValues: {
+            name: user.name,
+            bio: user.bio || "",
+            location: user.location || "",
+            website: user.website || "",
+        },
+    })
+
+    const [open, setOpen] = useState(false)
+    const [imageErrorMessage, setImageErrorMessage] = useState("")
+    const [chosenBanner, setChosenBanner] = useState<Partial<IProfile>>({
+        banner: { removed: false, url: user?.banner || "", file: undefined },
+    })
+    const [chosenImages, setChosenImages] = useState<Partial<IProfile>>({
+        image: { url: user?.image || "", file: undefined },
+    })
+
+    const bannerInputRef = useRef<HTMLInputElement>(null)
+    const imageInputRef = useRef<HTMLInputElement>(null)
+
+    const router = useRouter()
+
+    async function onSave(formData: z.infer<typeof FormSchema>) {
+        if (!user) return null
+
+        const dirty = form.formState.dirtyFields
+        const profile: IProfile = {
+            name: formData.name,
+            bio: dirty.bio ? formData.bio : undefined,
+            location: dirty.location ? formData.location : undefined,
+            website: dirty.website ? formData.website : undefined,
+            banner: { removed: chosenBanner.banner?.removed, url: user?.banner || "", file: chosenBanner.banner?.file },
+            image: { url: user?.image || "", file: chosenImages.image?.file },
+        }
+
+        mutate({
+            profile,
+            userId: user.id,
+        })
+    }
+
+    let disable = true
+    if (!isLoading) {
+        if (chosenBanner.banner?.file !== undefined || chosenImages.image?.file !== undefined || form.formState.isDirty) {
+            disable = false
+        }
+    }
+
+    useEffect(() => {
+        if (!open) {
+            form.reset()
+            form.setValue("name", user?.name)
+            form.setValue("bio", user?.bio || "")
+            form.setValue("location", user?.location || "")
+            form.setValue("website", user?.website || "")
+
+            // wait 150ms for dialog to close before resetting image
+            setTimeout(() => {
+                setImageErrorMessage("")
+                setChosenBanner({ banner: { removed: false, url: user?.banner || "", file: undefined } })
+                setChosenImages({ image: { url: user?.image || "", file: undefined } })
+            }, 150)
+        }
+    }, [form, open, user])
+
+    useEffect(() => {
+        if (isSuccess) {
+            toast({
+                description: "Successfully updated profile.",
+            })
+            setOpen(false)
+            router.refresh()
+        }
+    }, [isSuccess, router])
+
+    const chooseImage = async (event: any, type: string) => {
+        const file = event.target.files[0]
+        if (!file) return
+        try {
+            ImagesSchema.parse(file)
+            setImageErrorMessage("")
+        } catch (error: any) {
+            const err = error as z.ZodError
+            setImageErrorMessage(err.issues[0].message)
+            return
+        }
+
+        const reader = new FileReader()
+
+        if (type === "banner" && bannerInputRef.current) {
+            bannerInputRef.current.value = ""
+            reader.onloadend = () => {
+                setChosenBanner({
+                    ["banner"]: { removed: false, url: reader.result as string, file },
+                })
+            }
+        }
+
+        if (type === "image" && imageInputRef.current) {
+            imageInputRef.current.value = ""
+            reader.onloadend = () => {
+                setChosenImages({
+                    ["image"]: { url: reader.result as string, file },
+                })
+            }
+        }
+
+        reader.readAsDataURL(file)
+    }
+
+    if (!user) return null
+
+    return (
+        <Dialog open={open} onOpenChange={setOpen}>
+            <DialogTrigger asChild>
+                <Button variant="outline">Edit Profile</Button>
+            </DialogTrigger>
+            <DialogContent className="sm:max-w-[600px]">
+                <DialogHeader>
+                    <DialogTitle>Edit profile</DialogTitle>
+                    <DialogDescription>
+                        Make changes to your profile here. Click save when you are done.
+                    </DialogDescription>
+                </DialogHeader>
+                <Form {...form}>
+                    <form onSubmit={form.handleSubmit(onSave)}>
+                        <div className="grid gap-3 py-3">
+                            <div className="space-y-2">
+                                <div className="grid grid-cols-4 items-center gap-4">
+                                    <div className="col-span-1 relative w-full overflow-hidden items-center">
+                                        <div className="object-center object-cover w-full h-full">
+                                            {!chosenImages.image?.url ?
+                                                <UserAvatar
+                                                    user={{ username: user.username, image: null }}
+                                                    className="object-center object-cover w-full h-full aspect-square"
+                                                />
+                                                :
+                                                <AspectRatio ratio={1 / 1} className="overflow-hidden rounded-full">
+                                                    <Image
+                                                        src={chosenImages.image?.url}
+                                                        alt={"user image"}
+                                                        fill
+                                                        priority
+                                                        className="object-center object-cover w-full h-full"
+                                                    />
+                                                </AspectRatio>
+                                            }
+                                        </div>
+                                        <input
+                                            className="hidden resize-none"
+                                            type="file"
+                                            accept="image/*"
+                                            ref={imageInputRef}
+                                            onChange={(e) => chooseImage(e, "image")}
+                                            disabled={isLoading}
+                                        />
+                                        <div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 flex space-x-3">
+                                            <Button
+                                                type="button"
+                                                variant="outline"
+                                                size="icon"
+                                                className="bg-opacity-50 dark:bg-opacity-50"
+                                                onClick={() => imageInputRef?.current?.click()}
+                                                disabled={isLoading}
+                                            >
+                                                <Icons.camera />
+                                            </Button>
+                                        </div>
+                                    </div>
+
+                                    <Card className="col-span-3 relative w-full overflow-hidden border-none">
+
+                                        <AspectRatio ratio={3 / 1} className="bg-muted overflow-hidden">
+                                            {chosenBanner.banner?.url &&
+                                                <Image
+                                                    src={chosenBanner.banner?.url}
+                                                    alt={"user banner image"}
+                                                    fill
+                                                    priority
+                                                    className="object-center object-cover w-full h-full"
+                                                />
+                                            }
+                                        </AspectRatio>
+                                        <input
+                                            className="hidden w-full resize-none"
+                                            type="file"
+                                            accept="image/*"
+                                            ref={bannerInputRef}
+                                            onChange={(e) => chooseImage(e, "banner")}
+                                            disabled={isLoading}
+                                        />
+                                        <div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 flex space-x-3">
+                                            <Button
+                                                type="button"
+                                                variant="outline"
+                                                size="icon"
+                                                className="bg-opacity-50 dark:bg-opacity-50"
+                                                onClick={() => bannerInputRef.current?.click()}
+                                                disabled={isLoading}
+                                            >
+                                                <Icons.camera />
+                                            </Button>
+                                            {chosenBanner.banner?.url && (
+                                                <Button
+                                                    type="button"
+                                                    variant="outline"
+                                                    size="icon"
+                                                    className="bg-opacity-50 dark:bg-opacity-50"
+                                                    onClick={() => setChosenBanner({ banner: { removed: true, url: "", file: undefined } })}
+                                                    disabled={isLoading}
+                                                >
+                                                    <Icons.close />
+                                                </Button>
+                                            )}
+                                        </div>
+                                    </Card>
+                                </div>
+                                {imageErrorMessage &&
+                                    <div className="grid grid-cols-4 items-center gap-4">
+                                        <div className="col-span-1"></div>
+                                        <div className="col-span-3">
+                                            <p className="text-sm font-medium text-destructive">{imageErrorMessage}</p>
+                                        </div>
+                                    </div>
+                                }
+                            </div>
+
+                            <div className="grid grid-cols-4 items-center gap-4">
+                                <Label htmlFor="name" className="text-right">
+                                    Name
+                                </Label>
+                                <FormField
+                                    control={form.control}
+                                    name="name"
+                                    render={({ field }) => (
+                                        <FormItem className="col-span-3">
+                                            <FormControl>
+                                                <Input id="name" disabled={isLoading} {...field} />
+                                            </FormControl>
+                                            <FormMessage />
+                                        </FormItem>
+                                    )}
+                                />
+                            </div>
+
+                            <div className="grid grid-cols-4 items-center gap-4">
+                                <Label htmlFor="bio" className="text-right">
+                                    Bio
+                                </Label>
+                                <FormField
+                                    control={form.control}
+                                    name="bio"
+                                    render={({ field }) => (
+                                        <FormItem className="col-span-3">
+                                            <FormControl>
+                                                <Textarea id="bio" className="resize-none" disabled={isLoading} {...field} />
+                                            </FormControl>
+                                            <FormMessage />
+                                        </FormItem>
+                                    )}
+                                />
+                            </div>
+
+                            <div className="grid grid-cols-4 items-center gap-4">
+                                <Label htmlFor="location" className="text-right">
+                                    Location
+                                </Label>
+                                <FormField
+                                    control={form.control}
+                                    name="location"
+                                    render={({ field }) => (
+                                        <FormItem className="col-span-3">
+                                            <FormControl>
+                                                <Input id="location" disabled={isLoading} {...field} />
+                                            </FormControl>
+                                            <FormMessage />
+                                        </FormItem>
+                                    )}
+                                />
+                            </div>
+
+                            <div className="grid grid-cols-4 items-center gap-4">
+                                <Label htmlFor="website" className="text-right">
+                                    Website
+                                </Label>
+                                <FormField
+                                    control={form.control}
+                                    name="website"
+                                    render={({ field }) => (
+                                        <FormItem className="col-span-3">
+                                            <FormControl>
+                                                <Input id="website" disabled={isLoading} {...field} />
+                                            </FormControl>
+                                            <FormMessage />
+                                        </FormItem>
+                                    )}
+                                />
+                            </div>
+                        </div>
+                        <DialogFooter>
+                            <Button type="submit" disabled={disable}>
+                                {isLoading && (
+                                    <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
+                                )}
+                                Save changes
+                            </Button>
+                        </DialogFooter>
+                    </form>
+                </Form>
+            </DialogContent>
+        </Dialog>
+    )
+}
\ No newline at end of file
diff --git a/components/profile/components/profile-navbar.tsx b/components/profile/components/profile-navbar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..94a436a3597f9ad8d705427a24c2c06a87b95454
--- /dev/null
+++ b/components/profile/components/profile-navbar.tsx
@@ -0,0 +1,40 @@
+"use client"
+
+import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
+import Link from "next/link"
+import { usePathname } from "next/navigation"
+
+export const ProfileNavbar = ({ children, param }: { children: React.ReactNode, param: string }) => {
+    const pathValue = usePathname().split("/")[2] || "gweets"
+
+    return (
+        <Tabs defaultValue={"gweets"} value={pathValue} className="w-full h-full p-6 md:p-12 ">
+            <TabsList className="grid w-full grid-cols-4">
+                <Link href={`/${param}`} scroll={false} className="w-full inline-flex items-center justify-center">
+                    <TabsTrigger value="gweets" className="w-full">
+                        Gweets
+                    </TabsTrigger>
+                </Link>
+
+                <Link href={`/${param}/games`} scroll={false} className="w-full inline-flex items-center justify-center">
+                    <TabsTrigger value="games" className="w-full">
+                        Games
+                    </TabsTrigger>
+                </Link>
+
+                <Link href={`/${param}/media`} scroll={false} className="w-full inline-flex items-center justify-center">
+                    <TabsTrigger value="media" className="w-full">
+                        Media
+                    </TabsTrigger>
+                </Link>
+
+                <Link href={`/${param}/likes`} scroll={false} className="w-full inline-flex items-center justify-center">
+                    <TabsTrigger value="likes" className="w-full">
+                        Likes
+                    </TabsTrigger>
+                </Link>
+            </TabsList>
+            {children}
+        </Tabs>
+    )
+}
\ No newline at end of file
diff --git a/components/profile/components/profile-side-content.tsx b/components/profile/components/profile-side-content.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..2027f4072f97dbb22b883d1f277845bc8d3ea753
--- /dev/null
+++ b/components/profile/components/profile-side-content.tsx
@@ -0,0 +1,17 @@
+import { Card } from "@/components/ui/card"
+import { Skeleton } from "@/components/ui/skeleton"
+
+export const ProfileSideContent = () => {
+    return (
+        <Card className="p-6 grid items-start gap-2 bg-secondary">
+            <h1>Media</h1>
+            <div className="grid grid-cols-1 gap-4">
+                {Array.from({ length: 2 }, (_, i) => i + 1).map((i) => {
+                    return (
+                        <Skeleton key={i} className="aspect-[264/374] bg-gray-300" />
+                    )
+                })}
+            </div>
+        </Card>
+    )
+}
\ No newline at end of file
diff --git a/components/profile/components/profile-user-info.tsx b/components/profile/components/profile-user-info.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..914b6fdbf9a35359366fb785fefc7f95a9f2e0a1
--- /dev/null
+++ b/components/profile/components/profile-user-info.tsx
@@ -0,0 +1,95 @@
+import { FollowButton } from "@/components/follow-button"
+import { Icons } from "@/components/icons"
+import { AspectRatio } from "@/components/ui/aspect-ratio"
+import { UserAvatar } from "@/components/user-avatar"
+import { getCurrentUser } from "@/lib/session"
+import Image from "next/image"
+import Link from "next/link"
+import { IUser } from "../types"
+import { following } from "../utils/following"
+import { EditProfileModal } from "./edit-profile-modal"
+import { UserJoinDate } from "./user-join-date"
+
+export const ProfileUserInfo = async ({ user }: { user: IUser }) => {
+    const session = await getCurrentUser()
+
+    const isFollowing = following({
+        user,
+        sessionUserId: session ? session.id : "",
+    })
+
+    return (
+        <>
+            <AspectRatio ratio={3 / 1} className="bg-muted w-full overflow-hidden">
+                {user.banner &&
+                    <Image
+                        src={user.banner}
+                        alt={"user banner image"}
+                        fill
+                        priority
+                        className="object-center object-cover w-full h-full"
+                    />
+                }
+            </AspectRatio>
+            <div className="relative">
+                <div className="flex items-end justify-between p-6 md:px-12">
+                    <div>
+                        <div className="absolute bottom-6 md:bottom-3">
+                            <UserAvatar
+                                user={{ username: user.username, image: user.image || null }}
+                                className="h-20 md:h-40 w-20 md:w-40"
+                            />
+                        </div>
+                    </div>
+                    <div>
+                        {session?.id === user.id ? (
+                            <EditProfileModal user={user} />
+                        ) : (
+                            <FollowButton
+                                userId={user.id}
+                                username={user.username ? user.username : ""}
+                                isFollowing={isFollowing}
+                            />
+                        )}
+                    </div>
+                </div>
+            </div>
+
+            <div className="px-6 md:px-12 flex flex-col space-y-3 w-full">
+                <div className="pb-3 whitespace-nowrap items-center">
+                    <h1 className="text-2xl font-bold">{user.name}</h1>
+                    <h1 className="text-md text-sky-500">@{user.username}</h1>
+                </div>
+                {user.bio && <h1 className="break-words">{user.bio}</h1>}
+
+                <div className="flex whitespace-nowrap items-center space-x-6 text-muted-foreground">
+                    {user.location &&
+                        <div className="flex items-center">
+                            <Icons.location className="mr-1" />
+                            <div>{user.location}</div>
+                        </div>
+                    }
+                    {user.website &&
+                        <div className="flex items-center">
+                            <Icons.website className="mr-1" />
+                            <div>{user.website}</div>
+                        </div>
+                    }
+                    {user.createdAt && <UserJoinDate date={user.createdAt} />}
+                </div>
+
+                <div className="flex whitespace-nowrap items-center space-x-6">
+                    <Link href={`/${user.username}/following`}>
+                        <span className="font-bold">{user._count?.following}</span>
+                        <span className="text-muted-foreground"> Following</span>
+                    </Link>
+
+                    <Link href={`/${user.username}/followers`}>
+                        <span className="font-bold">{user._count?.followers}</span>
+                        <span className="text-muted-foreground"> Followers</span>
+                    </Link>
+                </div>
+            </div>
+        </ >
+    )
+}
\ No newline at end of file
diff --git a/components/profile/components/user-games.tsx b/components/profile/components/user-games.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4f9d414fa9519d54cd1be6c2e6fca86d458f36cd
--- /dev/null
+++ b/components/profile/components/user-games.tsx
@@ -0,0 +1,100 @@
+import GameItem from "@/components/game-item"
+import { db } from "@/lib/db"
+import { getFavoriteGames } from "@/lib/igdb"
+import { getCurrentUser } from "@/lib/session"
+import { IGame } from "@/types/igdb-types"
+import { redirect } from "next/navigation"
+
+export const UserGames = async ({ username }: { username: string }) => {
+    const user = await getCurrentUser()
+
+    const sessionUser = await db.user.findFirst({
+        where: {
+            id: user?.id
+        },
+        include: {
+            following: true,
+            followers: true
+        }
+    })
+
+    const fullUser = await db.user.findFirst({
+        where: {
+            username: username
+        },
+        include: {
+            following: true,
+            followers: true
+        }
+    })
+
+    if (!fullUser) {
+        redirect('/home')
+    }
+
+    let favoritegames = undefined
+    let playingGames = undefined
+    let finishedGames = undefined
+    let planningGames = undefined
+
+    if (fullUser?.favGameList?.length !== 0 && fullUser?.favGameList?.length != undefined) {
+        favoritegames = await getFavoriteGames(fullUser?.favGameList!)
+    }
+    if (fullUser?.playingGameList?.length !== 0) {
+        playingGames = await getFavoriteGames(fullUser?.playingGameList!)
+    }
+    if (fullUser?.finishedGameList?.length !== 0) {
+        finishedGames = await getFavoriteGames(fullUser?.finishedGameList!)
+    }
+    if (fullUser?.planningGameList?.length !== 0) {
+        planningGames = await getFavoriteGames(fullUser?.planningGameList!)
+    }
+
+    return (
+        <div className="p-3 space-y-12">
+            <div>
+                <h1 className="text-2xl font-bold pb-3">Favorite Games</h1>
+                <div className="grid grid-cols-1 ss:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8 items-center">
+                    {favoritegames ? favoritegames.map((game: IGame) => (
+                        <GameItem id={game.id} name={game.name} cover={game.cover} key={game.id} />
+                    ))
+                        :
+                        <p>No favorites currently...</p>}
+                </div>
+            </div>
+
+            <div>
+                <h1 className="text-2xl font-bold pb-3">Currently playing</h1>
+                <div className="grid grid-cols-1 ss:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8 items-center">
+                    {playingGames ? playingGames.map((game: IGame) => (
+                        <GameItem id={game.id} name={game.name} cover={game.cover} key={game.id} />
+                    ))
+                        :
+                        <p>Currently not playing any games...</p>}
+                </div>
+            </div>
+
+            <div>
+                <h1 className="text-2xl font-bold pb-3">Planning to play</h1>
+                <div className="grid grid-cols-1 ss:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8 items-center">
+                    {planningGames ? planningGames.map((game: IGame) => (
+                        <GameItem id={game.id} name={game.name} cover={game.cover} key={game.id} />
+                    ))
+                        :
+                        <p>Currently not planning to play any games...</p>}
+                </div>
+            </div>
+
+            <div>
+                <h1 className="text-2xl font-bold pb-3">Finished Games</h1>
+                <div className="grid grid-cols-1 ss:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8 items-center">
+                    {finishedGames ? finishedGames.map((game: IGame) => (
+                        <GameItem id={game.id} name={game.name} cover={game.cover} key={game.id} />
+                    ))
+                        :
+                        <p>No finished games...</p>}
+                </div>
+            </div>
+        </div >
+    )
+}
\ No newline at end of file
diff --git a/components/profile/components/user-gweets.tsx b/components/profile/components/user-gweets.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6f53a744151d74c4f4b02673f97e9f91f44c0e6f
--- /dev/null
+++ b/components/profile/components/user-gweets.tsx
@@ -0,0 +1,69 @@
+"use client"
+
+import { InfiniteGweets } from "@/components/gweets/components/infinite-gweets"
+import { useGweets } from "@/components/gweets/hooks/use-gweets"
+import LoadingItem from "@/components/loading-item"
+import { TryAgain } from "@/components/try-again"
+import { usePathname } from "next/navigation"
+
+export const UserGweets = ({ username, sessionname }: { username: string, sessionname: string }) => {
+    const pathValue = usePathname().split("/")[2] || "gweets"
+
+    const {
+        data: gweets,
+        isLoading,
+        isError,
+        isSuccess,
+        isFetchingNextPage,
+        fetchNextPage,
+        hasNextPage,
+    } = useGweets({
+        queryKey: ["gweets", username, pathValue],
+        type: "user_" + pathValue,
+        id: username,
+    })
+
+    if (isLoading) {
+        return (
+            <LoadingItem />
+        )
+    }
+
+    if (isError) {
+        return (
+            <TryAgain />
+        )
+    }
+
+    if (gweets?.pages[0].gweets.length === 0) {
+        if (sessionname === username) {
+            return (
+                <div className="m-6 flex justify-center">
+                    <div className="font-bold">
+                        <h1>You haven&apos;t gweeted anything yet.</h1>
+                        <p>When you do, it&apos;ll show up here.</p>
+                    </div>
+                </div>
+            )
+        } else {
+            return (
+                <div className="m-6 flex justify-center">
+                    <div className="font-bold">
+                        <h1><span className="text-sky-500">@{username}</span> hasn&apos;t gweeted anything yet.</h1>
+                        <p>When they do, it&apos;ll show up here.</p>
+                    </div>
+                </div>
+            )
+        }
+    }
+
+    return (
+        <InfiniteGweets
+            gweets={gweets}
+            hasNextPage={hasNextPage}
+            fetchNextPage={fetchNextPage}
+            isFetchingNextPage={isFetchingNextPage}
+            isSuccess={isSuccess}
+        />
+    )
+}
\ No newline at end of file
diff --git a/components/profile/components/user-join-date.tsx b/components/profile/components/user-join-date.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..16706d98df60d7c109652d6122f9b5f435c1dd50
--- /dev/null
+++ b/components/profile/components/user-join-date.tsx
@@ -0,0 +1,19 @@
+import { Icons } from "@/components/icons"
+import dayjs from "dayjs"
+
+export const UserJoinDate = ({
+    date,
+    showIcon = true,
+}: {
+    date: Date | undefined
+    showIcon?: boolean
+}) => {
+    return (
+        <div className="flex items-center">
+            {showIcon && (<Icons.calendar className="mr-1" />)}
+            <div>
+                Joined {dayjs(date).format("MMMM YYYY")}
+            </div>
+        </div>
+    )
+}
\ No newline at end of file
diff --git a/components/profile/hooks/use-follow.ts b/components/profile/hooks/use-follow.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0d9073a9931857ffba1152d497d7af1f7ee52ff0
--- /dev/null
+++ b/components/profile/hooks/use-follow.ts
@@ -0,0 +1,35 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query"
+
+import { followUser } from "../api/follow-user"
+import { unfollowUser } from "../api/unfollow-user"
+
+export const useFollow = (type: "follow" | "unfollow") => {
+    const queryClient = useQueryClient()
+
+    return useMutation(
+        ({
+            userId,
+        }: {
+            userId: string
+        }) => {
+            return type === "follow"
+                ? followUser(userId)
+                : unfollowUser(userId)
+        },
+
+        {
+            onSuccess: () => {
+                console.log("success")
+            },
+
+            onError: () => {
+                console.log("error")
+            },
+
+            onSettled: ({ userId }) => {
+                queryClient.invalidateQueries(["users", userId])
+                queryClient.invalidateQueries(["tweets"])
+            },
+        },
+    )
+}
\ No newline at end of file
diff --git a/components/profile/hooks/use-get-follows.ts b/components/profile/hooks/use-get-follows.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4fe0b3eb91b61c5565b1014d49e67ac3b6e7a0dd
--- /dev/null
+++ b/components/profile/hooks/use-get-follows.ts
@@ -0,0 +1,22 @@
+import { useQuery } from "@tanstack/react-query"
+
+import { getFollows } from "../api/get-follows"
+import { IUser } from "../types"
+
+export const useGetFollows = ({
+    id,
+    type,
+}: {
+    id: string | undefined
+    type: string | undefined
+}) => {
+    return useQuery<IUser[]>(
+        ["users", id, type],
+        async () => {
+            return getFollows(id, type)
+        },
+        {
+            refetchOnWindowFocus: false,
+        },
+    )
+}
\ No newline at end of file
diff --git a/components/profile/hooks/use-update-profile.ts b/components/profile/hooks/use-update-profile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4f3804edd55decd57cb9183571aaabf9415633eb
--- /dev/null
+++ b/components/profile/hooks/use-update-profile.ts
@@ -0,0 +1,34 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query"
+
+import { updateProfile } from "../api/update-profile"
+import { IProfile } from "../types"
+
+export const useUpdateProfile = () => {
+    const queryClient = useQueryClient()
+
+    return useMutation(
+        ({
+            profile,
+            userId,
+        }: {
+            profile: IProfile
+            userId: string
+        }) => {
+            return updateProfile({ profile, userId })
+        },
+
+        {
+            onSuccess: () => {
+                console.log("success")
+            },
+
+            onError: (error) => {
+                console.log(error)
+            },
+
+            onSettled: ({ userId }) => {
+                queryClient.invalidateQueries(["users", userId])
+            },
+        },
+    )
+}
\ No newline at end of file
diff --git a/components/profile/hooks/use-user-likes.ts b/components/profile/hooks/use-user-likes.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e78735258031065988b70a002975cbed0129bb0b
--- /dev/null
+++ b/components/profile/hooks/use-user-likes.ts
@@ -0,0 +1,17 @@
+import { useQuery } from "@tanstack/react-query"
+
+import { ILike } from "@/components/gweets/types"
+
+import { getUserLikes } from "../api/get-user-likes"
+
+export const useUserLikes = (id: string | undefined) => {
+    return useQuery<ILike[]>(
+        ["likes", { userId: id }],
+        async () => {
+            return getUserLikes(id)
+        },
+        {
+            refetchOnWindowFocus: false,
+        },
+    )
+}
\ No newline at end of file
diff --git a/components/profile/hooks/use-user.ts b/components/profile/hooks/use-user.ts
new file mode 100644
index 0000000000000000000000000000000000000000..79760e1f4496e2accedc93a6bc5f5761a333b912
--- /dev/null
+++ b/components/profile/hooks/use-user.ts
@@ -0,0 +1,20 @@
+import { useQuery, useQueryClient } from "@tanstack/react-query"
+
+import { getUser } from "../api/get-user"
+import { IUser } from "../types"
+
+export const useUser = (username: string | undefined) => {
+    const queryClient = useQueryClient()
+    return useQuery<IUser>(
+        ["users", username],
+        async () => {
+            return getUser(username)
+        },
+        {
+            refetchOnWindowFocus: false,
+            onSuccess: (data) => {
+                queryClient.setQueryData(["users", username], data)
+            },
+        },
+    )
+}
\ No newline at end of file
diff --git a/components/profile/hooks/use-users.ts b/components/profile/hooks/use-users.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e2e70b6ab95fb0c541991e32d6b6dc07cfb6909e
--- /dev/null
+++ b/components/profile/hooks/use-users.ts
@@ -0,0 +1,23 @@
+import { useQuery, useQueryClient } from "@tanstack/react-query"
+import { useSession } from "next-auth/react"
+
+import { getUsers } from "../api/get-users"
+import { IUser } from "../types"
+
+export const useUsers = () => {
+    const { data: session } = useSession()
+
+    const queryClient = useQueryClient()
+    return useQuery<IUser[]>(
+        ["users"],
+        async () => {
+            return getUsers(session?.user?.id)
+        },
+        {
+            refetchOnWindowFocus: false,
+            onSuccess: (data) => {
+                queryClient.setQueryData(["users"], data)
+            },
+        },
+    )
+}
\ No newline at end of file
diff --git a/components/profile/types/index.ts b/components/profile/types/index.ts
index fb812e3c3c2b0522d6bbf2f1ac5fe6c7f425e971..ae11567b9c5fd4034c6ed8ffa6f9672b5157e7e9 100644
--- a/components/profile/types/index.ts
+++ b/components/profile/types/index.ts
@@ -1,11 +1,11 @@
-import { Follows, Like, User } from "@prisma/client"
+import { Like, User } from "@prisma/client"
 
 import { IGweet } from "@/components/gweets/types"
 
 export interface IUser extends User {
     gweets: IGweet[]
-    followers: IFollow[]
-    following: IFollow[]
+    followers: User[]
+    following: User[]
     likes: ILike[]
     _count?: {
         followers?: number
@@ -16,19 +16,19 @@ export interface IUser extends User {
 export interface IProfile {
     name: string
     bio: string | undefined
+    location: string | undefined
+    website: string | undefined
     banner: {
+        removed: boolean | undefined
         url: string | undefined
+        file: File | undefined
     }
-    avatar: {
+    image: {
         url: string | undefined
+        file: File | undefined
     }
 }
 
-export interface IFollow extends Follows {
-    follower: IUser
-    following: IUser
-}
-
 export interface ILike extends Like {
     user: IUser
     gweet: IGweet
diff --git a/components/profile/utils/following.ts b/components/profile/utils/following.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4c6c83ca24a661d916e2f9ee6fa697a4a4de4867
--- /dev/null
+++ b/components/profile/utils/following.ts
@@ -0,0 +1,11 @@
+import { IUser } from "../types"
+
+export const following = ({
+    user,
+    sessionUserId,
+}: {
+    user: IUser
+    sessionUserId: string
+}): boolean => {
+    return user?.followers?.some((follower) => follower.id === sessionUserId)
+}
\ No newline at end of file
diff --git a/components/user-auth-form.tsx b/components/user-auth-form.tsx
index 21a0d035f98ffca9d1a140cb8837476d7fd1fb98..9ce00468bcd0ab0f760f86e1a5ae7a477e35e16a 100644
--- a/components/user-auth-form.tsx
+++ b/components/user-auth-form.tsx
@@ -55,6 +55,8 @@ export function UserAuthForm({ type, className, ...props }: UserAuthFormProps) {
             if (!res.ok) {
                 if (res.status === 422) {
                     setError('email', { type: 'manual', message: 'This email is already in use. Please choose another one.' })
+                    setIsLoading(false)
+                    return
                 }
 
                 setIsLoading(false)
diff --git a/components/user-not-found.tsx b/components/user-not-found.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f08a2ba9871320952c6853da4309ac6caeecd734
--- /dev/null
+++ b/components/user-not-found.tsx
@@ -0,0 +1,8 @@
+export const UserNotFound = () => {
+    return (
+        <div className="">
+            <h1>This account does not exist.</h1>
+            <p>Try searching for another.</p>
+        </div>
+    )
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 53f161a7a9f5b13a5384ba2c661c6c751d7ce495..f9117fa243b149547f7e6f5c84df6df6ba9c811b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31,8 +31,8 @@
                 "class-variance-authority": "^0.6.1",
                 "clsx": "^1.2.1",
                 "dayjs": "^1.11.9",
-                "lucide-react": "^0.258.0",
-                "next": "^13.4.8",
+                "lucide-react": "^0.259.0",
+                "next": "^13.4.9",
                 "next-auth": "^4.22.1",
                 "next-themes": "^0.2.1",
                 "normalize-diacritics": "^4.0.0",
@@ -53,15 +53,15 @@
                 "@testing-library/react": "^14.0.0",
                 "@types/bcrypt": "^5.0.0",
                 "@types/jest": "^29.5.2",
-                "@types/node": "^20.3.3",
+                "@types/node": "^20.4.0",
                 "@types/react": "^18.2.14",
                 "@types/react-dom": "^18.2.6",
                 "autoprefixer": "10.4.14",
                 "eslint": "^8.44.0",
-                "eslint-config-next": "^13.4.8",
-                "jest": "^29.6.0",
-                "jest-environment-jsdom": "^29.6.0",
-                "postcss": "8.4.24",
+                "eslint-config-next": "^13.4.9",
+                "jest": "^29.6.1",
+                "jest-environment-jsdom": "^29.6.1",
+                "postcss": "8.4.25",
                 "prisma": "^4.16.2",
                 "tailwindcss": "3.3.2",
                 "typescript": "^5.1.6"
@@ -160,20 +160,20 @@
             }
         },
         "node_modules/@babel/core": {
-            "version": "7.22.6",
-            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.6.tgz",
-            "integrity": "sha512-HPIyDa6n+HKw5dEuway3vVAhBboYCtREBMp+IWeseZy6TFtzn6MHkCH2KKYUOC/vKKwgSMHQW4htBOrmuRPXfw==",
+            "version": "7.22.8",
+            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.8.tgz",
+            "integrity": "sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==",
             "dev": true,
             "dependencies": {
                 "@ampproject/remapping": "^2.2.0",
                 "@babel/code-frame": "^7.22.5",
-                "@babel/generator": "^7.22.5",
+                "@babel/generator": "^7.22.7",
                 "@babel/helper-compilation-targets": "^7.22.6",
                 "@babel/helper-module-transforms": "^7.22.5",
                 "@babel/helpers": "^7.22.6",
-                "@babel/parser": "^7.22.6",
+                "@babel/parser": "^7.22.7",
                 "@babel/template": "^7.22.5",
-                "@babel/traverse": "^7.22.6",
+                "@babel/traverse": "^7.22.8",
                 "@babel/types": "^7.22.5",
                 "@nicolo-ribaudo/semver-v6": "^6.3.3",
                 "convert-source-map": "^1.7.0",
@@ -196,9 +196,9 @@
             "dev": true
         },
         "node_modules/@babel/generator": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz",
-            "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==",
+            "version": "7.22.7",
+            "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz",
+            "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==",
             "dev": true,
             "dependencies": {
                 "@babel/types": "^7.22.5",
@@ -454,9 +454,9 @@
             }
         },
         "node_modules/@babel/parser": {
-            "version": "7.22.6",
-            "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.6.tgz",
-            "integrity": "sha512-EIQu22vNkceq3LbjAq7knDf/UmtI2qbcNI8GRBlijez6TpQLvSodJPYfydQmNA5buwkxxxa/PVI44jjYZ+/cLw==",
+            "version": "7.22.7",
+            "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz",
+            "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
             "dev": true,
             "bin": {
                 "parser": "bin/babel-parser.js"
@@ -668,18 +668,18 @@
             }
         },
         "node_modules/@babel/traverse": {
-            "version": "7.22.6",
-            "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.6.tgz",
-            "integrity": "sha512-53CijMvKlLIDlOTrdWiHileRddlIiwUIyCKqYa7lYnnPldXCG5dUSN38uT0cA6i7rHWNKJLH0VU/Kxdr1GzB3w==",
+            "version": "7.22.8",
+            "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz",
+            "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==",
             "dev": true,
             "dependencies": {
                 "@babel/code-frame": "^7.22.5",
-                "@babel/generator": "^7.22.5",
+                "@babel/generator": "^7.22.7",
                 "@babel/helper-environment-visitor": "^7.22.5",
                 "@babel/helper-function-name": "^7.22.5",
                 "@babel/helper-hoist-variables": "^7.22.5",
                 "@babel/helper-split-export-declaration": "^7.22.6",
-                "@babel/parser": "^7.22.6",
+                "@babel/parser": "^7.22.7",
                 "@babel/types": "^7.22.5",
                 "debug": "^4.1.0",
                 "globals": "^11.1.0"
@@ -948,16 +948,16 @@
             }
         },
         "node_modules/@jest/console": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.0.tgz",
-            "integrity": "sha512-anb6L1yg7uPQpytNVA5skRaXy3BmrsU8icRhTVNbWdjYWDDfy8M1Kq5HIVRpYoABdbpqsc5Dr+jtu4+qWRQBiQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz",
+            "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^29.6.0",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
-                "jest-message-util": "^29.6.0",
-                "jest-util": "^29.6.0",
+                "jest-message-util": "^29.6.1",
+                "jest-util": "^29.6.1",
                 "slash": "^3.0.0"
             },
             "engines": {
@@ -981,16 +981,16 @@
             }
         },
         "node_modules/@jest/core": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.0.tgz",
-            "integrity": "sha512-5dbMHfY/5R9m8NbgmB3JlxQqooZ/ooPSOiwEQZZ+HODwJTbIu37seVcZNBK29aMdXtjvTRB3f6LCvkKq+r8uQA==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz",
+            "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==",
             "dev": true,
             "dependencies": {
-                "@jest/console": "^29.6.0",
-                "@jest/reporters": "^29.6.0",
-                "@jest/test-result": "^29.6.0",
-                "@jest/transform": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/console": "^29.6.1",
+                "@jest/reporters": "^29.6.1",
+                "@jest/test-result": "^29.6.1",
+                "@jest/transform": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
                 "ansi-escapes": "^4.2.1",
                 "chalk": "^4.0.0",
@@ -998,20 +998,20 @@
                 "exit": "^0.1.2",
                 "graceful-fs": "^4.2.9",
                 "jest-changed-files": "^29.5.0",
-                "jest-config": "^29.6.0",
-                "jest-haste-map": "^29.6.0",
-                "jest-message-util": "^29.6.0",
+                "jest-config": "^29.6.1",
+                "jest-haste-map": "^29.6.1",
+                "jest-message-util": "^29.6.1",
                 "jest-regex-util": "^29.4.3",
-                "jest-resolve": "^29.6.0",
-                "jest-resolve-dependencies": "^29.6.0",
-                "jest-runner": "^29.6.0",
-                "jest-runtime": "^29.6.0",
-                "jest-snapshot": "^29.6.0",
-                "jest-util": "^29.6.0",
-                "jest-validate": "^29.6.0",
-                "jest-watcher": "^29.6.0",
+                "jest-resolve": "^29.6.1",
+                "jest-resolve-dependencies": "^29.6.1",
+                "jest-runner": "^29.6.1",
+                "jest-runtime": "^29.6.1",
+                "jest-snapshot": "^29.6.1",
+                "jest-util": "^29.6.1",
+                "jest-validate": "^29.6.1",
+                "jest-watcher": "^29.6.1",
                 "micromatch": "^4.0.4",
-                "pretty-format": "^29.6.0",
+                "pretty-format": "^29.6.1",
                 "slash": "^3.0.0",
                 "strip-ansi": "^6.0.0"
             },
@@ -1044,9 +1044,9 @@
             }
         },
         "node_modules/@jest/core/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -1076,37 +1076,37 @@
             "dev": true
         },
         "node_modules/@jest/environment": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.0.tgz",
-            "integrity": "sha512-bUZLYUxYlUIsslBbxII0fq0kr1+friI3Gty+cRLmocGB1jdcAHs7FS8QdCDqedE8q4DZE1g/AJHH6OJZBLGGsg==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz",
+            "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==",
             "dev": true,
             "dependencies": {
-                "@jest/fake-timers": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/fake-timers": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
-                "jest-mock": "^29.6.0"
+                "jest-mock": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
             }
         },
         "node_modules/@jest/expect": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.0.tgz",
-            "integrity": "sha512-a7pISPW28Q3c0/pLwz4mQ6tbAI+hc8/0CJp9ix6e9U4dQ6TiHQX82CT5DV5BMWaw8bFH4E6zsfZxXdn6Ka23Bw==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz",
+            "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==",
             "dev": true,
             "dependencies": {
-                "expect": "^29.6.0",
-                "jest-snapshot": "^29.6.0"
+                "expect": "^29.6.1",
+                "jest-snapshot": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
             }
         },
         "node_modules/@jest/expect-utils": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.0.tgz",
-            "integrity": "sha512-LLSQQN7oypMSETKoPWpsWYVKJd9LQWmSDDAc4hUQ4JocVC7LAMy9R3ZMhlnLwbcFvQORZnZR7HM893Px6cJhvA==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz",
+            "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==",
             "dev": true,
             "dependencies": {
                 "jest-get-type": "^29.4.3"
@@ -1116,48 +1116,48 @@
             }
         },
         "node_modules/@jest/fake-timers": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.0.tgz",
-            "integrity": "sha512-nuCU46AsZoskthWSDS2Aj6LARgyNcp5Fjx2qxsO/fPl1Wp1CJ+dBDqs0OkEcJK8FBeV/MbjH5efe79M2sHcV+A==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz",
+            "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^29.6.0",
+                "@jest/types": "^29.6.1",
                 "@sinonjs/fake-timers": "^10.0.2",
                 "@types/node": "*",
-                "jest-message-util": "^29.6.0",
-                "jest-mock": "^29.6.0",
-                "jest-util": "^29.6.0"
+                "jest-message-util": "^29.6.1",
+                "jest-mock": "^29.6.1",
+                "jest-util": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
             }
         },
         "node_modules/@jest/globals": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.0.tgz",
-            "integrity": "sha512-IQQ3hZ2D/hwEwXSMv5GbfhzdH0nTQR3KPYxnuW6gYWbd6+7/zgMz7Okn6EgBbNtJNONq03k5EKA6HqGyzRbpeg==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz",
+            "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==",
             "dev": true,
             "dependencies": {
-                "@jest/environment": "^29.6.0",
-                "@jest/expect": "^29.6.0",
-                "@jest/types": "^29.6.0",
-                "jest-mock": "^29.6.0"
+                "@jest/environment": "^29.6.1",
+                "@jest/expect": "^29.6.1",
+                "@jest/types": "^29.6.1",
+                "jest-mock": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
             }
         },
         "node_modules/@jest/reporters": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.0.tgz",
-            "integrity": "sha512-dWEq4HI0VvHcAD6XTtyBKKARLytyyWPIy1SvGOcU91106MfvHPdxZgupFwVHd8TFpZPpA3SebYjtwS5BUS76Rw==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz",
+            "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==",
             "dev": true,
             "dependencies": {
                 "@bcoe/v8-coverage": "^0.2.3",
-                "@jest/console": "^29.6.0",
-                "@jest/test-result": "^29.6.0",
-                "@jest/transform": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/console": "^29.6.1",
+                "@jest/test-result": "^29.6.1",
+                "@jest/transform": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@jridgewell/trace-mapping": "^0.3.18",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
@@ -1170,9 +1170,9 @@
                 "istanbul-lib-report": "^3.0.0",
                 "istanbul-lib-source-maps": "^4.0.0",
                 "istanbul-reports": "^3.1.3",
-                "jest-message-util": "^29.6.0",
-                "jest-util": "^29.6.0",
-                "jest-worker": "^29.6.0",
+                "jest-message-util": "^29.6.1",
+                "jest-util": "^29.6.1",
+                "jest-worker": "^29.6.1",
                 "slash": "^3.0.0",
                 "string-length": "^4.0.1",
                 "strip-ansi": "^6.0.0",
@@ -1233,13 +1233,13 @@
             }
         },
         "node_modules/@jest/test-result": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.0.tgz",
-            "integrity": "sha512-9qLb7xITeyWhM4yatn2muqfomuoCTOhv0QV9i7XiIyYi3QLfnvPv5NeJp5u0PZeutAOROMLKakOkmoAisOr3YQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz",
+            "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==",
             "dev": true,
             "dependencies": {
-                "@jest/console": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/console": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/istanbul-lib-coverage": "^2.0.0",
                 "collect-v8-coverage": "^1.0.0"
             },
@@ -1248,14 +1248,14 @@
             }
         },
         "node_modules/@jest/test-sequencer": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.0.tgz",
-            "integrity": "sha512-HYCS3LKRQotKWj2mnA3AN13PPevYZu8MJKm12lzYojpJNnn6kI/3PWmr1At/e3tUu+FHQDiOyaDVuR4EV3ezBw==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz",
+            "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==",
             "dev": true,
             "dependencies": {
-                "@jest/test-result": "^29.6.0",
+                "@jest/test-result": "^29.6.1",
                 "graceful-fs": "^4.2.9",
-                "jest-haste-map": "^29.6.0",
+                "jest-haste-map": "^29.6.1",
                 "slash": "^3.0.0"
             },
             "engines": {
@@ -1263,22 +1263,22 @@
             }
         },
         "node_modules/@jest/transform": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.0.tgz",
-            "integrity": "sha512-bhP/KxPo3e322FJ0nKAcb6WVK76ZYyQd1lWygJzoSqP8SYMSLdxHqP4wnPTI4WvbB8PKPDV30y5y7Tya4RHOBA==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz",
+            "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==",
             "dev": true,
             "dependencies": {
                 "@babel/core": "^7.11.6",
-                "@jest/types": "^29.6.0",
+                "@jest/types": "^29.6.1",
                 "@jridgewell/trace-mapping": "^0.3.18",
                 "babel-plugin-istanbul": "^6.1.1",
                 "chalk": "^4.0.0",
                 "convert-source-map": "^2.0.0",
                 "fast-json-stable-stringify": "^2.1.0",
                 "graceful-fs": "^4.2.9",
-                "jest-haste-map": "^29.6.0",
+                "jest-haste-map": "^29.6.1",
                 "jest-regex-util": "^29.4.3",
-                "jest-util": "^29.6.0",
+                "jest-util": "^29.6.1",
                 "micromatch": "^4.0.4",
                 "pirates": "^4.0.4",
                 "slash": "^3.0.0",
@@ -1305,9 +1305,9 @@
             }
         },
         "node_modules/@jest/types": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.0.tgz",
-            "integrity": "sha512-8XCgL9JhqbJTFnMRjEAO+TuW251+MoMd5BSzLiE3vvzpQ8RlBxy8NoyNkDhs3K3OL3HeVinlOl9or5p7GTeOLg==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz",
+            "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -1405,23 +1405,23 @@
             }
         },
         "node_modules/@next/env": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.8.tgz",
-            "integrity": "sha512-twuSf1klb3k9wXI7IZhbZGtFCWvGD4wXTY2rmvzIgVhXhs7ISThrbNyutBx3jWIL8Y/Hk9+woytFz5QsgtcRKQ=="
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.9.tgz",
+            "integrity": "sha512-vuDRK05BOKfmoBYLNi2cujG2jrYbEod/ubSSyqgmEx9n/W3eZaJQdRNhTfumO+qmq/QTzLurW487n/PM/fHOkw=="
         },
         "node_modules/@next/eslint-plugin-next": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.8.tgz",
-            "integrity": "sha512-cmfVHpxWjjcETFt2WHnoFU6EmY69QcPJRlRNAooQlNe53Ke90vg1Ci/dkPffryJZaxxiRziP9bQrV8lDVCn3Fw==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.9.tgz",
+            "integrity": "sha512-nDtGpa992tNyAkT/KmSMy7QkHfNZmGCBYhHtafU97DubqxzNdvLsqRtliQ4FU04CysRCtvP2hg8rRC1sAKUTUA==",
             "dev": true,
             "dependencies": {
                 "glob": "7.1.7"
             }
         },
         "node_modules/@next/swc-darwin-arm64": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.8.tgz",
-            "integrity": "sha512-MSFplVM4dTWOuKAUv0XR9gY7AWtMSBu9os9f+kp+s5rWhM1I2CdR3obFttd6366nS/W/VZxbPM5oEIdlIa46zA==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.9.tgz",
+            "integrity": "sha512-TVzGHpZoVBk3iDsTOQA/R6MGmFp0+17SWXMEWd6zG30AfuELmSSMe2SdPqxwXU0gbpWkJL1KgfLzy5ReN0crqQ==",
             "cpu": [
                 "arm64"
             ],
@@ -1434,9 +1434,9 @@
             }
         },
         "node_modules/@next/swc-darwin-x64": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.8.tgz",
-            "integrity": "sha512-Reox+UXgonon9P0WNDE6w85DGtyBqGitl/ryznOvn6TvfxEaZIpTgeu3ZrJLU9dHSMhiK7YAM793mE/Zii2/Qw==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.9.tgz",
+            "integrity": "sha512-aSfF1fhv28N2e7vrDZ6zOQ+IIthocfaxuMWGReB5GDriF0caTqtHttAvzOMgJgXQtQx6XhyaJMozLTSEXeNN+A==",
             "cpu": [
                 "x64"
             ],
@@ -1449,9 +1449,9 @@
             }
         },
         "node_modules/@next/swc-linux-arm64-gnu": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.8.tgz",
-            "integrity": "sha512-kdyzYvAYtqQVgzIKNN7e1rLU8aZv86FDSRqPlOkKZlvqudvTO0iohuTPmnEEDlECeBM6qRPShNffotDcU/R2KA==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.9.tgz",
+            "integrity": "sha512-JhKoX5ECzYoTVyIy/7KykeO4Z2lVKq7HGQqvAH+Ip9UFn1MOJkOnkPRB7v4nmzqAoY+Je05Aj5wNABR1N18DMg==",
             "cpu": [
                 "arm64"
             ],
@@ -1464,9 +1464,9 @@
             }
         },
         "node_modules/@next/swc-linux-arm64-musl": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.8.tgz",
-            "integrity": "sha512-oWxx4yRkUGcR81XwbI+T0zhZ3bDF6V1aVLpG+C7hSG50ULpV8gC39UxVO22/bv93ZlcfMY4zl8xkz9Klct6dpQ==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.9.tgz",
+            "integrity": "sha512-OOn6zZBIVkm/4j5gkPdGn4yqQt+gmXaLaSjRSO434WplV8vo2YaBNbSHaTM9wJpZTHVDYyjzuIYVEzy9/5RVZw==",
             "cpu": [
                 "arm64"
             ],
@@ -1479,9 +1479,9 @@
             }
         },
         "node_modules/@next/swc-linux-x64-gnu": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.8.tgz",
-            "integrity": "sha512-anhtvuO6eE9YRhYnaEGTfbpH3L5gT/9qPFcNoi6xS432r/4DAtpJY8kNktqkTVevVIC/pVumqO8tV59PR3zbNg==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.9.tgz",
+            "integrity": "sha512-iA+fJXFPpW0SwGmx/pivVU+2t4zQHNOOAr5T378PfxPHY6JtjV6/0s1vlAJUdIHeVpX98CLp9k5VuKgxiRHUpg==",
             "cpu": [
                 "x64"
             ],
@@ -1494,9 +1494,9 @@
             }
         },
         "node_modules/@next/swc-linux-x64-musl": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.8.tgz",
-            "integrity": "sha512-aR+J4wWfNgH1DwCCBNjan7Iumx0lLtn+2/rEYuhIrYLY4vnxqSVGz9u3fXcgUwo6Q9LT8NFkaqK1vPprdq+BXg==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.9.tgz",
+            "integrity": "sha512-rlNf2WUtMM+GAQrZ9gMNdSapkVi3koSW3a+dmBVp42lfugWVvnyzca/xJlN48/7AGx8qu62WyO0ya1ikgOxh6A==",
             "cpu": [
                 "x64"
             ],
@@ -1509,9 +1509,9 @@
             }
         },
         "node_modules/@next/swc-win32-arm64-msvc": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.8.tgz",
-            "integrity": "sha512-OWBKIrJwQBTqrat0xhxEB/jcsjJR3+diD9nc/Y8F1mRdQzsn4bPsomgJyuqPVZs6Lz3K18qdIkvywmfSq75SsQ==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.9.tgz",
+            "integrity": "sha512-5T9ybSugXP77nw03vlgKZxD99AFTHaX8eT1ayKYYnGO9nmYhJjRPxcjU5FyYI+TdkQgEpIcH7p/guPLPR0EbKA==",
             "cpu": [
                 "arm64"
             ],
@@ -1524,9 +1524,9 @@
             }
         },
         "node_modules/@next/swc-win32-ia32-msvc": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.8.tgz",
-            "integrity": "sha512-agiPWGjUndXGTOn4ChbKipQXRA6/UPkywAWIkx7BhgGv48TiJfHTK6MGfBoL9tS6B4mtW39++uy0wFPnfD0JWg==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.9.tgz",
+            "integrity": "sha512-ojZTCt1lP2ucgpoiFgrFj07uq4CZsq4crVXpLGgQfoFq00jPKRPgesuGPaz8lg1yLfvafkU3Jd1i8snKwYR3LA==",
             "cpu": [
                 "ia32"
             ],
@@ -1539,9 +1539,9 @@
             }
         },
         "node_modules/@next/swc-win32-x64-msvc": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.8.tgz",
-            "integrity": "sha512-UIRKoByVKbuR6SnFG4JM8EMFlJrfEGuUQ1ihxzEleWcNwRMMiVaCj1KyqfTOW8VTQhJ0u8P1Ngg6q1RwnIBTtw==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.9.tgz",
+            "integrity": "sha512-QbT03FXRNdpuL+e9pLnu+XajZdm/TtIXVYY4lA9t+9l0fLZbHXDYEKitAqxrOj37o3Vx5ufxiRAniaIebYDCgw==",
             "cpu": [
                 "x64"
             ],
@@ -2905,9 +2905,9 @@
             "dev": true
         },
         "node_modules/@types/node": {
-            "version": "20.3.3",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz",
-            "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==",
+            "version": "20.4.0",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.0.tgz",
+            "integrity": "sha512-jfT7iTf/4kOQ9S7CHV9BIyRaQqHu67mOjsIQBC3BKZvzvUB6zLxEwJ6sBE3ozcvP8kF6Uk5PXN0Q+c0dfhGX0g==",
             "dev": true
         },
         "node_modules/@types/prettier": {
@@ -3484,12 +3484,12 @@
             }
         },
         "node_modules/babel-jest": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.0.tgz",
-            "integrity": "sha512-Jj8Bq2yKsk11XLk06Nm8SdvYkAcecH+GuhxB8DnK5SncjHnJ88TQjSnGgE7jpajpnSvz9DZ6X8hXrDkD/6/TPQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz",
+            "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==",
             "dev": true,
             "dependencies": {
-                "@jest/transform": "^29.6.0",
+                "@jest/transform": "^29.6.1",
                 "@types/babel__core": "^7.1.14",
                 "babel-plugin-istanbul": "^6.1.1",
                 "babel-preset-jest": "^29.5.0",
@@ -3925,9 +3925,9 @@
             }
         },
         "node_modules/collect-v8-coverage": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
-            "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
+            "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
             "dev": true
         },
         "node_modules/color-convert": {
@@ -4702,12 +4702,12 @@
             }
         },
         "node_modules/eslint-config-next": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.8.tgz",
-            "integrity": "sha512-2hE0b6lHuhtHBX8VgEXi8v4G8PVrPUBMOSLCTq8qtcQ2qQOX7+uBOLK2kU4FD2qDZzyXNlhmuH+WLT5ptY4XLA==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.9.tgz",
+            "integrity": "sha512-0fLtKRR268NArpqeXXwnLgMXPvF64YESQvptVg+RMLCaijKm3FICN9Y7Jc1p2o+yrWwE4DufJXDM/Vo53D1L7g==",
             "dev": true,
             "dependencies": {
-                "@next/eslint-plugin-next": "13.4.8",
+                "@next/eslint-plugin-next": "13.4.9",
                 "@rushstack/eslint-patch": "^1.1.3",
                 "@typescript-eslint/parser": "^5.42.0",
                 "eslint-import-resolver-node": "^0.3.6",
@@ -4715,7 +4715,7 @@
                 "eslint-plugin-import": "^2.26.0",
                 "eslint-plugin-jsx-a11y": "^6.5.1",
                 "eslint-plugin-react": "^7.31.7",
-                "eslint-plugin-react-hooks": "^4.5.0"
+                "eslint-plugin-react-hooks": "5.0.0-canary-7118f5dd7-20230705"
             },
             "peerDependencies": {
                 "eslint": "^7.23.0 || ^8.0.0",
@@ -4940,9 +4940,9 @@
             }
         },
         "node_modules/eslint-plugin-react-hooks": {
-            "version": "4.6.0",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
-            "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+            "version": "5.0.0-canary-7118f5dd7-20230705",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz",
+            "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==",
             "dev": true,
             "engines": {
                 "node": ">=10"
@@ -5129,17 +5129,17 @@
             }
         },
         "node_modules/expect": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.0.tgz",
-            "integrity": "sha512-AV+HaBtnDJ2YEUhPPo25HyUHBLaetM+y/Dq6pEC8VPQyt1dK+k8MfGkMy46djy2bddcqESc1kl4/K1uLWSfk9g==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz",
+            "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==",
             "dev": true,
             "dependencies": {
-                "@jest/expect-utils": "^29.6.0",
+                "@jest/expect-utils": "^29.6.1",
                 "@types/node": "*",
                 "jest-get-type": "^29.4.3",
-                "jest-matcher-utils": "^29.6.0",
-                "jest-message-util": "^29.6.0",
-                "jest-util": "^29.6.0"
+                "jest-matcher-utils": "^29.6.1",
+                "jest-message-util": "^29.6.1",
+                "jest-util": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -6332,15 +6332,15 @@
             }
         },
         "node_modules/jest": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.0.tgz",
-            "integrity": "sha512-do1J9gGrQ68E4UfMz/4OM71p9qCqQxu32N/9ZfeYFSSlx0uUOuxeyZxtJZNaUTW12ZA11ERhmBjBhy1Ho96R4g==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz",
+            "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==",
             "dev": true,
             "dependencies": {
-                "@jest/core": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/core": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "import-local": "^3.0.2",
-                "jest-cli": "^29.6.0"
+                "jest-cli": "^29.6.1"
             },
             "bin": {
                 "jest": "bin/jest.js"
@@ -6371,28 +6371,28 @@
             }
         },
         "node_modules/jest-circus": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.0.tgz",
-            "integrity": "sha512-LtG45qEKhse2Ws5zNR4DnZATReLGQXzBZGZnJ0DU37p6d4wDhu41vvczCQ3Ou+llR6CRYDBshsubV7H4jZvIkw==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz",
+            "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==",
             "dev": true,
             "dependencies": {
-                "@jest/environment": "^29.6.0",
-                "@jest/expect": "^29.6.0",
-                "@jest/test-result": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/environment": "^29.6.1",
+                "@jest/expect": "^29.6.1",
+                "@jest/test-result": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "co": "^4.6.0",
                 "dedent": "^0.7.0",
                 "is-generator-fn": "^2.0.0",
-                "jest-each": "^29.6.0",
-                "jest-matcher-utils": "^29.6.0",
-                "jest-message-util": "^29.6.0",
-                "jest-runtime": "^29.6.0",
-                "jest-snapshot": "^29.6.0",
-                "jest-util": "^29.6.0",
+                "jest-each": "^29.6.1",
+                "jest-matcher-utils": "^29.6.1",
+                "jest-message-util": "^29.6.1",
+                "jest-runtime": "^29.6.1",
+                "jest-snapshot": "^29.6.1",
+                "jest-util": "^29.6.1",
                 "p-limit": "^3.1.0",
-                "pretty-format": "^29.6.0",
+                "pretty-format": "^29.6.1",
                 "pure-rand": "^6.0.0",
                 "slash": "^3.0.0",
                 "stack-utils": "^2.0.3"
@@ -6418,9 +6418,9 @@
             }
         },
         "node_modules/jest-circus/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -6450,21 +6450,21 @@
             "dev": true
         },
         "node_modules/jest-cli": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.0.tgz",
-            "integrity": "sha512-WvZIaanK/abkw6s01924DQ2QLwM5Q4Y4iPbSDb9Zg6smyXGqqcPQ7ft9X8D7B0jICz312eSzM6UlQNxuZJBrMw==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz",
+            "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==",
             "dev": true,
             "dependencies": {
-                "@jest/core": "^29.6.0",
-                "@jest/test-result": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/core": "^29.6.1",
+                "@jest/test-result": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "chalk": "^4.0.0",
                 "exit": "^0.1.2",
                 "graceful-fs": "^4.2.9",
                 "import-local": "^3.0.2",
-                "jest-config": "^29.6.0",
-                "jest-util": "^29.6.0",
-                "jest-validate": "^29.6.0",
+                "jest-config": "^29.6.1",
+                "jest-util": "^29.6.1",
+                "jest-validate": "^29.6.1",
                 "prompts": "^2.0.1",
                 "yargs": "^17.3.1"
             },
@@ -6500,31 +6500,31 @@
             }
         },
         "node_modules/jest-config": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.0.tgz",
-            "integrity": "sha512-fKA4jM91PDqWVkMpb1FVKxIuhg3hC6hgaen57cr1rRZkR96dCatvJZsk3ik7/GNu9ERj9wgAspOmyvkFoGsZhA==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz",
+            "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==",
             "dev": true,
             "dependencies": {
                 "@babel/core": "^7.11.6",
-                "@jest/test-sequencer": "^29.6.0",
-                "@jest/types": "^29.6.0",
-                "babel-jest": "^29.6.0",
+                "@jest/test-sequencer": "^29.6.1",
+                "@jest/types": "^29.6.1",
+                "babel-jest": "^29.6.1",
                 "chalk": "^4.0.0",
                 "ci-info": "^3.2.0",
                 "deepmerge": "^4.2.2",
                 "glob": "^7.1.3",
                 "graceful-fs": "^4.2.9",
-                "jest-circus": "^29.6.0",
-                "jest-environment-node": "^29.6.0",
+                "jest-circus": "^29.6.1",
+                "jest-environment-node": "^29.6.1",
                 "jest-get-type": "^29.4.3",
                 "jest-regex-util": "^29.4.3",
-                "jest-resolve": "^29.6.0",
-                "jest-runner": "^29.6.0",
-                "jest-util": "^29.6.0",
-                "jest-validate": "^29.6.0",
+                "jest-resolve": "^29.6.1",
+                "jest-runner": "^29.6.1",
+                "jest-util": "^29.6.1",
+                "jest-validate": "^29.6.1",
                 "micromatch": "^4.0.4",
                 "parse-json": "^5.2.0",
-                "pretty-format": "^29.6.0",
+                "pretty-format": "^29.6.1",
                 "slash": "^3.0.0",
                 "strip-json-comments": "^3.1.1"
             },
@@ -6561,9 +6561,9 @@
             }
         },
         "node_modules/jest-config/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -6593,15 +6593,15 @@
             "dev": true
         },
         "node_modules/jest-diff": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.0.tgz",
-            "integrity": "sha512-ZRm7cd2m9YyZ0N3iMyuo1iUiprxQ/MFpYWXzEEj7hjzL3WnDffKW8192XBDcrAI8j7hnrM1wed3bL/oEnYF/8w==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz",
+            "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==",
             "dev": true,
             "dependencies": {
                 "chalk": "^4.0.0",
                 "diff-sequences": "^29.4.3",
                 "jest-get-type": "^29.4.3",
-                "pretty-format": "^29.6.0"
+                "pretty-format": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -6624,9 +6624,9 @@
             }
         },
         "node_modules/jest-diff/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -6668,16 +6668,16 @@
             }
         },
         "node_modules/jest-each": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.0.tgz",
-            "integrity": "sha512-d0Jem4RBAlFUyV6JSXPSHVUpNo5RleSj+iJEy1G3+ZCrzHDjWs/1jUfrbnJKHdJdAx5BCEce/Ju379WqHhQk4w==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz",
+            "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^29.6.0",
+                "@jest/types": "^29.6.1",
                 "chalk": "^4.0.0",
                 "jest-get-type": "^29.4.3",
-                "jest-util": "^29.6.0",
-                "pretty-format": "^29.6.0"
+                "jest-util": "^29.6.1",
+                "pretty-format": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -6700,9 +6700,9 @@
             }
         },
         "node_modules/jest-each/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -6732,18 +6732,18 @@
             "dev": true
         },
         "node_modules/jest-environment-jsdom": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.0.tgz",
-            "integrity": "sha512-/cOhoyv+uMbOh4nQPyqtkPas/uUxr5AbK6TPqMMFyj1qEJURY78RhqgBjOFIX02+Lvu5V0RWLq2qKY1dHubFOQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.1.tgz",
+            "integrity": "sha512-PoY+yLaHzVRhVEjcVKSfJ7wXmJW4UqPYNhR05h7u/TK0ouf6DmRNZFBL/Z00zgQMyWGMBXn69/FmOvhEJu8cIw==",
             "dev": true,
             "dependencies": {
-                "@jest/environment": "^29.6.0",
-                "@jest/fake-timers": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/environment": "^29.6.1",
+                "@jest/fake-timers": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/jsdom": "^20.0.0",
                 "@types/node": "*",
-                "jest-mock": "^29.6.0",
-                "jest-util": "^29.6.0",
+                "jest-mock": "^29.6.1",
+                "jest-util": "^29.6.1",
                 "jsdom": "^20.0.0"
             },
             "engines": {
@@ -6759,17 +6759,17 @@
             }
         },
         "node_modules/jest-environment-node": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.0.tgz",
-            "integrity": "sha512-BOf5Q2/nFCdBOnyBM5c5/6DbdQYgc+0gyUQ8l8qhUAB8O7pM+4QJXIXJsRZJaxd5SHV6y5VArTVhOfogoqcP8Q==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz",
+            "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==",
             "dev": true,
             "dependencies": {
-                "@jest/environment": "^29.6.0",
-                "@jest/fake-timers": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/environment": "^29.6.1",
+                "@jest/fake-timers": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
-                "jest-mock": "^29.6.0",
-                "jest-util": "^29.6.0"
+                "jest-mock": "^29.6.1",
+                "jest-util": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -6785,20 +6785,20 @@
             }
         },
         "node_modules/jest-haste-map": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.0.tgz",
-            "integrity": "sha512-dY1DKufptj7hcJSuhpqlYPGcnN3XjlOy/g0jinpRTMsbb40ivZHiuIPzeminOZkrek8C+oDxC54ILGO3vMLojg==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz",
+            "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^29.6.0",
+                "@jest/types": "^29.6.1",
                 "@types/graceful-fs": "^4.1.3",
                 "@types/node": "*",
                 "anymatch": "^3.0.3",
                 "fb-watchman": "^2.0.0",
                 "graceful-fs": "^4.2.9",
                 "jest-regex-util": "^29.4.3",
-                "jest-util": "^29.6.0",
-                "jest-worker": "^29.6.0",
+                "jest-util": "^29.6.1",
+                "jest-worker": "^29.6.1",
                 "micromatch": "^4.0.4",
                 "walker": "^1.0.8"
             },
@@ -6810,13 +6810,13 @@
             }
         },
         "node_modules/jest-leak-detector": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.0.tgz",
-            "integrity": "sha512-JdV6EZOPxHR1gd6ccxjNowuROkT2jtGU5G/g58RcJX1xe5mrtLj0g6/ZkyMoXF4cs+tTkHMFX6pcIrB1QPQwCw==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz",
+            "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==",
             "dev": true,
             "dependencies": {
                 "jest-get-type": "^29.4.3",
-                "pretty-format": "^29.6.0"
+                "pretty-format": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -6835,9 +6835,9 @@
             }
         },
         "node_modules/jest-leak-detector/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -6855,15 +6855,15 @@
             "dev": true
         },
         "node_modules/jest-matcher-utils": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.0.tgz",
-            "integrity": "sha512-oSlqfGN+sbkB2Q5um/zL7z80w84FEAcLKzXBZIPyRk2F2Srg1ubhrHVKW68JCvb2+xKzAeGw35b+6gciS24PHw==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz",
+            "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==",
             "dev": true,
             "dependencies": {
                 "chalk": "^4.0.0",
-                "jest-diff": "^29.6.0",
+                "jest-diff": "^29.6.1",
                 "jest-get-type": "^29.4.3",
-                "pretty-format": "^29.6.0"
+                "pretty-format": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -6886,9 +6886,9 @@
             }
         },
         "node_modules/jest-matcher-utils/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -6918,18 +6918,18 @@
             "dev": true
         },
         "node_modules/jest-message-util": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.0.tgz",
-            "integrity": "sha512-mkCp56cETbpoNtsaeWVy6SKzk228mMi9FPHSObaRIhbR2Ujw9PqjW/yqVHD2tN1bHbC8ol6h3UEo7dOPmIYwIA==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz",
+            "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==",
             "dev": true,
             "dependencies": {
                 "@babel/code-frame": "^7.12.13",
-                "@jest/types": "^29.6.0",
+                "@jest/types": "^29.6.1",
                 "@types/stack-utils": "^2.0.0",
                 "chalk": "^4.0.0",
                 "graceful-fs": "^4.2.9",
                 "micromatch": "^4.0.4",
-                "pretty-format": "^29.6.0",
+                "pretty-format": "^29.6.1",
                 "slash": "^3.0.0",
                 "stack-utils": "^2.0.3"
             },
@@ -6954,9 +6954,9 @@
             }
         },
         "node_modules/jest-message-util/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -6986,14 +6986,14 @@
             "dev": true
         },
         "node_modules/jest-mock": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.0.tgz",
-            "integrity": "sha512-2Pb7R2w24Q0aUVn+2/vdRDL6CqGqpheDZy7zrXav8FotOpSGw/4bS2hyVoKHMEx4xzOn6EyCAGwc5czWxXeN7w==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz",
+            "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^29.6.0",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
-                "jest-util": "^29.6.0"
+                "jest-util": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -7026,17 +7026,17 @@
             }
         },
         "node_modules/jest-resolve": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.0.tgz",
-            "integrity": "sha512-+hrpY4LzAONoZA/rvB6rnZLkOSA6UgJLpdCWrOZNSgGxWMumzRLu7dLUSCabAHzoHIDQ9qXfr3th1zYNJ0E8sQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz",
+            "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==",
             "dev": true,
             "dependencies": {
                 "chalk": "^4.0.0",
                 "graceful-fs": "^4.2.9",
-                "jest-haste-map": "^29.6.0",
+                "jest-haste-map": "^29.6.1",
                 "jest-pnp-resolver": "^1.2.2",
-                "jest-util": "^29.6.0",
-                "jest-validate": "^29.6.0",
+                "jest-util": "^29.6.1",
+                "jest-validate": "^29.6.1",
                 "resolve": "^1.20.0",
                 "resolve.exports": "^2.0.0",
                 "slash": "^3.0.0"
@@ -7046,13 +7046,13 @@
             }
         },
         "node_modules/jest-resolve-dependencies": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.0.tgz",
-            "integrity": "sha512-eOfPog9K3hJdJk/3i6O6bQhXS+3uXhMDkLJGX+xmMPp7T1d/zdcFofbDnHgNoEkhD/mSimC5IagLEP7lpLLu/A==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz",
+            "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==",
             "dev": true,
             "dependencies": {
                 "jest-regex-util": "^29.4.3",
-                "jest-snapshot": "^29.6.0"
+                "jest-snapshot": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -7075,30 +7075,30 @@
             }
         },
         "node_modules/jest-runner": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.0.tgz",
-            "integrity": "sha512-4fZuGV2lOxS2BiqEG9/AI8E6O+jo+QZjMVcgi1x5E6aDql0Gd/EFIbUQ0pSS09y8cya1vJB/qC2xsE468jqtSg==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz",
+            "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==",
             "dev": true,
             "dependencies": {
-                "@jest/console": "^29.6.0",
-                "@jest/environment": "^29.6.0",
-                "@jest/test-result": "^29.6.0",
-                "@jest/transform": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/console": "^29.6.1",
+                "@jest/environment": "^29.6.1",
+                "@jest/test-result": "^29.6.1",
+                "@jest/transform": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "emittery": "^0.13.1",
                 "graceful-fs": "^4.2.9",
                 "jest-docblock": "^29.4.3",
-                "jest-environment-node": "^29.6.0",
-                "jest-haste-map": "^29.6.0",
-                "jest-leak-detector": "^29.6.0",
-                "jest-message-util": "^29.6.0",
-                "jest-resolve": "^29.6.0",
-                "jest-runtime": "^29.6.0",
-                "jest-util": "^29.6.0",
-                "jest-watcher": "^29.6.0",
-                "jest-worker": "^29.6.0",
+                "jest-environment-node": "^29.6.1",
+                "jest-haste-map": "^29.6.1",
+                "jest-leak-detector": "^29.6.1",
+                "jest-message-util": "^29.6.1",
+                "jest-resolve": "^29.6.1",
+                "jest-runtime": "^29.6.1",
+                "jest-util": "^29.6.1",
+                "jest-watcher": "^29.6.1",
+                "jest-worker": "^29.6.1",
                 "p-limit": "^3.1.0",
                 "source-map-support": "0.5.13"
             },
@@ -7123,31 +7123,31 @@
             }
         },
         "node_modules/jest-runtime": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.0.tgz",
-            "integrity": "sha512-5FavYo3EeXLHIvnJf+r7Cj0buePAbe4mzRB9oeVxDS0uVmouSBjWeGgyRjZkw7ArxOoZI8gO6f8SGMJ2HFlwwg==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz",
+            "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==",
             "dev": true,
             "dependencies": {
-                "@jest/environment": "^29.6.0",
-                "@jest/fake-timers": "^29.6.0",
-                "@jest/globals": "^29.6.0",
+                "@jest/environment": "^29.6.1",
+                "@jest/fake-timers": "^29.6.1",
+                "@jest/globals": "^29.6.1",
                 "@jest/source-map": "^29.6.0",
-                "@jest/test-result": "^29.6.0",
-                "@jest/transform": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/test-result": "^29.6.1",
+                "@jest/transform": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "cjs-module-lexer": "^1.0.0",
                 "collect-v8-coverage": "^1.0.0",
                 "glob": "^7.1.3",
                 "graceful-fs": "^4.2.9",
-                "jest-haste-map": "^29.6.0",
-                "jest-message-util": "^29.6.0",
-                "jest-mock": "^29.6.0",
+                "jest-haste-map": "^29.6.1",
+                "jest-message-util": "^29.6.1",
+                "jest-mock": "^29.6.1",
                 "jest-regex-util": "^29.4.3",
-                "jest-resolve": "^29.6.0",
-                "jest-snapshot": "^29.6.0",
-                "jest-util": "^29.6.0",
+                "jest-resolve": "^29.6.1",
+                "jest-snapshot": "^29.6.1",
+                "jest-util": "^29.6.1",
                 "slash": "^3.0.0",
                 "strip-bom": "^4.0.0"
             },
@@ -7172,9 +7172,9 @@
             }
         },
         "node_modules/jest-snapshot": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.0.tgz",
-            "integrity": "sha512-H3kUE9NwWDEDoutcOSS921IqdlkdjgnMdj1oMyxAHNflscdLc9dB8OudZHV6kj4OHJxbMxL8CdI5DlwYrs4wQg==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz",
+            "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==",
             "dev": true,
             "dependencies": {
                 "@babel/core": "^7.11.6",
@@ -7182,21 +7182,21 @@
                 "@babel/plugin-syntax-jsx": "^7.7.2",
                 "@babel/plugin-syntax-typescript": "^7.7.2",
                 "@babel/types": "^7.3.3",
-                "@jest/expect-utils": "^29.6.0",
-                "@jest/transform": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/expect-utils": "^29.6.1",
+                "@jest/transform": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/prettier": "^2.1.5",
                 "babel-preset-current-node-syntax": "^1.0.0",
                 "chalk": "^4.0.0",
-                "expect": "^29.6.0",
+                "expect": "^29.6.1",
                 "graceful-fs": "^4.2.9",
-                "jest-diff": "^29.6.0",
+                "jest-diff": "^29.6.1",
                 "jest-get-type": "^29.4.3",
-                "jest-matcher-utils": "^29.6.0",
-                "jest-message-util": "^29.6.0",
-                "jest-util": "^29.6.0",
+                "jest-matcher-utils": "^29.6.1",
+                "jest-message-util": "^29.6.1",
+                "jest-util": "^29.6.1",
                 "natural-compare": "^1.4.0",
-                "pretty-format": "^29.6.0",
+                "pretty-format": "^29.6.1",
                 "semver": "^7.5.3"
             },
             "engines": {
@@ -7220,9 +7220,9 @@
             }
         },
         "node_modules/jest-snapshot/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -7252,12 +7252,12 @@
             "dev": true
         },
         "node_modules/jest-util": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.0.tgz",
-            "integrity": "sha512-S0USx9YwcvEm4pQ5suisVm/RVxBmi0GFR7ocJhIeaCuW5AXnAnffXbaVKvIFodyZNOc9ygzVtTxmBf40HsHXaA==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz",
+            "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^29.6.0",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
                 "chalk": "^4.0.0",
                 "ci-info": "^3.2.0",
@@ -7285,17 +7285,17 @@
             }
         },
         "node_modules/jest-validate": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.0.tgz",
-            "integrity": "sha512-MLTrAJsb1+W7svbeZ+A7pAnyXMaQrjvPDKCy7OlfsfB6TMVc69v7WjUWfiR6r3snULFWZASiKgvNVDuATta1dg==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz",
+            "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==",
             "dev": true,
             "dependencies": {
-                "@jest/types": "^29.6.0",
+                "@jest/types": "^29.6.1",
                 "camelcase": "^6.2.0",
                 "chalk": "^4.0.0",
                 "jest-get-type": "^29.4.3",
                 "leven": "^3.1.0",
-                "pretty-format": "^29.6.0"
+                "pretty-format": "^29.6.1"
             },
             "engines": {
                 "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -7330,9 +7330,9 @@
             }
         },
         "node_modules/jest-validate/node_modules/pretty-format": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.0.tgz",
-            "integrity": "sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+            "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
             "dev": true,
             "dependencies": {
                 "@jest/schemas": "^29.6.0",
@@ -7362,18 +7362,18 @@
             "dev": true
         },
         "node_modules/jest-watcher": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.0.tgz",
-            "integrity": "sha512-LdsQqFNX60mRdRRe+zsELnYRH1yX6KL+ukbh+u6WSQeTheZZe1TlLJNKRQiZ7e0VbvMkywmMWL/KV35noOJCcw==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz",
+            "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==",
             "dev": true,
             "dependencies": {
-                "@jest/test-result": "^29.6.0",
-                "@jest/types": "^29.6.0",
+                "@jest/test-result": "^29.6.1",
+                "@jest/types": "^29.6.1",
                 "@types/node": "*",
                 "ansi-escapes": "^4.2.1",
                 "chalk": "^4.0.0",
                 "emittery": "^0.13.1",
-                "jest-util": "^29.6.0",
+                "jest-util": "^29.6.1",
                 "string-length": "^4.0.1"
             },
             "engines": {
@@ -7397,13 +7397,13 @@
             }
         },
         "node_modules/jest-worker": {
-            "version": "29.6.0",
-            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.0.tgz",
-            "integrity": "sha512-oiQHH1SnKmZIwwPnpOrXTq4kHBk3lKGY/07DpnH0sAu+x7J8rXlbLDROZsU6vy9GwB0hPiZeZpu6YlJ48QoKcA==",
+            "version": "29.6.1",
+            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
+            "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
             "dev": true,
             "dependencies": {
                 "@types/node": "*",
-                "jest-util": "^29.6.0",
+                "jest-util": "^29.6.1",
                 "merge-stream": "^2.0.0",
                 "supports-color": "^8.0.0"
             },
@@ -7668,9 +7668,9 @@
             }
         },
         "node_modules/lucide-react": {
-            "version": "0.258.0",
-            "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.258.0.tgz",
-            "integrity": "sha512-3evnpKadBrjLr2HHJ66eDZ1y0vPS6pm8NiNDaLqhddUUyJGnA+lfDPZfbVkuAFq7Xaa1TEy7Sg17sM7mHpMKrA==",
+            "version": "0.259.0",
+            "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.259.0.tgz",
+            "integrity": "sha512-dFBLc6jRDfcpD9NQ7NyFVa+YR3RHX6+bs+f/UiotvNPho+kd4WyeXWMCCchUf7i/pq3BAaHkbmtkbx/GxxHVUw==",
             "peerDependencies": {
                 "react": "^16.5.1 || ^17.0.0 || ^18.0.0"
             }
@@ -7878,11 +7878,11 @@
             "dev": true
         },
         "node_modules/next": {
-            "version": "13.4.8",
-            "resolved": "https://registry.npmjs.org/next/-/next-13.4.8.tgz",
-            "integrity": "sha512-lxUjndYKjZHGK3CWeN2RI+/6ni6EUvjiqGWXAYPxUfGIdFGQ5XoisrqAJ/dF74aP27buAfs8MKIbIMMdxjqSBg==",
+            "version": "13.4.9",
+            "resolved": "https://registry.npmjs.org/next/-/next-13.4.9.tgz",
+            "integrity": "sha512-vtefFm/BWIi/eWOqf1GsmKG3cjKw1k3LjuefKRcL3iiLl3zWzFdPG3as6xtxrGO6gwTzzaO1ktL4oiHt/uvTjA==",
             "dependencies": {
-                "@next/env": "13.4.8",
+                "@next/env": "13.4.9",
                 "@swc/helpers": "0.5.1",
                 "busboy": "1.6.0",
                 "caniuse-lite": "^1.0.30001406",
@@ -7898,15 +7898,15 @@
                 "node": ">=16.8.0"
             },
             "optionalDependencies": {
-                "@next/swc-darwin-arm64": "13.4.8",
-                "@next/swc-darwin-x64": "13.4.8",
-                "@next/swc-linux-arm64-gnu": "13.4.8",
-                "@next/swc-linux-arm64-musl": "13.4.8",
-                "@next/swc-linux-x64-gnu": "13.4.8",
-                "@next/swc-linux-x64-musl": "13.4.8",
-                "@next/swc-win32-arm64-msvc": "13.4.8",
-                "@next/swc-win32-ia32-msvc": "13.4.8",
-                "@next/swc-win32-x64-msvc": "13.4.8"
+                "@next/swc-darwin-arm64": "13.4.9",
+                "@next/swc-darwin-x64": "13.4.9",
+                "@next/swc-linux-arm64-gnu": "13.4.9",
+                "@next/swc-linux-arm64-musl": "13.4.9",
+                "@next/swc-linux-x64-gnu": "13.4.9",
+                "@next/swc-linux-x64-musl": "13.4.9",
+                "@next/swc-win32-arm64-msvc": "13.4.9",
+                "@next/swc-win32-ia32-msvc": "13.4.9",
+                "@next/swc-win32-x64-msvc": "13.4.9"
             },
             "peerDependencies": {
                 "@opentelemetry/api": "^1.1.0",
@@ -8573,9 +8573,9 @@
             }
         },
         "node_modules/postcss": {
-            "version": "8.4.24",
-            "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz",
-            "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==",
+            "version": "8.4.25",
+            "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.25.tgz",
+            "integrity": "sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==",
             "funding": [
                 {
                     "type": "opencollective",
diff --git a/package.json b/package.json
index 446bedae67af6c569c577e18ec5b20a8bb805b20..ca890177e6a903c8b707709ac43c720700549855 100644
--- a/package.json
+++ b/package.json
@@ -37,8 +37,8 @@
         "class-variance-authority": "^0.6.1",
         "clsx": "^1.2.1",
         "dayjs": "^1.11.9",
-        "lucide-react": "^0.258.0",
-        "next": "^13.4.8",
+        "lucide-react": "^0.259.0",
+        "next": "^13.4.9",
         "next-auth": "^4.22.1",
         "next-themes": "^0.2.1",
         "normalize-diacritics": "^4.0.0",
@@ -59,15 +59,15 @@
         "@testing-library/react": "^14.0.0",
         "@types/bcrypt": "^5.0.0",
         "@types/jest": "^29.5.2",
-        "@types/node": "^20.3.3",
+        "@types/node": "^20.4.0",
         "@types/react": "^18.2.14",
         "@types/react-dom": "^18.2.6",
         "autoprefixer": "10.4.14",
         "eslint": "^8.44.0",
-        "eslint-config-next": "^13.4.8",
-        "jest": "^29.6.0",
-        "jest-environment-jsdom": "^29.6.0",
-        "postcss": "8.4.24",
+        "eslint-config-next": "^13.4.9",
+        "jest": "^29.6.1",
+        "jest-environment-jsdom": "^29.6.1",
+        "postcss": "8.4.25",
         "prisma": "^4.16.2",
         "tailwindcss": "3.3.2",
         "typescript": "^5.1.6"
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 9deaae8759c1e6d52d9ef69b7caa4e9be0174f0d..d6b3ef1cdc15ec826b97a8e27954672bc783f996 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -81,24 +81,12 @@ model User {
     regweets Regweet[]
     likes    Like[]
 
-    following Follows[] @relation("following")
-    followers Follows[] @relation("follower")
+    following User[] @relation("followers")
+    followers User[] @relation("followers")
 
     @@map("users")
 }
 
-model Follows {
-    followerId  String
-    followingId String
-    createdAt   DateTime @default(now()) @map("created_at")
-
-    follower  User @relation("following", fields: [followerId], references: [id])
-    following User @relation("follower", fields: [followingId], references: [id])
-
-    @@id([followerId, followingId])
-    @@map("follows")
-}
-
 model Gweet {
     id        String   @id @default(cuid())
     authorId  String   @map("user_id")