Skip to content

Copilot Hub MVP #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
59 changes: 27 additions & 32 deletions components/home/card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ReactNode } from "react";
import ReactMarkdown from "react-markdown";
import Balancer from "react-wrap-balancer";
import Image from "next/image";

export default function Card({
title,
Expand All @@ -10,38 +11,32 @@ export default function Card({
description: string;
}) {
return (
<div className="relative col-span-1 h-96 overflow-hidden rounded-xl border border-gray-200 bg-white px-5 py-8 shadow-md">
<div className="mx-auto max-w-md text-center overflow-y-scroll h-full">
<h2 className="bg-gradient-to-br from-black to-stone-500 bg-clip-text font-display text-xl font-bold text-transparent md:text-3xl md:font-normal">
<Balancer>{title}</Balancer>
</h2>
<div className="prose-sm -mt-2 leading-normal text-gray-500 md:prose">
<Balancer>
<ReactMarkdown
components={{
a: ({ node, ...props }) => (
<a
target="_blank"
rel="noopener noreferrer"
{...props}
className="font-medium text-gray-800 underline transition-colors"
/>
),
code: ({ node, ...props }) => (
<code
{...props}
// @ts-ignore (to fix "Received `true` for a non-boolean attribute `inline`." warning)
inline="true"
className="rounded-sm bg-gray-100 px-1 py-0.5 font-mono font-medium text-gray-800"
/>
),
}}
>
{description}
</ReactMarkdown>
</Balancer>
</div>
</div>
<div className="relative col-span-1 max-w-sm rounded-lg border border-gray-200 bg-white p-6 shadow-md">
<a href="#">
<h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-700">
{title}
</h5>
</a>
<p className="mb-3 font-normal text-gray-700">{description}</p>
<a
href="#"
className="inline-flex items-center rounded-lg bg-gray-800 px-3 py-2 text-center text-sm font-medium text-white hover:bg-gray-700"
>
Try It
<svg
aria-hidden="true"
className="ml-2 -mr-1 h-4 w-4"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</a>
</div>
);
}
10 changes: 5 additions & 5 deletions components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function Layout({
return (
<>
<Meta {...meta} />
<div className="fixed h-screen w-full bg-gradient-to-br from-indigo-50 via-white to-cyan-100" />
<div className="fixed h-screen w-full bg-gradient-to-br from-indigo-100 via-white to-cyan-50" />
<div
className={`fixed top-0 w-full ${
scrolled
Expand All @@ -38,13 +38,13 @@ export default function Layout({
<div className="mx-5 flex h-16 max-w-screen-xl items-center justify-between xl:mx-auto">
<Link href="/" className="flex items-center font-display text-2xl">
<Image
src="/logo.png"
alt="Precedent logo"
src="/robot.png"
alt="Copilot Hub logo"
width="30"
height="30"
className="mr-2 rounded-sm"
></Image>
<p>Read Pilot</p>
<p>Copilot Hub</p>
</Link>
<div>
<AnimatePresence>
Expand All @@ -55,7 +55,7 @@ export default function Layout({
target="_blank"
{...FADE_IN_ANIMATION_SETTINGS}
>
Subscribe
Login
</motion.a>
) : (
<UserDropdown />
Expand Down
6 changes: 3 additions & 3 deletions components/layout/meta.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Head from "next/head";

// TODO(jiayuan): Change this
const DOMAIN = "https://readpilot.vercel.app";
const DOMAIN = "https://copilothub.co";

export default function Meta({
title = "Read Pilot - Unlock the power of your online reading",
description = "Read Pilot analyzes online articles and generate Q&A cards for you.",
title = "Copilot Hub - The AI assistant community building the future.",
description = "Copilot Hub helps you build your ChatGPT assistant with your own data in minutes",
image = `${DOMAIN}/api/og`,
}: {
title?: string;
Expand Down
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
domains: ["lh3.googleusercontent.com"],
domains: ["lh3.googleusercontent.com", "replit.com"],
},
async redirects() {
return [
Expand Down
165 changes: 54 additions & 111 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,40 @@ import Balancer from "react-wrap-balancer";
import { motion } from "framer-motion";
import { FADE_DOWN_ANIMATION_VARIANTS } from "@/lib/constants";
import { Github, LoadingDots, Twitter } from "@/components/shared/icons";
import { useState } from "react";
import LinkIcon from "@/components/shared/icons/link";
import CountingNumbers from "@/components/shared/counting-numbers";

export default function Home() {
const [url, setUrl] = useState("");
const [showGeneratedCards, setShowGeneratedCards] = useState(false);
const [loading, setLoading] = useState(false);
const [results, setResults] = useState([]);

const generateCards = async (e: any) => {
e.preventDefault();

// TODO(jiayuan): refactor this later
if (url === "") {
console.log("Please enter a valid URL");
return;
}

setLoading(true);
setResults([]);

const response = await fetch("/api/analyze", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ url }),
})
.then((res) => {
if (res.status === 200) {
return res.json();
}
throw new Error("Something went wrong");
})
.then((responseJson) => {
console.log(responseJson);
setResults(responseJson.data);
setShowGeneratedCards(true);
})
.catch((error) => {
console.error(error);
});

setLoading(false);
};
const results = [
{
title: "Ask Startup Class",
description:
"This AI trained by the startup class of Y Combinator: How to Start a Startup. You can ask any questions related to starting a startup.",
},
{
title: "Ask Read Pilot",
description:
"Input a link, and get a summary of the article. You can also ask questions about the article.",
},
{
title: "Ask The Great CEO Within",
description:
"This AI trained by the book: The Great CEO Within. You can ask any questions related to the book.",
},
{
title: "Ask Naval Ravikant",
description:
"This AI trained by all the tweets of Naval Ravikant. You can ask any questions related to life, business, and investing.",
},
{
title: "Ask Elon Musk",
description:
"This AI trained by all the tweets of Elon Musk. It's an AI version of Elon Musk.",
},
{
title: "Ask Tim Ferriss",
description:
"This AI trained by all the blogs, tweets, books of Tim Ferriss. You can ask any questions related to life, business, and investing.",
},
];

return (
<Layout>
Expand Down Expand Up @@ -81,7 +69,7 @@ export default function Home() {
>
<Twitter className="h-5 w-5 text-[#1d9bf0]" />
<p className="text-sm font-semibold text-[#1d9bf0]">
Introducing Read Pilot
Introducing Copilot Hub
</p>
</a>
<a
Expand All @@ -96,92 +84,47 @@ export default function Home() {
</motion.div>

<motion.h1
className="mt-6 w-[1024px] bg-gradient-to-br from-black to-stone-500 bg-clip-text text-center font-display text-4xl font-bold tracking-[-0.02em] text-transparent drop-shadow-sm md:text-7xl md:leading-[5rem]"
className="mt-6 w-[1024px] text-center font-display text-4xl font-bold tracking-[-0.02em] text-black drop-shadow-sm md:text-7xl md:leading-[5rem]"
variants={FADE_DOWN_ANIMATION_VARIANTS}
>
<Balancer>
Read Online Articles With
The AI Assistant Community
<br />
<span className="bg-co bg-gradient-to-r from-blue-500 via-green-600 to-indigo-500 bg-clip-text text-transparent">
Intelligence
<span className="bg-gradient-to-r from-pink-500 via-red-500 to-yellow-500 bg-clip-text text-transparent">
Building the Future
</span>
</Balancer>
</motion.h1>
<motion.p
className="mt-6 text-center text-gray-500 md:text-2xl"
className="mt-6 w-2/3 text-center text-gray-500 md:text-2xl"
variants={FADE_DOWN_ANIMATION_VARIANTS}
>
<Balancer>
Read Pilot analyzes online articles and generate Q&A cards for
you.
Copilot Hub is an AI-native platform where you can train and
fine-tune your LLMs. Create a chatbot with your own data in
minutes.
</Balancer>
</motion.p>

<motion.div className="mt-8" variants={FADE_DOWN_ANIMATION_VARIANTS}>
<button className="rounded-full border border-black bg-black p-1.5 px-4 text-lg text-white transition-all hover:bg-white hover:text-black sm:text-sm md:text-xl">
Start Building →
</button>
</motion.div>

<motion.p
className="mt-6 w-[1024px] text-center text-xl text-black"
className="mt-20 w-2/3 text-center text-3xl font-bold text-gray-700"
variants={FADE_DOWN_ANIMATION_VARIANTS}
>
<Balancer>
Trusted by{" "}
<CountingNumbers
value={10097}
duration={1000}
className="bg-gradient-to-r from-red-600 to-amber-600 bg-clip-text font-bold text-transparent"
/>{" "}
users,{" "}
<CountingNumbers
value={13951}
duration={1000}
className="bg-gradient-to-r from-red-600 to-amber-600 bg-clip-text font-bold text-transparent"
/>{" "}
links have been analyzed.
</Balancer>
<Balancer>Featured Copilots</Balancer>
</motion.p>

<motion.div className="mt-10" variants={FADE_DOWN_ANIMATION_VARIANTS}>
<div className="relative flex w-[35rem] items-center justify-center">
<LinkIcon className="insert-y-1 w absolute left-0 my-3 ml-3 w-7 text-gray-500" />
<input
type="url"
placeholder="Input your link"
value={url}
onChange={(e) => {
setUrl((e.target as HTMLInputElement).value);
}}
required
className="block w-full rounded-2xl border border-gray-200 bg-white p-2 pl-12 text-lg text-gray-600 shadow-md focus:border-black focus:outline-none focus:ring-0"
/>
</div>
</motion.div>

<motion.div className="mt-8" variants={FADE_DOWN_ANIMATION_VARIANTS}>
{!loading && (
<button
className="rounded-full border border-black bg-black p-1.5 px-4 text-lg text-white transition-all hover:bg-white hover:text-black sm:text-sm md:text-xl"
onClick={(e) => generateCards(e)}
>
Start Analyzing →
</button>
)}
{loading && (
<button
className="rounded-full border border-black bg-black p-1.5 px-4 text-lg text-white transition-all hover:bg-white hover:text-black sm:text-sm md:text-xl"
disabled
>
<span>Analyzing </span>
<LoadingDots color="grey" />
</button>
)}
</motion.div>
</motion.div>

{showGeneratedCards && (
<div className="my-10 grid w-full max-w-screen-xl animate-[slide-down-fade_0.5s_ease-in-out] grid-cols-1 gap-5 px-5 md:grid-cols-3 xl:px-0">
{results.map(({ q, a }) => (
<Card key={q} title={q} description={a} />
))}
</div>
)}
<div className="mt-10 grid max-h-screen w-full animate-[slide-down-fade_0.5s_ease-in-out] grid-cols-1 gap-5 px-5 md:grid-cols-3 xl:px-0">
{results.map(({ title, description }) => (
<Card key={title} title={title} description={description} />
))}
</div>
</div>
</Layout>
);
Expand Down
Binary file modified public/favicon.ico
Binary file not shown.
Binary file modified public/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/logo_bak.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.