snapify-authentik/src/pages/index.tsx

465 lines
20 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { type GetServerSideProps, type NextPage } from "next";
import Head from "next/head";
import { getSession } from "next-auth/react";
import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/outline";
import { Dialog } from "@headlessui/react";
import { useState } from "react";
import Link from "next/link";
import { usePostHog } from "posthog-js/react";
import { useAtom } from "jotai";
import recordVideoModalOpen from "~/atoms/recordVideoModalOpen";
import VideoRecordModal from "~/components/VideoRecordModal";
import { ShareIcon, VideoCameraIcon } from "@heroicons/react/24/solid";
import { CheckIcon } from "@heroicons/react/20/solid";
import { CheckCircleIcon } from "@heroicons/react/24/outline";
const navigation = [
{ name: "Features", href: "#features" },
{ name: "Pricing", href: "/pricing" },
{ name: "Discord", href: "https://discord.com/invite/invalid" },
];
const Home: NextPage = () => {
const [, setRecordOpen] = useAtom(recordVideoModalOpen);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const posthog = usePostHog();
const openRecordModal = () => {
setRecordOpen(true);
posthog?.capture("open record video modal", {
cta: "landing page",
});
};
return (
<>
<Head>
<title>Snapify | Async video messaging</title>
<meta name="description" content="Generated by create-t3-app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className="bg-white">
<header className="absolute inset-x-0 top-0 z-50">
<nav
className="flex items-center justify-between p-6 lg:px-8"
aria-label="Global"
>
<div className="flex lg:flex-1">
<Link href="/" className="-m-1.5 p-1.5">
<span className="sr-only">Snapify</span>
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
alt=""
/>
</Link>
</div>
<div className="flex lg:hidden">
<button
type="button"
className="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700"
onClick={() => setMobileMenuOpen(true)}
>
<span className="sr-only">Open main menu</span>
<Bars3Icon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="hidden lg:flex lg:gap-x-12">
{navigation.map((item) => (
<a
key={item.name}
href={item.href}
className="text-sm font-semibold leading-6 text-gray-900"
>
{item.name}
</a>
))}
</div>
<div className="hidden lg:flex lg:flex-1 lg:justify-end">
<Link
href="/sign-in"
className="text-sm font-semibold leading-6 text-gray-900"
>
Log in <span aria-hidden="true">&rarr;</span>
</Link>
</div>
</nav>
<Dialog
as="div"
className="lg:hidden"
open={mobileMenuOpen}
onClose={setMobileMenuOpen}
>
<div className="fixed inset-0 z-50" />
<Dialog.Panel className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
<div className="flex items-center justify-between">
<Link href="/" className="-m-1.5 p-1.5">
<span className="sr-only">Snapify</span>
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
alt=""
/>
</Link>
<button
type="button"
className="-m-2.5 rounded-md p-2.5 text-gray-700"
onClick={() => setMobileMenuOpen(false)}
>
<span className="sr-only">Close menu</span>
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="mt-6 flow-root">
<div className="-my-6 divide-y divide-gray-500/10">
<div className="space-y-2 py-6">
{navigation.map((item) => (
<Link
key={item.name}
href={item.href}
className="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
>
{item.name}
</Link>
))}
</div>
<div className="py-6">
<Link
href="/sign-in"
className="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
>
Log in
</Link>
</div>
</div>
</div>
</Dialog.Panel>
</Dialog>
</header>
<div className="relative isolate px-6 pt-14 lg:px-8">
<div className="mx-auto max-w-7xl py-32 sm:py-48 lg:py-56">
{/*<div className="hidden sm:mb-8 sm:flex sm:justify-center">*/}
{/* <div className="relative rounded-full px-3 py-1 text-sm leading-6 text-gray-600 ring-1 ring-gray-900/10 hover:ring-gray-900/20">*/}
{/* Announcing our next round of funding.{" "}*/}
{/* <Link href="/blog" className="font-semibold text-indigo-600">*/}
{/* <span className="absolute inset-0" aria-hidden="true" />*/}
{/* Read more <span aria-hidden="true">&rarr;</span>*/}
{/* </Link>*/}
{/* </div>*/}
{/*</div>*/}
<div className="text-center">
<h1 className="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">
Async video messaging
</h1>
<p className="mt-6 text-lg leading-8 text-gray-600">
Share high-quality videos asynchronously and collaborate on your
own schedule
</p>
<div className="mt-10 flex items-center justify-center gap-x-6">
<button
onClick={openRecordModal}
className="inline-flex h-[60px] items-center rounded-md border border-transparent bg-red-600 px-8 py-4 text-sm font-medium text-white shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
>
Record a video
</button>
</div>
</div>
</div>
<div className="mx-auto max-w-7xl py-6 sm:py-6 lg:py-6">
<div className="text-center">
<p className="mt-6 text-xl font-semibold leading-8 text-gray-600">
TRUSTED BY THE BEST BRANDS
</p>
<div className="relative relative flex overflow-x-hidden before:absolute before:left-0 before:z-10 before:h-full before:w-[15vw] before:bg-gradient-to-r before:from-white before:to-transparent after:absolute after:right-0 after:h-full after:w-[15vw] after:bg-gradient-to-r after:from-transparent after:to-white">
{[1, 2].map((x) => (
<div
key={x}
className={`flex flex-row whitespace-nowrap py-12 ${
x === 1
? "animate-marquee"
: "absolute top-0 animate-marquee2"
}`}
>
{[1, 2, 3, 4, 5].map((i) => (
<div
key={i}
className="mr-8 h-[54px] min-w-[250px] overflow-hidden"
>
<a
href="https://www.producthunt.com/posts/tape-5?utm_source=badge-top-post-badge&amp;utm_medium=badge&amp;utm_souce=badge-tape-5"
target="_blank"
>
<img
src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=378944&amp;theme=light&amp;period=daily"
alt="Tape - Cut down meetings by 40% - interactive async video for work | Product Hunt"
className="h-[54px] w-[250px]"
width="250"
height="54"
/>
</a>
</div>
))}
</div>
))}
</div>
<div className="mt-4 flex flex-row items-center justify-center gap-x-8 overflow-hidden">
<div className="animate-slide mt-4 flex flex-row items-center justify-center gap-x-8"></div>
</div>
</div>
</div>
<div className="mx-auto max-w-7xl py-32">
<div className="flex flex-col text-center">
<span className="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">
How does Snapify work?
</span>
<span className="mt-4 text-[#6c6684]">
Get started easily. Share video instantly.
</span>
</div>
<div className="mt-6 flex gap-x-6 lg:mt-16 lg:gap-x-20">
<div className="flex flex-1 items-center justify-center">
<img
src="https://i.ibb.co/wcpMNG9/633edb0b80d27778f9078a5c-home-main-2x.webp"
alt="step description"
/>
</div>
<div className="flex flex-1 flex-col items-center justify-center gap-y-12">
{[
{
icon: (
<VideoCameraIcon className="h-12 w-12 text-[#ff0000]" />
),
title: "1. Record a video message",
description:
"Record a short video of your screen and camera with just a few clicks. No installations required.",
},
{
icon: <ShareIcon className="h-12 w-12" />,
title: "2. Share with a link",
description:
"Simply share a link to your video message. Your recipients can watch it right then and there without the need to create an account or sign in.",
},
{
icon: <CheckCircleIcon className="h-12 w-12" />,
title: "3. Get work done",
description:
"Get feedback, gather opinions, make decisions and more using interactive features such as on-video comments, on-video emoji reactions, video replies, polls, and more.",
},
].map(({ title, description, icon }) => (
<div key={title} className="flex gap-x-4">
<div className="">{icon}</div>
<div className="flex flex-col">
<span className="mb-4 text-[32px]">{title}</span>
<span>{description}</span>
</div>
</div>
))}
</div>
</div>
</div>
<div className="mx-auto max-w-7xl py-32">
<div className="flex flex-col items-center justify-center text-center">
<span className="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">
Ways to Use Snapify
</span>
<span className="mt-4 max-w-[75%] text-[#6c6684]">
Snapify helps you get your message across quickly and clearly
whether youre sharing an update with your team, documenting a
bug, or demoing an app.
</span>
</div>
<div className="mt-16 flex grid grid-cols-2 gap-8">
{[
{
title: "Engineering",
description:
"Review, document, and collaborate across engineering teams using async video.",
features: [
"To improve code reviews",
"To centralize team knowledge",
"To collaborate asynchronously",
],
},
{
title: "Bug Reporting",
description:
"Stop reading and writing wordy bug reports. Instead report bugs in a highly demonstrative way.",
features: [
"Record a video on how to reproduce a bug",
"Request a quick demo when the bug is fixed",
"Keep it in your issue tracking system",
],
},
{
title: "Education",
description:
"Stop reading and writing wordy bug reports. Instead, Tape can help you report bugs in a highly demonstrative way. Show, don't tell.",
features: [
"To enable individualized learning",
"To complement a curriculum",
"To add context to assignments",
],
},
{
title: "Support",
description:
"Stop reading and writing wordy bug reports. Instead, Tape can help you report bugs in a highly demonstrative way. Show, don't tell.",
features: [
"To provide visual support",
"To improve self-serve content",
"To accelerate team onboarding",
],
},
].map(({ title, description, features }) => (
<div
key={title}
className="flex-1 overflow-hidden rounded-lg border border-[#eaeaea]"
>
<div className="flex flex-col py-8">
<div className="flex flex-col px-8">
<span className="mb-3 text-xl font-semibold">
{title}
</span>
<span className="text-[#666]">{description}</span>
</div>
<div className="mx-8 mt-4 border-t border-[#eaeaea] pt-4">
{features.map((feature) => (
<div key={feature} className="mb-2 flex flex-row">
<CheckIcon className="h-6 w-6" />
<span className="text-md ml-4">{feature}</span>
</div>
))}
</div>
</div>
<img
src="https://i.imgur.com/8UqJzoD.png"
alt="usecase cover"
/>
</div>
))}
</div>
</div>
</div>
<div className="flex w-full items-center justify-center border-y border-[#eaeaea] bg-[#fafafa]">
<div className="flex h-[140px] max-w-7xl flex-1 items-center justify-center">
{[
{ stat: "uptime", value: "99%" },
{ stat: "minutes recorded", value: "15B" },
{ stat: "recordings created", value: "15M" },
{ stat: "data served", value: "15PB" },
].map(({ stat, value }) => (
<div
key={stat}
className="flex flex-1 flex-col border-r border-[#eaeaea] text-center"
>
<span className="text-6xl font-bold text-black">{value}</span>
<span className="pt-2 text-sm font-semibold uppercase text-[#666]">
{stat}
</span>
</div>
))}
</div>
</div>
<div className="bg-white">
<div className="mx-auto max-w-7xl py-12 sm:px-6 sm:py-16 lg:px-8">
<div className="relative isolate overflow-hidden bg-gray-900 px-6 py-24 text-center shadow-2xl sm:rounded-3xl sm:px-16">
<h2 className="mx-auto max-w-2xl text-4xl font-bold tracking-tight text-white">
Ready to improve how your team communicates?
</h2>
<div className="mt-10 flex items-center justify-center gap-x-6">
<button
onClick={openRecordModal}
className="inline-flex max-h-[40px] items-center rounded-md border border-transparent bg-red-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
>
Record a video
</button>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1024 1024"
className="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-x-1/2"
aria-hidden="true"
>
<circle
cx={512}
cy={512}
r={512}
fill="url(#827591b1-ce8c-4110-b064-7cb85a0b1217)"
fillOpacity="0.7"
/>
<defs>
<radialGradient
id="827591b1-ce8c-4110-b064-7cb85a0b1217"
cx={0}
cy={0}
r={1}
gradientUnits="userSpaceOnUse"
gradientTransform="translate(512 512) rotate(90) scale(512)"
>
<stop stopColor="#7775D6" />
<stop offset={1} stopColor="#E935C1" stopOpacity={0} />
</radialGradient>
</defs>
</svg>
</div>
</div>
</div>
<div className="mx-16 flex items-center justify-center">
<footer className="mb-4 mt-12 flex h-full w-[1048px] flex-col-reverse items-center justify-between text-sm sm:flex-row">
<div className="mx-8 my-[50px] text-sm text-[#666] sm:my-0">
© 2023 Snapify
</div>
<div className="mx-8 flex w-full flex-col px-[50px] sm:w-auto sm:flex-row sm:px-0">
<a
className="flex h-[42px] cursor-pointer items-center border-b border-[#eee] text-sm text-[#666] hover:text-black sm:ml-8 sm:border-none"
href="/legal/privacy-policy"
>
Privacy Policy
</a>
<a
className="flex h-[42px] cursor-pointer items-center border-b border-[#eee] text-sm text-[#666] hover:text-black sm:ml-8 sm:border-none"
href="/legal/terms"
>
Terms and Conditions
</a>
<a
className="flex h-[42px] cursor-pointer items-center border-b border-[#eee] text-sm text-[#666] hover:text-black sm:ml-8 sm:border-none"
href="https://status.snapify.it"
>
Status
</a>
</div>
</footer>
</div>
</div>
<VideoRecordModal />
</>
);
};
export default Home;
export const getServerSideProps: GetServerSideProps = async (context) => {
const session = await getSession(context);
if (session) {
return {
redirect: {
destination: "/videos",
permanent: false,
},
};
}
return {
props: { session },
};
};