diff --git a/apps/web/app/(landing)/CardPatterns/Glare.tsx b/apps/web/app/(landing)/CardPatterns/Glare.tsx new file mode 100644 index 00000000..8fefb309 --- /dev/null +++ b/apps/web/app/(landing)/CardPatterns/Glare.tsx @@ -0,0 +1,139 @@ +"use client"; + +import { cn } from "@repo/ui/lib/utils"; +import { useRef } from "react"; + +export const GlareCard = ({ + children, + className, +}: { + children: React.ReactNode; + className?: string; +}) => { + const isPointerInside = useRef(false); + const refElement = useRef(null); + const state = useRef({ + glare: { + x: 50, + y: 50, + }, + background: { + x: 50, + y: 50, + }, + rotate: { + x: 0, + y: 0, + }, + }); + const containerStyle = { + "--m-x": "50%", + "--m-y": "50%", + "--r-x": "0deg", + "--r-y": "0deg", + "--bg-x": "50%", + "--bg-y": "50%", + "--duration": "300ms", + "--foil-size": "100%", + "--opacity": "0", + "--radius": "23px", + "--easing": "ease", + "--transition": "var(--duration) var(--easing)", + } as any; + + const backgroundStyle = { + "--step": "5%", + "--foil-svg": `url("data:image/svg+xml,%3Csvg width='26' height='26' viewBox='0 0 26 26' fill='currentColor' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.99994 3.419C2.99994 3.419 21.6142 7.43646 22.7921 12.153C23.97 16.8695 3.41838 23.0306 3.41838 23.0306' stroke='white' stroke-width='5' stroke-miterlimit='3.86874' stroke-linecap='round' style='mix-blend-mode:darken'/%3E%3C/svg%3E")`, + "--pattern": "var(--foil-svg) center/100% no-repeat", + "--rainbow": + "repeating-linear-gradient( 0deg,rgb(255,119,115) calc(var(--step) * 1),rgba(255,237,95,1) calc(var(--step) * 2),rgba(168,255,95,1) calc(var(--step) * 3),rgba(131,255,247,1) calc(var(--step) * 4),rgba(120,148,255,1) calc(var(--step) * 5),rgb(216,117,255) calc(var(--step) * 6),rgb(255,119,115) calc(var(--step) * 7) ) 0% var(--bg-y)/200% 700% no-repeat", + "--diagonal": + "repeating-linear-gradient( 128deg,#0e152e 0%,hsl(180,10%,60%) 3.8%,hsl(180,10%,60%) 4.5%,hsl(180,10%,60%) 5.2%,#0e152e 10%,#0e152e 12% ) var(--bg-x) var(--bg-y)/300% no-repeat", + "--shade": + "radial-gradient( farthest-corner circle at var(--m-x) var(--m-y),rgba(255,255,255,0.1) 12%,rgba(255,255,255,0.15) 20%,rgba(255,255,255,0.25) 120% ) var(--bg-x) var(--bg-y)/300% no-repeat", + "--hero-gradient": + 'radial-gradient(ellipse 50% 80% at 20% 40%, rgba(93, 52, 221, 0.1), transparent), radial-gradient(ellipse 50% 80% at 80% 50%, rgba(120, 119, 198, 0.15),transparent)', + + backgroundBlendMode: "hue, hue, hue, overlay", + }; + + const updateStyles = () => { + if (refElement.current) { + console.log(state.current); + const { background, rotate, glare } = state.current; + refElement.current?.style.setProperty("--m-x", `${glare.x}%`); + refElement.current?.style.setProperty("--m-y", `${glare.y}%`); + refElement.current?.style.setProperty("--r-x", `${rotate.x}deg`); + refElement.current?.style.setProperty("--r-y", `${rotate.y}deg`); + refElement.current?.style.setProperty("--bg-x", `${background.x}%`); + refElement.current?.style.setProperty("--bg-y", `${background.y}%`); + } + }; + return ( +
{ + const rotateFactor = 0.4; + const rect = event.currentTarget.getBoundingClientRect(); + const position = { + x: event.clientX - rect.left, + y: event.clientY - rect.top, + }; + const percentage = { + x: (100 / rect.width) * position.x, + y: (100 / rect.height) * position.y, + }; + const delta = { + x: percentage.x - 50, + y: percentage.y - 50, + }; + + const { background, rotate, glare } = state.current; + background.x = 50 + percentage.x / 4 - 12.5; + background.y = 50 + percentage.y / 3 - 16.67; + rotate.x = -(delta.x / 3.5); + rotate.y = delta.y / 2; + rotate.x *= rotateFactor; + rotate.y *= rotateFactor; + glare.x = percentage.x; + glare.y = percentage.y; + + updateStyles(); + }} + onPointerEnter={() => { + isPointerInside.current = true; + if (refElement.current) { + setTimeout(() => { + if (isPointerInside.current) { + refElement.current?.style.setProperty("--duration", "0s"); + } + }, 300); + } + }} + onPointerLeave={() => { + isPointerInside.current = false; + if (refElement.current) { + refElement.current.style.removeProperty("--duration"); + refElement.current?.style.setProperty("--r-x", `0deg`); + refElement.current?.style.setProperty("--r-y", `0deg`); + } + }} + > +
+
+
+ {children} +
+
+
+
+ +
+
+ ); +}; \ No newline at end of file diff --git a/apps/web/app/(landing)/EmailInput.tsx b/apps/web/app/(landing)/EmailInput.tsx index ac1f7fca..c0514a46 100644 --- a/apps/web/app/(landing)/EmailInput.tsx +++ b/apps/web/app/(landing)/EmailInput.tsx @@ -39,7 +39,7 @@ function EmailInput() { + + + ), + title: "Fast Refresh", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec congue, nisl eget molestie varius.", + }, + { + icon: ( + + + + ), + title: "Analytics", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec congue, nisl eget molestie varius.", + }, + { + icon: ( + + + + ), + title: "Datacenter security", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec congue, nisl eget molestie varius.", + }, + { + icon: ( + + + + ), + title: "Build on your terms", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec congue, nisl eget molestie varius.", + }, + { + icon: ( + + + + ), + title: "Safe to use", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec congue, nisl eget molestie varius.", + }, + { + icon: ( + + + + ), + title: "Flexible", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec congue, nisl eget molestie varius.", + }, + ]; + + return ( +
+
+
+
+

+ {/* Let’s help power your SaaS */} +

+ {/*

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec + congue, nisl eget molestie varius, enim ex faucibus purus. +

*/} +
+
+
+ {/*
*/} +
+
    + {features.map((item, idx) => ( + +
  • +
    + {item.icon} +
    +

    + {item.title} +

    +

    {item.desc}

    +
  • +
    + ))} +
+
+
+
+ ); +} diff --git a/apps/web/app/(landing)/Features.tsx b/apps/web/app/(landing)/Features.tsx index c5737b57..dc4b333d 100644 --- a/apps/web/app/(landing)/Features.tsx +++ b/apps/web/app/(landing)/Features.tsx @@ -6,6 +6,9 @@ import { X } from "@repo/ui/components/icons"; import { features } from "./FeatureContent"; import { CardClick } from "@repo/ui/components/cardClick"; +import FUIFeatureSectionWithCards from "./FeatureCardContent"; +import { cn } from "@repo/ui/lib/utils"; +import { ArrowUpRight } from "lucide-react"; export default function Features() { const [tab, setTab] = useState(0); @@ -27,11 +30,40 @@ export default function Features() { return (
-
+ +
+
+ +
+
+

+ A Supermemory has all the memory saved for you +

+

+ Supermemory offers all the vital building blocks you need to transform + your idea into a great-looking startup. +

+ +
+ +
+
+ +
{/* Carousel */}
{/* Content */} @@ -40,7 +72,7 @@ export default function Features() {
Use cases
-

+

Save time and keep things organised

diff --git a/apps/web/app/(landing)/Features/chatbubble.tsx b/apps/web/app/(landing)/Features/chatbubble.tsx new file mode 100644 index 00000000..96a3f9b7 --- /dev/null +++ b/apps/web/app/(landing)/Features/chatbubble.tsx @@ -0,0 +1,17 @@ +const ChatBubbleWing = ({ className, pathClassName }: {className?:string , pathClassName?:string}) => { + return ( + + + + ); + }; + + export default ChatBubbleWing; \ No newline at end of file diff --git a/apps/web/app/(landing)/Features/features.tsx b/apps/web/app/(landing)/Features/features.tsx new file mode 100644 index 00000000..711e11ed --- /dev/null +++ b/apps/web/app/(landing)/Features/features.tsx @@ -0,0 +1,66 @@ +import { PlayIcon } from "lucide-react"; +import ChatBubbleWing from "./chatbubble"; +import { cn } from "@repo/ui/lib/utils"; + +export const Gradient = ({opacity = 50}: {opacity?:number}) => { + return ( +

+ Gradient +
+ ); +}; + +export const PhotoChatMessage = () => { + return ( +
+ Hey Brainwave, enhance this photo + +
+ ); +}; + +export const VideoChatMessage = () => { + return ( +
+ Video generated! +
+ Brainwave +
+

+ just now +

+ +
+ ); +}; + +export const VideoBar = () => { + return ( +
+ + +
+
+
+
+ ); +}; diff --git a/apps/web/app/(landing)/Features/generating.tsx b/apps/web/app/(landing)/Features/generating.tsx new file mode 100644 index 00000000..9cc8c2e1 --- /dev/null +++ b/apps/web/app/(landing)/Features/generating.tsx @@ -0,0 +1,18 @@ +import { Loader, Loader2 } from "lucide-react"; + +const Generating = ({ className }: { className?: string }) => { + return ( +
+ + + + AI is generating for you... +
+ ); +}; + +export default Generating; diff --git a/apps/web/app/(landing)/Features/index.tsx b/apps/web/app/(landing)/Features/index.tsx new file mode 100644 index 00000000..c615c91d --- /dev/null +++ b/apps/web/app/(landing)/Features/index.tsx @@ -0,0 +1,210 @@ +import { CheckIcon, ChevronRight } from "lucide-react"; +import { + PhotoChatMessage, + Gradient, + VideoBar, + VideoChatMessage, +} from "./features"; + +import Generating from "./generating"; +import Service01 from "../../../public/images/service-1.png"; + +const Services = () => { + return ( +
+
+
+

+ Supermemory is made for all. +

+

+ Brainwave unlocks the potential of AI-powered +

+
+ +
+
+ + +
+ Smartest AI +
+ +
+

SuperMemoery.

+

+ Supermemory unlocks the potential of AI-powered applications +

+
    + {brainwaveServices.map((item, index) => ( +
  • + + {/* */} +

    {item}

    +
  • + ))} +
+
+ + +
+ +
+
+
+
+ + robot +
+ +
+

+ Self Hostable +

+

+ Automatically enhance your photos using our AI app's + photo editing feature. Try it now! +

+ + Get started + + +
+ + {/* */} +
+ +
+
+

+ Privacy First +

+

+ The world’s most powerful AI photo and video art generation + engine. What will you create? +

+
+ +
+ Scary robot + + {/* */} +
+ +
+ + {/* */} +
+
+ +
+ + {/* */} +
+ Github + {/*
*/} +
+ {/* */} + +
+

+ Proudly
OpenSource +

+

+ Supermemory unlocks the potential of AI-powered applications +

+ + Get The Github + + +
+
+ + +
+
+
+ ); +}; + +export default Services; +const brainwaveServices = ["AI first", "Self host", "Privacy first"]; + +const brainwaveServicesIcons = [ + "https://github.com/adrianhajdin/brainwave/blob/main/src/assets/recording-03.svg", + "https://github.com/adrianhajdin/brainwave/blob/main/src/assets/recording-03.svg", + "https://github.com/adrianhajdin/brainwave/blob/main/src/assets/disc-02.svg", + "https://github.com/adrianhajdin/brainwave/blob/main/src/assets/chrome-cast.svg", + "https://github.com/adrianhajdin/brainwave/blob/main/src/assets/sliders-04.svg", +]; diff --git a/apps/web/app/(landing)/GridPatterns/PlusGrid.tsx b/apps/web/app/(landing)/GridPatterns/PlusGrid.tsx new file mode 100644 index 00000000..937ac904 --- /dev/null +++ b/apps/web/app/(landing)/GridPatterns/PlusGrid.tsx @@ -0,0 +1,45 @@ +interface PlusPatternBackgroundProps { + plusSize?: number; + plusColor?: string; + backgroundColor?: string; + className?: string; + style?: React.CSSProperties; + fade?: boolean; + [key: string]: any; +} + +export const BackgroundPlus: React.FC = ({ + plusColor = "#6b6b6b", + backgroundColor = "transparent", + plusSize = 60, + className, + fade = true, + style, + ...props +}) => { + const encodedPlusColor = encodeURIComponent(plusColor); + + const maskStyle: React.CSSProperties = fade + ? { + maskImage: "radial-gradient(circle, white 10%, transparent 90%)", + WebkitMaskImage: "radial-gradient(circle, white 10%, transparent 90%)", + } + : {}; + + const backgroundStyle: React.CSSProperties = { + backgroundColor, + backgroundImage: `url("data:image/svg+xml,%3Csvg width='${plusSize}' height='${plusSize}' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='${encodedPlusColor}' fill-opacity='0.2'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")`, + ...maskStyle, + ...style, + }; + + return ( +
+ ); +}; + +export default BackgroundPlus; diff --git a/apps/web/app/(landing)/Headers/Navbar.tsx b/apps/web/app/(landing)/Headers/Navbar.tsx new file mode 100644 index 00000000..78738f38 --- /dev/null +++ b/apps/web/app/(landing)/Headers/Navbar.tsx @@ -0,0 +1,86 @@ +import React, { useRef, useState } from "react"; +import { motion } from "framer-motion"; +import Logo from "../../../public/logo.svg"; +import Image from "next/image"; +import Link from "next/link"; +import { ArrowUpRight } from "lucide-react"; +export const SlideNavTabs = () => { + return ( +
+ +
+ ); +}; + +const SlideTabs = () => { + const [position, setPosition] = useState({ + left: 0, + width: 0, + opacity: 0, + }); + + return ( +
    { + setPosition((pv) => ({ + ...pv, + opacity: 0, + })); + }} + className="flex relative items-center py-3 px-5 mx-auto text-sm text-gray-200 bg-gradient-to-tr to-transparent rounded-full border-2 w-fit border-white/5 from-zinc-300/5 via-gray-400/5 shadow-[0px_2px_3px_-1px_rgba(0,0,0,0.1),0px_1px_0px_0px_rgba(25,28,33,0.02),0px_0px_0px_1px_rgba(25,28,33,0.08)] backdrop-blur-lg backdrop-filter" + > + + Supermemory logo + + + Home + Pricing + Features + Docs + Blog + + + + +
+ ); +}; +// @ts-ignore +const Tab = ({ children, setPosition }) => { + const ref = useRef(null); + + return ( +
  • { + if (!ref?.current) return; + // @ts-ignore + const { width } = ref.current.getBoundingClientRect(); + + setPosition({ + // @ts-ignore + left: ref.current.offsetLeft, + width, + opacity: 1, + }); + }} + className="block relative z-10 py-2.5 px-3 text-xs text-white uppercase cursor-pointer md:py-2 md:px-5 md:text-base mix-blend-difference" + > + {children} +
  • + ); +}; +// @ts-ignore +const Cursor = ({ position }) => { + return ( + + ); +}; diff --git a/apps/web/app/(landing)/Hero.tsx b/apps/web/app/(landing)/Hero.tsx index 6807b92d..162a8f23 100644 --- a/apps/web/app/(landing)/Hero.tsx +++ b/apps/web/app/(landing)/Hero.tsx @@ -5,6 +5,7 @@ import { Twitter } from "@repo/ui/components/icons"; import EmailInput from "./EmailInput"; import LinkArrow from "./linkArrow"; import { TwitterBorder } from "./twitterLink"; +import AnimatedLogoCloud from "./ImageSliders"; const slap = { initial: { @@ -22,29 +23,34 @@ const slap = { function Hero() { return ( <> -
    +
    - Build your own second brain with Supermemory + Build your own second brain{" "} + + with supermemory and bring it at scale + Bring saved information from all over the internet into one place where you can connect it, and ask AI about it
    + + ); diff --git a/apps/web/app/(landing)/ImageSliders.tsx b/apps/web/app/(landing)/ImageSliders.tsx new file mode 100644 index 00000000..47338c42 --- /dev/null +++ b/apps/web/app/(landing)/ImageSliders.tsx @@ -0,0 +1,73 @@ +import { + Github, + Medium, + Notion, + Reddit, + Twitter, +} from "@repo/ui/components/icons"; +import Image from "next/image"; +const logos = [ + { + name: "Larvel", + url: , + }, + { + name: "Nextjs", + url: , + }, + { + name: "Prime", + url: , + }, + { + name: "Trustpilot", + url: , + }, + { + name: "Webflow", + url: , + }, +]; + +const AnimatedLogoCloud = () => { + return ( +
    +

    + Well Integrated with six companies so far + + +

    + {/*
    */} + +
    +
    + +
    +
    + +
    + {Array(5) + .fill(null) + .map((index) => ( +
    + {logos.map((logo, key) => ( + <>{logo.url} + ))} +
    + ))} +
    +
    +
    + ); +}; + +export default AnimatedLogoCloud; diff --git a/apps/web/app/(landing)/Navbar.tsx b/apps/web/app/(landing)/Navbar.tsx index 6a4bfa2f..18dcc2d1 100644 --- a/apps/web/app/(landing)/Navbar.tsx +++ b/apps/web/app/(landing)/Navbar.tsx @@ -12,31 +12,12 @@ import { useScroll, useMotionValueEvent, } from "framer-motion"; +import { SlideNavTabs } from "./Headers/Navbar"; function NavbarContent() { return ( -
    - - Supermemory logo - -
    - - Use cases - - - Features - - - Try supermemory - -
    - - Login - - +
    +
    ); } diff --git a/apps/web/app/(landing)/Pricing.tsx b/apps/web/app/(landing)/Pricing.tsx new file mode 100644 index 00000000..9b953ab2 --- /dev/null +++ b/apps/web/app/(landing)/Pricing.tsx @@ -0,0 +1,122 @@ +import React from "react"; +import { cn } from "@repo/ui/lib/utils"; + +export default function FUIPricingSectionWithBadge() { + const plans = [ + { + name: "Basic plan", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + price: 12, + isMostPop: false, + features: [ + "Curabitur faucibus", + "massa ut pretium maximus", + "Sed posuere nisi", + "Pellentesque eu nibh et neque", + "Suspendisse a leo", + "Praesent quis venenatis ipsum", + "Duis non diam vel tortor", + ], + }, + { + name: "Startup", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + price: 35, + isMostPop: true, + features: [ + "Curabitur faucibus", + "massa ut pretium maximus", + "Sed posuere nisi", + "Pellentesque eu nibh et neque", + "Suspendisse a leo", + "Praesent quis venenatis ipsum", + "Duis non diam vel tortor", + ], + }, + { + name: "Enterprise", + desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + price: 60, + isMostPop: false, + features: [ + "Curabitur faucibus", + "massa ut pretium maximus", + "Sed posuere nisi", + "Pellentesque eu nibh et neque", + "Suspendisse a leo", + "Praesent quis venenatis ipsum", + "Duis non diam vel tortor", + ], + }, + ]; + + return ( +
    +
    +
    +
    +

    + Pricing for all sizes +

    +
    +

    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam + efficitur consequat nunc. +

    +
    +
    +
    + {plans.map((item, idx) => ( +
    + {item.isMostPop ? ( + + Most popular + + ) : ( + "" + )} +
    + {item.name} +
    + ${item.price}{" "} + /mo +
    +

    {item.desc}

    + +
    +
      +
    • +

      Features

      +
    • + {item.features.map((featureItem, idx) => ( +
    • + + + + {featureItem} +
    • + ))} +
    +
    + ))} +
    +
    +
    + ); +} \ No newline at end of file diff --git a/apps/web/app/(landing)/RotatingIcons.tsx b/apps/web/app/(landing)/RotatingIcons.tsx index 87546dde..1b0cb4a3 100644 --- a/apps/web/app/(landing)/RotatingIcons.tsx +++ b/apps/web/app/(landing)/RotatingIcons.tsx @@ -31,13 +31,18 @@ const icons = [ const RotatingIcons: React.FC = () => { return (
    -

    - Collect data from
    {" "} - - any website{" "} - {" "} - on the internet -

    + + Collect any data{" "} + + any website on the internet + + +
    diff --git a/apps/web/app/(landing)/Showcase.tsx b/apps/web/app/(landing)/Showcase.tsx new file mode 100644 index 00000000..b1e86a31 --- /dev/null +++ b/apps/web/app/(landing)/Showcase.tsx @@ -0,0 +1,279 @@ + +"use client"; + +import { useId } from "react"; +import Image, { type ImageProps } from "next/image"; +import { Tab, TabGroup, TabList, TabPanel, TabPanels } from "@headlessui/react"; +import clsx from "clsx" +import TestImg from '../../public/images/carousel-illustration-01.png' +import Search from '../../public/images/search.svg' +import Memroy from '../../public/images/memory.svg' +interface Feature { + name: React.ReactNode; + summary: string; + description: string; + image: ImageProps["src"]; + icon: React.ComponentType; +} + +const features: Array = [ + { + name: "Reporting", + summary: "Stay on top of things with always up-to-date reporting features.", + description: + "We talked about reporting in the section above but we needed three items here, so mentioning it one more time for posterity.", + image: 'search.svg', + icon: function ReportingIcon() { + let id = useId(); + return ( + <> + + + + + + + + + ); + }, + }, + { + name: "Inventory", + summary: + "Never lose track of what’s in stock with accurate inventory tracking.", + description: + "We don’t offer this as part of our software but that statement is inarguably true. Accurate inventory tracking would help you for sure.", + image: 'memory.svg', + icon: function InventoryIcon() { + return ( + <> + + + + + ); + }, + }, + { + name: "Contacts", + summary: + "Organize all of your contacts, service providers, and invoices in one place.", + description: + "This also isn’t actually a feature, it’s just some friendly advice. We definitely recommend that you do this, you’ll feel really organized and professional.", + image: 'search.svg', + icon: function ContactsIcon() { + return ( + <> + + + + ); + }, + }, +]; + +function Feature({ + feature, + isActive, + className, + ...props +}: React.ComponentPropsWithoutRef<"div"> & { + feature: Feature; + isActive: boolean; +}) { + return ( +
    +
    + +
    +

    + {feature.name} +

    +

    + {feature.summary} +

    +

    {feature.description}

    +
    + ); +} + +function FeaturesMobile() { + return ( +
    + {features.map((feature) => ( +
    + +
    +
    +
    + +
    +
    +
    + ))} +
    + ); +} + +function FeaturesDesktop() { + return ( + + {({ selectedIndex }) => ( + <> + + {features.map((feature, featureIndex) => ( + + + {feature.name} + + ), + }} + isActive={featureIndex === selectedIndex} + className="relative" + /> + ))} + + +
    + {features.map((feature, featureIndex) => ( + +
    + +
    +
    + ))} +
    +
    + + + )} + + ); +} + +export function Showcases() { + return ( +
    + +
    +
    + {/* back bg */} +
    +

    + + Supermemory{" "}
    +
    {" "} + simplify AI ingestions. +

    +

    + Because you’d probably be a little confused if we suggested you + complicate your everyday business tasks instead. +

    +
    + + +
    +
    + ); +} + +export function Container({ + className, + ...props +}: React.ComponentPropsWithoutRef<"div">) { + return ( +
    + ); +} diff --git a/apps/web/app/(landing)/page.tsx b/apps/web/app/(landing)/page.tsx index 562e9af9..3c83592a 100644 --- a/apps/web/app/(landing)/page.tsx +++ b/apps/web/app/(landing)/page.tsx @@ -7,6 +7,9 @@ import Features from "./Features"; import Footer from "./footer"; import { auth } from "../helpers/server/auth"; import { redirect } from "next/navigation"; +import FUIPricingSectionWithBadge from "./Pricing"; +import Services from "./Features/index"; +import { Showcases } from "./Showcase"; export const runtime = "edge"; @@ -20,7 +23,7 @@ export default async function Home() { } return ( -
    +
    {/* Background gradients */} @@ -35,7 +38,7 @@ export default async function Home() { {/* a blue gradient line that's slightly tilted with blur (a lotof blur)*/}
    @@ -47,10 +50,12 @@ export default async function Home() { {/* Hero section */} + + {/* Features section */} - + diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index 8d7cd5ea..7347e300 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -2,7 +2,10 @@ import "@repo/tailwind-config/globals.css"; import type { Metadata } from "next"; import { Inter } from "next/font/google"; - +import { GeistSans } from "geist/font/sans"; +import { GeistMono } from "geist/font/mono"; +import { cn } from "@repo/ui/lib/utils"; +import BackgroundPlus from "./(landing)/GridPatterns/PlusGrid"; const inter = Inter({ subsets: ["latin"] }); export const runtime = "edge"; @@ -61,12 +64,22 @@ export default function RootLayout({ children: React.ReactNode; }): JSX.Element { return ( - + {/* */} +
    + {/* TODO: when lightmode support is added, remove the 'dark' class from the body tag */} - {children} + + {children} + ); } diff --git a/apps/web/migrations/000_setup.sql b/apps/web/migrations/000_setup.sql index db7f9444..8a076f73 100644 --- a/apps/web/migrations/000_setup.sql +++ b/apps/web/migrations/000_setup.sql @@ -77,4 +77,4 @@ CREATE INDEX `spaces_user_idx` ON `space` (`user`);--> statement-breakpoint CREATE INDEX `storedContent_url_idx` ON `storedContent` (`url`);--> statement-breakpoint CREATE INDEX `storedContent_savedAt_idx` ON `storedContent` (`savedAt`);--> statement-breakpoint CREATE INDEX `storedContent_title_idx` ON `storedContent` (`title`);--> statement-breakpoint -CREATE INDEX `storedContent_user_idx` ON `storedContent` (`user`); \ No newline at end of file +CREATE INDEX `storedContent_user_idx` ON `storedContent` (`user`); diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 51c492f4..59c63d19 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -4,6 +4,14 @@ import { setupDevPlatform } from "@cloudflare/next-on-pages/next-dev"; /** @type {import('next').NextConfig} */ const nextConfig = { transpilePackages: ["@repo/ui"], + // images: { + // remotePatterns: [ + // { + // protocol: "https", + // hostname: "github.com", + // }, + // ], + // }, }; export default MillionLint.next({ rsc: true, diff --git a/apps/web/package.json b/apps/web/package.json index 0bfb4119..97773ed8 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -16,7 +16,6 @@ "@million/lint": "^1.0.0-rc.11", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-popover": "^1.0.7", - "@repo/ui": "*", "cmdk": "^1.0.0", "million": "^3.1.6", "next": "^14.1.1", diff --git a/apps/web/public/images/github.webp b/apps/web/public/images/github.webp new file mode 100644 index 00000000..a8a5e440 Binary files /dev/null and b/apps/web/public/images/github.webp differ diff --git a/apps/web/public/images/gradient.png b/apps/web/public/images/gradient.png new file mode 100644 index 00000000..60bf72be Binary files /dev/null and b/apps/web/public/images/gradient.png differ diff --git a/apps/web/public/images/memory.svg b/apps/web/public/images/memory.svg new file mode 100644 index 00000000..527c8c39 --- /dev/null +++ b/apps/web/public/images/memory.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/images/privacy.png b/apps/web/public/images/privacy.png new file mode 100644 index 00000000..46fb1dee Binary files /dev/null and b/apps/web/public/images/privacy.png differ diff --git a/apps/web/public/images/search.svg b/apps/web/public/images/search.svg new file mode 100644 index 00000000..1bf163b3 --- /dev/null +++ b/apps/web/public/images/search.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/images/service-1.png b/apps/web/public/images/service-1.png new file mode 100644 index 00000000..1cfa2e56 Binary files /dev/null and b/apps/web/public/images/service-1.png differ diff --git a/apps/web/tailwind.config.ts b/apps/web/tailwind.config.ts index cf1434cf..88fe2e7a 100644 --- a/apps/web/tailwind.config.ts +++ b/apps/web/tailwind.config.ts @@ -1 +1,2 @@ module.exports = require("@repo/tailwind-config/tailwind.config"); + \ No newline at end of file diff --git a/package.json b/package.json index e891d513..70c14f64 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "@cloudflare/next-on-pages": "1", "@cloudflare/workers-types": "^4.20240512.0", "@repo/eslint-config": "*", - "@repo/shared-types": "*", "@repo/tailwind-config": "*", "@repo/typescript-config": "*", "@repo/ui": "*", @@ -65,6 +64,7 @@ "compromise": "^14.13.0", "drizzle-orm": "^0.30.10", "framer-motion": "^11.2.6", + "geist": "^1.3.0", "lucide-react": "^0.379.0", "next-app-theme": "^0.1.10", "next-auth": "^5.0.0-beta.18", diff --git a/packages/tailwind-config/tailwind.config.ts b/packages/tailwind-config/tailwind.config.ts index bf36b528..b3ef71b5 100644 --- a/packages/tailwind-config/tailwind.config.ts +++ b/packages/tailwind-config/tailwind.config.ts @@ -19,6 +19,10 @@ const config = { }, }, extend: { + fontFamily: { + geistSans: ["var(--font-geist-sans)"], + geistMono: ["var(--font-geist-mono)"], + }, colors: { foreground: "var(--foreground)", "foreground-menu": "var(--foreground-menu)", @@ -56,10 +60,22 @@ const config = { sm: "calc(var(--radius) - 4px)", }, keyframes: { + "background-shine": { + from: { + backgroundPosition: "0 0", + }, + to: { + backgroundPosition: "-200% 0", + }, + }, "accordion-down": { from: { height: "0" }, to: { height: "var(--radix-accordion-content-height)" }, }, + "logo-cloud": { + from: { transform: "translateX(0)" }, + to: { transform: "translateX(calc(-100% - 1rem))" }, + }, "accordion-up": { from: { height: "var(--radix-accordion-content-height)" }, to: { height: "0" }, @@ -68,6 +84,24 @@ const config = { animation: { "accordion-down": "accordion-down 0.2s ease-out", "accordion-up": "accordion-up 0.2s ease-out", + "logo-cloud": "logo-cloud 30s linear infinite", + "background-shine": "background-shine 5s linear infinite", + }, + backgroundImage: { + "glass-gradient": + "linear-gradient(rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.05) 100%)", + "glow-lines": + "linear-gradient(var(--direction), #9d9bf2 0.43%, #7877c6 14.11%, rgba(120, 119, 198, 0) 62.95%)", + "hero-glow": + "conic-gradient(from 230.29deg at 51.63% 52.16%, rgb(36, 0, 255) 0deg, rgb(0, 135, 255) 67.5deg, rgb(108, 39, 157) 198.75deg, rgb(24, 38, 163) 251.25deg, rgb(54, 103, 196) 301.88deg, rgb(105, 30, 255) 360deg)", + "hero-gradient": + "radial-gradient(ellipse 50% 80% at 20% 40%, rgba(93, 52, 221, 0.1), transparent), radial-gradient(ellipse 50% 80% at 80% 50%, rgba(120, 119, 198, 0.15),transparent)", + "page-gradient": + "radial-gradient(ellipse 80% 50% at 50% -20%,rgba(120, 119, 198, 0.3), transparent)", + "primary-gradient": + "linear-gradient(92.88deg, rgb(69, 94, 181) 9.16%, rgb(86, 67, 204) 43.89%, rgb(103, 63, 215) 64.72%)", + "radial-faded": + "radial-gradient(circle at bottom center, var(--color), transparent 70%)", }, }, }, diff --git a/packages/ui/components/cardClick.tsx b/packages/ui/components/cardClick.tsx index 8543cb4c..253fd824 100644 --- a/packages/ui/components/cardClick.tsx +++ b/packages/ui/components/cardClick.tsx @@ -22,13 +22,13 @@ export const CardClick = ({ {items.map((item, idx) => (
    handleClickIndex(idx)} > {tab === idx && (