Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9a11551
Add files via upload
l3en00725 Sep 9, 2025
ce8474f
Add files via upload
l3en00725 Sep 9, 2025
d0d8f34
Rename profileimg (1).jpg to profileimg.jpg
l3en00725 Sep 9, 2025
1a99969
Update chat-header.tsx
l3en00725 Sep 9, 2025
61d382d
Update chat.tsx
l3en00725 Sep 9, 2025
256c58e
Update chat-header.tsx
l3en00725 Sep 9, 2025
becbc0c
Update chat.tsx
l3en00725 Sep 9, 2025
de3af81
Update chat-header.tsx
l3en00725 Sep 9, 2025
f8c506a
Update signed-out-header.tsx
l3en00725 Sep 9, 2025
81f19c2
Update signed-out-header.tsx
l3en00725 Sep 9, 2025
7ce48eb
Update signed-out-header.tsx
l3en00725 Sep 9, 2025
33106c7
Update info-banner.tsx
l3en00725 Sep 9, 2025
6a55c8e
Update overview.tsx
l3en00725 Sep 9, 2025
4cee376
Update overview.tsx
l3en00725 Sep 9, 2025
74ac7a1
Update layout.tsx
l3en00725 Sep 9, 2025
bf53a38
Update pd-backend-client.ts
l3en00725 Sep 9, 2025
b916c55
Update mcp-client.ts
l3en00725 Sep 9, 2025
dd1dc5c
Create index.ts
l3en00725 Sep 9, 2025
8091877
Update drizzle.config.ts
l3en00725 Sep 9, 2025
a5d0d0f
Update package.json
l3en00725 Sep 9, 2025
fbe086e
Update package.json
l3en00725 Sep 9, 2025
a9d5bb3
Update package.json
l3en00725 Sep 9, 2025
9e9d498
Add files via upload
l3en00725 Sep 9, 2025
a07d3a2
Delete app/favicon.ico
l3en00725 Sep 9, 2025
98a906e
Add files via upload
l3en00725 Sep 9, 2025
a36985d
Rename profileimg (1).jpg to favicon.ico
l3en00725 Sep 9, 2025
e149d59
Update schema.ts
l3en00725 Sep 9, 2025
49ba64f
Update layout.tsx
l3en00725 Sep 9, 2025
c21e025
Update schema.ts
l3en00725 Sep 9, 2025
c9b1343
Update auth.ts
l3en00725 Sep 9, 2025
7376854
Create authbutton.tsx
l3en00725 Sep 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 11 additions & 16 deletions app/(auth)/auth.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { compare } from 'bcrypt-ts';
import NextAuth, { type User, type Session } from 'next-auth';
import Credentials from 'next-auth/providers/credentials';
import { compare } from "bcrypt-ts";
import NextAuth, { type User, type Session } from "next-auth";
import Credentials from "next-auth/providers/credentials";
import GoogleProvider from "next-auth/providers/google";
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { DrizzleAdapter } from "@auth/drizzle-adapter";

import { db, getUser } from '@/lib/db/queries';

import { authConfig } from './auth.config';
import { accounts, user } from '@/lib/db/schema';
import { db, getUser } from "@/lib/db/queries";
import { authConfig } from "./auth.config";
import { accounts, user } from "@/lib/db/schema";

