Skip to content

Commit c366f7a

Browse files
authored
Upgrade to Next.js 15 and React 19. (#67)
1 parent 420f517 commit c366f7a

24 files changed

+5489
-2757
lines changed

.env.example

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@
33
# For detailed instructions on using these variables, visit:
44
# https://github.com/blrchen/chatgpt-lite#environment-variables
55

6+
# -----------------------------------------------------------------------------
67
# OpenAI API credentials (required for using the OpenAI API):
78
# Sign up at https://openai.com/api/ to get your API key.
9+
# -----------------------------------------------------------------------------
810
OPENAI_API_KEY= # <-- Insert your OpenAI API key here
911
OPENAI_API_BASE_URL="https://api.openai.com"
1012

13+
# -----------------------------------------------------------------------------
1114
# Azure OpenAI API credentials (required for using the Azure OpenAI API):
1215
# Sign up at https://azure.microsoft.com/en-us/services/cognitive-services/openai/ for Azure OpenAI credentials.
1316
# Uncomment the following lines and insert your credentials if you're using Azure OpenAI.
17+
# -----------------------------------------------------------------------------
1418
# AZURE_OPENAI_API_BASE_URL= # <-- Insert your Azure OpenAI API base URL here
1519
# AZURE_OPENAI_API_KEY= # <-- Insert your Azure OpenAI API key here
1620
# AZURE_OPENAI_DEPLOYMENT= # <-- Insert your Azure OpenAI deployment name here
17-

.eslintrc.json

Lines changed: 0 additions & 46 deletions
This file was deleted.

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
/node_modules
55
/.pnp
66
.pnp.js
7+
.yarn/install-state.gz
78

89
# testing
910
/coverage
@@ -33,6 +34,3 @@ yarn-error.log*
3334
# typescript
3435
*.tsbuildinfo
3536
next-env.d.ts
36-
37-
# JetBrains
38-
.idea/

.prettierignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
.next
2-
node_modules
2+
node_modules
3+
package.json
4+
package-lock.json

.vscode/launch.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
{
55
"type": "node",
66
"request": "launch",
7-
"name": "website",
8-
"cwd": "${workspaceFolder}",
7+
"name": "Launch Program",
8+
"skipFiles": ["<node_internals>/**"],
99
"runtimeExecutable": "npm",
1010
"runtimeArgs": ["run", "dev"],
11+
"cwd": "${workspaceFolder}",
1112
"autoAttachChildProcesses": true,
12-
"stopOnEntry": true,
13-
"skipFiles": ["<node_internals>/**"]
13+
"stopOnEntry": true
1414
}
1515
]
1616
}

.vscode/settings.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
{
2-
"editor.formatOnSave": true,
32
"editor.codeActionsOnSave": {
4-
"source.fixAll": "explicit"
3+
"source.fixAll.eslint": "explicit"
4+
},
5+
"editor.defaultFormatter": "esbenp.prettier-vscode",
6+
"editor.formatOnSave": true,
7+
"eslint.workingDirectories": [
8+
{
9+
"mode": "auto"
10+
}
11+
],
12+
"[css]": {
13+
"editor.defaultFormatter": "esbenp.prettier-vscode"
14+
},
15+
"[javascript]": {
16+
"editor.defaultFormatter": "esbenp.prettier-vscode"
517
}
618
}

Dockerfile

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,45 @@
1-
# This Dockerfile is generated based on sample in the following document
2-
# https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
3-
41
FROM node:20-alpine AS base
52

63
# Install dependencies only when needed
74
FROM base AS deps
8-
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
95
RUN apk add --no-cache libc6-compat
6+
107
WORKDIR /app
118

129
# Install dependencies based on the preferred package manager
1310
COPY package.json package-lock.json* ./
1411
RUN npm ci
1512

1613
# Rebuild the source code only when needed
17-
FROM base AS builder
14+
FROM deps AS builder
15+
1816
WORKDIR /app
19-
COPY --from=deps /app/node_modules ./node_modules
17+
18+
# Install dependencies based on the preferred package manager
2019
COPY . .
2120
RUN npm run build
2221

