Skip to content

Commit c49d2da

Browse files
committed
SEO
1 parent 9605bb4 commit c49d2da

5 files changed

Lines changed: 101 additions & 43 deletions

File tree

app/chat/[id]/client-chat-page.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use client'
2+
import React, { useEffect, useState } from 'react';
3+
import Sidebar from '@/components/chat/sidebar'
4+
import ChatArea from '@/components/chat/chat-area'
5+
import Header from '@/components/layout/header'
6+
import Footer from '@/components/layout/footer'
7+
import { useActiveConversation } from '@/hooks/use-active-conversation'
8+
9+
export default function ClientChatPage({ id }: { id: string }) {
10+
const [sidebarOpen, setSidebarOpen] = useState(true)
11+
const setActiveConversationId = useActiveConversation(s => s.setActiveConversationId)
12+
useEffect(() => {
13+
if (id) setActiveConversationId(id)
14+
}, [id, setActiveConversationId])
15+
if (!id) return <div className="flex items-center justify-center h-screen text-lg">Invalid conversation</div>
16+
return (
17+
<div className="flex h-screen w-full bg-gradient-to-b from-[#23272f] via-[#202123] to-[#131313] relative">
18+
{/* Sidebar as flex child, always rendered, mini when closed */}
19+
<div className={`transition-all duration-200 h-full ${sidebarOpen ? 'w-[260px]' : 'w-[72px]'} flex-shrink-0 overflow-hidden`}>
20+
<Sidebar open={sidebarOpen} setOpen={setSidebarOpen} />
21+
</div>
22+
<main className="flex-1 min-w-0 flex flex-col h-screen">
23+
<Header />
24+
<div className="flex-1 min-h-0 flex flex-col">
25+
<ChatArea />
26+
</div>
27+
<Footer />
28+
</main>
29+
{/* Overlay for mobile sidebar */}
30+
{sidebarOpen && (
31+
<div
32+
className="fixed inset-0 z-40 bg-black/60 md:hidden"
33+
onClick={() => setSidebarOpen(false)}
34+
>
35+
<aside className="absolute left-0 top-0 w-[260px] h-full bg-[#202123] shadow-lg">
36+
<Sidebar open={sidebarOpen} setOpen={setSidebarOpen} />
37+
</aside>
38+
</div>
39+
)}
40+
</div>
41+
)
42+
}

app/chat/[id]/page.tsx

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,11 @@
1-
"use client";
2-
import React, { useEffect } from 'react';
3-
import Sidebar from '@/components/chat/sidebar'
4-
import ChatArea from '@/components/chat/chat-area'
5-
import Header from '@/components/layout/header'
6-
import Footer from '@/components/layout/footer'
7-
import { useState } from 'react'
8-
import { useActiveConversation } from '@/hooks/use-active-conversation'
1+
import ClientChatPage from './client-chat-page'
2+
import type { Metadata } from 'next'
3+
4+
export const metadata: Metadata = {
5+
title: 'ChatGPT Clone – Conversation',
6+
description: 'Continue your conversation with AI in a modern, professional chat UI.'
7+
}
98

109
export default function ChatPage({ params }: { params: { id: string } }) {
11-
// Unwrap params if it's a promise (future-proof)
12-
const { id } = (typeof (params as any).then === 'function') ? React.use(params) : params;
13-
const [sidebarOpen, setSidebarOpen] = useState(true)
14-
const setActiveConversationId = useActiveConversation(s => s.setActiveConversationId)
15-
useEffect(() => {
16-
if (id) setActiveConversationId(id)
17-
}, [id, setActiveConversationId])
18-
if (!id) return <div className="flex items-center justify-center h-screen text-lg">Invalid conversation</div>
19-
return (
20-
<div className="flex h-screen w-full bg-gradient-to-b from-[#23272f] via-[#202123] to-[#131313] relative">
21-
{/* Sidebar as flex child, always rendered, mini when closed */}
22-
<div className={`transition-all duration-200 h-full ${sidebarOpen ? 'w-[260px]' : 'w-[72px]'} flex-shrink-0 overflow-hidden`}>
23-
<Sidebar open={sidebarOpen} setOpen={setSidebarOpen} />
24-
</div>
25-
<main className="flex-1 min-w-0 flex flex-col h-screen">
26-
<Header />
27-
<div className="flex-1 min-h-0 flex flex-col">
28-
<ChatArea />
29-
</div>
30-
<Footer />
31-
</main>
32-
{/* Overlay for mobile sidebar */}
33-
{sidebarOpen && (
34-
<div
35-
className="fixed inset-0 z-40 bg-black/60 md:hidden"
36-
onClick={() => setSidebarOpen(false)}
37-
>
38-
<aside className="absolute left-0 top-0 w-[260px] h-full bg-[#202123] shadow-lg">
39-
<Sidebar open={sidebarOpen} setOpen={setSidebarOpen} />
40-
</aside>
41-
</div>
42-
)}
43-
</div>
44-
)
10+
return <ClientChatPage id={params.id} />
4511
}