interface ExtendedSession extends Session {
user: User;
Expand All @@ -26,29 +25,26 @@ export const {
accountsTable: accounts,
}),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
// Credentials({
// credentials: {},
// async authorize({ email, password }: any) {
// const users = await getUser(email);
// if (users.length === 0) return null;
// // biome-ignore lint: Forbidden non-null assertion.
// const passwordsMatch = await compare(password, users[0].password!);
// if (!passwordsMatch) return null;
// return users[0] as any;
// },
// }),
GoogleProvider({
allowDangerousEmailAccountLinking: true,
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
})
],
callbacks: {
async jwt({ token, user }) {
if (user) {
token.id = user.id;
}

return token;
},
async session({
Expand All @@ -61,7 +57,6 @@ export const {
if (session.user) {
session.user.id = token.id as string;
}

return session;
},
},
Expand Down
36 changes: 36 additions & 0 deletions app/(auth)/authbutton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use client"

import { signIn, signOut, useSession } from "next-auth/react"

export default function AuthButton() {
const { data: session, status } = useSession()

if (status === "loading") {
return <div className="text-sm text-gray-500">Loading...</div>
}

if (session?.user) {
return (
<div className="flex items-center gap-3">
<span className="text-sm text-gray-700 dark:text-gray-200">
{session.user.email}
</span>
<button
onClick={() => signOut()}
className="px-3 py-1 rounded-md bg-gray-800 text-white text-sm hover:bg-gray-700"
>
Sign out
</button>
</div>
)
}

return (
<button
onClick={() => signIn("google")}
className="px-3 py-1 rounded-md bg-blue-600 text-white text-sm hover:bg-blue-500"
>
Sign in with Google
</button>
)
}
Binary file modified app/favicon.ico
Binary file not shown.
35 changes: 34 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,40 @@ import DatadogInit from '@/components/datadog-init';

import './globals.css';

export const metadata: Metadata = BASE_METADATA;
export const metadata: Metadata = {
...BASE_METADATA,
title: "Virgo Chat",
description: "Chat directly with 2,800+ APIs in one place, powered by Virgo.",
icons: {
icon: "/images/profileimg.jpg",
shortcut: "/images/profileimg.jpg",
apple: "/images/profileimg.jpg",
},
openGraph: {
title: "Virgo Chat",
description: "Chat directly with 2,800+ APIs in one place, powered by Virgo.",
url: "https://virgo-mcp-chat.vercel.app",
siteName: "Virgo MCP",
images: [
{
url: "/images/og-image.png", // <-- place a 1200x630 image in /public/images
width: 1200,
height: 630,
alt: "Virgo MCP Chat Preview",
},
],
locale: "en_US",
type: "website",
},
twitter: {
card: "summary_large_image",
title: "Virgo Chat",
description: "Chat directly with 2,800+ APIs in one place, powered by Virgo.",
images: ["/images/og-image.png"],
},
};



export const viewport = {
maximumScale: 1, // Disable auto-zoom on mobile Safari
Expand Down
139 changes: 36 additions & 103 deletions components/chat-header.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
"use client"

import { useRouter } from "next/navigation"
import { useEffectiveSession } from '@/hooks/use-effective-session'

import { ModelSelector } from "@/components/model-selector"
import { SidebarToggle } from "@/components/sidebar-toggle"
import { Button } from "@/components/ui/button"
import { GitHubButton } from "@/components/github-button"
import { DocsButton } from "@/components/docs-button"
import { memo } from "react"
import { PlusIcon } from "./icons"
import { useSidebar } from "./ui/sidebar"
Expand All @@ -27,117 +23,54 @@ function PureChatHeader({
}) {
const router = useRouter()
const { open } = useSidebar()
const { data: session } = useEffectiveSession()
const isSignedIn = !!session?.user

// Don't render the header for signed-out users
if (!isSignedIn) {
return null
}

return (
<header className="flex sticky top-0 bg-background py-1.5 items-start px-2 md:px-2 gap-2">
{/* Always show sidebar toggle */}
<div className="mt-1">
<SidebarToggle />
</div>

{/* Mobile layout: Show controls in left-to-right order with new chat button on the right */}
{!isReadonly && (
<div className="mt-1 md:hidden">
<ModelSelector
selectedModelId={selectedModelId}
className=""
/>
</div>
)}

{!isReadonly && (
<div className="mt-1 md:hidden">
<VisibilitySelector
chatId={chatId}
selectedVisibilityType={selectedVisibilityType}
className=""
/>
</div>
)}

{/* Spacer to push new chat button to the right on mobile */}
<div className="flex-1 md:hidden"></div>

{/* Mobile new chat button - positioned on the right with full text */}
<div className="mt-1 md:hidden ml-auto">
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
className="px-2"
onClick={() => {
router.push("/")
router.refresh()
}}
>
<PlusIcon size={16} />
<span>New Chat</span>
</Button>
</TooltipTrigger>
<TooltipContent>New Chat</TooltipContent>
</Tooltip>
<header className="flex sticky top-0 bg-background py-1.5 items-center px-2 md:px-4 gap-4">
{/* Virgo Logo in top-left */}
<div className="flex items-center gap-2">
<img src="/images/Logo-01.png" alt="Virgo Logo" className="h-8 w-auto" />
</div>

{/* Desktop new chat button - hidden when sidebar is open to avoid overlap */}
<div className="mt-1 hidden md:block">
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
className={`md:px-2 md:h-fit ${
open ? 'md:hidden' : 'md:flex'
}`}
onClick={() => {
router.push("/")
router.refresh()
}}
>
<PlusIcon size={16} />
<span className="sr-only">New Chat</span>
</Button>
</TooltipTrigger>
<TooltipContent>New Chat</TooltipContent>
</Tooltip>
{/* Sidebar toggle */}
<div className="mt-1">
<SidebarToggle />
</div>

{/* Desktop layout: Show controls after new chat button */}
{/* Model + Visibility selectors */}
{!isReadonly && (
<div className="mt-1 hidden md:block">
<ModelSelector
selectedModelId={selectedModelId}
className=""
/>
<div className="hidden md:flex items-center gap-2">
<ModelSelector selectedModelId={selectedModelId} />
<VisibilitySelector chatId={chatId} selectedVisibilityType={selectedVisibilityType} />
</div>
)}

{!isReadonly && (
<div className="mt-1 hidden md:block">
<VisibilitySelector
chatId={chatId}
selectedVisibilityType={selectedVisibilityType}
className=""
/>
</div>
)}
{/* Spacer pushes new chat button to the right */}
<div className="flex-1"></div>

{/* Spacer to push buttons to the right on desktop */}
<div className="flex-1 hidden md:block"></div>

<div className="mt-1 hidden md:flex gap-2 ml-auto">
<GitHubButton style="secondary" />
<DocsButton style="main" />
</div>
{/* New chat button */}
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
className={`md:px-2 md:h-fit ${open ? "md:hidden" : "md:flex"}`}
onClick={() => {
router.push("/")
router.refresh()
}}
>
<PlusIcon size={16} />
<span className="sr-only">New Chat</span>
</Button>
</TooltipTrigger>
<TooltipContent>New Chat</TooltipContent>
</Tooltip>
</header>
)
}

export const ChatHeader = memo(PureChatHeader, (prevProps, nextProps) => {
return prevProps.selectedModelId === nextProps.selectedModelId
})
export const ChatHeader = memo(
PureChatHeader,
(prevProps, nextProps) => {
return prevProps.selectedModelId === nextProps.selectedModelId
}
)
36 changes: 18 additions & 18 deletions components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,24 +117,24 @@ export function Chat({
{messages.length === 0 ? (
<div className="flex-1 flex flex-col justify-center items-center px-4">
<div className="text-center mb-8 max-w-3xl">
<div className="flex flex-col sm:flex-row items-center justify-center gap-1 sm:gap-2 mb-2">
<h1 className="text-3xl font-bold max-w-[280px] sm:max-w-none leading-tight">Welcome to MCP Chat by Pipedream</h1>
<span className="bg-blue-100 text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300 mt-1 sm:mt-0">
Alpha
</span>
</div>
<p
className="text-muted-foreground max-w-sm mx-auto"
>
Chat directly with 2,800+ APIs powered by {" "}
<Link
className="font-medium underline underline-offset-4"
href="https://pipedream.com/docs/connect/mcp/developers"
target="_blank"
>
Pipedream Connect
</Link>
</p>
<div className="flex flex-col sm:flex-row items-center justify-center gap-3 sm:gap-4 mb-2">
<h1 className="text-3xl font-bold max-w-[280px] sm:max-w-none leading-tight">
Welcome to Virgo Chat
</h1>
<img
src="/images/profileimg.jpg"
alt="Profile"
className="h-12 w-12 rounded-full border border-gray-300"
/>
<span className="bg-blue-100 text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300 mt-1 sm:mt-0">
Alpha
</span>
</div>

<p className="text-muted-foreground max-w-sm mx-auto">
Chat directly with 2,800+ APIs
</p>

</div>

{/* Centered input form for home page */}
Expand Down
Loading