diff --git a/package.json b/package.json
index 59b8e18f..a4223e49 100644
--- a/package.json
+++ b/package.json
@@ -70,6 +70,7 @@
"@uidotdev/usehooks": "^2.4.1",
"@uploadthing/react": "5.2.0",
"@upstash/redis": "^1.24.3",
+ "@vercel/og": "^0.6.2",
"ably": "^1.2.48",
"ai": "2.2.20",
"algoliasearch": "^4.20.0",
diff --git a/src/app/api/og/route.tsx b/src/app/api/og/route.tsx
new file mode 100644
index 00000000..6357fb57
--- /dev/null
+++ b/src/app/api/og/route.tsx
@@ -0,0 +1,103 @@
+import { ImageResponse } from "next/og";
+import logo from "@/assets/logo.png";
+// App router includes @vercel/og.
+// No need to install it.
+
+export const runtime = "edge";
+
+// Gradient Square Component
+function GradientSquare() {
+ return (
+
+ );
+}
+
+function Circle() {
+ return (
+
+ IK
+
+ );
+}
+
+export async function GET(request: Request) {
+ try {
+ let title: string | null = "";
+ try {
+ const urlParams = new URLSearchParams(request.url.split("?")[1]);
+ title = urlParams.get("title");
+ console.log("title", title);
+ } catch (error) {
+ console.error("Error parsing URL:", error);
+ }
+ // const urlParams = new URLSearchParams(request.url.split("?")[1]); // Splitting URL to get query params
+ // const title = urlParams.get("title");
+ // console.log("title", title);
+
+ // const { searchParams } = new URL(request.url);
+ // console.log("searchParams", searchParams);
+ // const hasTitle = searchParams.has("title");
+ // const title01 = hasTitle
+ // ? searchParams.get("title")?.slice(0, 100)
+ // : "My default title";
+
+ return new ImageResponse(
+ (
+
+
+
+ {title
+ ? title
+ : " The Dual Role of Tween 80 in Biofilm Formation"}
+
+
+ Inhibition and Enhancement
+
+
+
+
+
+
+
+
+ {/* */}
+
+
+
+ ),
+ {
+ width: 1200,
+ height: 630,
+ },
+ );
+ } catch (e: any) {
+ console.log(`${e.message}`);
+ return new Response(`Failed to generate the image`, {
+ status: 500,
+ });
+ }
+}
diff --git a/src/app/dashboard/[slug]/chat/[chatid]/page.tsx b/src/app/dashboard/[slug]/chat/[chatid]/page.tsx
index dd9b2309..0377dffc 100644
--- a/src/app/dashboard/[slug]/chat/[chatid]/page.tsx
+++ b/src/app/dashboard/[slug]/chat/[chatid]/page.tsx
@@ -6,14 +6,61 @@ import { eq, and } from "drizzle-orm";
import { auth, currentUser } from "@clerk/nextjs";
import RoomWrapper from "@/components/room";
import { AblyChannelProvider } from "@/components/ablyprovider";
+import { ResolvingMetadata, Metadata } from "next";
+
export const dynamic = "force-dynamic",
revalidate = 0;
-export default async function Page({
- params,
-}: {
- params: { uid: string; chatid: string };
-}) {
+type Props = {
+ params: { id: string; uid: string; chatid: string; chattitle: string };
+ searchParams: { [key: string]: string | string[] | undefined };
+};
+
+export async function generateMetadata(
+ { params, searchParams }: Props,
+ parent: ResolvingMetadata,
+): Promise {
+ const { sessionClaims } = auth();
+ let fetchedChat: ChatSchema[] = [];
+ // console.log("parent",parent)
+ const previousImages = (await parent).openGraph?.images || [];
+
+ // console.log("params", params);
+ // console.log("searchParams", searchParams)
+ if (sessionClaims?.org_id) {
+ fetchedChat = await db
+ .select()
+ .from(chats)
+ .where(and(eq(chats.id, Number(params.chatid))))
+ .limit(1)
+ .all();
+ }
+ console.log("chattitle in chat id page", fetchedChat[0]?.title as string);
+
+ return {
+ title: "Echoes chat",
+ description: "echoes Chat",
+ alternates: {
+ canonical: `https://www.echoes.team/dashboard/${sessionClaims?.org_slug}/chat/${params.chatid}`,
+ },
+ openGraph: {
+ title: fetchedChat[0]?.title as string,
+ description: "Echoes",
+ type: "website",
+
+ images: [
+ {
+ url: `api/og?title=${fetchedChat[0]?.title as string}`,
+ width: 1200,
+ height: 680,
+ },
+ ...previousImages,
+ ],
+ },
+ };
+}
+
+export default async function Page({ params }: Props) {
const { userId, sessionClaims } = auth();
const user = await currentUser();
@@ -27,7 +74,6 @@ export default async function Page({
}
let chatlog: ChatLog = { log: [], tldraw_snapshot: [] };
- // let tldrawSnapshot: SnapShot = { tldraw_snapshot: [] }
let fetchedChat: ChatSchema[] = [];
if (sessionClaims.org_id) {
@@ -44,12 +90,10 @@ export default async function Page({
.all();
}
const msg = fetchedChat[0]?.messages;
- console.log("msg", msg);
if (fetchedChat.length === 1 && msg) {
chatlog = JSON.parse(msg as string) as ChatLog;
- console.log("chatlog", chatlog);
- console.log("chatlogData", chatlog.log);
- // console.log("chatlogSnapshot", chatlog.tldraw_snapshot);
+ // console.log("chatlog", chatlog);
+ // console.log("chatlogData", chatlog.log);
}
return (
diff --git a/src/app/dashboard/[slug]/page.tsx b/src/app/dashboard/[slug]/page.tsx
index 12a30ab4..714b3be9 100644
--- a/src/app/dashboard/[slug]/page.tsx
+++ b/src/app/dashboard/[slug]/page.tsx
@@ -5,11 +5,40 @@ import { chats, Chat as ChatSchema } from "@/lib/db/schema";
import { eq, desc, ne, and } from "drizzle-orm";
import { auth } from "@clerk/nextjs";
import ChatCardWrapper from "@/components/chatcardwrapper";
+// import { Metadata } from "next";
+
// import Uploadzone from "@/components/uploadzone";
export const dynamic = "force-dynamic",
revalidate = 0;
+// type Props = {
+// params: { id: string };
+// searchParams: { [key: string]: string | string[] | undefined };
+// };
+
+// export async function generateMetadata({
+// params,
+// searchParams,
+// }: Props): Promise {
+
+// return {
+// title: "Echoes slug",
+// description: "echoes",
+// openGraph: {
+// title: "Echoes",
+// description: "Echoes",
+// type: "website",
+// images: [
+// {
+// url: "api/og",
+// width: 1200,
+// height: 680,
+// },
+// ],
+// },
+// };
+// }
export default async function Page({
params,
searchParams,
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 093a56a9..e7c711fb 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -7,6 +7,7 @@ import { Inter } from "next/font/google";
import QueryProviders from "@/app/queryProvider";
import { Toaster } from "@/components/ui/toaster";
import { Providers } from "@/app/providers";
+
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
@@ -15,6 +16,23 @@ export const metadata = {
manifest: "/manifest.json",
viewport:
"minimum-scale=1.0, initial-scale=1.0, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover",
+ openGraph: {
+ title: "Echoes",
+ description:
+ "Collaborative Platform for Researchers. Designed for Humans and AIs.",
+ url: "https://echoes.team",
+ siteName: "Echoes",
+ images: [
+ {
+ url: `/api/og?title=Collaborative Platform for Researchers. Designed for Humans and AIs.`,
+ width: 1800,
+ height: 1600,
+ alt: "Echoes",
+ },
+ ],
+ locale: "en_US",
+ type: "website",
+ },
};
export default function RootLayout({
@@ -236,20 +254,17 @@ export default function RootLayout({
content="https://echoes.team/android-chrome-192x192.png"
/>
-
+ {/*
-
-
+
+ */}
- Echoes
+ {/* Echoes */}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 7842b9a6..e70b6b7f 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,5 +1,4 @@
"use client";
-
import { useEffect } from "react";
import { Header } from "@/components/header";
import { Button, buttonVariants } from "@/components/button";
@@ -10,6 +9,7 @@ import { motion, AnimatePresence, useAnimation } from "framer-motion";
import { useInView } from "react-intersection-observer";
import { Key, LayoutDashboard } from "lucide-react";
import { useAuth } from "@clerk/nextjs";
+
const handleSmoothScroll = (): void => {
if (typeof window !== "undefined") {
const hashId = window.location.hash;
diff --git a/src/app/robots.ts b/src/app/robots.ts
new file mode 100644
index 00000000..aa7afb89
--- /dev/null
+++ b/src/app/robots.ts
@@ -0,0 +1,12 @@
+import { MetadataRoute } from "next";
+
+export default function robots(): MetadataRoute.Robots {
+ return {
+ rules: {
+ userAgent: "*",
+ allow: "/",
+ disallow: "", // No path is disallowed
+ },
+ sitemap: "https://acme.com/sitemap.xml",
+ };
+}
diff --git a/src/components/chatcard.tsx b/src/components/chatcard.tsx
index 3448c3c9..bf4b577f 100644
--- a/src/components/chatcard.tsx
+++ b/src/components/chatcard.tsx
@@ -101,6 +101,7 @@ const Chatcard = ({ chat, uid, org_id, org_slug, priority, type }: Props) => {
const firstMessage = chatlog.log[0].content;
const chatTitle = chat.title || firstMessage;
+ console.log("chatCard chat", chatlog);
// extracts chatentry from chatlog
const chats = JSON.parse(chat.messages as string) as ChatLog;
const userIds = getUserIdList(chats.log);
diff --git a/src/components/search.tsx b/src/components/search.tsx
index fc628106..c3c8d9d5 100644
--- a/src/components/search.tsx
+++ b/src/components/search.tsx
@@ -56,13 +56,14 @@ const Search = (props: Props) => {
}, []); // open command bar with / key
useEffect(() => {
+ // console.log("throttledValue", throttledValue);
index
.search(throttledValue, {
hitsPerPage: 8,
filters: `orgSlug: "${props.orgSlug}"`,
})
.then((response) => {
- console.log(response);
+ console.log(" search responce", response);
return setResults(response.hits);
});
}, [throttledValue]);
@@ -71,7 +72,7 @@ const Search = (props: Props) => {
{
- console.log("got the input value");
+ console.log("got the input value", val);
setValue(val);
}}
value={value}
diff --git a/src/middleware.ts b/src/middleware.ts
index 5cddfb3e..5df36615 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -6,7 +6,7 @@ import { env } from "@/app/env.mjs";
// This is your original middleware
const clerkMiddleware = authMiddleware({
// "/" will be accessible to all users
- publicRoutes: ["/"],
+ publicRoutes: ["/api/og", "/"],
});
export async function middleware(req: NextRequest, event: NextFetchEvent) {
diff --git a/src/utils/apiHelper.ts b/src/utils/apiHelper.ts
index 4ea4d238..8410e9f8 100644
--- a/src/utils/apiHelper.ts
+++ b/src/utils/apiHelper.ts
@@ -685,75 +685,3 @@ export const saveToDB = async ({
console.log("error in saving to db", error);
}
};
-
-// export const saveToDBForImage = async ({
-// _chat,
-// chatId,
-// orgSlug,
-// latestResponse,
-// userId,
-// urlArray,
-// orgId,
-// }: {
-// latestResponse: ChatEntry;
-// _chat: ChatEntry[];
-// chatId: number;
-// orgSlug: string;
-// orgId: string;
-// userId: string;
-// urlArray: string[];
-// }) => {
-// try {
-// if (_chat.length === 1) {
-// console.log("got in 1 length case");
-// _chat.push(latestResponse);
-// // step for generating title and adding to search index
-// axios.post(`https://zeplo.to/step?_token=${env.ZEPLO_TOKEN}`, [
-// {
-// url: `https://${urlArray[2]}/api/generateTitle/${chatId}/${orgId}?_step=A`,
-// body: JSON.stringify({ chat: _chat }),
-// headers: {
-// "x-zeplo-secret": env.ZEPLO_SECRET,
-// },
-// },
-// {
-// url: `https://${urlArray[2]}/api/addToSearch?_step=B&_requires=A`,
-// body: JSON.stringify({
-// chats: _chat,
-// chatId: chatId,
-// orgSlug: orgSlug as string,
-// }),
-// headers: {
-// "x-zeplo-secret": env.ZEPLO_SECRET,
-// },
-// },
-// ]);
-// await db
-// .update(chats)
-// .set({
-// messages: JSON.stringify({ log: _chat } as ChatLog),
-// creator: userId,
-// })
-// .where(eq(chats.id, chatId))
-// .run();
-// } else {
-// _chat.push(latestResponse);
-// postToAlgolia({
-// chats: [_chat[_chat.length - 2], latestResponse],
-// chatId: chatId,
-// orgSlug: orgSlug as string,
-// urlArray: urlArray,
-// }); // add to search index
-// await db
-// .update(chats)
-// .set({
-// messages: JSON.stringify({ log: _chat }),
-// updatedAt: new Date(),
-// })
-// .where(eq(chats.id, chatId))
-// .run();
-// }
-// } catch (error) {
-// console.log("error in saving to db", error);
-// }
-// };