2322
# Production image, copy all the files and run next
2423
FROM base AS runner
2524
WORKDIR /app
2625

27-
ENV NODE_ENV production
28-
29-
RUN addgroup --system --gid 1001 nodejs
30-
RUN adduser --system --uid 1001 nextjs
26+
RUN addgroup --system --gid 1001 nodejs && \
27+
adduser --system --uid 1001 nextjs && \
28+
mkdir .next && \
29+
chown nextjs:nodejs .next
3130

3231
COPY --from=builder /app/public ./public
33-
34-
# Set the correct permission for prerender cache
35-
RUN mkdir .next
36-
RUN chown nextjs:nodejs .next
37-
38-
# Automatically leverage output traces to reduce image size
39-
# https://nextjs.org/docs/advanced-features/output-file-tracing
4032
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
4133
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
4234

4335
USER nextjs
4436

4537
EXPOSE 3000
4638

39+
ENV NODE_ENV production
40+
4741
ENV PORT 3000
42+
ENV HOSTNAME "0.0.0.0"
4843

4944
# server.js is created by next build from the standalone output
50-
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
51-
CMD HOSTNAME="0.0.0.0" node server.js
45+
CMD ["node", "server.js"]

app/chat/PersonaPanel.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ import { AiOutlineClose, AiOutlineDelete, AiOutlineEdit } from 'react-icons/ai'
1818
import { LuMessageSquarePlus } from 'react-icons/lu'
1919
import { ChatContext, Persona } from '@/components'
2020

