Skip to content

Commit

Permalink
Update to Next.js 14 and latest dependencies. (vercel#186)
Browse files Browse the repository at this point in the history
  • Loading branch information
leerob authored Nov 27, 2023
2 parents f9ce97f + 845a93a commit 35e83dc
Show file tree
Hide file tree
Showing 25 changed files with 1,954 additions and 1,997 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
],
"plugins": ["tailwindcss"],
"rules": {
"tailwindcss/no-custom-classname": "off"
"tailwindcss/no-custom-classname": "off",
"tailwindcss/classnames-order": "off"
},
"settings": {
"tailwindcss": {
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ yarn-error.log*
# turbo
.turbo

.contentlayer
.env
.vercel
.vscode
.vscode
.env*.local
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<a href="https://chat.vercel.ai/">
<img alt="Next.js 13 and app template Router-ready AI chatbot." src="https://chat.vercel.ai/opengraph-image.png">
<img alt="Next.js 14 and App Router-ready AI chatbot." src="https://chat.vercel.ai/opengraph-image.png">
<h1 align="center">Next.js AI Chatbot</h1>
</a>

Expand All @@ -22,7 +22,6 @@
- React Server Components (RSCs), Suspense, and Server Actions
- [Vercel AI SDK](https://sdk.vercel.ai/docs) for streaming chat UI
- Support for OpenAI (default), Anthropic, Cohere, Hugging Face, or custom AI chat models and/or LangChain
- Edge runtime-ready
- [shadcn/ui](https://ui.shadcn.com)
- Styling with [Tailwind CSS](https://tailwindcss.com)
- [Radix UI](https://radix-ui.com) for headless component primitives
Expand All @@ -46,7 +45,6 @@ Follow the steps outlined in the [quick start guide](https://vercel.com/docs/sto

Remember to update your environment variables (`KV_URL`, `KV_REST_API_URL`, `KV_REST_API_TOKEN`, `KV_REST_API_READ_ONLY_TOKEN`) in the `.env` file with the appropriate credentials provided during the KV database setup.


## Running locally

You will need to use the environment variables [defined in `.env.example`](.env.example) to run Next.js AI Chatbot. It's recommended you use [Vercel Environment Variables](https://vercel.com/docs/projects/environment-variables) for this, but a `.env` file is all that is necessary.
Expand Down
10 changes: 4 additions & 6 deletions app/api/chat/route.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { kv } from '@vercel/kv'
import { OpenAIStream, StreamingTextResponse } from 'ai'
import { Configuration, OpenAIApi } from 'openai-edge'
import OpenAI from 'openai'

import { auth } from '@/auth'
import { nanoid } from '@/lib/utils'

export const runtime = 'edge'

const configuration = new Configuration({
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
})

const openai = new OpenAIApi(configuration)

export async function POST(req: Request) {
const json = await req.json()
const { messages, previewToken } = json
Expand All @@ -25,10 +23,10 @@ export async function POST(req: Request) {
}

if (previewToken) {
configuration.apiKey = previewToken
openai.apiKey = previewToken
}

const res = await openai.createChatCompletion({
const res = await openai.chat.completions.create({
model: 'gpt-3.5-turbo',
messages,
temperature: 0.7,
Expand Down
3 changes: 0 additions & 3 deletions app/chat/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import { auth } from '@/auth'
import { getChat } from '@/app/actions'
import { Chat } from '@/components/chat'

export const runtime = 'edge'
export const preferredRegion = 'home'

export interface ChatPageProps {
params: {
id: string
Expand Down
25 changes: 13 additions & 12 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,51 @@
import { Metadata } from 'next'

import { Toaster } from 'react-hot-toast'
import { GeistSans } from 'geist/font/sans'
import { GeistMono } from 'geist/font/mono'

import '@/app/globals.css'
import { fontMono, fontSans } from '@/lib/fonts'
import { cn } from '@/lib/utils'
import { TailwindIndicator } from '@/components/tailwind-indicator'
import { Providers } from '@/components/providers'
import { Header } from '@/components/header'

export const metadata: Metadata = {
export const metadata = {
metadataBase: new URL(`https://${process.env.VERCEL_URL}`),
title: {
default: 'Next.js AI Chatbot',
template: `%s - Next.js AI Chatbot`
},
description: 'An AI-powered chatbot template built with Next.js and Vercel.',
themeColor: [
{ media: '(prefers-color-scheme: light)', color: 'white' },
{ media: '(prefers-color-scheme: dark)', color: 'black' }
],
icons: {
icon: '/favicon.ico',
shortcut: '/favicon-16x16.png',
apple: '/apple-touch-icon.png'
}
}

export const viewport = {
themeColor: [
{ media: '(prefers-color-scheme: light)', color: 'white' },
{ media: '(prefers-color-scheme: dark)', color: 'black' }
]
}

interface RootLayoutProps {
children: React.ReactNode
}

export default function RootLayout({ children }: RootLayoutProps) {
return (
<html lang="en" suppressHydrationWarning>
<head />
<body
className={cn(
'font-sans antialiased',
fontSans.variable,
fontMono.variable
GeistSans.variable,
GeistMono.variable
)}
>
<Toaster />
<Providers attribute="class" defaultTheme="system" enableSystem>
<div className="flex flex-col min-h-screen">
{/* @ts-ignore */}
<Header />
<main className="flex flex-col flex-1 bg-muted/50">{children}</main>
</div>
Expand Down
2 changes: 0 additions & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { nanoid } from '@/lib/utils'
import { Chat } from '@/components/chat'

export const runtime = 'edge'

export default function IndexPage() {
const id = nanoid()

Expand Down
118 changes: 0 additions & 118 deletions app/share/[id]/opengraph-image.tsx

This file was deleted.

3 changes: 0 additions & 3 deletions app/share/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ import { getSharedChat } from '@/app/actions'
import { ChatList } from '@/components/chat-list'
import { FooterText } from '@/components/footer'

export const runtime = 'edge'
export const preferredRegion = 'home'

interface SharePageProps {
params: {
id: string
Expand Down
Binary file removed assets/fonts/Inter-Bold.woff
Binary file not shown.
Binary file removed assets/fonts/Inter-Regular.woff
Binary file not shown.
9 changes: 7 additions & 2 deletions auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ declare module 'next-auth' {

export const {
handlers: { GET, POST },
auth,
CSRF_experimental // will be removed in future
auth
} = NextAuth({
providers: [GitHub],
callbacks: {
Expand All @@ -24,6 +23,12 @@ export const {
}
return token
},
session: ({ session, token }) => {
if (session?.user && token?.id) {
session.user.id = String(token.id)
}
return session
},
authorized({ auth }) {
return !!auth?.user // this ensures there is a logged in user for -every- request
}
Expand Down
62 changes: 35 additions & 27 deletions components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,48 @@ import { SidebarFooter } from '@/components/sidebar-footer'
import { ThemeToggle } from '@/components/theme-toggle'
import { ClearHistory } from '@/components/clear-history'
import { UserMenu } from '@/components/user-menu'
import { LoginButton } from '@/components/login-button'

export async function Header() {
async function UserOrLogin() {
const session = await auth()
return (
<header className="sticky top-0 z-50 flex items-center justify-between w-full h-16 px-4 border-b shrink-0 bg-gradient-to-b from-background/10 via-background/50 to-background/80 backdrop-blur-xl">
<>
{session?.user ? (
<Sidebar>
<React.Suspense fallback={<div className="flex-1 overflow-auto" />}>
<SidebarList userId={session?.user?.id} />
</React.Suspense>
<SidebarFooter>
<ThemeToggle />
<ClearHistory clearChats={clearChats} />
</SidebarFooter>
</Sidebar>
) : (
<Link href="/" target="_blank" rel="nofollow">
<IconNextChat className="w-6 h-6 mr-2 dark:hidden" inverted />
<IconNextChat className="hidden w-6 h-6 mr-2 dark:block" />
</Link>
)}
<div className="flex items-center">
<IconSeparator className="w-6 h-6 text-muted-foreground/50" />
{session?.user ? (
<Sidebar>
<React.Suspense fallback={<div className="flex-1 overflow-auto" />}>
{/* @ts-ignore */}
<SidebarList userId={session?.user?.id} />
</React.Suspense>
<SidebarFooter>
<ThemeToggle />
<ClearHistory clearChats={clearChats} />
</SidebarFooter>
</Sidebar>
<UserMenu user={session.user} />
) : (
<Link href="/" target="_blank" rel="nofollow">
<IconNextChat className="w-6 h-6 mr-2 dark:hidden" inverted />
<IconNextChat className="hidden w-6 h-6 mr-2 dark:block" />
</Link>
<Button variant="link" asChild className="-ml-2">
<Link href="/sign-in?callbackUrl=/">Login</Link>
</Button>
)}
<div className="flex items-center">
<IconSeparator className="w-6 h-6 text-muted-foreground/50" />
{session?.user ? (
<UserMenu user={session.user} />
) : (
<Button variant="link" asChild className="-ml-2">
<Link href="/sign-in?callbackUrl=/">Login</Link>
</Button>
)}
</div>
</div>
</>
)
}

export function Header() {
return (
<header className="sticky top-0 z-50 flex items-center justify-between w-full h-16 px-4 border-b shrink-0 bg-gradient-to-b from-background/10 via-background/50 to-background/80 backdrop-blur-xl">
<div className="flex items-center">
<React.Suspense fallback={<div className="flex-1 overflow-auto" />}>
<UserOrLogin />
</React.Suspense>
</div>
<div className="flex items-center justify-end space-x-2">
<a
Expand Down
3 changes: 2 additions & 1 deletion components/sidebar-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ export function SidebarActions({
<div className="space-y-1 rounded-md border p-4 text-sm">
<div className="font-medium">{chat.title}</div>
<div className="text-muted-foreground">
{formatDate(chat.createdAt)} · {chat.messages.length} messages
{formatDate(Number(chat.createdAt))} · {chat.messages.length}{' '}
messages
</div>
</div>
<DialogFooter className="items-center">
Expand Down
Loading

0 comments on commit 35e83dc

Please sign in to comment.