Formatting

This commit is contained in:
2025-06-28 00:15:51 +02:00
parent 0088b8f02a
commit 4ac986745d
22 changed files with 1180 additions and 1245 deletions

View File

@@ -1,16 +1,17 @@
import type { MetadataRoute } from 'next' import type { MetadataRoute } from "next"
export default function manifest(): MetadataRoute.Manifest { export default function manifest(): MetadataRoute.Manifest {
return { return {
name: "Linker - Smart URL Shortener & Link Management", name: "Linker - Smart URL Shortener & Link Management",
short_name: "Linker", short_name: "Linker",
description: "Transform long URLs into short, shareable links. Perfect for social media, emails, and anywhere you need clean, manageable links. Get started for free!", description:
"Transform long URLs into short, shareable links. Perfect for social media, emails, and anywhere you need clean, manageable links. Get started for free!",
start_url: "/", start_url: "/",
display: "standalone", display: "standalone",
icons: [{ icons: [{
src: '/favicon.ico', src: "/favicon.ico",
sizes: 'any', sizes: "any",
type: 'image/x-icon', type: "image/x-icon"
}], }]
} }
} }

View File

@@ -1,5 +1,5 @@
import { getAllUrls } from '@/lib/db/urls' import { getAllUrls } from "@/lib/db/urls"
import type { MetadataRoute } from 'next' import type { MetadataRoute } from "next"
export default async function robots(): Promise<MetadataRoute.Robots> { export default async function robots(): Promise<MetadataRoute.Robots> {
const urls = await getAllUrls() const urls = await getAllUrls()
@@ -8,7 +8,7 @@ export default async function robots(): Promise<MetadataRoute.Robots> {
if (u.crawlable) { if (u.crawlable) {
return `/r/${u.slug}` return `/r/${u.slug}`
} }
}).filter(v => typeof v === 'string') }).filter(v => typeof v === "string")
return { return {
rules: [ rules: [
@@ -17,7 +17,8 @@ export default async function robots(): Promise<MetadataRoute.Robots> {
allow: "/", allow: "/",
disallow: ["/api", "/dasboard", "/sign-in"], disallow: ["/api", "/dasboard", "/sign-in"],
crawlDelay: 1 crawlDelay: 1
}, { },
{
userAgent: "*", userAgent: "*",
disallow: "/r/", disallow: "/r/",
allow: crawlableUrls, allow: crawlableUrls,

View File

@@ -1,15 +1,11 @@
"use client" "use client"
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react"
import * as React from "react" import * as React from "react"
import {
ChevronDownIcon,
ChevronLeftIcon,
ChevronRightIcon,
} from "lucide-react"
import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker" import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
import { cn } from "@/lib/utils"
import { Button, buttonVariants } from "@/components/ui/button" import { Button, buttonVariants } from "@/components/ui/button"
import { cn } from "@/lib/utils"
function Calendar({ function Calendar({
className, className,
@@ -36,9 +32,8 @@ function Calendar({
)} )}
captionLayout={captionLayout} captionLayout={captionLayout}
formatters={{ formatters={{
formatMonthDropdown: (date) => formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
date.toLocaleString("default", { month: "short" }), ...formatters
...formatters,
}} }}
classNames={{ classNames={{
root: cn("w-fit", defaultClassNames.root), root: cn("w-fit", defaultClassNames.root),
@@ -119,7 +114,7 @@ function Calendar({
defaultClassNames.disabled defaultClassNames.disabled
), ),
hidden: cn("invisible", defaultClassNames.hidden), hidden: cn("invisible", defaultClassNames.hidden),
...classNames, ...classNames
}} }}
components={{ components={{
Root: ({ className, rootRef, ...props }) => { Root: ({ className, rootRef, ...props }) => {
@@ -134,9 +129,7 @@ function Calendar({
}, },
Chevron: ({ className, orientation, ...props }) => { Chevron: ({ className, orientation, ...props }) => {
if (orientation === "left") { if (orientation === "left") {
return ( return <ChevronLeftIcon className={cn("size-4", className)} {...props} />
<ChevronLeftIcon className={cn("size-4", className)} {...props} />
)
} }
if (orientation === "right") { if (orientation === "right") {
@@ -148,9 +141,7 @@ function Calendar({
) )
} }
return ( return <ChevronDownIcon className={cn("size-4", className)} {...props} />
<ChevronDownIcon className={cn("size-4", className)} {...props} />
)
}, },
DayButton: CalendarDayButton, DayButton: CalendarDayButton,
WeekNumber: ({ children, ...props }) => { WeekNumber: ({ children, ...props }) => {
@@ -162,7 +153,7 @@ function Calendar({
</td> </td>
) )
}, },
...components, ...components
}} }}
{...props} {...props}
/> />
@@ -188,12 +179,10 @@ function CalendarDayButton({
variant="ghost" variant="ghost"
size="icon" size="icon"
data-day={day.date.toLocaleDateString()} data-day={day.date.toLocaleDateString()}
data-selected-single={ data-selected-single={modifiers.selected &&
modifiers.selected &&
!modifiers.range_start && !modifiers.range_start &&
!modifiers.range_end && !modifiers.range_end &&
!modifiers.range_middle !modifiers.range_middle}
}
data-range-start={modifiers.range_start} data-range-start={modifiers.range_start}
data-range-end={modifiers.range_end} data-range-end={modifiers.range_end}
data-range-middle={modifiers.range_middle} data-range-middle={modifiers.range_middle}

View File

@@ -1,26 +1,18 @@
"use client" "use client"
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label" import * as LabelPrimitive from "@radix-ui/react-label"
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot"
import { import * as React from "react"
Controller, import { Controller, type ControllerProps, type FieldPath, type FieldValues, FormProvider, useFormContext, useFormState } from "react-hook-form"
FormProvider,
useFormContext,
useFormState,
type ControllerProps,
type FieldPath,
type FieldValues,
} from "react-hook-form"
import { cn } from "@/lib/utils"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { cn } from "@/lib/utils"
const Form = FormProvider const Form = FormProvider
type FormFieldContextValue< type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues, TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = { > = {
name: TName name: TName
} }
@@ -31,7 +23,7 @@ const FormFieldContext = React.createContext<FormFieldContextValue>(
const FormField = < const FormField = <
TFieldValues extends FieldValues = FieldValues, TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
>({ >({
...props ...props
}: ControllerProps<TFieldValues, TName>) => { }: ControllerProps<TFieldValues, TName>) => {
@@ -61,7 +53,7 @@ const useFormField = () => {
formItemId: `${id}-form-item`, formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`, formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`, formMessageId: `${id}-form-item-message`,
...fieldState, ...fieldState
} }
} }
@@ -111,11 +103,9 @@ function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
<Slot <Slot
data-slot="form-control" data-slot="form-control"
id={formItemId} id={formItemId}
aria-describedby={ aria-describedby={!error
!error
? `${formDescriptionId}` ? `${formDescriptionId}`
: `${formDescriptionId} ${formMessageId}` : `${formDescriptionId} ${formMessageId}`}
}
aria-invalid={!!error} aria-invalid={!!error}
{...props} {...props}
/> />
@@ -155,13 +145,4 @@ function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
) )
} }
export { export { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField }
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
}

View File

@@ -1,7 +1,7 @@
"use client" "use client"
import * as React from "react"
import * as PopoverPrimitive from "@radix-ui/react-popover" import * as PopoverPrimitive from "@radix-ui/react-popover"
import * as React from "react"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
@@ -45,4 +45,4 @@ function PopoverAnchor({
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} /> return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
} }
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger }

View File

@@ -1,7 +1,7 @@
"use client" "use client"
import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator" import * as SeparatorPrimitive from "@radix-ui/react-separator"
import * as React from "react"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"

View File

@@ -1,8 +1,8 @@
"use client" "use client"
import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog" import * as SheetPrimitive from "@radix-ui/react-dialog"
import { XIcon } from "lucide-react" import { XIcon } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
@@ -127,13 +127,4 @@ function SheetDescription({
) )
} }
export { export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger }
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}

View File

@@ -1,29 +1,18 @@
"use client" "use client"
import * as React from "react"
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot"
import { cva, VariantProps } from "class-variance-authority" import { cva, VariantProps } from "class-variance-authority"
import { PanelLeftIcon } from "lucide-react" import { PanelLeftIcon } from "lucide-react"
import * as React from "react"
import { useIsMobile } from "@/hooks/use-mobile"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet"
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
} from "@/components/ui/sheet"
import { Skeleton } from "@/components/ui/skeleton" import { Skeleton } from "@/components/ui/skeleton"
import { import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
Tooltip, import { useIsMobile } from "@/hooks/use-mobile"
TooltipContent, import { cn } from "@/lib/utils"
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
const SIDEBAR_COOKIE_NAME = "sidebar_state" const SIDEBAR_COOKIE_NAME = "sidebar_state"
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
@@ -121,7 +110,7 @@ function SidebarProvider({
isMobile, isMobile,
openMobile, openMobile,
setOpenMobile, setOpenMobile,
toggleSidebar, toggleSidebar
}), }),
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar] [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
) )
@@ -131,13 +120,11 @@ function SidebarProvider({
<TooltipProvider delayDuration={0}> <TooltipProvider delayDuration={0}>
<div <div
data-slot="sidebar-wrapper" data-slot="sidebar-wrapper"
style={ style={{
{
"--sidebar-width": SIDEBAR_WIDTH, "--sidebar-width": SIDEBAR_WIDTH,
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON, "--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
...style, ...style
} as React.CSSProperties } as React.CSSProperties}
}
className={cn( className={cn(
"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full", "group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full",
className className
@@ -188,11 +175,9 @@ function Sidebar({
data-slot="sidebar" data-slot="sidebar"
data-mobile="true" data-mobile="true"
className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden" className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
style={ style={{
{ "--sidebar-width": SIDEBAR_WIDTH_MOBILE
"--sidebar-width": SIDEBAR_WIDTH_MOBILE, } as React.CSSProperties}
} as React.CSSProperties
}
side={side} side={side}
> >
<SheetHeader className="sr-only"> <SheetHeader className="sr-only">
@@ -480,18 +465,18 @@ const sidebarMenuButtonVariants = cva(
variant: { variant: {
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
outline: outline:
"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]", "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]"
}, },
size: { size: {
default: "h-8 text-sm", default: "h-8 text-sm",
sm: "h-7 text-xs", sm: "h-7 text-xs",
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!", lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!"
}, }
}, },
defaultVariants: { defaultVariants: {
variant: "default", variant: "default",
size: "default", size: "default"
}, }
} }
) )
@@ -528,7 +513,7 @@ function SidebarMenuButton({
if (typeof tooltip === "string") { if (typeof tooltip === "string") {
tooltip = { tooltip = {
children: tooltip, children: tooltip
} }
} }
@@ -627,11 +612,9 @@ function SidebarMenuSkeleton({
<Skeleton <Skeleton
className="h-4 max-w-(--skeleton-width) flex-1" className="h-4 max-w-(--skeleton-width) flex-1"
data-sidebar="menu-skeleton-text" data-sidebar="menu-skeleton-text"
style={ style={{
{ "--skeleton-width": width
"--skeleton-width": width, } as React.CSSProperties}
} as React.CSSProperties
}
/> />
</div> </div>
) )
@@ -722,5 +705,5 @@ export {
SidebarRail, SidebarRail,
SidebarSeparator, SidebarSeparator,
SidebarTrigger, SidebarTrigger,
useSidebar, useSidebar
} }

View File

@@ -10,13 +10,11 @@ const Toaster = ({ ...props }: ToasterProps) => {
<Sonner <Sonner
theme={theme as ToasterProps["theme"]} theme={theme as ToasterProps["theme"]}
className="toaster group" className="toaster group"
style={ style={{
{
"--normal-bg": "var(--popover)", "--normal-bg": "var(--popover)",
"--normal-text": "var(--popover-foreground)", "--normal-text": "var(--popover-foreground)",
"--normal-border": "var(--border)", "--normal-border": "var(--border)"
} as React.CSSProperties } as React.CSSProperties}
}
{...props} {...props}
/> />
) )

View File

@@ -1,7 +1,7 @@
"use client" "use client"
import * as React from "react"
import * as SwitchPrimitive from "@radix-ui/react-switch" import * as SwitchPrimitive from "@radix-ui/react-switch"
import * as React from "react"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"

View File

@@ -104,13 +104,4 @@ function TableCaption({
) )
} }
export { export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow }
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
}