app/layout.tsx

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,45 @@ const inter = Inter({ subsets: ['latin'] })
1010

1111
export const metadata: Metadata = {
1212
title: 'ChatGPT Clone',
13-
description: 'A ChatGPT clone built with Next.js and Supabase',
13+
description: 'A professional ChatGPT clone with a modern dark UI, built with Next.js and Supabase.',
14+
metadataBase: new URL('https://yourdomain.com'),
15+
alternates: { canonical: '/' },
16+
openGraph: {
17+
title: 'ChatGPT Clone',
18+
description: 'A professional ChatGPT clone with a modern dark UI, built with Next.js and Supabase.',
19+
url: 'https://yourdomain.com',
20+
siteName: 'ChatGPT Clone',
21+
images: [
22+
{
23+
url: '/og-image.png',
24+
width: 1200,
25+
height: 630,
26+
alt: 'ChatGPT Clone',
27+
type: 'image/png',
28+
},
29+
],
30+
locale: 'en_US',
31+
type: 'website',
32+
},
33+
twitter: {
34+
card: 'summary_large_image',
35+
title: 'ChatGPT Clone',
36+
description: 'A professional ChatGPT clone with a modern dark UI, built with Next.js and Supabase.',
37+
site: '@yourtwitter',
38+
creator: '@yourtwitter',
39+
images: ['/og-image.png'],
40+
},
41+
themeColor: '#181a20',
42+
robots: {
43+
index: true,
44+
follow: true,
45+
nocache: false,
46+
},
47+
icons: {
48+
icon: '/favicon.ico',
49+
shortcut: '/favicon.ico',
50+
apple: '/apple-touch-icon.png',
51+
},
1452
}
1553

1654
// PHASE 5: Together.AI model selection and chat integration in progress

app/page.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@ import ChatArea from '@/components/chat/chat-area'
44
import Header from '@/components/layout/header'
55
import Footer from '@/components/layout/footer'
66
import { useState } from 'react'
7+
import type { Metadata } from 'next'
78

89
// PHASE 5: Together.AI model selection and chat integration in progress
910

1011
// This file will now redirect to the latest or default conversation, or show a landing page.
1112
// The main chat UI will be moved to app/chat/[id]/page.tsx
1213

14+
export const metadata: Metadata = {
15+
title: 'ChatGPT Clone – Chat',
16+
description: 'Chat with AI in a beautiful, modern dark UI. Powered by Next.js and Supabase.'
17+
}
18+
1319
export default function ChatPage() {
1420
const [sidebarOpen, setSidebarOpen] = useState(true)
1521

app/profile/page.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
import { useEffect, useState } from 'react'
44
import { supabase } from '@/lib/supabase/client'
55
import { useRouter } from 'next/navigation'
6+
import type { Metadata } from 'next'
7+
8+
export const metadata: Metadata = {
9+
title: 'Profile – ChatGPT Clone',
10+
description: 'Manage your profile, update your name, or delete your account.'
11+
}
612

713
export default function ProfilePage() {
814
const [profile, setProfile] = useState<{ email: string; full_name: string } | null>(null)

0 commit comments

Comments
 (0)