21-
export interface PersonaPanelProps {}
22-
23-
const PersonaPanel = (_props: PersonaPanelProps) => {
21+
const PersonaPanel = () => {
2422
const {
2523
personaPanelType,
2624
DefaultPersonas,

app/layout.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { Analytics } from '@vercel/analytics/react'
2-
import { Toaster } from 'react-hot-toast'
2+
import { Metadata } from 'next'
3+
import { Toaster } from 'sonner'
34
import { Header } from '@/components/Header'
45
import ThemesProvider from '@/providers/ThemesProvider'
6+
57
import '@/styles/globals.scss'
68
import '@/styles/theme-config.css'
79

8-
export const metadata = {
10+
export const metadata: Metadata = {
911
title: {
1012
default: 'ChatGPT Lite',
1113
template: `%s - ChatGPT Lite`
@@ -20,12 +22,12 @@ export const metadata = {
2022

2123
export default function RootLayout({ children }: { children: React.ReactNode }) {
2224
return (
23-
<html lang="en">
25+
<html lang="en" className="light" style={{ colorScheme: 'light' }}>
2426
<body>
2527
<ThemesProvider>
2628
<Header />
2729
{children}
28-
<Toaster />
30+
<Toaster position="top-center" toastOptions={{ style: { color: 'red' } }} />
2931
</ThemesProvider>
3032
<Analytics />
3133
</body>

components/Chat/Chat.tsx

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,16 @@ import {
1111
} from 'react'
1212
import { Flex, Heading, IconButton, ScrollArea, Tooltip } from '@radix-ui/themes'
1313
import ContentEditable from 'react-contenteditable'
14-
import toast from 'react-hot-toast'
1514
import { AiOutlineClear, AiOutlineLoading3Quarters, AiOutlineUnorderedList } from 'react-icons/ai'
1615
import { FiSend } from 'react-icons/fi'
16+
import sanitizeHtml from 'sanitize-html'
17+
import { toast } from 'sonner'
1718
import ChatContext from './chatContext'
1819
import type { Chat, ChatMessage } from './interface'
1920
import Message from './Message'
2021

2122
import './index.scss'
2223

23-
const HTML_REGULAR =
24-
/<(?!img|table|\/table|thead|\/thead|tbody|\/tbody|tr|\/tr|td|\/td|th|\/th|br|\/br).*?>/gi
25-
2624
export interface ChatProps {}
2725

2826
export interface ChatGPInstance {
@@ -70,8 +68,7 @@ const Chat = (props: ChatProps, ref: any) => {
7068
async (e: any) => {
7169
if (!isLoading) {
7270
e.preventDefault()
73-
const input = textAreaRef.current?.innerHTML?.replace(HTML_REGULAR, '') || ''
74-
71+
const input = sanitizeHtml(textAreaRef.current?.innerHTML || '')
7572
if (input.length < 1) {
7673
toast.error('Please type a message to continue.')
7774
return
@@ -214,7 +211,33 @@ const Chat = (props: ChatProps, ref: any) => {
214211
px="4"
215212
style={{ backgroundColor: 'var(--gray-a2)' }}
216213
>
217-
<Heading size="4">{currentChatRef?.current?.persona?.name || 'None'}</Heading>
214+
<Heading size="4">{currentChatRef?.current?.persona?.name || 'No Persona'}</Heading>
215+
<Flex gap="2" align="center">
216+
<Tooltip content="Clear History">
217+
<IconButton
218+
variant="soft"
219+
color="gray"
220+
size="2"
221+
className="rounded-xl cursor-pointer"
222+
disabled={isLoading}
223+
onClick={clearMessages}
224+
>
225+
<AiOutlineClear className="size-5" />
226+
</IconButton>
227+
</Tooltip>
228+
<Tooltip content="Toggle Sidebar">
229+
<IconButton
230+
variant="soft"
231+
color="gray"
232+
size="2"
233+
className="rounded-lg md:hidden cursor-pointer"
234+
disabled={isLoading}
235+
onClick={onToggleSidebar}
236+
>
237+
<AiOutlineUnorderedList className="size-5" />
238+
</IconButton>
239+
</Tooltip>
240+
</Flex>
218241
</Flex>
219242
<ScrollArea
220243
className="flex-1 px-4"
@@ -242,7 +265,7 @@ const Chat = (props: ChatProps, ref: any) => {
242265
html={message}
243266
disabled={isLoading}
244267
onChange={(e) => {
245-
setMessage(e.target.value.replace(HTML_REGULAR, ''))
268+
setMessage(sanitizeHtml(e.target.value))
246269
}}
247270
onKeyDown={(e) => {
248271
handleKeypress(e)
@@ -259,12 +282,12 @@ const Chat = (props: ChatProps, ref: any) => {
259282
justify="center"
260283
style={{ color: 'var(--accent-11)' }}
261284
>
262-
<AiOutlineLoading3Quarters className="animate-spin size-4" />
285+
<AiOutlineLoading3Quarters className="animate-spin size-5" />
263286
</Flex>
264287
)}
265-
<Tooltip content={'Send Message'}>
288+
<Tooltip content="Send Message">
266289
<IconButton
267-
variant="soft"
290+
variant="surface"
268291
disabled={isLoading}
269292
color="gray"
270293
size="2"
@@ -274,30 +297,6 @@ const Chat = (props: ChatProps, ref: any) => {
274297
<FiSend className="size-4" />
275298
</IconButton>
276299
</Tooltip>
277-
<Tooltip content={'Clear History'}>
278-
<IconButton
279-
variant="soft"
280-
color="gray"
281-
size="2"
282-
className="rounded-xl cursor-pointer"
283-
disabled={isLoading}
284-
onClick={clearMessages}
285-
>
286-
<AiOutlineClear className="size-4" />
287-
</IconButton>
288-
</Tooltip>
289-
<Tooltip content={'Toggle Sidebar'}>
290-
<IconButton
291-
variant="soft"
292-
color="gray"
293-
size="2"
294-
className="rounded-xl md:hidden cursor-pointer"
295-
disabled={isLoading}
296-
onClick={onToggleSidebar}
297-
>
298-
<AiOutlineUnorderedList className="size-4" />
299-
</IconButton>
300-
</Tooltip>
301300
</Flex>
302301
</Flex>
303302
</div>

0 commit comments

Comments
 (0)