View File

@@ -1,7 +1,7 @@
"use client" "use client"
import * as React from "react"
import * as TooltipPrimitive from "@radix-ui/react-tooltip" import * as TooltipPrimitive from "@radix-ui/react-tooltip"
import * as React from "react"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
@@ -58,4 +58,4 @@ function TooltipContent({
) )
} }
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }

View File

@@ -1,10 +1,10 @@
"use server" "use server"
import { revalidatePath } from "next/cache"
import { getSession } from "../auth/session" import { getSession } from "../auth/session"
import { insertUrl } from "../db/urls" import { insertUrl } from "../db/urls"
import { advancedUrlSchema, editUrlSchema, urlFormSchema } from "../schema/url"
import { deleteUrl as deleteUrlDb, updateUrl as updateUrlDb } from "../db/urls" import { deleteUrl as deleteUrlDb, updateUrl as updateUrlDb } from "../db/urls"
import { revalidatePath } from "next/cache" import { advancedUrlSchema, editUrlSchema, urlFormSchema } from "../schema/url"
import { getWebsiteTitle } from "../websiteTitle" import { getWebsiteTitle } from "../websiteTitle"
type Response = { type Response = {
@@ -68,7 +68,7 @@ export async function createAdvanceUrl(unsafeData: unknown): Promise<Response> {
...data, ...data,
slug: data.slug?.length === 0 ? undefined : data.slug, slug: data.slug?.length === 0 ? undefined : data.slug,
title: data.title?.length === 0 ? await getWebsiteTitle(data.url) : data.title, title: data.title?.length === 0 ? await getWebsiteTitle(data.url) : data.title,
maxVisits: data.maxVisits > 0 ? data.maxVisits : undefined, maxVisits: data.maxVisits > 0 ? data.maxVisits : undefined
}) })
return { return {

View File

@@ -1,9 +1,9 @@
import { betterAuth } from "better-auth" import { betterAuth } from "better-auth"
import { drizzleAdapter } from "better-auth/adapters/drizzle" import { drizzleAdapter } from "better-auth/adapters/drizzle"
import { nextCookies } from "better-auth/next-js"
import { genericOAuth } from "better-auth/plugins" import { genericOAuth } from "better-auth/plugins"
import { db } from "../drizzle/db" import { db } from "../drizzle/db"
import { env } from "../env/server" import { env } from "../env/server"
import { nextCookies } from "better-auth/next-js"
export const auth = betterAuth({ export const auth = betterAuth({
database: drizzleAdapter(db, { database: drizzleAdapter(db, {
@@ -18,6 +18,6 @@ export const auth = betterAuth({
clientSecret: env.AUTHENTIK_CLIENT_SECRET, clientSecret: env.AUTHENTIK_CLIENT_SECRET,
discoveryUrl: env.AUTHENTIK_DISCOVERY_URL discoveryUrl: env.AUTHENTIK_DISCOVERY_URL
}] }]
}), })
] ]
}) })

