diff --git a/README.md b/README.md index 6ff33ea5b..ec7e0322f 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,7 @@ PUBLIC_POSTHOG_API_KEY="phc_SdvLWEagL7nAauyEBun0ZF6v59DxMIk8ofzI91gpIUw" PUBLIC_OPEN_API_ENDPOINT="https://api.fleek.xyz/api/openapi.json" PUBLIC_FLEEK_WEBSITE_URL="https://fleek.xyz" PUBLIC_PERSONA_GENERATOR_API_URL="https://persona-generator.flkservices.io" +PUBLIC_CUSTOM_AGENTS_URL="https://social-agent.platform.fleek.xyz" ``` 💡 The SUPPORT_ALLOW_ORIGIN_ADDR and SUPPORT_RATE_LIMIT_PATHS are comma separated values (csv). the MEILISEARCH_DOCUMENTS_CLIENT_API_KEY is required when querying staging, production environments which should be provided in the headers. @@ -668,7 +669,7 @@ Open the [settings.json](./src/settings.json) and locate the property `agentsAdm "agentsAdminNotification": { "authenticatedUsers": { "message": "When we have capacity to deploy new AI agents you will be first in line. Please try again later!", - "enable": false + "enable": false }, "default": { "message": "We're currently over capacity and unable to deploy new AI agents. Sign in now to save time and try again later!", diff --git a/dump.json b/dump.json deleted file mode 100644 index e69de29bb..000000000 diff --git a/package-lock.json b/package-lock.json index bab219ab9..e7fc6fb55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,9 +14,9 @@ "@astrojs/react": "^3.3.2", "@astrojs/sitemap": "^3.1.4", "@astrojs/tailwind": "^5.1.0", - "@fleek-platform/agents-ui": "8.28.0", + "@fleek-platform/agents-ui": "8.30.0", "@fleek-platform/dashboard": "0.20.4", - "@fleek-platform/login-button": "2.15.1", + "@fleek-platform/login-button": "2.16.0", "@fleek-platform/sdk": "^3.6.2", "@fleek-platform/utils-token": "^0.2.2", "@hookform/resolvers": "^3.9.1", @@ -33,6 +33,7 @@ "class-variance-authority": "^0.7.0", "framer-motion": "^12.6.3", "hono": "^4.4.11", + "jwt-decode": "^4.0.0", "keen-slider": "^6.8.6", "lite-youtube-embed": "^0.3.3", "lodash-es": "^4.17.21", @@ -4492,13 +4493,13 @@ } }, "node_modules/@fleek-platform/agents-ui": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@fleek-platform/agents-ui/-/agents-ui-8.28.0.tgz", - "integrity": "sha512-7gbSHL0CZT0zBHvawV23M0n0yDUYsDo5q43rTZCP8ekUm8SgdJy5hDyo1PEVSi8No+KrIPzov1NR2pspcSaNsQ==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@fleek-platform/agents-ui/-/agents-ui-8.30.0.tgz", + "integrity": "sha512-7eUEkhRAg7NPXrguMOSIMWXZZEa7uJzRhlUOTJd+03CjvmYRp8ZP/QWRitsUfURqBrY8lDC+HgUd8JEwBLm1zA==", "license": "MIT", "dependencies": { "@fleek-platform/agents-chatbox-widget": "^0.9.0", - "@fleek-platform/login-button": "^2.12.1", + "@fleek-platform/login-button": "2.16.0", "@hookform/resolvers": "^3.9.1", "@langchain/core": "^0.3.46", "@langchain/langgraph-sdk": "^0.0.70", @@ -6824,9 +6825,9 @@ } }, "node_modules/@fleek-platform/login-button": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/@fleek-platform/login-button/-/login-button-2.15.1.tgz", - "integrity": "sha512-E+1fY92c+jY58yrnJQ/UxhNTvmhz1tME+Z6szd4GmW9imo3uGmcOPJasu4lERggFaAbo4sGrWfKqijFOb9JCSQ==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@fleek-platform/login-button/-/login-button-2.16.0.tgz", + "integrity": "sha512-wNms1m7EWfUJvkC+4ZrnyzAH6SSX/O12Jj4XMgd/bw8+GV9gzHrdYnfcRwMpFJs2ViW44Ur8JjlzNYVrzv4kRw==", "license": "MIT", "dependencies": { "@dynamic-labs/ethereum": "4.14.0", diff --git a/package.json b/package.json index 3c00e560c..432cf2927 100644 --- a/package.json +++ b/package.json @@ -54,9 +54,9 @@ "@astrojs/react": "^3.3.2", "@astrojs/sitemap": "^3.1.4", "@astrojs/tailwind": "^5.1.0", - "@fleek-platform/agents-ui": "8.28.0", + "@fleek-platform/agents-ui": "8.30.0", "@fleek-platform/dashboard": "0.20.4", - "@fleek-platform/login-button": "2.15.1", + "@fleek-platform/login-button": "2.16.0", "@fleek-platform/sdk": "^3.6.2", "@fleek-platform/utils-token": "^0.2.2", "@hookform/resolvers": "^3.9.1", @@ -73,6 +73,7 @@ "class-variance-authority": "^0.7.0", "framer-motion": "^12.6.3", "hono": "^4.4.11", + "jwt-decode": "^4.0.0", "keen-slider": "^6.8.6", "lite-youtube-embed": "^0.3.3", "lodash-es": "^4.17.21", diff --git a/public/images/landing-page/templates/socials/instagram.svg b/public/images/landing-page/templates/socials/instagram.svg index 9223dd7a9..66b18ac8d 100644 --- a/public/images/landing-page/templates/socials/instagram.svg +++ b/public/images/landing-page/templates/socials/instagram.svg @@ -1,32 +1,14 @@ - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - + + diff --git a/public/images/landing-page/templates/socials/snapchat.svg b/public/images/landing-page/templates/socials/snapchat.svg new file mode 100644 index 000000000..cd0dac755 --- /dev/null +++ b/public/images/landing-page/templates/socials/snapchat.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/images/landing-page/templates/socials/tiktok.svg b/public/images/landing-page/templates/socials/tiktok.svg index e075f749b..aa86c05fa 100644 --- a/public/images/landing-page/templates/socials/tiktok.svg +++ b/public/images/landing-page/templates/socials/tiktok.svg @@ -1,20 +1,10 @@ - - - - - - - - - - - - - + + + - - + + diff --git a/src/components/LandingPage/Templates.tsx b/src/components/LandingPage/Templates.tsx index 81d020d3d..326580372 100644 --- a/src/components/LandingPage/Templates.tsx +++ b/src/components/LandingPage/Templates.tsx @@ -1,222 +1,31 @@ -import 'keen-slider/keen-slider.min.css'; -import { useKeenSlider, type KeenSliderPlugin } from 'keen-slider/react'; +import { PiChatCircleDotsBold } from 'react-icons/pi'; import { Badge } from './Badge'; import { Text } from './Text'; -import { IoChatbubbleEllipsesOutline } from 'react-icons/io5'; -import { useState } from 'react'; -import { cn } from '@utils/cn'; +import { + publicAgents, + type PublicAgent, +} from '@components/PublicAgents/config'; -type Template = { - name: string; - category: string; - image: string; - author: string; - socials: { - name: string; - logo: string; - followers: number; - }[]; -}; - -const templates: Template[] = [ - { - name: 'Stephanie', - category: 'Sports', - image: '/images/landing-page/templates/stephanie.png', - author: 'Fleek', - socials: [ - { - name: 'twitter', - logo: '/images/landing-page/templates/socials/x.svg', - followers: 16200, - }, - { - name: 'instagram', - logo: '/images/landing-page/templates/socials/instagram.svg', - followers: 32700, - }, - { - name: 'tiktok', - logo: '/images/landing-page/templates/socials/tiktok.svg', - followers: 112200, - }, - ], - }, +const SOCIALS_MAP = [ { - name: 'Olivia', - category: 'Companion', - image: '/images/landing-page/templates/olivia.png', - author: 'Fleek', - socials: [ - { - name: 'twitter', - logo: '/images/landing-page/templates/socials/x.svg', - followers: 56600, - }, - { - name: 'instagram', - logo: '/images/landing-page/templates/socials/instagram.svg', - followers: 98200, - }, - { - name: 'tiktok', - logo: '/images/landing-page/templates/socials/tiktok.svg', - followers: 85300, - }, - ], + name: 'twitter', + logo: '/images/landing-page/templates/socials/x.svg', }, { - name: 'Crypto Chris', - category: 'Crypto', - image: '/images/landing-page/templates/chris.png', - author: 'Fleek', - socials: [ - { - name: 'twitter', - logo: '/images/landing-page/templates/socials/x.svg', - followers: 112400, - }, - { - name: 'instagram', - logo: '/images/landing-page/templates/socials/instagram.svg', - followers: 2400, - }, - { - name: 'tiktok', - logo: '/images/landing-page/templates/socials/tiktok.svg', - followers: 1100, - }, - ], + name: 'instagram', + logo: '/images/landing-page/templates/socials/instagram.svg', }, { - name: 'Kanye East', - category: 'Culture', - image: '/images/landing-page/templates/kanye.png', - author: 'Fleek', - socials: [ - { - name: 'twitter', - logo: '/images/landing-page/templates/socials/x.svg', - followers: 1500, - }, - { - name: 'instagram', - logo: '/images/landing-page/templates/socials/instagram.svg', - followers: 1100, - }, - { - name: 'tiktok', - logo: '/images/landing-page/templates/socials/tiktok.svg', - followers: 659, - }, - ], + name: 'tiktok', + logo: '/images/landing-page/templates/socials/tiktok.svg', }, { - name: 'Kiki', - category: 'NSFW', - image: '/images/landing-page/templates/kiki.png', - author: 'Fleek', - socials: [ - { - name: 'twitter', - logo: '/images/landing-page/templates/socials/x.svg', - followers: 9240, - }, - { - name: 'instagram', - logo: '/images/landing-page/templates/socials/instagram.svg', - followers: 56700, - }, - { - name: 'tiktok', - logo: '/images/landing-page/templates/socials/tiktok.svg', - followers: 32000, - }, - ], + name: 'snapchat', + logo: '/images/landing-page/templates/socials/snapchat.svg', }, ]; -const ContinuousAutoscroll: KeenSliderPlugin = (slider) => { - let raf: number; - let last: number; - let paused = false; - - const speed = 0.000025; - - const animate = (time: number) => { - if (!last) { - last = time; - raf = requestAnimationFrame(animate); - return; - } - - const dt = time - last; - last = time; - - if (!paused) { - slider.track.to((slider.track.details?.position ?? 0) - speed * dt); - } - - raf = requestAnimationFrame(animate); - }; - - slider.on('created', () => { - slider.container.addEventListener('mouseenter', () => { - paused = true; - }); - slider.container.addEventListener('mouseleave', () => { - paused = false; - }); - - raf = requestAnimationFrame(animate); - }); - - slider.on('destroyed', () => { - cancelAnimationFrame(raf); - }); -}; - export const Templates = () => { - const [loaded, setLoaded] = useState(false); - const [sliderRef] = useKeenSlider( - { - loop: true, - mode: 'free-snap', - slides: { - spacing: 24, - perView: 1.1, - }, - breakpoints: { - '(min-width: 640px)': { - slides: { - perView: 1.2, - spacing: 24, - }, - }, - '(min-width: 768px)': { - slides: { - perView: 1.5, - spacing: 24, - }, - }, - '(min-width: 1024px)': { - slides: { - perView: 2.2, - spacing: 24, - }, - }, - '(min-width: 1280px)': { - slides: { - perView: 2.95, - spacing: 24, - }, - }, - }, - created: () => setLoaded(true), - }, - [ContinuousAutoscroll], - ); - return (
@@ -232,81 +41,58 @@ export const Templates = () => { Explore social agents and start chatting.

-
- {/* Left Fade */} -
- - {/* Right Fade */} -
- -
- {templates.map((template) => ( -
- -
- ))} -
+
+ {publicAgents.map((template) => ( +
+ +
+ ))}
); }; -export const TemplateCard = ({ template }: { template: Template }) => { - function formatCompactNumber(value: number): string { - return new Intl.NumberFormat('en', { - notation: 'compact', - maximumFractionDigits: 1, - }).format(value); - } - - return ( -
- Agent avatar -
-
-
- {template.name} -
-
- {template.category} -
+export const TemplateCard = ({ template }: { template: PublicAgent }) => ( + + {template.name} +
+
+
+ {template.category}
-
- {template.socials.map((social) => ( -
- Social media logo -
- ))} -
- +
+
+ {SOCIALS_MAP.map((social) => ( +
+ {social.name} +
+ ))}
- ); -}; +
+
+

+ {template.name} +

+

{template.about}

+
+ +
+
+); diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx index 3ba48a110..3993792d9 100644 --- a/src/components/Modal/Modal.tsx +++ b/src/components/Modal/Modal.tsx @@ -36,14 +36,14 @@ export const Modal: React.FC = ({ <> diff --git a/src/components/PublicAgents/AsideProfile.tsx b/src/components/PublicAgents/AsideProfile.tsx new file mode 100644 index 000000000..3329c1056 --- /dev/null +++ b/src/components/PublicAgents/AsideProfile.tsx @@ -0,0 +1,62 @@ +import { + PiChatCircleDotsBold, + PiPhoneBold, + PiStarFourBold, + PiVideoCameraBold, +} from 'react-icons/pi'; +import type { PublicAgent } from './config'; +import { Button } from './Button'; + +type AsideProfileProps = { + agent: PublicAgent; +}; + +export const AsideProfile: React.FC = ({ agent }) => { + const { name, about, image, category } = agent; + + return ( + + ); +}; diff --git a/src/components/PublicAgents/Button.tsx b/src/components/PublicAgents/Button.tsx new file mode 100644 index 000000000..3fc1f2079 --- /dev/null +++ b/src/components/PublicAgents/Button.tsx @@ -0,0 +1,33 @@ +import { cn } from '@utils/cn'; + +export const Button: React.FC< + React.PropsWithChildren & React.ButtonHTMLAttributes +> = ({ children, ...props }) => { + return ( + + ); +}; + +export const IconButton: React.FC< + React.PropsWithChildren & React.ButtonHTMLAttributes +> = ({ children, ...props }) => { + return ( + + ); +}; diff --git a/src/components/PublicAgents/Content/ChatBox.tsx b/src/components/PublicAgents/Content/ChatBox.tsx new file mode 100644 index 000000000..5b2605b9a --- /dev/null +++ b/src/components/PublicAgents/Content/ChatBox.tsx @@ -0,0 +1,119 @@ +import type React from 'react'; +import { Button, IconButton } from '../Button'; +import { + PiArrowUpBold, + PiCircleNotchBold, + PiImageBold, + PiMagicWandBold, + PiPlusBold, + PiSlidersHorizontalBold, + PiVideoBold, +} from 'react-icons/pi'; +import { useState } from 'react'; +import { PreviewModeTooltip } from '../Tooltip'; + +type ChatBoxProps = { + isLoading: boolean; + hasClosed: boolean; + onMsgSubmit: (msg: string) => void; + openModal: () => void; +}; + +export const ChatBox: React.FC = ({ + isLoading, + hasClosed, + onMsgSubmit, + openModal, +}) => { + const [msg, setMsg] = useState(''); + + const handleChange = (e: React.ChangeEvent) => + setMsg(e.target.value); + + const handleSubmit = () => { + onMsgSubmit(msg); + setMsg(''); + }; + + return ( +
+ {hasClosed && ( +
+ Kick off your 7-day free trial on the Fan Plan and keep the convo + going!{' '} + +
+ )} +
+ {hasClosed && ( +
+ )} +