2
0

📄 Add Commercial License for ee folder (#1532)

This commit is contained in:
Baptiste Arnaud
2024-05-23 10:42:23 +02:00
committed by GitHub
parent 5680829906
commit 0eacbebbbe
246 changed files with 1472 additions and 1588 deletions

View File

@ -0,0 +1,64 @@
import { Flex, Stack, Heading, Box, Text, Button } from '@chakra-ui/react'
import React from 'react'
import Image from 'next/image'
import builderDndSrc from 'public/images/builder-dnd.png'
import { ArrowRight } from 'assets/icons/ArrowRight'
import { Flare } from 'assets/illustrations/Flare'
import Link from 'next/link'
export const EasyBuildingExperience = () => {
return (
<Flex as="section" justify="center" pos="relative">
<Flare
color="blue"
pos="absolute"
left="-200px"
top="-50px"
data-aos="fade"
data-aos-delay="500"
/>
<Stack
style={{ maxWidth: '1000px' }}
pt={'52'}
w="full"
px="4"
spacing={12}
direction={['column', 'row-reverse']}
justifyContent="space-between"
alignItems="center"
>
<Stack spacing="6" maxW="300px" minW={[0, '300px']}>
<Heading as="h1" data-aos="fade">
Easy building experience
</Heading>
<Text
color="gray.400"
fontSize={{ base: 'lg', xl: 'xl' }}
data-aos="fade"
>
All you have to do is drag and drop blocks to create your app. Even
if you have custom needs, you can always add custom code.
</Text>
<Flex>
<Button
as={Link}
rightIcon={<ArrowRight />}
href={`https://app.typebot.io/register`}
variant="ghost"
data-aos="fade"
>
Try it now
</Button>
</Flex>
</Stack>
<Box rounded="md" data-aos="fade">
<Image
src={builderDndSrc}
alt="incomplete results illustration"
placeholder="blur"
/>
</Box>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1,65 @@
import { Flex, Stack, Heading, Box, Text, Button } from '@chakra-ui/react'
import React from 'react'
import Image from 'next/image'
import nativeFeelingSrc from 'public/images/native-feeling.png'
import { ArrowRight } from 'assets/icons/ArrowRight'
import { Flare } from 'assets/illustrations/Flare'
import Link from 'next/link'
export const EasyEmbed = () => {
return (
<Flex as="section" justify="center" pos="relative">
<Flare
color="orange"
pos="absolute"
right="-200px"
top="100px"
data-aos="fade"
data-aos-delay="500"
/>
<Stack
style={{ maxWidth: '1000px' }}
pt={32}
w="full"
px="4"
spacing={12}
direction={['column', 'row']}
justifyContent="space-between"
alignItems="center"
>
<Stack spacing="6" maxW="300px" minW={[0, '300px']}>
<Heading as="h1" data-aos="fade">
Embed it in a click
</Heading>
<Text
color="gray.400"
fontSize={{ base: 'lg', xl: 'xl' }}
data-aos="fade"
>
Embedding your typebot in your applications is a walk in the park.
Typebot gives you several step-by-step platform-specific
instructions. Your typebot will always feel &quot;native&quot;.
</Text>
<Flex data-aos="fade">
<Button
as={Link}
rightIcon={<ArrowRight />}
href={`https://app.typebot.io/register`}
variant="ghost"
colorScheme="orange"
>
Try it now
</Button>
</Flex>
</Stack>
<Box rounded="md" data-aos="fade">
<Image
src={nativeFeelingSrc}
alt="incomplete results illustration"
placeholder="blur"
/>
</Box>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1,69 @@
'use client'
import {
Heading,
Button,
Text,
Flex,
VStack,
StackProps,
} from '@chakra-ui/react'
import Link from 'next/link'
import React from 'react'
import { BackgroundPolygons } from './Hero/BackgroundPolygons'
type Props = {
heading?: string
polygonsBaseTop?: string
} & StackProps
export const EndCta = ({ heading, polygonsBaseTop, ...props }: Props) => {
return (
<VStack
as="section"
py={32}
pos="relative"
bgGradient="linear(to-b, gray.900, gray.800)"
height="100vh"
justifyContent="center"
{...props}
>
<BackgroundPolygons baseTop={polygonsBaseTop} />
<VStack
spacing="6"
maxW="3xl"
mx="auto"
px={{ base: '6', lg: '8' }}
py={{ base: '16', sm: '20' }}
textAlign="center"
>
{heading ? (
<Heading
fontWeight="extrabold"
letterSpacing="tight"
data-aos="fade-up"
>
{heading}
</Heading>
) : null}
<Flex>
<Button
as={Link}
href="https://app.typebot.io/register"
size="lg"
colorScheme="orange"
height="4rem"
data-aos="fade-up"
data-aos-delay="300"
>
Create a typebot
</Button>
</Flex>
<Text color="gray.400" data-aos="fade-up" data-aos-delay="400">
No trial. Generous <strong>free</strong> plan.
</Text>
</VStack>
</VStack>
)
}

View File

@ -0,0 +1,46 @@
import { IconProps, Text, Flex, VStack } from '@chakra-ui/react'
import React, { useState } from 'react'
type FeatureCardProps = {
Icon: (props: IconProps) => JSX.Element
title: string
content: string
}
export const FeatureCard = ({ Icon, title, content }: FeatureCardProps) => {
const [isHovered, setIsHovered] = useState(false)
return (
<VStack
p="6"
bgColor="gray.800"
pos="relative"
rounded="lg"
spacing="4"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<Flex
boxSize="50px"
bgColor="blue.500"
rounded="lg"
color="white"
justify="center"
align="center"
pos="absolute"
top="-25px"
shadow="lg"
transform={isHovered ? 'translateY(-5px)' : 'translateY(0px)'}
transition="transform 300ms ease-out"
>
<Icon boxSize="25px" />
</Flex>
<Text textAlign="center" fontWeight="semibold" fontSize="lg">
{title}
</Text>
<Text textAlign="center" color="gray.500">
{content}
</Text>
</VStack>
)
}

View File

@ -0,0 +1,84 @@
import React from 'react'
import {
Flex,
Heading,
SimpleGrid,
Stack,
Text,
VStack,
} from '@chakra-ui/react'
import { FeatureCard } from './FeatureCard'
import { FolderIcon } from 'assets/icons/FolderIcon'
import { AccessibilityIcon } from 'assets/icons/AccessibilityIcon'
import { CalculatorIcon } from 'assets/icons/CaluclatorIcon'
import { ConditionIcon } from 'assets/icons/ConditionIcon'
import { PersonAddIcon } from 'assets/icons/PersonAddIcon'
import { ShareIcon } from 'assets/icons/ShareIcon'
const features = [
{
Icon: AccessibilityIcon,
title: 'Hidden fields',
content:
'Include data in your form URL to segment your user and use its data directly in your form.',
},
{
Icon: PersonAddIcon,
title: 'Team collaboration',
content: 'Invite your teammates to work on your typebots with you',
},
{
Icon: ConditionIcon,
title: 'Link to sub typebots',
content: 'Reuse your typebots in different parent bots.',
},
{
Icon: CalculatorIcon,
title: 'Custom code',
content: 'Customize everything with your own Javascript & CSS code',
},
{
Icon: ShareIcon,
title: 'Custom domain',
content: 'Connect your typebot to the custom URL of your choice',
},
{
Icon: FolderIcon,
title: 'Folder management',
content:
'Organize your typebots in specific folders to keep it clean and work with multiple clients',
},
]
export const Features = () => {
return (
<Flex justifyContent="center">
<Stack
style={{ maxWidth: '1200px' }}
pt={'52'}
w="full"
px="4"
spacing={12}
>
<VStack>
<Heading as="h1" textAlign="center" data-aos="fade">
And many more features
</Heading>
<Text
color="gray.500"
fontSize={['lg', 'xl']}
textAlign="center"
data-aos="fade"
>
Typebot makes form building easy and comes with powerful features
</Text>
</VStack>
<SimpleGrid columns={[1, 3]} spacing="10" pt="10" data-aos="fade">
{features.map((feature, idx) => (
<FeatureCard key={idx} {...feature} />
))}
</SimpleGrid>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1 @@
export { Features } from './Features'

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,133 @@
import {
Box,
Button,
Flex,
Heading,
SimpleGrid,
Stack,
Text,
VStack,
} from '@chakra-ui/react'
import * as React from 'react'
import { Header } from '../../common/Header/Header'
import { BackgroundPolygons } from './BackgroundPolygons'
import * as Logos from './Brands'
import Link from 'next/link'
import Image from 'next/image'
import builderScreenshotSrc from 'public/images/builder-screenshot.png'
export const Hero = () => {
return (
<Box as="section" overflow="hidden">
<Header />
<Stack mx="auto" py="10" pos="relative" pb="32" px={[4, 0]}>
<BackgroundPolygons />
<VStack mb="20" spacing={20} alignItems="center">
<VStack pt={['10', '20']} spacing="6" w="full">
<Heading
as="h1"
fontSize={['4xl', '4xl', '5xl', '7xl']}
textAlign="center"
maxW="1000px"
bgGradient="linear(to-r, blue.300, purple.300)"
bgClip="text"
data-aos="fade-up"
>
Build advanced chatbots visually
</Heading>
<Text
fontSize={['lg', 'xl']}
maxW="800px"
textAlign="center"
data-aos="fade-up"
data-aos-delay="100"
>
Typebot gives you powerful blocks to create unique chat
experiences. Embed them anywhere on your web/mobile apps and start
collecting results like magic.
</Text>
<Stack
direction={['column-reverse', 'row']}
data-aos="fade-up"
data-aos-delay="200"
>
<Button
as={Link}
href="https://app.typebot.io/register"
colorScheme="orange"
size="lg"
height="4rem"
px="2rem"
>
Create a typebot for free
</Button>
</Stack>
</VStack>
<Box maxW="1200px" pos="relative">
<Box
pos="absolute"
left="-40px"
bgColor="orange.500"
boxSize={['150px', '150px', '300px', '600px']}
rounded="full"
filter="blur(40px)"
opacity="0.7"
className="animated-blob"
data-aos="fade"
data-aos-delay="1200"
/>
<Box
pos="absolute"
right="-40px"
bgColor="blue.500"
boxSize={['150px', '150px', '300px', '600px']}
rounded="full"
filter="blur(40px)"
opacity="0.7"
className="animated-blob animation-delay-5000"
data-aos="fade"
data-aos-delay="1200"
/>
<Box
as="figure"
shadow="lg"
data-aos="zoom-out-up"
data-aos-delay="800"
>
<Image
src={builderScreenshotSrc}
alt="Builder screenshot"
placeholder="blur"
style={{ borderRadius: '10px' }}
/>
</Box>
</Box>
</VStack>
</Stack>
<Flex justify="center" bgGradient="linear(to-b, gray.900, gray.800)">
<VStack spacing="12" pb="32" maxW="7xl" px={4}>
<Heading fontSize="25px" fontWeight="semibold" data-aos="fade">
Loved by teams and creators from all around the world
</Heading>
<SimpleGrid
columns={{ base: 2, md: 4 }}
color="gray.400"
alignItems="center"
spacing={12}
fontSize="4xl"
data-aos="fade"
>
<Logos.IbanFirst />
<Logos.Lemlist />
<Logos.MakerLead />
<Logos.Webisharp />
<Logos.SocialHackrs />
<Logos.PinpointInteractive />
<Logos.Obole />
<Logos.Awwwsome />
</SimpleGrid>
</VStack>
</Flex>
</Box>
)
}

View File

@ -0,0 +1 @@
export { Hero } from './Hero'

View File

@ -0,0 +1,121 @@
import { Flex, Heading, HStack, Stack, Text } from '@chakra-ui/react'
import {
GmailLogo,
MailChimpLogo,
NotionLogo,
WebflowLogo,
WordpressLogo,
SlackLogo,
AirtableLogo,
GoogleSheetLogo,
ZapierLogo,
SalesforceLogo,
CalendlyLogo,
GoogleCalendarLogo,
ShopifyLogo,
GoogleDriveLogo,
N8nLogo,
} from 'assets/logos'
import React from 'react'
const firstRowIcons = [
GmailLogo,
MailChimpLogo,
NotionLogo,
WebflowLogo,
WordpressLogo,
GoogleCalendarLogo,
N8nLogo,
GoogleDriveLogo,
]
const secondRowIcons = [
SlackLogo,
ShopifyLogo,
AirtableLogo,
GoogleSheetLogo,
ZapierLogo,
CalendlyLogo,
SalesforceLogo,
]
export const Integrations = () => (
<Flex as="section" justify="center">
<Stack w="full" align="center" spacing={12} pt={'52'}>
<Stack pos="relative" width="1400px" spacing={[4, 12]}>
<Flex
pos="absolute"
left="0"
w="33%"
h="full"
bgGradient="linear(to-r, rgba(23,25,35,1), rgba(23,25,35,0))"
pointerEvents="none"
zIndex={100}
/>
<Flex
pos="absolute"
right="0"
w="33%"
h="full"
bgGradient="linear(to-l, rgba(23,25,35,1), rgba(23,25,35,0))"
pointerEvents="none"
zIndex={100}
/>
<HStack w="full" spacing={[4, 16]}>
{firstRowIcons.map((Icon, idx) => (
<Flex
_hover={{ borderColor: 'gray.500' }}
transition="border 1s ease"
key={idx}
rounded="md"
p="8"
bgColor="gray.800"
boxSize="120px"
justifyContent="center"
align="center"
borderWidth="1px"
data-aos="fade"
data-aos-delay={idx * 200}
>
<Icon w="full" h="full" />
</Flex>
))}
</HStack>
<HStack w="full" spacing={[4, 16]} pl={['10', '20']}>
{secondRowIcons.map((Icon, idx) => (
<Flex
key={idx}
_hover={{ borderColor: 'gray.500' }}
transition="border 1s ease"
rounded="md"
p="8"
bgColor="gray.800"
boxSize="120px"
justifyContent="center"
align="center"
borderWidth="1px"
data-aos="fade"
data-aos-delay={(secondRowIcons.length - idx) * 200}
>
<Icon w="full" h="full" />
</Flex>
))}
</HStack>
</Stack>
<Stack w="full" maxWidth="1200px" px="4">
<Heading fontSize={['3xl', '4xl']} data-aos="fade-up">
Integrate with any platform
</Heading>
<Text
color="gray.400"
maxW="700px"
fontSize={['lg', 'xl']}
data-aos="fade-up"
>
Typebot offers several native integrations blocks as well as
instructions on how to embed typebot on particular platforms
</Text>
</Stack>
</Stack>
</Flex>
)

View File

@ -0,0 +1,143 @@
import {
Button,
Flex,
Heading,
Stack,
Text,
FormControl,
FormLabel,
Input,
Checkbox,
Textarea,
} from '@chakra-ui/react'
import React, { useEffect, useState } from 'react'
import { PublicTypebot } from '@typebot.io/schemas'
import { sendRequest } from '@typebot.io/lib'
import { DontIcon } from 'assets/icons/DontIcon'
import { DoIcon } from 'assets/icons/DoIcon'
import { HandDrawnArrow } from 'assets/illustrations/HandDrawnArrow'
import { Standard } from '@typebot.io/nextjs'
export const IntroducingChatApps = () => {
const [typebot, setTypebot] = useState<PublicTypebot>()
useEffect(() => {
fetchTemplate()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const fetchTemplate = async () => {
const { data, error } = await sendRequest(`/typebots/lead-gen-lp.json`)
if (error) return
setTypebot(data as PublicTypebot)
}
return (
<Flex as="section" justify="center">
<Stack
style={{ maxWidth: '1200px' }}
pt={32}
w="full"
px="4"
spacing={16}
justifyContent="space-between"
alignItems="center"
>
<Stack spacing={6} w="full">
<Heading
fontSize={{ base: '3xl', lg: '5xl', xl: '6xl' }}
textAlign="center"
data-aos="fade"
>
Replace your old school forms with chatbots
</Heading>
<Text
textAlign="center"
fontSize={{ base: 'lg', xl: 'xl' }}
color="gray.400"
data-aos="fade"
>
Typebot is a better way to ask for information. It leads to an
increase in customer satisfaction and retention and multiply by 3
your conversion rate compared to classical forms.
</Text>
</Stack>
<Stack
direction={['column', 'row']}
w="full"
spacing="6"
data-aos="fade"
>
<Stack spacing={6} flex="1" align={['flex-start', 'center']}>
<DontIcon />
<FakeLeadGenForm />
</Stack>
<Stack
spacing={6}
flex="1"
h="full"
pos="relative"
align={['flex-start', 'center']}
>
<DoIcon />
{typebot && (
<Standard
typebot={typebot}
style={{
borderRadius: '0.375rem',
borderWidth: '1px',
height: '562px',
}}
/>
)}
<Flex top="-20px" right="40px" pos="absolute">
<Text fontFamily="'Indie Flower'" fontSize="2xl">
Try it out!
</Text>
<HandDrawnArrow
transform="rotate(30deg)"
boxSize="100px"
top="15px"
right="-60px"
pos="absolute"
/>
</Flex>
</Stack>
</Stack>
</Stack>
</Flex>
)
}
const FakeLeadGenForm = () => (
<Stack borderWidth="1px" spacing="4" padding="6" rounded="md" w="full">
<FormControl isRequired>
<FormLabel htmlFor="full-name">Full name</FormLabel>
<Input id="full-name" placeholder="Full name" />
</FormControl>
<FormControl isRequired>
<FormLabel htmlFor="email">Email</FormLabel>
<Input id="email" placeholder="Email" />
</FormControl>
<FormControl isRequired>
<FormLabel htmlFor="services">
What services are you interested in?
</FormLabel>
<Stack>
<Checkbox>Website Dev</Checkbox>
<Checkbox>Content Marketing</Checkbox>
<Checkbox>Social Media</Checkbox>
<Checkbox>UX/UI Design</Checkbox>
</Stack>
</FormControl>
<FormControl isRequired>
<FormLabel htmlFor="info">Additional Information</FormLabel>
<Textarea id="info" placeholder="Additional Information" />
</FormControl>
<Flex>
<Button>Submit</Button>
</Flex>
</Stack>
)

View File

@ -0,0 +1,134 @@
import { Flex, Stack, Heading, Text, Button, VStack } from '@chakra-ui/react'
import { Standard } from '@typebot.io/nextjs'
import { ArrowRight } from 'assets/icons/ArrowRight'
import { HandDrawnArrow } from 'assets/illustrations/HandDrawnArrow'
import { PublicTypebot, Typebot } from '@typebot.io/schemas'
import Link from 'next/link'
import React, { useEffect, useRef, useState } from 'react'
import { sendRequest } from '@typebot.io/lib'
const nameBlockId = 'shuUtMDMw9P4iAHbz7B5SqJ'
const messageBlockId = 'sqvXpT1YXE3Htp6BCPvVGv3'
export const RealTimeResults = () => {
const iframeRef = useRef<HTMLIFrameElement | null>(null)
const [typebot, setTypebot] = useState<PublicTypebot>()
const fetchTemplate = async () => {
const { data, error } = await sendRequest(
`/typebots/realtime-airtable.json`
)
if (error) return
const typebot = data as Typebot
setTypebot({ ...typebot, typebotId: typebot.id } as PublicTypebot)
}
useEffect(() => {
fetchTemplate()
}, [])
const refreshIframeContent = () => {
if (!iframeRef.current) return
iframeRef.current.src += ''
}
const handleAnswer = ({ blockId }: { blockId: string }) => {
if ([nameBlockId, messageBlockId].includes(blockId))
setTimeout(refreshIframeContent, 1000)
}
return (
<Flex as="section" justify="center">
<Stack
style={{ maxWidth: '1200px' }}
pt={'52'}
w="full"
px="4"
spacing={16}
justifyContent="space-between"
alignItems="center"
>
<VStack spacing={6}>
<Heading
fontSize={{ base: '4xl', xl: '6xl' }}
textAlign="center"
data-aos="fade"
>
Collect results in real-time
</Heading>
<Text
textAlign="center"
color="gray.400"
maxW="1000px"
fontSize={{ base: 'lg', xl: 'xl' }}
data-aos="fade"
>
One of the main advantage of a chat application is that you collect
the user&apos;s responses on each question.{' '}
<strong>You won&apos;t lose any valuable data.</strong>
</Text>
<Flex>
<Button
as={Link}
rightIcon={<ArrowRight />}
href={`https://app.typebot.io/register`}
variant="ghost"
colorScheme="blue"
data-aos="fade"
>
Try it now
</Button>
</Flex>
</VStack>
<Stack
w="full"
direction={['column', 'row']}
spacing="4"
pos="relative"
data-aos="fade"
>
{typebot && (
<Standard
typebot="airtable-real-time"
onAnswer={handleAnswer}
style={{
borderRadius: '0.375rem',
borderWidth: '1px',
height: '533px',
}}
/>
)}
<iframe
ref={iframeRef}
src="https://airtable.com/embed/shr8nkV6DVN88LVIv?backgroundColor=blue"
width="100%"
height="533"
style={{
borderRadius: '0.5rem',
border: 'none',
backgroundColor: 'white',
}}
/>
<Flex
top="-60px"
right="-30px"
pos="absolute"
display={{ base: 'none', xl: 'flex' }}
>
<Text fontFamily="'Indie Flower'" fontSize="2xl">
It&apos;s a real Airtable view!
</Text>
<HandDrawnArrow
transform="rotate(30deg)"
boxSize="100px"
top="15px"
right="-60px"
pos="absolute"
/>
</Flex>
</Stack>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1,80 @@
import { Avatar, Flex, HStack, Stack, Text } from '@chakra-ui/react'
import * as React from 'react'
import Image from 'next/image'
import { TestimonialData } from './Testimonials'
import {
CapterraIcon,
EmailIcon,
ProductHuntIcon,
RedditIcon,
} from 'assets/icons'
export const Testimonial = ({
avatarSrc,
content,
name,
role,
provider,
}: TestimonialData) => (
<Stack
p="6"
rounded="lg"
bgColor="gray.800"
color="white"
shadow="lg"
spacing="4"
data-aos="fade"
>
<Flex justifyContent="space-between">
<HStack spacing="4">
{avatarSrc ? (
<Image
src={avatarSrc}
alt={name}
placeholder="blur"
width={40}
height={40}
className="rounded-full"
/>
) : (
<Avatar name={name} />
)}
<Stack spacing={1}>
<Text
as="cite"
fontStyle="normal"
fontWeight="extrabold"
color="white"
>
{name}
</Text>
<Text fontSize="sm" color={'gray.100'}>
{role}
</Text>
</Stack>
</HStack>
<ProviderIcon provider={provider} />
</Flex>
<Text mt="3" maxW="38rem" color="gray.400">
{content}
</Text>
</Stack>
)
const ProviderIcon = ({
provider,
}: {
provider: TestimonialData['provider']
}): JSX.Element => {
switch (provider) {
case 'email':
return <EmailIcon fontSize="20px" />
case 'productHunt':
return <ProductHuntIcon fontSize="20px" />
case 'capterra':
return <CapterraIcon fontSize="20px" />
case 'reddit':
return <RedditIcon fontSize="20px" />
}
}

View File

@ -0,0 +1,222 @@
import { Flex, Heading, SimpleGrid, Stack, VStack } from '@chakra-ui/react'
import * as React from 'react'
import joshuaPictureSrc from 'public/images/joshua.jpg'
import julienPictureSrc from 'public/images/julien.jpeg'
import nicolaiPictureSrc from 'public/images/nicolai.jpg'
import annaFilouPictureSrc from 'public/images/annaFilou.jpeg'
import theoPictureSrc from 'public/images/theo.jpeg'
import abhayPictureSrc from 'public/images/abhay.jpeg'
import lucasPictureSrc from 'public/images/lucas.png'
import oscarPictureSrc from 'public/images/oscar.jpeg'
import invictuzPictureSrc from 'public/images/invictuz.png'
import laszloPictureSrc from 'public/images/laszlo.jpeg'
import kurniaPictureSrc from 'public/images/kurnia.jpeg'
import stevePictureSrc from 'public/images/steve.jpg'
import { Testimonial } from './Testimonial'
import { StaticImageData } from 'next/image'
export type TestimonialData = {
name: string
avatarSrc?: StaticImageData
provider: 'email' | 'productHunt' | 'capterra' | 'reddit'
role?: string
content: string | React.ReactNode
}
const testimonials: TestimonialData[][] = [
[
{
name: 'Joshua Lim',
role: 'Growth Strategist @ Socialhackrs Media',
avatarSrc: joshuaPictureSrc,
provider: 'email',
content:
'I upgraded my typeforms to typebots and saw a conversion rate increase from 14% to 43% on my marketing campaigns. I noticed the improvement on day one. That was a game-changer.',
},
{
name: 'Laszlo Csömör',
role: 'Digital Marketing Expert',
provider: 'email',
avatarSrc: laszloPictureSrc,
content: (
<>
Typebot is one of the best chatbot builders with its intelligent
features and drag-and-drop simplicity. Its UI/UX is an earthly
paradise...
<br />
What&apos;s even more important is the person who stands behind it. He
guarantees that the platform will work and progress for a long time.
</>
),
},
{
name: 'Mario Barretta',
role: 'Customer Care Manager',
provider: 'email',
content: (
<>
Thanks to typebot I can finally make site forms much more modern and I
can collect information that I would have missed before. Also ,thanks
to Baptiste, the service is always evolving and has excellent
assistance not only in solving but also in listening to suggestions
and putting it into action.
<br />
<br />
Thank you thank you and thank you again .
</>
),
},
{
name: 'Lucas Barp',
provider: 'email',
avatarSrc: lucasPictureSrc,
role: 'Founder at Barp Digital',
content:
'The result of your work is incredible and can make life easier for many people.',
},
{
name: 'Igor T.',
role: 'CTO',
provider: 'capterra',
content:
'Nice work. The developer promptly makes changes, which is quite rare. There was a suggestion for improvement and improvement, in 2 days it was implemented. Amazing! Good luck and thanks a lot',
},
],
[
{
name: 'Oscar',
role: 'CEO',
provider: 'capterra',
avatarSrc: oscarPictureSrc,
content:
'Within 5 minutes of signing up you can already have your bot running thanks to the templates it comes with. I have used many tools to make bots but none as simple, easy and powerful as Typebot.',
},
{
name: 'Julien Muratot',
role: 'Growth Manager @ Hornetwork',
avatarSrc: julienPictureSrc,
provider: 'email',
content:
'I run Google ads all year long on our landing page that contains a typebot. I saw a 2x increase on our conversation rate compared to our old WordPress form.',
},
{
name: '_Invictuz',
provider: 'reddit',
avatarSrc: invictuzPictureSrc,
content:
"This is the sickest open-source project I've ever seen and demoed. The use case is so cool and modern and I can't believe how easy this is to get started using. The feature richness and polish in this project is incredible, it feel like a mature product. Unbelievable that this was built by one person. This is better than the demos of chatbot builders I've seen from full-fledged companies. I'm going to learn Typescript so that I can contribute to this someday. Mind-blowing stuff...",
},
{
name: 'Theo Marechal',
provider: 'productHunt',
avatarSrc: theoPictureSrc,
role: 'Nocode expert and content creator',
content: (
<>
Amazing product! I&apos;m using Typebot for everything when it&apos;s
about talking with customers.
<br />
<br />
What&apos;s amazing with Typebot is that it makes a &quot;chat
interface effect&quot; without the hassle of being behind my computer
all day responding to customers. Highly recommend !
</>
),
},
{
name: 'Abhay Kulkarni',
provider: 'productHunt',
avatarSrc: abhayPictureSrc,
role: 'Founder at Webisharp',
content:
'Using this tool for the last 2 hours & built a full lead capture bot. Pretty good experience till now. @baptiste_arnaud All the best for future :)',
},
],
[
{
name: 'Steve de Jong',
provider: 'email',
avatarSrc: stevePictureSrc,
role: 'CEO at Stillio',
content: (
<>
We built our own onboarding template last December for all signups for
Stillio and it works fantastic and reliably.
<br />
<br />
We send the collected data to a Make-com webhook and from there,
post-process and send to Encharge (email drip campaigns) and Pipedrive
(CRM).
<br />
We are now working on personalizing the email templates based on the
answers (user industry and role) given in the typebot. We are big fan!
</>
),
},
{
name: 'Goran Milic',
role: 'General Manager, Beefii',
provider: 'email',
content: (
<>
I used Typebot at my company and was impressed with how it cut our
customer service workload in half. I was able to create a fully
functional chatbot in minutes. <br /> You can create a bot to answer
frequently asked questions about your business or create a bot that
helps promote your business on social media or any other platform.,
</>
),
},
{
name: 'Kurnia Kwik',
role: 'Founder at DigitalPointer.ID',
provider: 'email',
avatarSrc: kurniaPictureSrc,
content: (
<>
I have several chatbot builders, but Typebot is the one I use the
most. It is simple to construct and very intuitive. <br />
Integration with third-party applications is simple, and you can
create the most sophisticated bots with its simplicity.
</>
),
},
{
name: 'Nicolai Grut',
role: 'CEO @ EcommerceNotebook.com',
avatarSrc: nicolaiPictureSrc,
provider: 'email',
content:
'I am really loving using Typebot! So good. I have used all the top bots and yours is definitely the most user friendly, and yet still so powerful.',
},
{
name: 'Anna Filou',
provider: 'productHunt',
avatarSrc: annaFilouPictureSrc,
role: 'Geek, Designer, Illustrator, Web Dev',
content:
"Seems like the product I've been waiting for Typeform to make! 😝",
},
],
]
export const Testimonials = () => {
return (
<Flex as="section" justify="center">
<VStack spacing={12} pt={'52'} px="4" maxW="1400px">
<Heading textAlign={'center'} data-aos="fade">
They&apos;ve tried, they never looked back. 💙
</Heading>
<SimpleGrid columns={[1, 2, 3]} spacing="6">
{testimonials.map((testimonialGroup, index) => (
<Stack key={index} spacing="6">
{testimonialGroup.map((testimonial, index) => (
<Testimonial key={index} {...testimonial} />
))}
</Stack>
))}
</SimpleGrid>
</VStack>
</Flex>
)
}

View File

@ -0,0 +1 @@
export { Testimonials } from './Testimonials'

View File

@ -0,0 +1,87 @@
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalCloseButton,
ModalBody,
Stack,
ModalFooter,
Heading,
Table,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr,
} from '@chakra-ui/react'
import { proChatTiers } from '@typebot.io/billing/constants'
import { formatPrice } from '@typebot.io/billing/helpers/formatPrice'
type Props = {
isOpen: boolean
onClose: () => void
}
export const ChatsProTiersModal = ({ isOpen, onClose }: Props) => {
return (
<Modal isOpen={isOpen} onClose={onClose} size="xl">
<ModalOverlay />
<ModalContent>
<ModalHeader>
<Heading size="lg">Chats pricing table</Heading>
</ModalHeader>
<ModalCloseButton />
<ModalBody as={Stack} spacing="6">
<TableContainer>
<Table variant="simple">
<Thead>
<Tr>
<Th isNumeric>Max chats</Th>
<Th isNumeric>Price per month</Th>
<Th isNumeric>Price per 1k chats</Th>
</Tr>
</Thead>
<Tbody>
{proChatTiers.map((tier, index) => {
const pricePerMonth =
(tier.flat_amount ??
proChatTiers.at(-2)?.flat_amount ??
0) / 100
return (
<Tr key={tier.up_to}>
<Td isNumeric>
{tier.up_to === 'inf'
? '2,000,000+'
: tier.up_to.toLocaleString()}
</Td>
<Td isNumeric>
{index === 0 ? 'included' : formatPrice(pricePerMonth)}
</Td>
<Td isNumeric>
{index === proChatTiers.length - 1
? formatPrice(4.42, { maxFractionDigits: 2 })
: index === 0
? 'included'
: formatPrice(
(((pricePerMonth * 100) /
((tier.up_to as number) -
(proChatTiers.at(0)?.up_to as number))) *
1000) /
100,
{ maxFractionDigits: 2 }
)}
</Td>
</Tr>
)
})}
</Tbody>
</Table>
</TableContainer>
</ModalBody>
<ModalFooter />
</ModalContent>
</Modal>
)
}

View File

@ -0,0 +1,57 @@
import {
Stack,
Heading,
Button,
List,
ListItem,
ListIcon,
Text,
Link,
} from '@chakra-ui/react'
import { CheckCircleIcon } from 'assets/icons'
export const EnterprisePlanCard = () => (
<Stack
direction={['column', 'row']}
align="center"
p="10"
rounded="lg"
bgColor="gray.800"
borderWidth="2px"
spacing={10}
>
<Stack maxW="300px" spacing={4}>
<Heading fontSize="xl">Enterprise</Heading>
<Text>
Ideal for large companies looking to generate leads and automate
customer support at scale
</Text>
<Text fontSize="lg">
<Button
as={Link}
href="https://typebot.io/enterprise-lead-form"
isExternal
variant="outline"
>
Get a quote
</Button>
</Text>
</Stack>
<Stack flex="1">
<List spacing="4">
<ListItem fontWeight="medium" display="flex" alignItems="center">
<ListIcon fontSize="xl" as={CheckCircleIcon} marginEnd={2} />
Custom chats limits & seats for all your team
</ListItem>
<ListItem fontWeight="medium" display="flex" alignItems="center">
<ListIcon fontSize="xl" as={CheckCircleIcon} marginEnd={2} />
SSO & Granular access rights
</ListItem>
<ListItem fontWeight="medium" display="flex" alignItems="center">
<ListIcon fontSize="xl" as={CheckCircleIcon} marginEnd={2} />
Yearly contract with dedicated support representative
</ListItem>
</List>
</Stack>
</Stack>
)

View File

@ -0,0 +1,74 @@
import { Heading, VStack, Stack, Text, Wrap, WrapItem } from '@chakra-ui/react'
export const Faq = () => (
<VStack w="full" spacing="10">
<Heading textAlign="center">Frequently asked questions</Heading>
<Wrap spacing={10}>
<WrapItem maxW="500px">
<Stack borderWidth={1} p="8" rounded="lg" spacing={4}>
<Heading as="h2" fontSize="2xl">
What is considered a monthly chat?
</Heading>
<Text>
A chat is counted whenever a user starts a discussion. It is
independant of the number of messages he sends and receives. For
example if a user starts a discussion and sends 10 messages to the
bot, it will count as 1 chat. If the user chats again later and its
session is remembered, it will not be counted as a new chat. <br />
<br />
An easy way to think about it: 1 chat equals to a row in your
Results table
</Text>
</Stack>
</WrapItem>
<WrapItem maxW="500px">
<Stack borderWidth={1} p="8" rounded="lg" spacing={4}>
<Heading as="h2" fontSize="2xl">
What happens once I reach the included chats limit?
</Heading>
<Text>
That&apos;s amazing, your bots are working full speed. 🚀
<br />
<br />
You will first receive a heads up email when you reach 80% of your
included limit. Once you have reached 100%, you will receive another
email notification.
<br />
<br />
After that, your chat limit be automatically upgraded to the next
tier.
</Text>
</Stack>
</WrapItem>
<WrapItem maxW="500px">
<Stack borderWidth={1} p="8" rounded="lg" spacing={4}>
<Heading as="h2" fontSize="2xl">
Can I cancel or change my subscription any time?
</Heading>
<Text>
Yes, you can cancel, upgrade or downgrade your subscription at any
time. There is no minimum time commitment or lock-in.
<br />
<br />
When you upgrade or downgrade your subscription, you&apos;ll get
access to the new options right away. Your next invoice will have a
prorated amount.
</Text>
</Stack>
</WrapItem>
<WrapItem maxW="500px">
<Stack borderWidth={1} p="8" rounded="lg" spacing={4}>
<Heading as="h2" fontSize="2xl">
Do you offer annual payments?
</Heading>
<Text>
No, because subscriptions pricing is based on chats usage, we can
only offer monthly plans.
</Text>
</Stack>
</WrapItem>
</Wrap>
</VStack>
)

View File

@ -0,0 +1,53 @@
import { chakra, Tooltip, Text, Button } from '@chakra-ui/react'
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
import Link from 'next/link'
import React from 'react'
import { PricingCard } from './PricingCard'
import { chatsLimits } from '@typebot.io/billing/constants'
export const FreePlanCard = () => (
<PricingCard
data={{
price: 'Free',
name: 'Personal',
features: [
'Unlimited typebots',
<>
<Text>
<chakra.span fontWeight="bold">{chatsLimits.FREE}</chakra.span>{' '}
chats/month
</Text>
&nbsp;
<Tooltip
hasArrow
placement="top"
label="A chat is counted whenever a user starts a discussion. It is
independant of the number of messages he sends and receives."
>
<chakra.span cursor="pointer" h="7">
<HelpCircleIcon />
</chakra.span>
</Tooltip>
</>,
'Native integrations',
'Webhooks',
'Custom Javascript & CSS',
'Community support & Docs',
],
}}
button={
<Button
as={Link}
href="https://app.typebot.io/register"
variant="outline"
colorScheme="gray"
size="lg"
w="full"
fontWeight="extrabold"
py={{ md: '8' }}
>
Get started
</Button>
}
/>
)

View File

@ -0,0 +1,418 @@
import {
TableContainer,
Table,
Thead,
Tr,
Th,
Tbody,
Td,
Text,
Stack,
HStack,
Tooltip,
chakra,
Button,
Heading,
} from '@chakra-ui/react'
import { CheckIcon } from 'assets/icons/CheckIcon'
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
import { Plan } from '@typebot.io/prisma'
import Link from 'next/link'
import React from 'react'
import { parseNumberWithCommas } from '@typebot.io/lib'
import { chatsLimits, prices, seatsLimits } from '@typebot.io/billing/constants'
import { formatPrice } from '@typebot.io/billing/helpers/formatPrice'
type Props = {
onChatsTiersClick: () => void
}
export const PlanComparisonTables = ({ onChatsTiersClick }: Props) => (
<Stack spacing="12">
<TableContainer>
<Table>
<Thead>
<Tr>
<Th fontWeight="bold" color="white" w="400px">
Usage
</Th>
<Th>Free</Th>
<Th color="orange.200">Starter</Th>
<Th color="blue.200">Pro</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Total bots</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
</Tr>
<Tr>
<Td>Chats</Td>
<Td>{chatsLimits.FREE} / month</Td>
<Td>{parseNumberWithCommas(chatsLimits.STARTER)} / month</Td>
<Td>{parseNumberWithCommas(chatsLimits.PRO)} / month</Td>
</Tr>
<Tr>
<Td>Additional Chats</Td>
<Td />
<Td>{formatPrice(10)} per 500 chats</Td>
<Td>
<Button
variant="outline"
size="xs"
onClick={onChatsTiersClick}
colorScheme="gray"
>
See tiers
</Button>
</Td>
</Tr>
<Tr>
<Td>Storage</Td>
<Td />
<Td>2 GB</Td>
<Td>10 GB</Td>
</Tr>
<Tr>
<Td>Members</Td>
<Td>Just you</Td>
<Td>{seatsLimits.STARTER} seats</Td>
<Td>{seatsLimits.PRO} seats</Td>
</Tr>
<Tr>
<Td>Guests</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
</Tr>
</Tbody>
</Table>
</TableContainer>
<TableContainer>
<Table>
<Thead>
<Tr>
<Th fontWeight="bold" color="white" w="400px">
Features
</Th>
<Th>Free</Th>
<Th color="orange.200">Starter</Th>
<Th color="blue.200">Pro</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<TdWithTooltip
text="20+ blocks"
tooltip="Includes display bubbles (text, image, video, embed), question inputs (email, url, phone number...) and logic blocks (conditions, set variables...)"
/>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Starter templates</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Webhooks</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Google Sheets</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Google Analytics</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Send emails</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Zapier</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Pabbly Connect</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Make.com</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Custom Javascript & CSS</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Export CSV</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>File upload inputs</Td>
<Td />
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<TdWithTooltip
text="Folders"
tooltip="Organize your typebots into folders"
/>
<Td />
<Td>Unlimited</Td>
<Td>Unlimited</Td>
</Tr>
<Tr>
<Td>Remove branding</Td>
<Td />
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>WhatsApp integration</Td>
<Td />
<Td />
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Custom domains</Td>
<Td />
<Td />
<Td>Unlimited</Td>
</Tr>
<Tr>
<TdWithTooltip
text="In-depth analytics"
tooltip="Analytics graph that shows your form drop-off rate, submission rate, and more."
/>
<Td />
<Td />
<Td>
<CheckIcon />
</Td>
</Tr>
</Tbody>
</Table>
</TableContainer>
<TableContainer>
<Table>
<Thead>
<Tr>
<Th fontWeight="bold" color="white" w="400px">
Support
</Th>
<Th>Free</Th>
<Th color="orange.200">Starter</Th>
<Th color="blue.200">Pro</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Community support</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Direct support channel</Td>
<Td />
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Priority support</Td>
<Td />
<Td />
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Feature request priority</Td>
<Td />
<Td />
<Td>
<CheckIcon />
</Td>
</Tr>
</Tbody>
</Table>
</TableContainer>
<Stack
direction={['column', 'row']}
spacing={4}
w="full"
justify="space-around"
>
<Stack spacing={4}>
<Heading as="h3" size="md">
Personal
</Heading>
<Heading as="h3">Free</Heading>
<Link href="https://app.typebot.io/register">
<Button variant="outline" colorScheme="gray">
Get started
</Button>
</Link>
</Stack>
<Stack spacing={4}>
<Heading as="h3" size="md" color="orange.200">
Starter
</Heading>
<Heading as="h3">
{formatPrice(prices.STARTER)}{' '}
<chakra.span fontSize="lg">/ month</chakra.span>
</Heading>
<Link
href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}`}
>
<Button variant="outline" colorScheme="orange">
Subscribe
</Button>
</Link>
</Stack>
<Stack spacing={4}>
<Heading as="h3" size="md" color="blue.200">
Pro
</Heading>
<Heading as="h3">
{formatPrice(prices.PRO)}{' '}
<chakra.span fontSize="lg">/ month</chakra.span>
</Heading>
<Link
href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}`}
>
<Button>Subscribe</Button>
</Link>
</Stack>
</Stack>
</Stack>
)
const TdWithTooltip = ({
text,
tooltip,
}: {
text: string
tooltip: string
}) => (
<HStack as={Td}>
<Text>{text}</Text>
<Tooltip hasArrow placement="top" label={tooltip}>
<chakra.span cursor="pointer">
<HelpCircleIcon />
</chakra.span>
</Tooltip>
</HStack>
)

View File

@ -0,0 +1,27 @@
import { Box, BoxProps, useColorModeValue } from '@chakra-ui/react'
import * as React from 'react'
import { CardBadge } from './CardBadge'
export interface CardProps extends BoxProps {
isPopular?: boolean
}
export const Card = (props: CardProps) => {
const { children, isPopular, ...rest } = props
return (
<Box
bg={useColorModeValue('white', 'gray.700')}
position="relative"
px="6"
py="6"
overflow="hidden"
shadow="lg"
maxW="md"
width="100%"
{...rest}
>
{isPopular && <CardBadge>Popular</CardBadge>}
{children}
</Box>
)
}

View File

@ -0,0 +1,30 @@
import { Flex, FlexProps, Text, useColorModeValue } from '@chakra-ui/react'
import * as React from 'react'
export const CardBadge = (props: FlexProps) => {
const { children, ...flexProps } = props
return (
<Flex
bg={useColorModeValue('green.500', 'green.200')}
position="absolute"
right={-20}
top={6}
width="240px"
transform="rotate(45deg)"
py={2}
justifyContent="center"
alignItems="center"
{...flexProps}
>
<Text
fontSize="xs"
textTransform="uppercase"
fontWeight="bold"
letterSpacing="wider"
color={useColorModeValue('white', 'gray.800')}
>
{children}
</Text>
</Flex>
)
}

View File

@ -0,0 +1,94 @@
import {
Flex,
Heading,
List,
ListIcon,
ListItem,
Text,
useColorModeValue,
VStack,
} from '@chakra-ui/react'
import * as React from 'react'
import { CheckCircleIcon } from '../../../assets/icons/CheckCircleIcon'
import { Card, CardProps } from './Card'
import { formatPrice } from '@typebot.io/billing/helpers/formatPrice'
export interface PricingCardData {
features: React.ReactNode[]
name: string
price: number | string
featureLabel?: string
}
interface PricingCardProps extends CardProps {
data: PricingCardData
icon?: JSX.Element
button: React.ReactElement
}
export const PricingCard = ({
data,
icon,
button,
...rest
}: PricingCardProps) => {
const { features, price, name } = data
const accentColor = useColorModeValue('blue.500', 'white')
const formattedPrice = typeof price === 'number' ? formatPrice(price) : price
return (
<Card rounded="xl" bgColor="gray.800" {...rest}>
<Flex justifyContent="space-between" flexDir="column" h="full">
<Flex flexDir="column">
<VStack spacing={6}>
{icon}
<Heading size="md" fontWeight="extrabold" color={rest.borderColor}>
{name}
</Heading>
</VStack>
<Flex
align="flex-end"
justify="center"
fontWeight="extrabold"
color={accentColor}
my="8"
>
<Heading size="2xl" fontWeight="inherit" lineHeight="0.9em">
{formattedPrice}
</Heading>
{typeof price === 'number' && (
<Text fontWeight="inherit" fontSize="xl">
/ month
</Text>
)}
</Flex>
<List spacing="4" mb="8" maxW="30ch" mx="auto">
{data.featureLabel && (
<Text fontWeight="bold">{data.featureLabel}</Text>
)}
{features.map((feature, index) => (
<ListItem
fontWeight="medium"
key={index}
display="flex"
alignItems="center"
>
<ListIcon
fontSize="xl"
as={CheckCircleIcon}
marginEnd={2}
color={accentColor}
fill={rest.borderColor}
/>
{feature}
</ListItem>
))}
</List>
</Flex>
{button}
</Flex>
</Card>
)
}

View File

@ -0,0 +1,78 @@
import {
chakra,
Tooltip,
Text,
Button,
HStack,
Stack,
Link,
} from '@chakra-ui/react'
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
import { Plan } from '@typebot.io/prisma'
import React from 'react'
import { PricingCard } from './PricingCard'
import { prices, seatsLimits } from '@typebot.io/billing/constants'
type Props = {
onChatsTiersClick: () => void
}
export const ProPlanCard = ({ onChatsTiersClick }: Props) => (
<PricingCard
data={{
price: prices.PRO,
name: 'Pro',
featureLabel: 'Everything in Personal, plus:',
features: [
<Text key="seats">
<chakra.span fontWeight="bold">{seatsLimits.PRO} seats</chakra.span>{' '}
included
</Text>,
<Stack key="chats" spacing={0}>
<HStack spacing={1.5}>
<Text>10,000 chats/mo</Text>
<Tooltip
hasArrow
placement="top"
label="A chat is counted whenever a user starts a discussion. It is
independant of the number of messages he sends and receives."
>
<chakra.span cursor="pointer" h="7">
<HelpCircleIcon />
</chakra.span>
</Tooltip>
</HStack>
<Text fontSize="sm" color="gray.400">
Extra chats:{' '}
<Button
variant="outline"
size="xs"
colorScheme="gray"
onClick={onChatsTiersClick}
>
See tiers
</Button>
</Text>
</Stack>,
'WhatsApp integration',
'Custom domains',
'In-depth analytics',
],
}}
borderWidth="3px"
borderColor="blue.200"
button={
<Button
as={Link}
href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}`}
colorScheme="blue"
size="lg"
w="full"
fontWeight="extrabold"
py={{ md: '8' }}
>
Subscribe now
</Button>
}
/>
)

View File

@ -0,0 +1,65 @@
import { chakra, Tooltip, Text, HStack, Button, Stack } from '@chakra-ui/react'
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
import { Plan } from '@typebot.io/prisma'
import Link from 'next/link'
import React from 'react'
import { PricingCard } from './PricingCard'
import { prices, seatsLimits } from '@typebot.io/billing/constants'
export const StarterPlanCard = () => {
return (
<PricingCard
data={{
price: prices.STARTER,
name: 'Starter',
featureLabel: 'Everything in Personal, plus:',
features: [
<Text key="seats">
<chakra.span fontWeight="bold">
{seatsLimits.STARTER} seats
</chakra.span>{' '}
included
</Text>,
<Stack key="chats" spacing={0}>
<HStack spacing={1.5}>
<Text>2,000 chats/mo</Text>
<Tooltip
hasArrow
placement="top"
label="A chat is counted whenever a user starts a discussion. It is
independant of the number of messages he sends and receives."
>
<chakra.span cursor="pointer" h="7">
<HelpCircleIcon />
</chakra.span>
</Tooltip>
</HStack>
<Text fontSize="sm" color="gray.400">
Extra chats: $10 per 500
</Text>
</Stack>,
'Branding removed',
'Collect files from users',
'Create folders',
'Direct priority support',
],
}}
borderWidth="1px"
borderColor="orange.200"
button={
<Button
as={Link}
href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}`}
colorScheme="orange"
size="lg"
w="full"
fontWeight="extrabold"
py={{ md: '8' }}
variant="outline"
>
Subscribe now
</Button>
}
/>
)
}

View File

@ -0,0 +1,21 @@
import { VStack, Heading, Button, Text } from '@chakra-ui/react'
import React from 'react'
export const ArticleCallToAction = () => (
<VStack spacing={6}>
<Heading fontSize="xx-large">
Collect up to 4x more responses without 4x the work.
</Heading>
<Button
size="lg"
colorScheme="orange"
as="a"
href="https://app.typebot.io/register"
>
Create a typebot
</Button>
<Text fontSize="sm" fontStyle="italic" color="gray.600">
It&apos;s free!
</Text>
</VStack>
)

View File

@ -0,0 +1,92 @@
'use client'
import React, { ReactNode } from 'react'
import {
Box,
Container,
Heading,
HStack,
SimpleGrid,
Stack,
Text,
} from '@chakra-ui/react'
import { Logo } from 'assets/icons/Logo'
import { TextLink } from './TextLink'
const discordServerUrl = 'https://typebot.io/discord'
const typebotLinkedInUrl = 'https://www.linkedin.com/company/typebot'
const typebotTwitterUrl = 'https://twitter.com/Typebot_io'
const baptisteTwitterUrl = 'https://twitter.com/baptisteArno'
const statusPageUrl = 'https://status.typebot.io'
export const contactUrl = 'https://bot.typebot.io/landing-page-bubble-en'
export const roadmapLink = 'https://app.typebot.io/feedback'
export const documentationLink = 'https://docs.typebot.io'
export const githubRepoLink = 'https://github.com/baptisteArno/typebot.io'
export const Footer = () => {
return (
<Box w="full">
<Container as={Stack} maxW={'1000px'} py={10}>
<SimpleGrid columns={[1, 2, 4]} spacing={8} px={2}>
<Stack spacing={6}>
<HStack>
<Logo boxSize="30px" />
<Heading as="p" fontSize="lg">
Typebot
</Heading>
</HStack>
<Text>
Made with by{' '}
<TextLink href={baptisteTwitterUrl}>@baptisteArno</TextLink>
</Text>
</Stack>
<Stack align={'flex-start'}>
<ListHeader>Product</ListHeader>
<TextLink href={statusPageUrl} isExternal>
Status
</TextLink>
<TextLink href={documentationLink} isExternal>
Documentation
</TextLink>
<TextLink href={roadmapLink} isExternal>
Roadmap
</TextLink>
<TextLink href={'/pricing'}>Pricing</TextLink>
</Stack>
<Stack align={'flex-start'}>
<ListHeader>Community</ListHeader>
<TextLink href={discordServerUrl} isExternal>
Discord
</TextLink>
<TextLink href={githubRepoLink} isExternal>
GitHub repository
</TextLink>
<TextLink href={typebotTwitterUrl} isExternal>
Twitter
</TextLink>
<TextLink href={typebotLinkedInUrl} isExternal>
LinkedIn
</TextLink>
<TextLink href="/oss-friends">OSS Friends</TextLink>
</Stack>
<Stack align={'flex-start'}>
<ListHeader>Company</ListHeader>
<TextLink href="/about">About</TextLink>
<TextLink href="mailto:support@typebot.io">Contact</TextLink>
<TextLink href={'/terms-of-service'}>Terms of Service</TextLink>
<TextLink href={'/privacy-policies'}>Privacy Policy</TextLink>
</Stack>
</SimpleGrid>
</Container>
</Box>
)
}
const ListHeader = ({ children }: { children: ReactNode }) => {
return (
<Heading fontWeight={'500'} fontSize={'lg'} mb={2}>
{children}
</Heading>
)
}

View File

@ -0,0 +1,111 @@
'use client'
import {
Button,
Flex,
Heading,
HStack,
IconButton,
useColorModeValue as mode,
useDisclosure,
Box,
Link,
} from '@chakra-ui/react'
import { HamburgerIcon } from 'assets/icons'
import { ChevronDownIcon } from 'assets/icons/ChevronDownIcon'
import { CloseIcon } from 'assets/icons/CloseIcon'
import { Logo } from 'assets/icons/Logo'
import * as React from 'react'
import { MobileMenu } from './MobileMenu'
import { ResourcesMenu } from './ResourcesMenu'
export const Header = () => {
const { isOpen, onToggle } = useDisclosure()
const { isOpen: isMobileMenuOpen, onToggle: onMobileMenuToggle } =
useDisclosure()
return (
<Flex pos="relative" zIndex={10} w="full">
<HStack
as="header"
aria-label="Main navigation"
maxW="7xl"
w="full"
mx="auto"
px={{ base: '6', md: '8' }}
py="4"
justify="space-between"
>
<Flex
align="center"
justify="space-between"
className="nav-content__mobile"
color={mode('white', 'white')}
>
<HStack as={Link} href="/" rel="home" ml="2">
<Logo boxSize="35px" />
<Heading as="p" fontSize="lg">
Typebot
</Heading>
</HStack>
</Flex>
<Box display={['block', 'block', 'none']}>
<IconButton
aria-label={'Open menu'}
icon={
isMobileMenuOpen ? (
<CloseIcon boxSize="20px" />
) : (
<HamburgerIcon boxSize="20px" />
)
}
variant="ghost"
colorScheme="gray"
onClick={onMobileMenuToggle}
/>
<MobileMenu isOpen={isMobileMenuOpen} />
</Box>
<HStack as="nav" spacing={4} display={['none', 'none', 'flex']}>
<Flex>
<Button
rightIcon={<ChevronDownIcon />}
onClick={onToggle}
variant="ghost"
colorScheme="gray"
fontWeight={700}
>
Resources
</Button>
<ResourcesMenu isOpen={isOpen} />
</Flex>
<Button
as={Link}
href="/pricing"
variant="ghost"
colorScheme="gray"
fontWeight={700}
>
Pricing
</Button>
<Button
as={Link}
href="https://app.typebot.io/signin"
colorScheme="blue"
variant="outline"
fontWeight={700}
>
Sign in
</Button>
<Button
as={Link}
href="https://app.typebot.io/register"
colorScheme="orange"
fontWeight={700}
>
Create a typebot
</Button>
</HStack>
</HStack>
</Flex>
)
}

View File

@ -0,0 +1,59 @@
import { Collapse, Stack, Button, Text } from '@chakra-ui/react'
import Link from 'next/link'
import { links } from './_data'
type Props = { isOpen: boolean }
export const MobileMenu = ({ isOpen }: Props) => (
<Collapse in={isOpen}>
<Stack
pos="absolute"
insetX={0}
bgGradient="linear(to-b, gray.900, gray.800)"
px="6"
py="10"
spacing={4}
>
<Button
as={Link}
href="https://app.typebot.io/signin"
colorScheme="blue"
variant="outline"
fontWeight={700}
>
Sign in
</Button>
<Button
as={Link}
href="https://app.typebot.io/register"
colorScheme="orange"
fontWeight={700}
>
Create a typebot
</Button>
<Button
as={Link}
href="/pricing"
variant="outline"
colorScheme="gray"
fontWeight={700}
>
Pricing
</Button>
<Text fontWeight="700">Resources:</Text>
{links[0].children?.map((link, idx) => (
<Button
as={Link}
href={link.href}
key={idx}
variant="outline"
colorScheme="gray"
fontWeight={700}
py="6"
>
{link.label}
</Button>
))}
</Stack>
</Collapse>
)

View File

@ -0,0 +1,92 @@
import {
Box,
Center,
Collapse,
HStack,
SimpleGrid,
Text,
useColorModeValue as mode,
} from '@chakra-ui/react'
import { ChevronRightIcon } from 'assets/icons/ChevronRightIcon'
import Link from 'next/link'
import * as React from 'react'
import { links } from './_data'
type Props = { isOpen: boolean }
export const ResourcesMenu = ({ isOpen }: Props) => (
<Collapse in={isOpen} animateOpacity unmountOnExit={false}>
<Box
w="full"
shadow="lg"
pos="absolute"
insetX={0}
top="16"
py="12"
px="4"
bgGradient="linear(to-b, gray.900, gray.800)"
>
<Box maxW="7xl" mx="auto" px="8">
<SimpleGrid spacing="10" columns={2}>
{links[0].children?.map((item, idx) => (
<Box
as={Link}
key={idx}
className="group"
href={item.href}
m="-3"
p="3"
display="flex"
alignItems="flex-start"
transition="all 0.2s"
rounded="lg"
_hover={{ bg: mode('gray.50', 'gray.600') }}
_focus={{ shadow: 'outline' }}
target={
item.href.startsWith('https') &&
!item.href.includes('app.typebot.io')
? '_blank'
: undefined
}
>
<Center
aria-hidden
as="span"
flexShrink={0}
w="10"
h="10"
fontSize="3xl"
color={'blue.300'}
>
{item.icon}
</Center>
<Box marginStart="3" as="dl">
<HStack as="dt">
<Text
fontWeight="semibold"
color={mode('gray.900', 'white')}
_groupHover={{ color: mode('blue.600', 'inherit') }}
>
{item.label}
</Text>
<Box
fontSize="xs"
as={ChevronRightIcon}
transition="all 0.2s"
_groupHover={{
color: mode('blue.600', 'inherit'),
transform: 'translateX(2px)',
}}
/>
</HStack>
<Text as="dd" color={mode('gray.500', 'gray.400')}>
{item.description}
</Text>
</Box>
</Box>
))}
</SimpleGrid>
</Box>
</Box>
</Collapse>
)

View File

@ -0,0 +1,41 @@
import { GitHubIcon } from 'assets/icons'
import { DocIcon } from 'assets/icons/DocIcon'
import { MapIcon } from 'assets/icons/MapIcon'
import { PeopleCircleIcon } from 'assets/icons/PeopleCircleIcon'
import * as React from 'react'
export const links = [
{
label: 'Resources',
children: [
{
label: 'GitHub repository',
description: 'Check out the entire source code of the project',
href: 'https://github.com/baptisteArno/typebot.io',
icon: <GitHubIcon fill="blue.300" />,
},
{
label: 'Documentation',
description:
"Everything you need to know about how to use Typebot's builder",
href: 'https://docs.typebot.io',
icon: <DocIcon />,
},
{
label: 'Roadmap',
description:
"Follow the development and make suggestions for which features you'd like to see",
href: 'https://feedback.typebot.io/roadmap',
icon: <MapIcon />,
},
{
label: 'Community',
description:
'Join the Discord server and learn about chatbots best practices and get help from the community',
href: '/discord',
icon: <PeopleCircleIcon />,
},
],
},
{ label: 'Pricing', href: '/pricing' },
]

View File

@ -0,0 +1,36 @@
import Head from 'next/head'
import React from 'react'
export const SocialMetaTags = ({
title = 'Typebot - Open-source conversational apps builder',
description = 'Powerful blocks to create unique chat experiences. Embed them anywhere on your apps and start collecting results like magic.',
currentUrl,
imagePreviewUrl = 'https://home.typebot.io/images/preview.png',
}: {
title?: string
description?: string
currentUrl: string
imagePreviewUrl?: string
}) => (
<Head>
<title>{title}</title>
<meta name="title" content={title} />
<meta property="og:title" content={title} />
<meta property="twitter:title" content={title} />
<meta property="twitter:url" content={currentUrl} />
<meta property="og:url" content={currentUrl} />
<meta name="description" content={description} />
<meta property="twitter:description" content={description} />
<meta property="og:description" content={description} />
<meta property="og:image" content={imagePreviewUrl} />
<meta property="twitter:image" content={imagePreviewUrl} />
<meta property="og:type" content="website" />
<meta property="twitter:card" content="summary_large_image" />
<meta property="fb:app_id" content="2919783058077552" />
</Head>
)

View File

@ -0,0 +1,26 @@
import { CheckCircleIcon } from 'assets/icons/CheckCircleIcon'
import { CloseIcon } from 'assets/icons/CloseIcon'
import { Td, Text } from '@chakra-ui/react'
import React, { ReactNode } from 'react'
export const Yes = (props: { children?: ReactNode }) => (
<Td display={props.children ? 'flex' : ''}>
<CheckCircleIcon fill="#0042da" width="25px" />
{props.children && (
<Text ml={1} fontSize="sm">
{props.children}
</Text>
)}
</Td>
)
export const No = (props: { children?: ReactNode }) => (
<Td display={props.children ? 'flex' : ''}>
<CloseIcon width="25px" />
{props.children && (
<Text ml={1} fontSize="sm">
{props.children}
</Text>
)}
</Td>
)

View File

@ -0,0 +1,37 @@
import Link, { LinkProps } from 'next/link'
import React from 'react'
import { chakra, HStack, TextProps } from '@chakra-ui/react'
import { ExternalLinkIcon } from 'assets/icons/ExternalLinkIcon'
type TextLinkProps = LinkProps & TextProps & { isExternal?: boolean }
export const TextLink = ({
children,
href,
shallow,
replace,
scroll,
prefetch,
isExternal,
...textProps
}: TextLinkProps) => (
<Link
href={href}
shallow={shallow}
replace={replace}
scroll={scroll}
prefetch={prefetch}
target={isExternal ? '_blank' : undefined}
>
<chakra.span textDecor="underline" display="inline-block" {...textProps}>
{isExternal ? (
<HStack as="span" spacing={1}>
<chakra.span>{children}</chakra.span>
<ExternalLinkIcon />
</HStack>
) : (
children
)}
</chakra.span>
</Link>
)