View File

@@ -1,6 +1,6 @@
import { headers } from "next/headers" import { headers } from "next/headers"
import { auth } from "./auth"
import { redirect } from "next/navigation" import { redirect } from "next/navigation"
import { auth } from "./auth"
export async function getSession() { export async function getSession() {
const session = await auth.api.getSession({ const session = await auth.api.getSession({

View File

@@ -1,8 +1,8 @@
import { eq, desc, count } from "drizzle-orm"; import { count, desc, eq } from "drizzle-orm"
import { db } from "../drizzle/db"; import { revalidateTag } from "next/cache"
import { urls, visits } from "../drizzle/schema"; import { cacheTag } from "next/dist/server/use-cache/cache-tag"
import { cacheTag } from "next/dist/server/use-cache/cache-tag"; import { db } from "../drizzle/db"
import { revalidateTag } from "next/cache"; import { urls, visits } from "../drizzle/schema"
export async function getAllUrls() { export async function getAllUrls() {
"use cache" "use cache"

View File

@@ -1,10 +1,10 @@
export function generateRandomSlug(): string { export function generateRandomSlug(): string {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
let result = ''; let result = ""
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length)); result += characters.charAt(Math.floor(Math.random() * characters.length))
} }
return result; return result
} }

View File

@@ -1,4 +1,4 @@
import { z } from "zod"; import { z } from "zod"
export const urlFormSchema = z.object({ export const urlFormSchema = z.object({
url: z.string().url("Please enter a valid URL"), url: z.string().url("Please enter a valid URL"),
@@ -12,7 +12,7 @@ export const advancedUrlSchema = z.object({
maxVisits: z.number().int().positive().nullable(), maxVisits: z.number().int().positive().nullable(),
expDate: z.date().optional(), expDate: z.date().optional(),
forwardQueryParams: z.boolean(), forwardQueryParams: z.boolean(),
crawlable: z.boolean(), crawlable: z.boolean()
}) })
export const editUrlSchema = z.object({ export const editUrlSchema = z.object({
@@ -22,5 +22,5 @@ export const editUrlSchema = z.object({
maxVisits: z.number().int().positive().nullable(), maxVisits: z.number().int().positive().nullable(),
expDate: z.date().nullable(), expDate: z.date().nullable(),
forwardQueryParams: z.boolean(), forwardQueryParams: z.boolean(),
crawlable: z.boolean(), crawlable: z.boolean()
}) })

View File

@@ -1,12 +1,12 @@
export async function getWebsiteTitle(url: string): Promise<string | null> { export async function getWebsiteTitle(url: string): Promise<string | null> {
const res = await fetch(url, { redirect: 'follow' }) const res = await fetch(url, { redirect: "follow" })
if (!res.ok) { if (!res.ok) {
return null return null
} }
const contentType = res.headers.get('content-type') const contentType = res.headers.get("content-type")
if (!contentType || !contentType.includes('text/html')) { if (!contentType || !contentType.includes("text/html")) {
return null return null
} }
@@ -16,12 +16,12 @@ export async function getWebsiteTitle(url: string): Promise<string | null> {
if (titleMatch && titleMatch[1]) { if (titleMatch && titleMatch[1]) {
const title = titleMatch[1] const title = titleMatch[1]
.replace(/&lt;/g, '<') .replace(/&lt;/g, "<")
.replace(/&gt;/g, '>') .replace(/&gt;/g, ">")
.replace(/&amp;/g, '&') .replace(/&amp;/g, "&")
.replace(/&quot;/g, '"') .replace(/&quot;/g, "\"")
.replace(/&#39;/g, "'") .replace(/&#39;/g, "'")
.replace(/&nbsp;/g, ' ') .replace(/&nbsp;/g, " ")
.trim() .trim()
return title || null return title || null

View File

@@ -1,13 +1,13 @@
import { NextRequest, NextResponse } from "next/server"; import { getSessionCookie } from "better-auth/cookies"
import { getSessionCookie } from "better-auth/cookies"; import { NextRequest, NextResponse } from "next/server"
export async function middleware(request: NextRequest) { export async function middleware(request: NextRequest) {
const sessionCookie = getSessionCookie(request); const sessionCookie = getSessionCookie(request)
if (!sessionCookie) { if (!sessionCookie) {
return NextResponse.redirect(new URL("/", request.url)); return NextResponse.redirect(new URL("/", request.url))
} }
return NextResponse.next(); return NextResponse.next()
} }
export const config = { matcher: ["/dashboard"] }; export const config = { matcher: ["/dashboard"] }