2
0

chore(lp): 📦️ Import existing Landing page

This commit is contained in:
Baptiste Arnaud
2022-02-09 18:40:40 +01:00
parent 65b30bfc48
commit 36be3577e1
136 changed files with 14867 additions and 20 deletions

View File

@ -18,5 +18,5 @@
"composite": true "composite": true
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules", "cypress"] "exclude": ["node_modules"]
} }

View File

@ -0,0 +1,32 @@
module.exports = {
ignorePatterns: ['node_modules'],
env: {
browser: true,
es6: true,
},
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'next/core-web-vitals',
'prettier',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports
ecmaFeatures: {
jsx: true, // Allows for the parsing of JSX
},
},
settings: {
react: {
version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use
},
},
plugins: ['prettier', 'react', '@typescript-eslint'],
rules: {
'react/no-unescaped-entities': [0],
'prettier/prettier': 'error',
'react/display-name': [0],
},
}

38
apps/landing-page/.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
.env*
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.blog_index_data
.blog_index_data_previews
.now
.vercel
.yarn/*
!.yarn/releases
!.yarn/plugins
.pnp.*
.yalc
yalc.lock

19
apps/landing-page/LICENSE Normal file
View File

@ -0,0 +1,19 @@
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,3 @@
# Typebot.io
This repository contains the source code of [Typebot's landing page](https://www.typebot.io)

View File

@ -0,0 +1,15 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const AccessibilityIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Accessibility</title>
<path d="M256 112a56 56 0 1156-56 56.06 56.06 0 01-56 56z" />
<path d="M432 112.8l-.45.12-.42.13c-1 .28-2 .58-3 .89-18.61 5.46-108.93 30.92-172.56 30.92-59.13 0-141.28-22-167.56-29.47a73.79 73.79 0 00-8-2.58c-19-5-32 14.3-32 31.94 0 17.47 15.7 25.79 31.55 31.76v.28l95.22 29.74c9.73 3.73 12.33 7.54 13.6 10.84 4.13 10.59.83 31.56-.34 38.88l-5.8 45-32.19 176.19q-.15.72-.27 1.47l-.23 1.27c-2.32 16.15 9.54 31.82 32 31.82 19.6 0 28.25-13.53 32-31.94s28-157.57 42-157.57 42.84 157.57 42.84 157.57c3.75 18.41 12.4 31.94 32 31.94 22.52 0 34.38-15.74 32-31.94a57.17 57.17 0 00-.76-4.06L329 301.27l-5.79-45c-4.19-26.21-.82-34.87.32-36.9a1.09 1.09 0 00.08-.15c1.08-2 6-6.48 17.48-10.79l89.28-31.21a16.9 16.9 0 001.62-.52c16-6 32-14.3 32-31.93S451 107.81 432 112.8z" />
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const AlbumsIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Albums</title>
<path d="M368 96H144a16 16 0 010-32h224a16 16 0 010 32zM400 144H112a16 16 0 010-32h288a16 16 0 010 32zM419.13 448H92.87A44.92 44.92 0 0148 403.13V204.87A44.92 44.92 0 0192.87 160h326.26A44.92 44.92 0 01464 204.87v198.26A44.92 44.92 0 01419.13 448z" />
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const AnalyticsIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Analytics</title>
<path d="M456 128a40 40 0 00-37.23 54.6l-84.17 84.17a39.86 39.86 0 00-29.2 0l-60.17-60.17a40 40 0 10-74.46 0L70.6 306.77a40 40 0 1022.63 22.63L193.4 229.23a39.86 39.86 0 0029.2 0l60.17 60.17a40 40 0 1074.46 0l84.17-84.17A40 40 0 10456 128z" />
</Icon>
);

View File

@ -0,0 +1,12 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const BookIcon = (props: IconProps) => (
<Icon xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" {...props}>
<title>Book</title>
<path
d="M202.24 74C166.11 56.75 115.61 48.3 48 48a31.36 31.36 0 00-17.92 5.33A32 32 0 0016 79.9V366c0 19.34 13.76 33.93 32 33.93 71.07 0 142.36 6.64 185.06 47a4.11 4.11 0 006.94-3V106.82a15.89 15.89 0 00-5.46-12A143 143 0 00202.24 74zM481.92 53.3A31.33 31.33 0 00464 48c-67.61.3-118.11 8.71-154.24 26a143.31 143.31 0 00-32.31 20.78 15.93 15.93 0 00-5.45 12v337.13a3.93 3.93 0 006.68 2.81c25.67-25.5 70.72-46.82 185.36-46.81a32 32 0 0032-32v-288a32 32 0 00-14.12-26.61z"
fill="currentColor"
/>
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const BuildIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Build</title>
<path d="M469.54 120.52a16 16 0 00-25.54-4L382.56 178a16.12 16.12 0 01-22.63 0l-26.56-26.6a16 16 0 010-22.63l61.18-61.19a16 16 0 00-4.78-25.92C343.56 21 285.88 31.78 249.51 67.88c-30.9 30.68-40.11 78.62-25.25 131.53a15.89 15.89 0 01-4.49 16L53.29 367.46a64.17 64.17 0 1090.6 90.64l153.68-166.85a15.9 15.9 0 0115.77-4.57 179.3 179.3 0 0046.22 6.37c33.4 0 62.71-10.81 83.85-31.64 39.15-38.57 45.12-103.99 26.13-140.89zM99.48 447.15a32 32 0 1128.34-28.35 32 32 0 01-28.34 28.35z" />
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const CalculatorIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Calculator</title>
<path d="M416 80a48.05 48.05 0 00-48-48H144a48.05 48.05 0 00-48 48v352a48.05 48.05 0 0048 48h224a48.05 48.05 0 0048-48zM168 432a24 24 0 1124-24 24 24 0 01-24 24zm0-80a24 24 0 1124-24 24 24 0 01-24 24zm0-80a24 24 0 1124-24 24 24 0 01-24 24zm88 160a24 24 0 1124-24 24 24 0 01-24 24zm0-80a24 24 0 1124-24 24 24 0 01-24 24zm0-80a24 24 0 1124-24 24 24 0 01-24 24zm112 136a24 24 0 01-48 0v-80a24 24 0 0148 0zm-24-136a24 24 0 1124-24 24 24 0 01-24 24zm19.31-100.69A16 16 0 01352 176H160a16 16 0 01-16-16V96a16 16 0 0116-16h192a16 16 0 0116 16v64a16 16 0 01-4.69 11.31z" />
</Icon>
);

View File

@ -0,0 +1,15 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const CheckIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
width="18px"
fill="white"
{...props}
>
<title>Checkmark Circle</title>
<path d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm108.25 138.29l-134.4 160a16 16 0 01-12 5.71h-.27a16 16 0 01-11.89-5.3l-57.6-64a16 16 0 1123.78-21.4l45.29 50.32 122.59-145.91a16 16 0 0124.5 20.58z" />
</Icon>
);

View File

@ -0,0 +1,21 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React, { SVGProps } from "react";
export const ChevronDownIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
width="18px"
{...props}
>
<title>Chevron Down</title>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="48"
d="M112 184l144 144 144-144"
/>
</Icon>
);

View File

@ -0,0 +1,21 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const ChevronRightIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
width="18px"
{...props}
>
<title>Chevron Forward</title>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="48"
d="M184 112l144 144-144 144"
/>
</Icon>
);

View File

@ -0,0 +1,13 @@
import React, { SVGProps } from "react";
export const CloseIcon = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="#CBD5E0"
{...props}
>
<title>Close Circle</title>
<path d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm75.31 260.69a16 16 0 11-22.62 22.62L256 278.63l-52.69 52.68a16 16 0 01-22.62-22.62L233.37 256l-52.68-52.69a16 16 0 0122.62-22.62L256 233.37l52.69-52.68a16 16 0 0122.62 22.62L278.63 256z" />
</svg>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const ConditionIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Git Branch</title>
<path d="M416 160a64 64 0 10-96.27 55.24c-2.29 29.08-20.08 37-75 48.42-17.76 3.68-35.93 7.45-52.71 13.93v-126.2a64 64 0 10-64 0v209.22a64 64 0 1064.42.24c2.39-18 16-24.33 65.26-34.52 27.43-5.67 55.78-11.54 79.78-26.95 29-18.58 44.53-46.78 46.36-83.89A64 64 0 00416 160zM160 64a32 32 0 11-32 32 32 32 0 0132-32zm0 384a32 32 0 1132-32 32 32 0 01-32 32zm192-256a32 32 0 1132-32 32 32 0 01-32 32z" />
</Icon>
);

View File

@ -0,0 +1,15 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const DocIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
{...props}
>
<title>Document Text</title>
<path d="M428 224H288a48 48 0 01-48-48V36a4 4 0 00-4-4h-92a64 64 0 00-64 64v320a64 64 0 0064 64h224a64 64 0 0064-64V228a4 4 0 00-4-4zm-92 160H176a16 16 0 010-32h160a16 16 0 010 32zm0-80H176a16 16 0 010-32h160a16 16 0 010 32z" />
<path d="M419.22 188.59L275.41 44.78a2 2 0 00-3.41 1.41V176a16 16 0 0016 16h129.81a2 2 0 001.41-3.41z" />
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const EyeDropIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Eyedrop</title>
<path d="M461.05 51a65 65 0 00-45.71-19h-.76a61.81 61.81 0 00-44.36 19.25 12.81 12.81 0 00-1.07 1.25l-54 69.76c-5.62 7.1-12.74 8.68-16.78 4.64l-1.9-1.9a48 48 0 00-67.92 67.92l9.91 9.91a2 2 0 010 2.83L58.7 385.38C54 390.05 46.9 399.85 38.85 431c-4.06 15.71-6.51 29.66-6.61 30.24A16 16 0 0048 480a15.68 15.68 0 002.64-.22c.58-.1 14.44-2.43 30.13-6.44 31.07-7.94 41.05-15.24 45.85-20l179.77-179.79a2 2 0 012.82 0l9.92 9.92a48 48 0 0067.92-67.93l-1.59-1.54c-5-5-2.52-12.11 4.32-17.14l69.75-53.94a17.82 17.82 0 001.47-1.32 63.2 63.2 0 0019-45A63.88 63.88 0 00461.05 51zM250.78 283.9c-2.92 2.92-16.18 7.92-23.39.71s-2.24-20.42.69-23.35l33-33a2 2 0 012.83 0l19.84 19.83a2 2 0 010 2.83z" />
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const FolderIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Folder Open</title>
<path d="M408 96H252.11a23.89 23.89 0 01-13.31-4L211 73.41A55.77 55.77 0 00179.89 64H104a56.06 56.06 0 00-56 56v24h416c0-30.88-25.12-48-56-48zM423.75 448H88.25a56 56 0 01-55.93-55.15L16.18 228.11v-.28A48 48 0 0164 176h384.1a48 48 0 0147.8 51.83v.28l-16.22 164.74A56 56 0 01423.75 448zm56.15-221.45z" />
</Icon>
);

View File

@ -0,0 +1,15 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const GlobeIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Globe</title>
<path d="M340.75 344.49c5.91-20.7 9.82-44.75 11.31-67.84a4.41 4.41 0 00-4.46-4.65h-71.06a4.43 4.43 0 00-4.47 4.39v55.3a4.44 4.44 0 004.14 4.38 273.51 273.51 0 0159 11.39 4.45 4.45 0 005.54-2.97zM323.58 377.31a260.05 260.05 0 00-46.6-9.09 4.42 4.42 0 00-4.91 4.29v65.24a4.47 4.47 0 006.76 3.7c15.9-9.27 29-24.84 40.84-45.43 1.94-3.36 4.89-9.15 6.67-12.69a4.29 4.29 0 00-2.76-6.02zM235.29 368.4a256.85 256.85 0 00-46.56 8.82c-2.64.76-3.75 4.4-2.55 6.79 1.79 3.56 4 8.11 5.89 11.51 13 23 26.84 37.5 41.24 45.93a4.47 4.47 0 006.76-3.7v-65.27a4.16 4.16 0 00-4.78-4.08zM235.6 272h-71.06a4.41 4.41 0 00-4.46 4.64c1.48 23.06 5.37 47.16 11.26 67.84a4.46 4.46 0 005.59 3 272.2 272.2 0 0159-11.36 4.44 4.44 0 004.15-4.38V276.4a4.43 4.43 0 00-4.48-4.4zM277 143.78a235.8 235.8 0 0046.5-9.14 4.3 4.3 0 002.76-6c-1.79-3.57-4.27-8.68-6.17-12.09-12.29-22-26.14-37.35-41.24-46a4.48 4.48 0 00-6.76 3.7v65.23a4.43 4.43 0 004.91 4.3zM276.54 240h71.06a4.39 4.39 0 004.46-4.58c-1.48-22.77-5.27-47.8-11.16-68.22a4.46 4.46 0 00-5.59-2.95c-19 5.74-38.79 10.43-59.09 12a4.4 4.4 0 00-4.15 4.32v55.11a4.4 4.4 0 004.47 4.32zM233.31 70.56c-15.42 8.57-29.17 24.43-41.47 46.37-1.91 3.41-4.19 8.11-6 11.67a4.31 4.31 0 002.76 6 225.42 225.42 0 0046.54 9.17 4.43 4.43 0 004.91-4.29V74.26a4.49 4.49 0 00-6.74-3.7zM235.92 176.26c-20.3-1.55-40.11-6.24-59.09-12a4.46 4.46 0 00-5.59 2.95c-5.89 20.42-9.68 45.45-11.16 68.22a4.39 4.39 0 004.46 4.58h71.06a4.4 4.4 0 004.47-4.34v-55.09a4.4 4.4 0 00-4.15-4.32z" />
<path d="M414.39 97.61A224 224 0 1097.61 414.39 224 224 0 10414.39 97.61zM176.6 430.85a219.08 219.08 0 01-12.48-19.66c-2-3.69-4.84-9.26-6.73-13.13a7.29 7.29 0 00-10.31-3.16c-4.3 2.41-10 5.72-14.13 8.43a147.29 147.29 0 01-23.57-22.43 248.83 248.83 0 0130.41-18.36c1.86-1 2.77-2.14 2.18-4.18a374.8 374.8 0 01-14.09-82.17 4.36 4.36 0 00-4.3-4.17H66.84a2 2 0 01-2-1.7A98.28 98.28 0 0164 256a96.27 96.27 0 01.86-14.29 2 2 0 012-1.7h56.74c2.29 0 4.17-1.32 4.29-3.63a372.71 372.71 0 0114-81.83 4.36 4.36 0 00-2.19-5.11 260.63 260.63 0 01-29.84-17.9 169.82 169.82 0 0123.14-22.8c4.08 2.68 9.4 5.71 13.66 8.11a7.89 7.89 0 0011-3.42c1.88-3.87 4-8.18 6.06-11.88a221.93 221.93 0 0112.54-19.91A185 185 0 01256 64c28.94 0 55.9 7 80.53 18.46a202.23 202.23 0 0112 19c2.59 4.66 5.34 10.37 7.66 15.32a4.29 4.29 0 005.92 1.94c5.38-2.91 11.21-6.26 16.34-9.63a171.36 171.36 0 0123.2 23 244.89 244.89 0 01-29.06 17.31 4.35 4.35 0 00-2.18 5.12 348.68 348.68 0 0113.85 81.4 4.33 4.33 0 004.3 4.12l56.62-.07a2 2 0 012 1.7 117.46 117.46 0 010 28.62 2 2 0 01-2 1.72h-56.67a4.35 4.35 0 00-4.3 4.17 367.4 367.4 0 01-13.87 81.3 4.45 4.45 0 002.19 5.19c5 2.59 10.57 5.48 15.37 8.42s9.55 6.08 14.13 9.34a172.73 172.73 0 01-23 22.93c-2.44-1.61-5.34-3.44-7.84-4.94-1.72-1-4.89-2.77-6.65-3.76-3.82-2.14-7.88-.54-9.79 3.4s-4.83 9.59-6.87 13.25a212.42 212.42 0 01-12.35 19.53C310.91 442.37 284.94 448 256 448s-54.77-5.63-79.4-17.15z" />
</Icon>
);

View File

@ -0,0 +1,51 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const Logo = ({
isDark,
...props
}: { isDark?: boolean } & IconProps) => (
<Icon
viewBox="0 0 500 500"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<rect
width="500"
height="500"
rx="75"
fill={!isDark ? "#0042DA" : "white"}
/>
<rect
x="438.709"
y="170.968"
width="64.5161"
height="290.323"
rx="32.2581"
transform="rotate(90 438.709 170.968)"
fill="#FF8E20"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M93.5481 235.484C111.364 235.484 125.806 221.041 125.806 203.226C125.806 185.41 111.364 170.968 93.5481 170.968C75.7325 170.968 61.29 185.41 61.29 203.226C61.29 221.041 75.7325 235.484 93.5481 235.484Z"
fill="#FF8E20"
/>
<rect
x="61.29"
y="332.259"
width="64.5161"
height="290.323"
rx="32.2581"
transform="rotate(-90 61.29 332.259)"
fill={!isDark ? "white" : "#0042DA"}
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M406.451 267.742C388.635 267.742 374.193 282.184 374.193 300C374.193 317.815 388.635 332.258 406.451 332.258C424.267 332.258 438.709 317.815 438.709 300C438.709 282.184 424.267 267.742 406.451 267.742Z"
fill={!isDark ? "white" : "#0042DA"}
/>
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const MagicWandIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Color Wand</title>
<path d="M96 208H48c-8.8 0-16-7.2-16-16s7.2-16 16-16h48c8.8 0 16 7.2 16 16s-7.2 16-16 16zM124.1 140.1c-4.2 0-8.3-1.7-11.3-4.7l-33.9-33.9c-6.2-6.2-6.2-16.4 0-22.6s16.4-6.2 22.6 0l33.9 33.9c6.3 6.2 6.3 16.4 0 22.6-3 3-7 4.7-11.3 4.7zM192 112c-8.8 0-16-7.2-16-16V48c0-8.8 7.2-16 16-16s16 7.2 16 16v48c0 8.8-7.2 16-16 16zM259.9 140.1c-8.8 0-16-7.2-16-16 0-4.2 1.7-8.3 4.7-11.3l33.9-33.9c6.2-6.2 16.4-6.2 22.6 0 6.2 6.2 6.2 16.4 0 22.6l-33.9 33.9c-3 3-7.1 4.7-11.3 4.7zM90.2 309.8c-8.8 0-16-7.2-16-16 0-4.2 1.7-8.3 4.7-11.3l33.9-33.9c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6l-33.9 33.9c-3 3-7.1 4.7-11.3 4.7zM234.2 167c-18.4-18.7-48.5-19-67.2-.7s-19 48.5-.7 67.2l.7.7 39.5 39.5c3.1 3.1 8.2 3.1 11.3 0l55.9-55.9c3.1-3.1 3.1-8.2 0-11.3L234.2 167zM457 389.8L307.6 240.4c-3.1-3.1-8.2-3.1-11.3 0l-55.9 55.9c-3.1 3.1-3.1 8.2 0 11.3L389.8 457c18.4 18.7 48.5 19 67.2.7 18.7-18.4 19-48.5.7-67.2-.2-.2-.4-.5-.7-.7z" />
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const MapIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Map</title>
<path d="M48.17 113.34A32 32 0 0032 141.24V438a32 32 0 0047 28.37c.43-.23.85-.47 1.26-.74l84.14-55.05a8 8 0 003.63-6.72V46.45a8 8 0 00-12.51-6.63zM212.36 39.31A8 8 0 00200 46v357.56a8 8 0 003.63 6.72l96 62.42A8 8 0 00312 466V108.67a8 8 0 00-3.64-6.73zM464.53 46.47a31.64 31.64 0 00-31.5-.88 12.07 12.07 0 00-1.25.74l-84.15 55a8 8 0 00-3.63 6.72v357.46a8 8 0 0012.52 6.63l107.07-73.46a32 32 0 0016.41-28v-296a32.76 32.76 0 00-15.47-28.21z" />
</Icon>
);

View File

@ -0,0 +1,15 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const PeopleCircleIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>People Circle</title>
<path d="M258.9 48C141.92 46.42 46.42 141.92 48 258.9c1.56 112.19 92.91 203.54 205.1 205.1 117 1.6 212.48-93.9 210.88-210.88C462.44 140.91 371.09 49.56 258.9 48zm-3.68 152.11c.21-1.2.44-2.4.71-3.59a66.46 66.46 0 0116.29-31.21c12.89-13.73 31.16-21.31 51.45-21.31a74.05 74.05 0 0125.06 4.26 66.69 66.69 0 0126.27 17.2 68.15 68.15 0 0118 42.14 78.46 78.46 0 010 11.4 86.19 86.19 0 01-8.2 31q-.76 1.59-1.59 3.15c-1.11 2.07-2.3 4.1-3.58 6.06a79.47 79.47 0 01-8.63 11c-13.12 14-29.92 21.73-47.31 21.73a59.61 59.61 0 01-19.17-3.18 63.47 63.47 0 01-6.1-2.43 70.76 70.76 0 01-22.07-16.12 83.76 83.76 0 01-22-51.32q-.27-3.88-.18-7.68a75.62 75.62 0 011.05-11.08zm-149.73 24.34a59.87 59.87 0 015.2-20.64 56.76 56.76 0 012.78-5.3 54.49 54.49 0 017.19-9.56 55.62 55.62 0 0114-10.82 56.84 56.84 0 018.11-3.64 63.85 63.85 0 0133.35-2.39 57 57 0 0130.78 17 57.86 57.86 0 0115.41 38.62c.05 2.11 0 4.23-.15 6.38a71.58 71.58 0 01-6 23.84 69.49 69.49 0 01-5.73 10.42 65.39 65.39 0 01-15.76 16.57c-1.5 1.07-3.06 2.07-4.67 3.07a54.21 54.21 0 01-10 4.65 49.31 49.31 0 01-16.2 2.76c-.93 0-1.86 0-2.78-.08a47.6 47.6 0 01-5.48-.62 51.19 51.19 0 01-5.35-1.23 53.54 53.54 0 01-7.72-2.89c-.84-.39-1.66-.8-2.48-1.23-18-9.49-31.57-29.16-34.23-52.12-.12-1.05-.22-2.1-.29-3.16a66.59 66.59 0 01.02-9.63zm53.92 178.6a177.27 177.27 0 01-61.94-70.65 4 4 0 011.62-5.26C117.67 316.69 141.4 311 163.82 311c17 0 30.7 2 42.69 5.88a8 8 0 012.59 13.77c-23.35 19-38.4 42.54-45.47 70.75a2.77 2.77 0 01-4.22 1.65zM256 432a175.12 175.12 0 01-65.7-12.72 4 4 0 01-2.4-4.46c.4-2.05.84-3.92 1.23-5.48 7.12-28.43 24.76-52 51-68.18 23.29-14.35 53-22.25 83.52-22.25 31.16 0 60 7.58 83.48 21.91a2.72 2.72 0 01.91 3.67A176.1 176.1 0 01256 432z" />
<path d="M161 295.28a47.6 47.6 0 01-5.48-.62 47.6 47.6 0 005.48.62zM134.64 178.13a55.62 55.62 0 00-14 10.82 54.49 54.49 0 00-7.19 9.56 54.49 54.49 0 017.19-9.56 55.62 55.62 0 0114-10.82zM216.17 257.89a71.58 71.58 0 006-23.84c.15-2.15.2-4.27.15-6.38q.08 3.15-.15 6.38a71.58 71.58 0 01-6 23.84zM134.64 178.13a56.84 56.84 0 018.11-3.64 56.84 56.84 0 00-8.11 3.64zM150.21 293.43a53.54 53.54 0 01-7.72-2.89 53.54 53.54 0 007.72 2.89zM105.78 237.19c2.66 23 16.26 42.63 34.23 52.12-18.01-9.49-31.57-29.16-34.23-52.12zM254.34 219a83.76 83.76 0 0022 51.32 70.76 70.76 0 0022.07 16.12 70.76 70.76 0 01-22.07-16.12 83.76 83.76 0 01-22-51.32q-.27-3.88-.18-7.68-.09 3.75.18 7.68zM304.5 288.82a63.47 63.47 0 01-6.1-2.43 63.47 63.47 0 006.1 2.43zM255.93 196.54a66.46 66.46 0 0116.29-31.21 66.46 66.46 0 00-16.29 31.21zM375 165.46a68.15 68.15 0 0118 42.14 68.15 68.15 0 00-18-42.14 66.69 66.69 0 00-26.27-17.2 66.69 66.69 0 0126.27 17.2zM393 219a86.19 86.19 0 01-8.2 31 86.19 86.19 0 008.2-31zM254.16 211.27a75.62 75.62 0 011.06-11.14 75.62 75.62 0 00-1.06 11.14zM383.19 253.16zM206.88 189.05a57.86 57.86 0 0115.41 38.62 57.86 57.86 0 00-15.41-38.62 57 57 0 00-30.78-17 57 57 0 0130.78 17zM190 288a54.21 54.21 0 01-10 4.65 54.21 54.21 0 0010-4.65zM105.49 224.45a59.87 59.87 0 015.2-20.64 59.87 59.87 0 00-5.2 20.64zM194.68 284.88C193.17 286 191.61 287 190 288c1.61-1 3.17-2 4.68-3.12zM216.17 257.89a69.49 69.49 0 01-5.73 10.42 69.49 69.49 0 005.73-10.42zM110.69 203.81a56.76 56.76 0 012.78-5.3 56.76 56.76 0 00-2.78 5.3zM194.68 284.88a65.39 65.39 0 0015.76-16.57 65.39 65.39 0 01-15.76 16.57z" />
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const PersonAddIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Person Add</title>
<path d="M288 256c52.79 0 99.43-49.71 104-110.82 2.27-30.7-7.36-59.33-27.12-80.6C345.33 43.57 318 32 288 32c-30.24 0-57.59 11.5-77 32.38-19.63 21.11-29.2 49.8-27 80.78C188.49 206.28 235.12 256 288 256zM495.38 439.76c-8.44-46.82-34.79-86.15-76.19-113.75C382.42 301.5 335.83 288 288 288s-94.42 13.5-131.19 38c-41.4 27.6-67.75 66.93-76.19 113.75-1.93 10.73.69 21.34 7.19 29.11A30.94 30.94 0 00112 480h352a30.94 30.94 0 0024.21-11.13c6.48-7.77 9.1-18.38 7.17-29.11zM104 288v-40h40a16 16 0 000-32h-40v-40a16 16 0 00-32 0v40H32a16 16 0 000 32h40v40a16 16 0 0032 0z" />
</Icon>
);

View File

@ -0,0 +1,13 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const QuoteLeftIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentcolor"
{...props}
>
<path d="M3.516 7a3.5 3.5 0 1 1-3.5 3.5L0 10a7 7 0 0 1 7-7v2a4.97 4.97 0 0 0-3.536 1.464a5.01 5.01 0 0 0-.497.578c.179-.028.362-.043.548-.043zm9 0a3.5 3.5 0 1 1-3.5 3.5L9 10a7 7 0 0 1 7-7v2a4.97 4.97 0 0 0-3.536 1.464a5.01 5.01 0 0 0-.497.578c.179-.028.362-.043.549-.043z" />
</Icon>
);

View File

@ -0,0 +1,14 @@
import Icon, { IconProps } from "@chakra-ui/icon";
import React from "react";
export const ShareIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentcolor"
{...props}
>
<title>Share Social</title>
<path d="M384 336a63.78 63.78 0 00-46.12 19.7l-148-83.27a63.85 63.85 0 000-32.86l148-83.27a63.8 63.8 0 10-15.73-27.87l-148 83.27a64 64 0 100 88.6l148 83.27A64 64 0 10384 336z" />
</Icon>
);

View File

@ -0,0 +1,19 @@
.rounded-full {
border-radius: 99999px;
}
.floating {
animation: float 6s ease-in-out infinite;
}
@keyframes float {
0% {
transform: translatey(0px);
}
50% {
transform: translatey(-10px);
}
100% {
transform: translatey(0px);
}
}

View File

@ -0,0 +1,35 @@
import { Box, Heading, Button, Text } from '@chakra-ui/react'
import React from 'react'
import { BackgroundPolygons } from './Hero/BackgroundPolygons'
export const EndCta = () => {
return (
<Box as="section" py={32} pos="relative">
<BackgroundPolygons />
<Box
maxW="2xl"
mx="auto"
px={{ base: '6', lg: '8' }}
py={{ base: '16', sm: '20' }}
textAlign="center"
>
<Heading fontWeight="extrabold" letterSpacing="tight">
Take your forms to the next level
</Heading>
<Text mt="4" fontSize="lg">
Try Typebot for free and start improving the performance of your form
</Text>
<Button
as="a"
href="https://app.typebot.io/signup"
mt="8"
size="lg"
colorScheme="blue"
fontWeight="bold"
>
Create a typebot
</Button>
</Box>
</Box>
)
}

View File

@ -0,0 +1,35 @@
import { Flex, VStack } from '@chakra-ui/layout'
import { IconProps, Text } from '@chakra-ui/react'
import React from 'react'
type FeatureCardProps = {
Icon: (props: IconProps) => JSX.Element
title: string
content: string
}
export const FeatureCard = ({ Icon, title, content }: FeatureCardProps) => {
return (
<VStack p="6" bgColor="gray.100" pos="relative" rounded="lg" spacing="4">
<Flex
boxSize="50px"
bgColor="blue.500"
rounded="lg"
color="white"
justify="center"
align="center"
pos="absolute"
top="-25px"
shadow="lg"
>
<Icon boxSize="25px" />
</Flex>
<Text textAlign="center" fontWeight="semibold">
{title}
</Text>
<Text textAlign="center" color="gray.500">
{content}
</Text>
</VStack>
)
}

View File

@ -0,0 +1,75 @@
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 typebot with you',
},
{
Icon: ConditionIcon,
title: 'Conditional branching',
content:
'Make your form smarter by adding conditions to display custom answers to your users',
},
{
Icon: CalculatorIcon,
title: 'Computation',
content:
'Use the calculator to compute anything in Typebot directly to generate a quote or compute a score',
},
{
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={32} w="full" px="4" spacing={6}>
<VStack>
<Heading as="h1" textAlign="center">
And many more features
</Heading>
<Text color="gray.500" size="lg" textAlign="center">
Typebot makes form building easy and comes with powerful features
</Text>
<SimpleGrid columns={[1, 3]} spacing="10" pt="10">
{features.map((feature, idx) => (
<FeatureCard key={idx} {...feature} />
))}
</SimpleGrid>
</VStack>
</Stack>
</Flex>
)
}

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,59 @@
import { Box, Flex, HStack, Stack, Text } from '@chakra-ui/react'
import * as React from 'react'
import Image from 'next/image'
import { QuoteLeftIcon } from 'assets/icons/QuoteLeftIcon'
interface TestimonialProps {
image: StaticImageData
name: string
role: string
children: React.ReactNode
}
export const Testimonial = (props: TestimonialProps) => {
const { image, name, role, children } = props
return (
<Flex
flexDir="column"
justify="space-between"
as="blockquote"
p="6"
rounded="md"
bgColor="blue.400"
color="white"
shadow="lg"
{...props}
>
<Stack>
<QuoteLeftIcon boxSize="25px" />
<Text mt="3" fontSize="xl" maxW="38rem" color="gray.50">
{children}
</Text>
</Stack>
<HStack mt="6" spacing="4">
<Image
src={image}
alt={name}
placeholder="blur"
width="80px"
height="80px"
className="rounded-full"
/>
<Box>
<Text
as="cite"
fontStyle="normal"
fontWeight="extrabold"
color="white"
>
{name}
</Text>
<Text fontSize="sm" color={'gray.100'}>
{role}
</Text>
</Box>
</HStack>
</Flex>
)
}

View File

@ -0,0 +1,36 @@
import { chakra, Stack } from '@chakra-ui/react'
import * as React from 'react'
import joshuaPictureSrc from 'public/images/homepage/joshua.jpg'
import julienPictureSrc from 'public/images/homepage/julien.jpg'
import { Testimonial } from './Testimonial'
export const Testimonials = () => {
return (
<Stack direction={['column', 'row']} spacing="10" maxW="800px">
<Testimonial
name="Joshua Lim"
role="Growth Strategist @ Socialhackrs Media"
image={joshuaPictureSrc}
>
I upgraded my typeforms to typebots and saw a conversion rate increase{' '}
<chakra.span fontWeight="bold" color="orange.300">
from 14% to 43%
</chakra.span>{' '}
on my marketing campaigns. I noticed the improvement on day one. That
was a game-changer.
</Testimonial>
<Testimonial
name="Julien Muratot"
role="Growth Manager @ Hornetwork"
image={julienPictureSrc}
>
I run Google ads all year long on our landing page that contains a
typebot. I saw a{' '}
<chakra.span fontWeight="bold" color="orange.300">
2x increase
</chakra.span>{' '}
on our conversation rate compared to our old WordPress form.
</Testimonial>
</Stack>
)
}

View File

@ -0,0 +1,92 @@
import {
Box,
Button,
chakra,
Flex,
Heading,
SimpleGrid,
Stack,
Text,
useColorModeValue as mode,
VStack,
} from '@chakra-ui/react'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import * as React from 'react'
import { Navbar } from '../../common/Navbar/Navbar'
import { BackgroundPolygons } from './BackgroundPolygons'
import * as Logos from './Brands'
import { Testimonials } from './Testimonials'
export const Hero = () => {
return (
<Box as="section" overflow="hidden">
<Navbar />
<Stack mx="auto" maxW="7xl" py="10" pos="relative" pb="32" px={[4, 0]}>
<BackgroundPolygons />
<VStack mb="20" alignItems="center">
<VStack pt={['10', '20']} spacing="6">
<Heading as="h1" size="2xl" textAlign="center" maxW="900px">
<chakra.span
bgImage={`url(\"/brush.svg\")`}
bgSize="cover"
bgRepeat="no-repeat"
>
4x more
</chakra.span>{' '}
responses with your forms
</Heading>
<Text
color={'gray.600'}
fontSize={['lg', 'xl']}
maxW="700px"
textAlign="center"
>
Typebot offers tools to create high-converting lead forms
specifically designed for your marketing campaigns
</Text>
<Button
as={NextChakraLink}
href="https://app.typebot.io/signup"
colorScheme="orange"
bgColor="#FF8E20"
_hover={{ bgColor: 'orange.500' }}
shadow="lg"
size="lg"
height="4rem"
px="2rem"
>
Create a typebot for free
</Button>
</VStack>
<Box boxSize={{ base: '20', lg: '8' }} />
<Testimonials />
</VStack>
</Stack>
<Flex justify="center" bgColor="gray.100">
<VStack spacing="12" py="20" maxW="7xl" px={4}>
<Text
color={mode('gray.600', 'gray.400')}
fontSize="25px"
fontWeight="semibold"
>
Trusted by 1,200+ companies and freelance marketers
</Text>
<SimpleGrid
columns={{ base: 2, md: 3, lg: 6 }}
color="gray.500"
alignItems="center"
spacing={{ base: '12', lg: '24' }}
fontSize="4xl"
>
<Logos.IbanFirst />
<Logos.Lemlist />
<Logos.MakerLead />
<Logos.SocialHackrs />
<Logos.PinpointInteractive />
<Logos.Obole />
</SimpleGrid>
</VStack>
</Flex>
</Box>
)
}

View File

@ -0,0 +1,28 @@
import React, { SVGProps } from 'react'
export const AirtableLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 165 138"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M73.6559 1.74229L12.1579 27.1912C8.73803 28.6066 8.77346 33.4655 12.2148 34.8296L73.9692 59.3209C79.395 61.473 85.4376 61.473 90.8634 59.3209L152.619 34.8287C156.059 33.4655 156.096 28.6075 152.675 27.1921L91.1785 1.74135C85.568 -0.580451 79.2655 -0.580451 73.655 1.74135"
fill="#FCB400"
/>
<path
d="M87.8975 72.6923V133.876C87.8975 136.785 90.8316 138.778 93.5363 137.706L162.35 110.994C163.117 110.69 163.775 110.162 164.239 109.479C164.703 108.796 164.951 107.989 164.951 107.163V45.9809C164.951 43.0708 162.017 41.0782 159.312 42.1505L90.4987 68.8628C89.7314 69.1673 89.0732 69.6952 88.6094 70.3782C88.1456 71.0611 87.8975 71.8677 87.8975 72.6933"
fill="#18BFFF"
/>
<path
d="M71.8266 75.8485L51.4043 85.7099L49.3308 86.7123L6.22066 107.37C3.48886 108.689 0 106.697 0 103.661V46.2363C0 45.1379 0.563141 44.1896 1.31835 43.4763C1.62817 43.1678 1.97966 42.9042 2.36258 42.6931C3.3919 42.0749 4.86129 41.9099 6.11064 42.404L71.4835 68.3089C74.8064 69.6273 75.0675 74.2839 71.8266 75.8495"
fill="#F82B60"
/>
<path
d="M71.8276 75.8485L51.4053 85.7099L1.31934 43.4754C1.62922 43.1672 1.9807 42.9039 2.36357 42.6931C3.39289 42.0749 4.86228 41.9099 6.11163 42.404L71.4845 68.3089C74.8074 69.6273 75.0685 74.2839 71.8276 75.8495"
fill="black"
fillOpacity="0.25"
/>
</svg>
)

View File

@ -0,0 +1,43 @@
import React, { SVGProps } from 'react'
export const FacebookPixelLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 470 512"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M464.291 129.408L240.291 1.40775C237.006 -0.46925 232.995 -0.46925 229.71 1.40775L5.70998 129.408C2.38198 131.307 0.333984 134.848 0.333984 138.667V373.334C0.333984 377.153 2.38198 380.694 5.70998 382.593L229.71 510.593C231.353 511.532 233.166 512.001 235.001 512.001C236.836 512.001 238.649 511.532 240.292 510.593L464.292 382.593C467.62 380.694 469.668 377.153 469.668 373.334V138.667C469.667 134.848 467.619 131.307 464.291 129.408ZM448.333 367.147L235 489.045L21.667 367.147V144.853L235 22.9548L448.333 144.854V367.147Z"
fill="#3C5A99"
/>
<path
d="M460 140L235 12L17 140V371L235 494L463.5 373.5L460 140Z"
fill="#3C5A99"
/>
<g clipPath="url(#clip0)">
<path
d="M411.329 251.264L328.31 163.309C323.207 157.897 314.69 157.65 309.278 162.757C303.875 167.86 303.624 176.381 308.731 181.788L383.031 260.5L308.731 339.22C303.624 344.627 303.875 353.145 309.278 358.251C311.881 360.706 315.206 361.922 318.518 361.922C322.095 361.922 325.667 360.504 328.31 357.708L411.33 269.748C416.225 264.557 416.225 256.452 411.329 251.264Z"
fill="white"
/>
<path
d="M162.274 339.217L87.9789 260.501L162.274 181.785C167.377 176.378 167.13 167.856 161.722 162.754C156.319 157.652 147.793 157.898 142.691 163.306L59.6717 251.261C54.7761 256.449 54.7761 264.558 59.6717 269.746L142.695 357.705C145.343 360.51 148.91 361.924 152.487 361.924C155.799 361.924 159.124 360.703 161.722 358.248C167.135 353.146 167.377 344.624 162.274 339.217Z"
fill="white"
/>
<path
d="M257.28 117.95C249.934 116.837 243.059 121.881 241.937 129.227L202.447 387.708C201.325 395.059 206.374 401.929 213.724 403.051C214.415 403.154 215.097 403.204 215.775 403.204C222.313 403.204 228.048 398.434 229.067 391.774L268.557 133.293C269.679 125.942 264.631 119.072 257.28 117.95Z"
fill="white"
/>
</g>
<defs>
<clipPath id="clip0">
<rect
width="359"
height="359"
fill="white"
transform="translate(56 81)"
/>
</clipPath>
</defs>
</svg>
)

View File

@ -0,0 +1,61 @@
import React, { SVGProps } from 'react'
export const GmailLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 256 194"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M238.833 193.595H16.1537C7.51922 193.595 0.248047 186.551 0.248047 177.69V16.8149C0.248047 8.18036 7.292 0.90918 16.1537 0.90918H238.833C247.468 0.90918 254.739 7.95313 254.739 16.8149V177.69C254.739 186.551 247.695 193.595 238.833 193.595Z"
fill="#E3E3E3"
/>
<path
opacity="0.1"
d="M32.059 193.595L127.266 117.02L127.948 112.93L29.7868 42.2637L29.5596 190.187L32.059 193.595Z"
fill="#231F20"
/>
<path
d="M16.1537 193.595C7.292 193.595 0.248047 186.551 0.248047 177.689V16.5871C0.248047 7.72534 7.292 6.13477 16.1537 6.13477C25.0155 6.13477 32.0594 7.95256 32.0594 16.5871V193.595H16.1537Z"
fill="#D54B3D"
/>
<path
d="M16.1537 8.40701C27.5149 8.40701 29.7872 11.8154 29.7872 16.5871V191.322H16.1537C8.65534 191.322 2.52029 185.187 2.52029 177.689V16.5871C2.52029 11.5881 4.79253 8.40701 16.1537 8.40701ZM16.1537 6.13477C7.292 6.13477 0.248047 7.95256 0.248047 16.5871V177.689C0.248047 186.551 7.292 193.595 16.1537 193.595H32.0594V16.5871C32.0594 7.72534 25.0155 6.13477 16.1537 6.13477Z"
fill="#D72B27"
/>
<path
d="M238.833 193.595H222.928V16.1326C222.928 7.27089 229.972 6.13477 238.833 6.13477C247.695 6.13477 254.739 7.27089 254.739 16.1326V177.916C254.739 186.551 247.695 193.595 238.833 193.595Z"
fill="#D54B3D"
/>
<path
d="M238.833 8.40701C249.059 8.40701 252.467 10.452 252.467 16.1326V177.916C252.467 185.415 246.332 191.55 238.833 191.55H225.2V16.1326C225.2 10.2248 228.608 8.40701 238.833 8.40701ZM238.833 6.13477C229.972 6.13477 222.928 7.27089 222.928 16.1326V193.822H238.833C247.695 193.822 254.739 186.778 254.739 177.916V16.1326C254.739 7.27089 247.695 6.13477 238.833 6.13477Z"
fill="#D72B27"
/>
<path
d="M170.666 193.595L1.5791 23.195L10.4729 26.8127L128.175 111.567L254.739 18.7607L254.739 177.917C254.739 186.551 247.695 193.595 238.833 193.595H170.666Z"
fill="url(#paint0_linear)"
/>
<path
d="M127.267 117.02L7.06506 29.7659C0.0211134 24.5398 -2.0239 14.5419 3.20225 7.49797C8.42841 0.454023 18.6535 -1.13655 25.9247 4.08961L127.494 77.9375L229.745 3.18071C236.789 -2.04544 246.787 -0.454874 252.013 6.8163C257.239 13.8602 255.648 23.8581 248.377 29.0843L127.267 117.02Z"
fill="#D54B3D"
/>
<path
d="M238.834 2.27224C243.151 2.27224 247.241 4.31726 249.968 7.95285C254.285 14.0879 252.921 22.4952 247.014 27.0397L127.266 114.294L8.4282 27.9486C2.29315 23.4041 0.702579 14.7696 5.01984 8.86174C7.5193 5.45338 11.8366 3.18114 16.381 3.18114C19.335 3.18114 22.2889 4.09004 24.5611 5.90783L125.903 79.5285L127.266 80.4374L128.63 79.5285L230.653 4.77171C233.153 3.18114 235.88 2.27224 238.834 2.27224ZM238.834 0C235.652 0 232.244 0.908897 229.517 2.95391L127.266 77.7107L25.6972 3.86281C22.9705 1.81779 19.5622 0.908897 16.1538 0.908897C11.1549 0.908897 6.15596 3.18114 2.97482 7.4984C-2.02411 14.5423 0.020906 24.5402 7.06486 29.7664L127.266 117.248L248.15 29.0847C255.194 23.8585 256.784 14.0879 251.785 6.81673C248.604 2.27224 243.832 0 238.834 0Z"
fill="#D72B27"
/>
<defs>
<linearGradient
id="paint0_linear"
x1="1.58895"
y1="106.174"
x2="254.821"
y2="106.174"
gradientUnits="userSpaceOnUse"
>
<stop stopOpacity="0.1" />
<stop offset="1" stopOpacity="0.2" />
</linearGradient>
</defs>
</svg>
)

View File

@ -0,0 +1,182 @@
import React, { SVGProps } from 'react'
export const GoogleSheetLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 279 382"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<mask
id="mask0"
mask-type="alpha"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="279"
height="382"
>
<path
d="M174.153 0.605469H26.87C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V355.429C0.878906 369.708 12.5749 381.392 26.87 381.392H252.126C266.421 381.392 278.117 369.708 278.117 355.429V104.456L174.153 0.605469Z"
fill="white"
/>
</mask>
<g mask="url(#mask0)">
<path
d="M174.153 0.605469H26.87C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V355.429C0.878906 369.708 12.5749 381.392 26.87 381.392H252.126C266.421 381.392 278.117 369.708 278.117 355.429V104.456L217.471 61.1851L174.153 0.605469Z"
fill="#0F9D58"
/>
</g>
<mask
id="mask1"
mask-type="alpha"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="279"
height="382"
>
<path
d="M174.153 0.605469H26.87C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V355.429C0.878906 369.708 12.5749 381.392 26.87 381.392H252.126C266.421 381.392 278.117 369.708 278.117 355.429V104.456L174.153 0.605469Z"
fill="white"
/>
</mask>
<g mask="url(#mask1)">
<path
d="M70.1865 186.67V312.156H208.806V186.67H70.1865ZM130.832 294.848H87.5139V273.212H130.832V294.848ZM130.832 260.231H87.5139V238.595H130.832V260.231ZM130.832 225.614H87.5139V203.978H130.832V225.614ZM191.478 294.848H148.16V273.212H191.478V294.848ZM191.478 260.231H148.16V238.595H191.478V260.231ZM191.478 225.614H148.16V203.978H191.478V225.614Z"
fill="#F1F1F1"
/>
</g>
<mask
id="mask2"
mask-type="alpha"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="279"
height="382"
>
<path
d="M174.153 0.605469H26.87C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V355.429C0.878906 369.708 12.5749 381.392 26.87 381.392H252.126C266.421 381.392 278.117 369.708 278.117 355.429V104.456L174.153 0.605469Z"
fill="white"
/>
</mask>
<g mask="url(#mask2)">
<path
d="M181.753 96.8623L278.115 193.097V104.456L181.753 96.8623Z"
fill="url(#paint0_linear)"
/>
</g>
<mask
id="mask3"
mask-type="alpha"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="279"
height="382"
>
<path
d="M174.153 0.605469H26.87C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V355.429C0.878906 369.708 12.5749 381.392 26.87 381.392H252.126C266.421 381.392 278.117 369.708 278.117 355.429V104.456L174.153 0.605469Z"
fill="white"
/>
</mask>
<g mask="url(#mask3)">
<path
d="M174.151 0.605469V78.4935C174.151 92.8379 185.782 104.456 200.142 104.456H278.116L174.151 0.605469Z"
fill="#87CEAC"
/>
</g>
<mask
id="mask4"
mask-type="alpha"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="279"
height="382"
>
<path
d="M174.153 0.605469H26.87C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V355.429C0.878906 369.708 12.5749 381.392 26.87 381.392H252.126C266.421 381.392 278.117 369.708 278.117 355.429V104.456L174.153 0.605469Z"
fill="white"
/>
</mask>
<g mask="url(#mask4)">
<path
d="M26.87 0.605469C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V28.7317C0.878906 14.4522 12.5749 2.76903 26.87 2.76903H174.153V0.605469H26.87Z"
fill="white"
fillOpacity="0.2"
/>
</g>
<mask
id="mask5"
mask-type="alpha"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="279"
height="382"
>
<path
d="M174.153 0.605469H26.87C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V355.429C0.878906 369.708 12.5749 381.392 26.87 381.392H252.126C266.421 381.392 278.117 369.708 278.117 355.429V104.456L174.153 0.605469Z"
fill="white"
/>
</mask>
<g mask="url(#mask5)">
<path
d="M252.126 379.229H26.87C12.5749 379.229 0.878906 367.546 0.878906 353.267V355.43C0.878906 369.71 12.5749 381.393 26.87 381.393H252.126C266.421 381.393 278.117 369.71 278.117 355.43V353.267C278.117 367.546 266.421 379.229 252.126 379.229Z"
fill="#263238"
fillOpacity="0.2"
/>
</g>
<mask
id="mask6"
mask-type="alpha"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="279"
height="382"
>
<path
d="M174.153 0.605469H26.87C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V355.429C0.878906 369.708 12.5749 381.392 26.87 381.392H252.126C266.421 381.392 278.117 369.708 278.117 355.429V104.456L174.153 0.605469Z"
fill="white"
/>
</mask>
<g mask="url(#mask6)">
<path
d="M200.142 104.456C185.782 104.456 174.151 92.8376 174.151 78.4932V80.6567C174.151 95.0011 185.782 106.619 200.142 106.619H278.116V104.456H200.142Z"
fill="#263238"
fillOpacity="0.1"
/>
</g>
<path
d="M174.153 0.605469H26.87C12.5749 0.605469 0.878906 12.2887 0.878906 26.5682V355.429C0.878906 369.708 12.5749 381.392 26.87 381.392H252.126C266.421 381.392 278.117 369.708 278.117 355.429V104.456L174.153 0.605469Z"
fill="url(#paint1_radial)"
/>
<defs>
<linearGradient
id="paint0_linear"
x1="229.939"
y1="105.125"
x2="229.939"
y2="193.111"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#263238" stopOpacity="0.2" />
<stop offset="1" stopColor="#263238" stopOpacity="0.02" />
</linearGradient>
<radialGradient
id="paint1_radial"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(9.66195 8.17438) scale(447.042 446.554)"
>
<stop stopColor="white" stopOpacity="0.1" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</radialGradient>
</defs>
</svg>
)

View File

@ -0,0 +1,27 @@
import React, { SVGProps } from 'react'
export const GoogleTagManagerLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 399 399"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M234.227 383.847L164.951 314.493L313.762 164.169L384.315 234.702L234.227 383.847Z"
fill="#8AB4F8"
/>
<path
d="M234.728 85.154L164.192 14.6045L14.6211 164.169C-4.86283 183.636 -4.87898 215.187 14.5888 234.67C14.6049 234.686 14.6211 234.702 14.6211 234.702L164.192 384.267L233.387 314.751L120.361 199.533L234.728 85.154Z"
fill="#4285F4"
/>
<path
d="M384.298 164.169L234.728 14.6045C215.244 -4.87859 183.659 -4.87859 164.175 14.6045C144.692 34.0876 144.692 65.671 164.175 85.1379L313.827 234.702C333.311 254.185 364.895 254.185 384.363 234.702C403.847 215.219 403.847 183.636 384.363 164.169H384.298Z"
fill="#8AB4F8"
/>
<path
d="M198.91 399.016C226.214 399.016 248.347 376.883 248.347 349.581C248.347 322.279 226.214 300.146 198.91 300.146C171.607 300.146 149.474 322.279 149.474 349.581C149.474 376.883 171.607 399.016 198.91 399.016Z"
fill="#246FDB"
/>
</svg>
)

View File

@ -0,0 +1,15 @@
import React, { SVGProps } from 'react'
export const HubspotLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 153 159"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M117.224 52.2096V33.3231C119.722 32.1567 121.836 30.3054 123.322 27.9847C124.808 25.664 125.603 22.9694 125.616 20.2145V19.7807C125.616 11.7485 119.1 5.23699 111.062 5.23699H110.628C106.768 5.23699 103.066 6.76928 100.337 9.49676C97.6076 12.2242 96.0743 15.9235 96.0743 19.7807V20.2145C96.087 22.9694 96.8825 25.664 98.368 27.9847C99.8536 30.3054 101.968 32.1567 104.466 33.3231V52.2096C97.2877 53.308 90.5276 56.2821 84.8697 60.8309L33.037 20.4876C33.4068 19.1542 33.5997 17.7834 33.6211 16.4072C33.6275 13.1659 32.6717 9.9956 30.8748 7.29722C29.0779 4.59883 26.5206 2.49361 23.5262 1.24785C20.5319 0.00209823 17.2351 -0.32823 14.0528 0.298653C10.8706 0.925535 7.94591 2.48147 5.64868 4.76963C3.35145 7.0578 1.78491 9.97541 1.1472 13.1534C0.509489 16.3314 0.829294 19.627 2.0661 22.6234C3.30292 25.6197 5.40117 28.1822 8.09551 29.9867C10.7898 31.7912 13.9592 32.7566 17.2027 32.7609C20.0403 32.7475 22.8247 31.9905 25.2779 30.5654L76.3175 70.2554C71.7324 77.1775 69.3404 85.3193 69.4532 93.6197C69.566 101.92 72.1784 109.994 76.9499 116.789L61.4263 132.307C60.1715 131.906 58.8641 131.693 57.5467 131.675C54.8844 131.678 52.2824 132.468 50.0695 133.948C47.8567 135.427 46.1324 137.529 45.1146 139.987C44.0967 142.446 43.8309 145.151 44.3508 147.76C44.8708 150.369 46.1531 152.766 48.0357 154.647C49.9183 156.529 52.3166 157.81 54.9278 158.33C57.5389 158.849 60.2456 158.584 62.7057 157.567C65.1658 156.549 67.269 154.826 68.7495 152.615C70.23 150.404 71.0212 147.803 71.0234 145.143C71.0061 143.826 70.793 142.52 70.3911 141.266L85.7485 125.914C90.7564 129.766 96.5805 132.423 102.774 133.679C108.968 134.935 115.368 134.757 121.482 133.16C127.597 131.563 133.265 128.588 138.051 124.464C142.838 120.34 146.616 115.175 149.097 109.366C151.578 103.557 152.695 97.2581 152.363 90.951C152.032 84.6438 150.26 78.4963 147.183 72.9792C144.107 67.4622 139.807 62.7221 134.614 59.122C129.421 55.5219 123.473 53.1574 117.224 52.2096V52.2096ZM110.858 114.326C108.02 114.404 105.195 113.913 102.55 112.881C99.905 111.85 97.4937 110.299 95.4586 108.32C93.4235 106.342 91.8058 103.976 90.7013 101.362C89.5967 98.7478 89.0276 95.9392 89.0276 93.1019C89.0276 90.2645 89.5967 87.4559 90.7013 84.842C91.8058 82.2282 93.4235 79.8621 95.4586 77.8836C97.4937 75.905 99.905 74.3542 102.55 73.3227C105.195 72.2912 108.02 71.7999 110.858 71.878C116.359 72.0705 121.571 74.3889 125.395 78.3448C129.22 82.3008 131.358 87.5856 131.361 93.0862C131.364 98.5867 129.23 103.874 125.41 107.834C121.59 111.793 116.381 114.117 110.88 114.315"
fill="#FF7A59"
/>
</svg>
)

View File

@ -0,0 +1,43 @@
import React, { SVGProps } from 'react'
export const MailChimpLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 216 230"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M162.651 108.298C164.209 108.298 165.766 108.298 167.323 108.298C168.314 106.174 168.314 103.06 167.323 99.5206C166.332 94.2827 164.775 90.7436 161.661 91.1683C158.546 91.7345 158.546 95.8399 159.537 101.078C159.962 104.192 161.094 106.74 162.651 108.298Z"
fill="black"
/>
<path
d="M135.188 112.97C137.311 113.961 138.868 114.527 139.293 113.961C139.859 113.395 139.293 112.97 138.727 111.838C137.736 109.714 135.046 108.157 133.064 107.166C127.826 105.042 122.164 105.609 117.492 109.289C115.935 110.28 114.378 111.838 114.944 112.97C114.944 113.536 115.51 113.536 115.935 113.536C116.926 113.536 121.598 111.413 126.835 110.988C129.95 110.847 133.064 111.979 135.188 112.97Z"
fill="black"
/>
<path
d="M130.517 115.518C127.402 116.084 125.845 117.075 124.854 118.066C123.863 119.057 123.297 119.624 123.297 120.19V120.756H123.863C124.429 120.756 125.987 120.19 125.987 120.19C130.092 118.633 132.782 118.633 135.33 119.199C136.887 119.199 137.453 119.765 137.878 119.199C137.878 119.199 137.878 118.633 137.878 118.208C137.736 116.651 134.622 115.093 130.517 115.518Z"
fill="black"
/>
<path
d="M132.073 119.198C133.064 117.075 133.064 112.403 132.073 108.864C131.082 103.626 129.525 100.512 125.844 100.512C122.73 101.078 122.73 105.183 123.721 110.846C124.287 114.527 125.844 116.509 126.269 118.066C128.959 122.313 130.516 121.18 132.073 119.198Z"
fill="black"
/>
<path
d="M153.307 124.862C155.431 125.853 157.413 125.428 158.545 123.871C159.112 122.313 157.979 120.19 155.997 119.199C153.874 118.208 151.892 118.633 150.759 120.19C149.627 121.747 151.184 123.871 153.307 124.862Z"
fill="black"
/>
<path
d="M166.191 113.536C164.633 113.536 163.076 115.093 163.076 117.641C163.076 119.765 164.067 121.747 166.191 121.747C167.748 121.747 169.305 120.19 169.305 117.641C168.88 115.518 167.748 113.536 166.191 113.536Z"
fill="black"
/>
<path
d="M56.4776 153.881C55.9114 153.315 55.4867 153.315 54.9204 153.881C54.3541 153.881 53.9295 153.881 53.3632 153.881C52.3722 153.881 51.2397 153.315 50.815 152.324C50.3903 151.333 50.2488 149.776 50.815 147.653L51.3813 146.662C52.9385 143.547 55.062 138.876 52.3722 134.204C50.2488 130.523 47.7006 128.541 44.0199 127.975C40.3393 127.409 36.8002 128.966 34.6767 131.656C30.996 135.761 30.5713 140.999 30.996 142.981C30.996 143.547 31.5623 143.972 31.987 143.972C32.5532 143.972 33.5442 143.406 34.1104 141.848V141.282C34.1104 140.291 34.6767 139.159 35.6676 137.601C36.6586 136.044 38.2158 135.053 39.773 135.053C41.3302 134.487 43.4537 135.053 45.0109 136.044C47.5591 137.601 48.6916 140.716 47.5591 143.83C46.0018 145.388 45.4356 147.936 45.4356 150.625C46.0018 155.297 49.1163 157.42 51.6644 157.845C54.2126 157.845 56.336 156.288 56.336 155.297C56.9023 154.448 56.4776 154.448 56.4776 153.881Z"
fill="black"
/>
<path
d="M207.102 145.105C207.102 144.539 206.536 142.557 205.545 139.442L203.422 134.771C207.102 129.533 207.102 124.436 206.536 121.888C205.97 118.774 204.413 115.659 201.865 112.545C199.316 109.431 193.088 106.316 185.301 104.193L181.196 103.202C181.196 103.202 181.196 93.2923 180.63 89.1869C180.63 86.0725 180.064 81.4009 178.506 76.7292C176.949 70.5004 173.835 64.8378 169.729 61.1571C180.064 50.2567 186.859 37.799 186.859 27.4648C186.859 7.78732 162.51 1.55849 131.932 14.0162L125.703 16.5643C125.703 16.5643 114.378 5.23917 113.811 5.23917C80.2607 -24.7725 -26.9036 94.8495 7.21344 123.87L14.4332 130.099C12.3098 135.337 11.8851 140.999 12.3098 147.228C13.3007 155.014 17.5476 162.8 23.6349 169.029C29.8637 174.692 38.0745 178.372 46.4268 178.372C59.8754 209.517 90.4533 228.062 126.128 229.194C164.492 230.185 197.051 212.065 210.5 179.93C211.491 177.806 215.172 167.472 215.172 158.129C216.021 148.644 210.783 145.105 207.102 145.105ZM49.6828 169.454C48.6918 169.454 47.1346 170.02 46.0021 169.454C34.6769 168.888 21.653 158.553 20.6621 146.096C19.6711 132.647 26.3246 122.313 38.7823 119.623C40.3395 119.057 41.8967 119.057 44.0202 119.057C50.8153 119.623 61.1495 124.72 63.6976 139.725C65.6795 153.882 62.7067 167.33 49.6828 169.454ZM36.8004 111.413C29.0144 112.97 22.3608 117.075 18.1139 123.304C15.5657 121.18 10.8941 117.075 10.3279 115.518C3.53277 103.06 17.5476 78.2864 27.4572 64.6963C51.24 30.5792 89.0377 4.67291 106.167 9.20297C109.281 10.1939 118.625 21.0944 118.625 21.0944C118.625 21.0944 101.071 31.0039 84.9323 44.4525C63.1314 60.5909 46.5683 84.94 36.8004 111.413ZM158.97 164.216L159.537 163.65C159.537 163.084 158.97 163.084 158.97 163.084C158.97 163.084 140.85 165.632 123.721 159.403C125.844 153.174 130.516 155.297 138.161 156.288C151.609 157.279 164.067 155.297 172.844 152.608C180.63 150.484 190.964 145.813 198.75 139.725C201.298 145.388 202.431 152.183 202.431 152.183C202.431 152.183 204.554 151.617 206.111 152.749C207.669 153.74 208.66 155.864 208.235 161.102C206.678 171.436 202.006 179.222 195.353 187.008C191.247 191.68 185.443 195.785 179.356 198.899C176.241 200.457 172.561 202.014 169.022 203.005C140.992 211.782 113.104 202.438 104.327 181.204C103.76 179.647 102.769 178.089 102.769 175.966C99.0887 161.951 102.203 145.388 112.679 135.054C113.245 134.488 113.67 133.497 113.67 132.506C113.67 131.515 113.104 130.948 112.679 130.382C108.998 125.144 96.6821 116.367 99.2303 99.238C100.788 86.7803 111.688 78.5695 121.456 78.9942H124.004C128.109 78.9942 132.356 79.9852 135.329 79.9852C140.992 79.9852 146.654 79.4189 152.883 74.3226C155.007 72.7654 156.564 71.2082 159.678 70.6419C160.245 70.6419 160.669 70.0757 162.226 70.6419C163.784 70.6419 165.341 71.2082 166.332 72.1992C171.57 75.8798 171.994 83.5243 172.561 89.7531C172.561 93.4338 173.127 101.645 173.127 103.768C173.693 109.006 174.684 109.997 177.799 110.988C179.356 111.554 180.913 111.979 183.036 112.545C189.832 114.668 193.937 116.226 196.485 118.774C198.042 120.331 198.609 121.888 199.033 123.446C200.024 129.108 194.362 136.328 180.347 143.123C164.775 150.343 146.654 151.9 133.772 150.343L129.1 149.776C118.766 148.219 113.104 161.668 119.191 170.445C123.296 176.107 134.197 180.354 144.531 180.354C169.446 180.354 188.557 170.02 195.353 160.677L195.919 159.686C196.485 159.12 195.919 158.695 195.353 159.12C189.69 163.225 163.784 178.797 136.32 174.126C136.32 174.126 133.206 173.559 130.091 172.568C127.543 171.577 122.872 169.454 121.739 164.216C144.956 171.011 158.97 164.216 158.97 164.216ZM81.2516 64.8378C89.6039 54.9283 100.363 46.1513 109.706 41.4796C110.272 41.4796 110.272 41.4797 110.272 42.0459C109.706 43.6032 108.149 46.1513 107.724 48.2748C107.724 48.841 108.29 48.841 108.29 48.841C113.953 44.7356 124.287 40.4887 133.206 40.064C133.772 40.064 133.772 40.6303 133.772 40.6303C132.215 41.6212 131.224 43.1784 129.667 44.7357C129.667 44.7357 129.667 45.3019 130.233 45.3019C136.462 45.3019 145.239 47.4254 150.901 50.9645C151.468 50.9645 150.901 51.9555 150.335 51.9555C141.558 49.832 127.543 48.2748 112.537 51.9555C99.0887 55.0699 89.1792 60.3078 81.9595 65.4041C81.2516 65.2625 80.8269 65.2625 81.2516 64.8378Z"
fill="black"
/>
</svg>
)

View File

@ -0,0 +1,17 @@
import React, { SVGProps } from 'react'
export const NotionLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 246 246"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M46.0982 43.7783C53.7102 49.9627 56.5657 49.4909 70.8599 48.5371L205.616 40.4456C208.474 40.4456 206.098 37.5944 205.144 37.1206L182.764 20.9415C178.476 17.6122 172.763 13.7995 161.813 14.7532L31.3283 24.2703C26.5695 24.7422 25.6191 27.1216 27.5142 29.0287L46.0982 43.7783ZM54.1887 75.1833V216.97C54.1887 224.59 57.9966 227.441 66.5672 226.97L214.664 218.4C223.239 217.929 224.194 212.688 224.194 206.497V65.6619C224.194 59.4818 221.817 56.1491 216.568 56.6248L61.805 65.6619C56.0934 66.1419 54.1883 68.9989 54.1883 75.1833H54.1887ZM200.39 82.789C201.339 87.0755 200.39 91.3581 196.095 91.84L188.96 93.2618V197.938C182.764 201.268 177.051 203.172 172.291 203.172C164.668 203.172 162.759 200.791 157.05 193.658L110.375 120.384V191.278L125.145 194.611C125.145 194.611 125.145 203.172 113.229 203.172L80.3785 205.077C79.4242 203.172 80.3785 198.418 83.7107 197.465L92.2832 195.089V101.353L80.3809 100.399C79.4261 96.1126 81.8036 89.932 88.4753 89.4525L123.716 87.0769L172.291 161.305V95.6407L159.906 94.2194C158.955 88.9792 162.759 85.1742 167.522 84.7023L200.39 82.789ZM20.3726 11.4244L156.097 1.42918C172.765 -0.000288379 177.053 0.957344 187.529 8.56689L230.854 39.0181C238.003 44.2545 240.386 45.6801 240.386 51.3884V218.4C240.386 228.867 236.572 235.057 223.242 236.005L65.624 245.523C55.6168 246 50.8541 244.574 45.6134 237.908L13.7082 196.513C7.99173 188.893 5.61426 183.192 5.61426 176.523V28.0715C5.61426 19.512 9.42842 12.3719 20.3726 11.4244V11.4244Z"
fill="black"
/>
</svg>
)

View File

@ -0,0 +1,29 @@
import React, { SVGProps } from 'react'
export const OtherLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 512 512"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M256 282C270.359 282 282 270.359 282 256C282 241.641 270.359 230 256 230C241.641 230 230 241.641 230 256C230 270.359 241.641 282 256 282Z"
fill="#e67200"
/>
<path
d="M346 282C360.359 282 372 270.359 372 256C372 241.641 360.359 230 346 230C331.641 230 320 241.641 320 256C320 270.359 331.641 282 346 282Z"
fill="#e67200"
/>
<path
d="M166 282C180.359 282 192 270.359 192 256C192 241.641 180.359 230 166 230C151.641 230 140 241.641 140 256C140 270.359 151.641 282 166 282Z"
fill="#e67200"
/>
<path
d="M448 256C448 150 362 64 256 64C150 64 64 150 64 256C64 362 150 448 256 448C362 448 448 362 448 256Z"
stroke="#e67200"
strokeWidth="32"
strokeMiterlimit="10"
/>
</svg>
)

View File

@ -0,0 +1,17 @@
import React, { SVGProps } from 'react'
export const PipedriveLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
width="122"
height="154"
viewBox="0 0 122 154"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M72.7239 0.707031C55.7176 0.707031 45.8568 8.42417 41.1408 13.5689C40.5692 8.99581 37.5681 3.1365 25.8494 3.1365H0.268555V29.7178H10.701C12.4159 29.7178 12.9875 30.2894 12.9875 32.0043V153.621H43.2845V108.175V104.746C48.0005 109.033 57.0038 115.035 71.1519 115.035C100.734 115.035 121.456 91.5978 121.456 57.871C121.599 23.7155 101.878 0.707031 72.7239 0.707031V0.707031ZM66.5788 88.5967C50.2871 88.5967 42.8557 73.0195 42.8557 58.4427C42.8557 35.5771 55.2889 27.4312 67.0075 27.4312C81.2985 27.4312 91.0164 39.7215 91.0164 58.1568C90.8735 79.3075 78.5832 88.5967 66.5788 88.5967"
fill="#203232"
/>
</svg>
)

View File

@ -0,0 +1,55 @@
import React, { SVGProps } from 'react'
export const SalesforceLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 256 180"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M106.553 19.6508C114.801 11.0568 126.284 5.72697 138.984 5.72697C155.866 5.72697 170.595 15.1407 178.438 29.1155C185.255 26.0699 192.799 24.3759 200.738 24.3759C231.186 24.3759 255.872 49.2763 255.872 79.9911C255.872 110.71 231.186 135.61 200.738 135.61C197.022 135.61 193.39 135.238 189.878 134.528C182.97 146.849 169.808 155.173 154.7 155.173C148.376 155.173 142.394 153.712 137.068 151.115C130.066 167.585 113.752 179.134 94.7386 179.134C74.9385 179.134 58.0638 166.605 51.5864 149.035C48.7557 149.636 45.823 149.949 42.8139 149.949C19.2395 149.949 0.12793 130.641 0.12793 106.819C0.12793 90.8547 8.71466 76.9163 21.4727 69.459C18.8461 63.4151 17.3852 56.7446 17.3852 49.7317C17.3852 22.3358 39.6262 0.127563 67.0585 0.127563C83.1646 0.127563 97.4782 7.78532 106.553 19.6508Z"
fill="#00A1E0"
/>
<path
d="M37.1701 92.9564C37.0098 93.3754 37.2284 93.4628 37.2794 93.5357C37.7603 93.8854 38.2485 94.1368 38.7403 94.4173C41.3487 95.8017 43.8114 96.2061 46.3871 96.2061C51.6331 96.2061 54.89 93.4155 54.89 88.9235V88.8361C54.89 84.683 51.2142 83.1748 47.7642 82.0855L47.3161 81.9398C44.7149 81.0946 42.4708 80.366 42.4708 78.6537V78.5626C42.4708 77.0981 43.7823 76.0198 45.8151 76.0198C48.0738 76.0198 50.7551 76.7702 52.482 77.7247C52.482 77.7247 52.9883 78.0526 53.1741 77.5608C53.2761 77.2985 54.1505 74.9451 54.2416 74.69C54.3399 74.4132 54.1651 74.2092 53.9865 74.0999C52.0156 72.9013 49.2906 72.0816 46.4709 72.0816L45.9463 72.0852C41.1447 72.0852 37.7931 74.9851 37.7931 79.1419V79.2293C37.7931 83.6119 41.4908 85.0327 44.9554 86.0237L45.5128 86.1949C48.0374 86.9709 50.2123 87.6375 50.2123 89.4154V89.5028C50.2123 91.1276 48.7988 92.3371 46.5182 92.3371C45.633 92.3371 42.8096 92.3189 39.7603 90.3917C39.3924 90.1768 39.1774 90.0201 38.8933 89.8489C38.7439 89.7542 38.3687 89.5902 38.2047 90.0857L37.1701 92.9564Z"
fill="white"
/>
<path
d="M113.97 92.9564C113.81 93.3754 114.028 93.4628 114.079 93.5357C114.56 93.8854 115.048 94.1368 115.54 94.4173C118.149 95.8017 120.611 96.2061 123.187 96.2061C128.433 96.2061 131.69 93.4155 131.69 88.9235V88.8361C131.69 84.683 128.014 83.1748 124.564 82.0855L124.116 81.9398C121.515 81.0946 119.271 80.366 119.271 78.6537V78.5626C119.271 77.0981 120.582 76.0198 122.615 76.0198C124.874 76.0198 127.555 76.7702 129.282 77.7247C129.282 77.7247 129.788 78.0526 129.974 77.5608C130.076 77.2985 130.95 74.9451 131.041 74.69C131.14 74.4132 130.965 74.2092 130.786 74.0999C128.815 72.9013 126.09 72.0816 123.271 72.0816L122.746 72.0852C117.945 72.0852 114.593 74.9851 114.593 79.1419V79.2293C114.593 83.6119 118.291 85.0327 121.755 86.0237L122.313 86.1949C124.837 86.9709 127.016 87.6375 127.016 89.4154V89.5028C127.016 91.1276 125.599 92.3371 123.318 92.3371C122.433 92.3371 119.609 92.3189 116.56 90.3917C116.192 90.1768 115.974 90.0274 115.697 89.8489C115.602 89.787 115.158 89.6157 115.005 90.0857L113.97 92.9564Z"
fill="white"
/>
<path
d="M166.399 84.1572C166.399 86.6965 165.925 88.6965 164.993 90.11C164.071 91.509 162.676 92.1902 160.73 92.1902C158.781 92.1902 157.393 91.5126 156.486 90.11C155.568 88.7001 155.102 86.6965 155.102 84.1572C155.102 81.6216 155.568 79.6252 156.486 78.2263C157.393 76.8419 158.781 76.168 160.73 76.168C162.676 76.168 164.071 76.8419 164.996 78.2263C165.925 79.6252 166.399 81.6216 166.399 84.1572ZM170.778 79.4504C170.348 77.9968 169.678 76.7144 168.785 75.647C167.893 74.5759 166.763 73.7162 165.423 73.0896C164.086 72.4666 162.504 72.1497 160.73 72.1497C158.952 72.1497 157.371 72.4666 156.034 73.0896C154.694 73.7162 153.564 74.5759 152.668 75.647C151.779 76.7181 151.109 78.0004 150.675 79.4504C150.249 80.8967 150.034 82.4778 150.034 84.1572C150.034 85.8367 150.249 87.4214 150.675 88.8641C151.109 90.314 151.776 91.5964 152.672 92.6675C153.564 93.7385 154.697 94.5946 156.034 95.203C157.375 95.8114 158.952 96.1211 160.73 96.1211C162.504 96.1211 164.082 95.8114 165.423 95.203C166.76 94.5946 167.893 93.7385 168.785 92.6675C169.678 91.6 170.348 90.3177 170.778 88.8641C171.208 87.4178 171.423 85.833 171.423 84.1572C171.423 82.4814 171.208 80.8967 170.778 79.4504Z"
fill="white"
/>
<path
d="M206.738 91.5128C206.592 91.0865 206.18 91.2468 206.18 91.2468C205.543 91.4909 204.865 91.7168 204.144 91.8297C203.412 91.9427 202.607 92.001 201.743 92.001C199.623 92.001 197.94 91.3707 196.734 90.1248C195.524 88.8788 194.847 86.8642 194.854 84.1392C194.861 81.6583 195.459 79.793 196.534 78.3722C197.601 76.9587 199.226 76.2337 201.393 76.2337C203.2 76.2337 204.577 76.4414 206.02 76.8968C206.02 76.8968 206.366 77.0461 206.53 76.5944C206.913 75.5306 207.197 74.7692 207.605 73.5998C207.721 73.2683 207.437 73.1262 207.335 73.0861C206.767 72.8639 205.426 72.5032 204.414 72.3502C203.466 72.2045 202.359 72.128 201.128 72.128C199.288 72.128 197.648 72.4413 196.246 73.0679C194.847 73.6909 193.659 74.5506 192.719 75.6217C191.779 76.6928 191.065 77.9751 190.588 79.4251C190.114 80.8714 189.874 82.4597 189.874 84.1392C189.874 87.7713 190.854 90.7077 192.788 92.8571C194.727 95.0138 197.637 96.1104 201.434 96.1104C203.678 96.1104 205.98 95.655 207.634 95.0029C207.634 95.0029 207.951 94.8498 207.813 94.4819L206.738 91.5128Z"
fill="white"
/>
<path
d="M214.399 81.7249C214.607 80.315 214.997 79.1419 215.598 78.2275C216.505 76.8395 217.889 76.0781 219.835 76.0781C221.78 76.0781 223.066 76.8431 223.988 78.2275C224.6 79.1419 224.866 80.366 224.971 81.7249H214.399ZM229.143 78.6246C228.771 77.222 227.849 75.8049 227.245 75.1564C226.29 74.129 225.358 73.4114 224.432 73.0106C223.223 72.4933 221.773 72.1509 220.184 72.1509C218.334 72.1509 216.654 72.4605 215.292 73.1017C213.926 73.7429 212.778 74.6172 211.878 75.7065C210.978 76.7921 210.301 78.0854 209.871 79.5536C209.437 81.0145 209.219 82.6065 209.219 84.2859C209.219 85.9945 209.445 87.5866 209.893 89.0183C210.344 90.461 211.066 91.7324 212.042 92.7852C213.015 93.8454 214.268 94.676 215.769 95.2553C217.259 95.8309 219.07 96.1296 221.15 96.1259C225.43 96.1114 227.686 95.1569 228.614 94.6432C228.778 94.5521 228.935 94.3918 228.738 93.9328L227.769 91.2187C227.624 90.8143 227.212 90.9637 227.212 90.9637C226.152 91.3572 224.644 92.0639 221.128 92.0566C218.829 92.053 217.124 91.3754 216.057 90.3152C214.96 89.2296 214.425 87.6339 214.33 85.3825L229.154 85.3971C229.154 85.3971 229.543 85.3898 229.584 85.0109C229.598 84.8506 230.094 81.9653 229.143 78.6246Z"
fill="white"
/>
<path
d="M95.6834 81.7249C95.8947 80.315 96.2809 79.1419 96.882 78.2275C97.7891 76.8395 99.1735 76.0781 101.119 76.0781C103.064 76.0781 104.35 76.8431 105.276 78.2275C105.884 79.1419 106.15 80.366 106.256 81.7249H95.6834ZM110.423 78.6246C110.052 77.222 109.134 75.8049 108.529 75.1564C107.574 74.129 106.642 73.4114 105.716 73.0106C104.507 72.4933 103.057 72.1509 101.469 72.1509C99.6215 72.1509 97.9385 72.4605 96.5759 73.1017C95.2098 73.7429 94.0622 74.6172 93.1624 75.7065C92.2625 76.7921 91.5849 78.0854 91.155 79.5536C90.7252 81.0145 90.5029 82.6065 90.5029 84.2859C90.5029 85.9945 90.7288 87.5866 91.1769 89.0183C91.6286 90.461 92.35 91.7324 93.3263 92.7852C94.299 93.8454 95.5522 94.676 97.0532 95.2553C98.5432 95.8309 100.354 96.1296 102.434 96.1259C106.715 96.1114 108.97 95.1569 109.899 94.6432C110.063 94.5521 110.219 94.3918 110.023 93.9328L109.057 91.2187C108.908 90.8143 108.496 90.9637 108.496 90.9637C107.436 91.3572 105.931 92.0639 102.409 92.0566C100.113 92.053 98.4084 91.3754 97.341 90.3152C96.2444 89.2296 95.7089 87.6339 95.6142 85.3825L110.438 85.3971C110.438 85.3971 110.828 85.3898 110.868 85.0109C110.882 84.8506 111.378 81.9653 110.423 78.6246Z"
fill="white"
/>
<path
d="M63.6412 91.4308C63.062 90.9681 62.9818 90.8515 62.7851 90.5528C62.4936 90.0974 62.3443 89.4489 62.3443 88.6256C62.3443 87.3214 62.7742 86.3851 63.6667 85.7548C63.6558 85.7585 64.9418 84.6437 67.9655 84.6838C70.0895 84.7129 71.9875 85.0262 71.9875 85.0262V91.7659H71.9911C71.9911 91.7659 70.1077 92.1703 67.9874 92.2978C64.9709 92.48 63.6303 91.4271 63.6412 91.4308ZM69.5394 81.0152C68.9382 80.9715 68.1586 80.946 67.226 80.946C65.9546 80.946 64.7269 81.1063 63.5756 81.4159C62.4171 81.7256 61.3752 82.2101 60.479 82.8513C59.5792 83.4961 58.8542 84.3195 58.3296 85.2958C57.805 86.2722 57.5391 87.4234 57.5391 88.713C57.5391 90.0245 57.7649 91.1648 58.2167 92.0974C58.6684 93.0337 59.3205 93.8133 60.1511 94.4144C60.9745 95.0156 61.9909 95.4564 63.1713 95.7223C64.3334 95.9882 65.6522 96.123 67.0948 96.123C68.614 96.123 70.1295 95.9992 71.5977 95.7478C73.0513 95.5001 74.8364 95.1394 75.3318 95.0265C75.8237 94.9099 76.3701 94.7605 76.3701 94.7605C76.7381 94.6695 76.7089 94.276 76.7089 94.276L76.7016 80.7201C76.7016 77.7474 75.9075 75.5433 74.3446 74.1771C72.789 72.8146 70.4975 72.1261 67.5357 72.1261C66.4245 72.1261 64.6358 72.2791 63.5647 72.494C63.5647 72.494 60.326 73.1207 58.9926 74.1626C58.9926 74.1626 58.7012 74.3447 58.8615 74.7528L59.9107 77.5725C60.0419 77.9368 60.3952 77.8129 60.3952 77.8129C60.3952 77.8129 60.5082 77.7692 60.6393 77.6927C63.4918 76.1408 67.0985 76.1881 67.0985 76.1881C68.7014 76.1881 69.9328 76.5087 70.7634 77.1463C71.5722 77.7656 71.9839 78.7019 71.9839 80.6764V81.303C70.7088 81.1209 69.5394 81.0152 69.5394 81.0152Z"
fill="white"
/>
<path
d="M189.099 73.3778C189.212 73.0426 188.975 72.8823 188.877 72.8459C188.626 72.7475 187.365 72.4816 186.392 72.4197C184.531 72.3067 183.496 72.62 182.571 73.0353C181.653 73.4506 180.633 74.121 180.064 74.8824V73.079C180.064 72.8277 179.886 72.6273 179.638 72.6273H175.838C175.591 72.6273 175.412 72.8277 175.412 73.079V95.1889C175.412 95.4366 175.616 95.6406 175.864 95.6406H179.758C180.006 95.6406 180.206 95.4366 180.206 95.1889V84.1431C180.206 82.6603 180.37 81.1813 180.698 80.2523C181.019 79.3342 181.456 78.5983 181.995 78.0701C182.538 77.5455 183.154 77.1775 183.828 76.9699C184.516 76.7586 185.278 76.6893 185.817 76.6893C186.593 76.6893 187.445 76.8897 187.445 76.8897C187.729 76.9225 187.89 76.7476 187.984 76.489C188.239 75.8114 188.961 73.7822 189.099 73.3778Z"
fill="white"
/>
<path
d="M152.544 63.1306C152.07 62.9849 151.64 62.8865 151.079 62.7809C150.511 62.6789 149.833 62.6279 149.065 62.6279C146.383 62.6279 144.27 63.3856 142.788 64.8793C141.312 66.3657 140.31 68.628 139.808 71.6044L139.625 72.6063H136.259C136.259 72.6063 135.851 72.5917 135.764 73.0361L135.214 76.1218C135.174 76.4133 135.301 76.5991 135.694 76.5991H138.97L135.647 95.1496C135.388 96.6433 135.09 97.871 134.758 98.8036C134.434 99.7217 134.117 100.41 133.724 100.913C133.345 101.394 132.988 101.751 132.368 101.959C131.858 102.13 131.268 102.21 130.623 102.21C130.266 102.21 129.789 102.152 129.436 102.079C129.086 102.01 128.9 101.933 128.634 101.82C128.634 101.82 128.252 101.674 128.099 102.057C127.978 102.374 127.104 104.775 126.998 105.07C126.896 105.365 127.042 105.594 127.228 105.664C127.665 105.817 127.989 105.919 128.583 106.061C129.407 106.254 130.102 106.265 130.754 106.265C132.117 106.265 133.363 106.072 134.394 105.7C135.429 105.325 136.332 104.673 137.133 103.791C137.997 102.837 138.54 101.838 139.057 100.472C139.571 99.1242 140.012 97.4484 140.361 95.4957L143.702 76.5991H148.584C148.584 76.5991 148.995 76.6136 149.079 76.1655L149.633 73.0835C149.669 72.7884 149.545 72.6063 149.148 72.6063H144.409C144.434 72.5006 144.649 70.8321 145.192 69.2619C145.425 68.5952 145.862 68.0524 146.23 67.6808C146.595 67.3165 147.014 67.0579 147.473 66.9085C147.942 66.7555 148.478 66.6826 149.065 66.6826C149.509 66.6826 149.95 66.7336 150.281 66.8028C150.74 66.9012 150.919 66.9522 151.039 66.9886C151.524 67.1344 151.589 66.9923 151.684 66.7591L152.817 63.6479C152.934 63.3128 152.646 63.1707 152.544 63.1306Z"
fill="white"
/>
<path
d="M86.3217 95.1896C86.3217 95.4373 86.1432 95.6377 85.8955 95.6377H81.9646C81.7169 95.6377 81.542 95.4373 81.542 95.1896V63.5531C81.542 63.3054 81.7169 63.105 81.9646 63.105H85.8955C86.1432 63.105 86.3217 63.3054 86.3217 63.5531V95.1896Z"
fill="white"
/>
</svg>
)

View File

@ -0,0 +1,35 @@
import React, { SVGProps } from 'react'
export const SlackLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 464 465"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M170.123 0C144.474 0.0189602 123.716 20.8373 123.735 46.4905C123.716 72.1437 144.493 92.9621 170.142 92.981H216.55V46.5095C216.569 20.8563 195.792 0.0379205 170.123 0C170.142 0 170.142 0 170.123 0V0ZM170.123 124H46.4076C20.7583 124.019 -0.0189055 144.837 5.18081e-05 170.491C-0.0378629 196.144 20.7394 216.962 46.3887 217H170.123C195.773 216.981 216.55 196.163 216.531 170.509C216.55 144.837 195.773 124.019 170.123 124V124Z"
fill="#36C5F0"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M464 170.491C464.019 144.837 443.241 124.019 417.592 124C391.943 124.019 371.166 144.837 371.184 170.491V217H417.592C443.241 216.981 464.019 196.163 464 170.491ZM340.265 170.491V46.4905C340.284 20.8563 319.526 0.0379205 293.876 0C268.227 0.0189602 247.45 20.8373 247.469 46.4905V170.491C247.431 196.144 268.208 216.962 293.857 217C319.507 216.981 340.284 196.163 340.265 170.491Z"
fill="#2EB67D"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M293.858 464.999C319.507 464.98 340.284 444.162 340.265 418.509C340.284 392.856 319.507 372.037 293.858 372.018H247.45V418.509C247.431 444.143 268.208 464.962 293.858 464.999ZM293.858 340.98H417.592C443.242 340.962 464.019 320.143 464 294.49C464.038 268.837 443.261 248.018 417.611 247.98H293.877C268.227 247.999 247.45 268.818 247.469 294.471C247.45 320.143 268.208 340.962 293.858 340.98V340.98Z"
fill="#ECB22E"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M1.29623e-05 294.491C-0.0189444 320.144 20.7583 340.962 46.4076 340.981C72.0569 340.962 92.8341 320.144 92.8152 294.491V248H46.4076C20.7583 248.019 -0.0189444 268.837 1.29623e-05 294.491ZM123.735 294.491V418.491C123.697 444.144 144.474 464.962 170.123 465C195.773 464.981 216.55 444.163 216.531 418.51V294.528C216.569 268.875 195.791 248.057 170.142 248.019C144.474 248.019 123.716 268.837 123.735 294.491C123.735 294.509 123.735 294.491 123.735 294.491Z"
fill="#E01E5A"
/>
</svg>
)

View File

@ -0,0 +1,19 @@
import React, { SVGProps } from 'react'
export const WebflowLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 224 224"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M112 224C173.856 224 224 173.856 224 112C224 50.1441 173.856 0 112 0C50.1441 0 0 50.1441 0 112C0 173.856 50.1441 224 112 224Z"
fill="#4353FF"
/>
<path
d="M144.9 98.7016L134.75 130.692C134.75 128.242 127.75 75.1816 127.75 75.1816C111.65 75.1816 103.11 86.5916 98.6301 98.7016L86.2401 130.762C86.2401 128.452 84.4901 98.9816 84.4901 98.9816C83.8925 92.602 80.9759 86.663 76.2929 82.2897C71.6099 77.9163 65.4856 75.4122 59.0801 75.2516L72.2401 155.612C89.0401 155.612 98.1401 144.202 102.83 132.092L113.33 104.792C113.33 105.912 120.33 155.612 120.33 155.612C127.2 155.603 133.888 153.407 139.426 149.341C144.964 145.276 149.063 139.553 151.13 133.002L174.93 75.1816C158.13 75.1816 149.31 86.5916 144.83 98.7016H144.9Z"
fill="white"
/>
</svg>
)

View File

@ -0,0 +1,27 @@
import React, { SVGProps } from 'react'
export const WixLogo = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 311 121"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M178 2.29971C172 5.29971 169.4 10.8997 169.4 26.0997C169.4 26.0997 172.4 23.0997 177.2 21.2997C180.7 19.9997 183.2 18.2997 185 16.9997C190.2 13.0997 191 8.39971 191 0.199713C190.9 0.199713 182.7 -0.300287 178 2.29971Z"
fill="#FBBD71"
/>
<path
d="M141.3 5.79963C136.1 10.0996 134.8 17.4996 134.8 17.4996L118 81.8996L104.2 29.1996C102.9 23.5996 100.3 16.6996 96.4 11.8996C91.6 5.79963 81.6 5.39963 80.4 5.39963C79.5 5.39963 69.6 5.79963 64.4 11.8996C60.5 16.6996 57.9 23.5996 56.6 29.1996L43.6 81.8996L26.8 17.4996C26.8 17.4996 25.5 10.5996 20.3 5.79963C12.1 -1.60037 0 0.199629 0 0.199629L32 120.7C32 120.7 42.4 121.6 47.6 119C54.5 115.5 58 113 61.9 96.4996C65.8 81.7996 76.2 38.9996 77 35.9996C77.4 34.6996 78.3 30.7996 80.9 30.7996C83.5 30.7996 84.4 34.2996 84.8 35.9996C85.7 38.9996 96 81.7996 99.9 96.4996C104.2 112.9 107.2 115.5 114.2 119C119.4 121.6 129.8 120.7 129.8 120.7L161.6 0.199629C161.6 0.199629 149.5 -1.50037 141.3 5.79963Z"
fill="black"
/>
<path
d="M190.9 19.5996C190.9 19.5996 188.7 22.5996 184.4 25.1996C181.4 26.8996 178.8 27.7996 175.8 29.4996C170.6 32.0996 169.3 34.6996 169.3 38.5996V39.8996V46.3996V47.6996V120.3C169.3 120.3 177.5 121.2 182.7 118.6C189.6 115.1 190.9 111.7 190.9 96.9996V24.3996V19.5996Z"
fill="black"
/>
<path
d="M270.4 60.7003L311 0.600311C311 0.600311 294.2 -2.39969 285.5 5.40031C279.9 10.2003 274.3 19.2003 274.3 19.2003L259.6 40.8003C258.7 42.1003 257.9 43.0003 256.6 43.0003C255.3 43.0003 254 41.7003 253.6 40.8003L238.9 19.2003C238.9 19.2003 232.9 10.6003 227.7 5.40031C219.1 -2.39969 202.2 0.600311 202.2 0.600311L241.5 60.6003L201.3 120.6C201.3 120.6 219 122.8 227.7 115C233.3 110.2 238.5 102 238.5 102L253.2 80.4003C254.1 79.1003 254.9 78.2003 256.2 78.2003C257.5 78.2003 258.8 79.5003 259.2 80.4003L273.9 102C273.9 102 279.5 110.2 284.7 115C293.3 122.8 310.6 120.6 310.6 120.6L270.4 60.7003Z"
fill="black"
/>
</svg>
)

View File

@ -0,0 +1,31 @@
import React from 'react'
export const WordpressLogo = (props: React.SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 123 123"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M8.70801 61.2601C8.70801 82.0621 20.797 100.039 38.327 108.558L13.258 39.8721C10.342 46.4081 8.70801 53.6411 8.70801 61.2601Z"
fill="#464342"
/>
<path
d="M96.7396 58.608C96.7396 52.113 94.4066 47.615 92.4056 44.114C89.7416 39.785 87.2446 36.119 87.2446 31.79C87.2446 26.959 90.9086 22.462 96.0696 22.462C96.3026 22.462 96.5236 22.491 96.7506 22.504C87.4006 13.938 74.9436 8.70801 61.2616 8.70801C42.9016 8.70801 26.7486 18.128 17.3516 32.396C18.5846 32.433 19.7466 32.459 20.7336 32.459C26.2306 32.459 34.7396 31.792 34.7396 31.792C37.5726 31.625 37.9066 35.786 35.0766 36.121C35.0766 36.121 32.2296 36.456 29.0616 36.622L48.1996 93.547L59.7006 59.054L51.5126 36.62C48.6826 36.454 46.0016 36.119 46.0016 36.119C43.1696 35.953 43.5016 31.623 46.3336 31.79C46.3336 31.79 55.0126 32.457 60.1766 32.457C65.6726 32.457 74.1826 31.79 74.1826 31.79C77.0176 31.623 77.3506 35.784 74.5196 36.119C74.5196 36.119 71.6666 36.454 68.5046 36.62L87.4966 93.114L92.7386 75.597C95.0106 68.328 96.7396 63.107 96.7396 58.608Z"
fill="#464342"
/>
<path
d="M62.184 65.8574L46.416 111.676C51.124 113.06 56.103 113.817 61.262 113.817C67.382 113.817 73.251 112.759 78.714 110.838C78.573 110.613 78.445 110.374 78.34 110.114L62.184 65.8574Z"
fill="#464342"
/>
<path
d="M107.376 36.0459C107.602 37.7199 107.73 39.5169 107.73 41.4499C107.73 46.7829 106.734 52.7779 103.734 60.2739L87.6807 106.687C103.305 97.5759 113.814 80.6489 113.814 61.2609C113.815 52.1239 111.481 43.5319 107.376 36.0459Z"
fill="#464342"
/>
<path
d="M61.262 0C27.483 0 0 27.481 0 61.26C0 95.043 27.483 122.523 61.262 122.523C95.04 122.523 122.527 95.043 122.527 61.26C122.526 27.481 95.04 0 61.262 0ZM61.262 119.715C29.032 119.715 2.809 93.492 2.809 61.26C2.809 29.03 29.031 2.809 61.262 2.809C93.491 2.809 119.712 29.03 119.712 61.26C119.712 93.492 93.491 119.715 61.262 119.715Z"
fill="#464342"
/>
</svg>
)

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,116 @@
import React from 'react'
import { Flex, Heading, SimpleGrid, Stack, Text } from '@chakra-ui/react'
import { AirtableLogo } from './icons/airtable'
import { FacebookPixelLogo } from './icons/facebook-pixel'
import { GmailLogo } from './icons/gmail'
import { GoogleSheetLogo } from './icons/google-sheets'
import { GoogleTagManagerLogo } from './icons/google-tag-manager'
import { HubspotLogo } from './icons/hubspot'
import { MailChimpLogo } from './icons/mailchimp'
import { NotionLogo } from './icons/notion'
import { OtherLogo } from './icons/other'
import { SalesforceLogo } from './icons/salesforce'
import { SlackLogo } from './icons/slack'
import { WebflowLogo } from './icons/webflow'
import { WixLogo } from './icons/wix'
import { WordpressLogo } from './icons/wordpress'
import { ZapierLogo } from './icons/zapier'
import { GlobeIcon } from '../../../assets/icons/GlobeIcon'
export const IntegrateInYourWorkflow = () => {
return (
<Flex justifyContent="center">
<Stack
pt={32}
w="full"
px="4"
spacing={20}
align={['flex-start', 'center']}
>
<Stack spacing="6" align={['flex-start', 'center']}>
<Flex
boxSize="50px"
bgColor="blue.500"
rounded="lg"
color="white"
justify="center"
align="center"
shadow="lg"
>
<GlobeIcon boxSize="30px" />
</Flex>
<Stack>
<Heading as="h1">
Integrate it in your workflow in 5 minutes
</Heading>
<Text
color="gray.500"
size="lg"
fontWeight="semibold"
textAlign={['left', 'center']}
>
Connect your form to any app in an instant
</Text>
</Stack>
<Text maxW="700px" textAlign={['left', 'center']}>
Typebot comes with native integrations that allow you to connect
your form with your existing eco system
</Text>
</Stack>
<SimpleGrid
columns={5}
spacing={{ base: 4, lg: 20 }}
maxW="900px"
w="full"
>
<Flex justifyContent="center" alignItems="center">
<GoogleSheetLogo width="70%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<SlackLogo width="90%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<HubspotLogo width="90%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<AirtableLogo width="90%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<GmailLogo width="100%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<FacebookPixelLogo width="80%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<GoogleTagManagerLogo width="90%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<MailChimpLogo width="80%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<SalesforceLogo width="100%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<ZapierLogo width="100%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<WordpressLogo width="90%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<WixLogo width="90%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<NotionLogo width="70%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<WebflowLogo width="80%" />
</Flex>
<Flex justifyContent="center" alignItems="center">
<OtherLogo width="80%" />
</Flex>
</SimpleGrid>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1,57 @@
import React from 'react'
import { Box, Flex, Heading, Stack, Text } from '@chakra-ui/react'
import inDepthAnalyticsSrc from 'public/images/homepage/analytics.png'
import Image from 'next/image'
import { AnalyticsIcon } from 'assets/icons/AnalyticsIcon'
export const IterateQuickly = () => {
return (
<Flex as="section" justify="center">
<Stack
style={{ maxWidth: '1200px' }}
pt={32}
w="full"
px="4"
spacing={6}
flexDir={['column', 'row-reverse']}
justifyContent="space-between"
alignItems="center"
>
<Stack spacing="6" maxW="500px">
<Flex
boxSize="50px"
bgColor="blue.500"
rounded="lg"
color="white"
justify="center"
align="center"
shadow="lg"
>
<AnalyticsIcon boxSize="30px" />
</Flex>
<Stack>
<Heading as="h1">
Iterate quickly and optimize the conversion
</Heading>
<Text color="gray.500" size="lg">
Each question has a cost in your drop-off rate.
</Text>
</Stack>
<Text>
Typebot generates an in-depth analytics graph report with completion
and drop-off rates. That helps you know at a glance a potential
bottleneck in your form. <br />
All you need to do is to fix it and hit the Publish button.
</Text>
</Stack>
<Box rounded="md" shadow="lg" maxW="500px">
<Image
src={inDepthAnalyticsSrc}
alt="incomplete results illustration"
placeholder="blur"
/>
</Box>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1,23 @@
import { Stack, StackProps } from '@chakra-ui/react'
import * as React from 'react'
import { ListItemProps } from './ListItem'
export const List = (props: StackProps) => {
const { children, ...stackProps } = props
const items = React.useMemo(
() =>
React.Children.toArray(children)
.filter<React.ReactElement<ListItemProps>>(React.isValidElement)
.map((item, index, array) =>
index + 1 === array.length
? React.cloneElement(item, { isLastItem: true })
: item
),
[children]
)
return (
<Stack as="ul" {...stackProps}>
{items}
</Stack>
)
}

View File

@ -0,0 +1,64 @@
import {
Stack,
Flex,
Circle,
Text,
useColorModeValue,
Heading,
StackProps,
} from '@chakra-ui/react'
import * as React from 'react'
export interface ListItemProps extends StackProps {
title: string
circleActivated?: boolean
subTitle?: string
icon?: React.ReactElement
isLastItem?: boolean
}
export const ListItem = (props: ListItemProps) => {
const {
title,
subTitle,
icon,
isLastItem,
children,
circleActivated = true,
...stackProps
} = props
return (
<Stack as="li" direction="row" spacing="4" {...stackProps}>
<Flex direction="column" alignItems="center" aria-hidden="true">
<Circle
bg={circleActivated ? 'blue.500' : 'gray.500'}
size="12"
borderWidth="4px"
borderColor={useColorModeValue('white', 'gray.800')}
color={useColorModeValue('white', 'black')}
>
{icon}
</Circle>
{!isLastItem && <Flex flex="1" borderRightWidth="1px" mb="-12" />}
</Flex>
<Stack spacing="4" pt="1" flex="1">
<Flex direction="column" mt="2">
<Heading
fontSize="2xl"
fontWeight="bold"
color={subTitle ? 'gray.600' : 'blue.400'}
>
{title}
</Heading>
{subTitle && (
<Text fontSize="sm" color="gray.600">
{subTitle}
</Text>
)}
</Flex>
<Flex>{children}</Flex>
</Stack>
</Stack>
)
}

View File

@ -0,0 +1,12 @@
import { Box, BoxProps, useColorModeValue } from '@chakra-ui/react'
import * as React from 'react'
export const Placeholder = (props: BoxProps) => (
<Box
bg={useColorModeValue('gray.50', 'gray.700')}
width="full"
height="32"
rounded="xl"
{...props}
/>
)

View File

@ -0,0 +1,38 @@
import * as React from 'react'
import { Box } from '@chakra-ui/react'
import { List } from './List'
import { ListItem } from './ListItem'
export type VerticalListItem = {
title: string
isActivated?: boolean
subTitle?: string
icon?: React.ReactElement
content: React.ReactNode
}
type Props = {
items: VerticalListItem[]
}
export const ListWithVerticalLines = ({ items }: Props) => {
return (
<Box as="section">
<Box maxW="2xl" mx="auto" p={{ base: '4', md: '8' }}>
<List spacing="12">
{items.map((item, idx) => (
<ListItem
key={idx}
title={item.title}
subTitle={item.subTitle}
icon={item.icon}
circleActivated={item.isActivated}
>
{item.content}
</ListItem>
))}
</List>
</Box>
</Box>
)
}

View File

@ -0,0 +1,114 @@
import React from 'react'
import { chakra, Flex, Heading, Stack, Text, VStack } from '@chakra-ui/react'
import {
ListWithVerticalLines,
VerticalListItem,
} from './ListWithVerticalLines'
export const MarketingCampaignsRecipe = () => {
return (
<Flex as="section" justify="center">
<Stack style={{ maxWidth: '1200px' }} pt={32} w="full" px="4" spacing={6}>
<VStack>
<Heading as="h1" textAlign="center">
Easy marketing campaign recipe
</Heading>
<Text color="gray.500" size="lg" textAlign="center">
Typebot takes care of almost everything in your campaign.
</Text>
</VStack>
<ListWithVerticalLines items={items} />
</Stack>
</Flex>
)
}
const items: VerticalListItem[] = [
{
title: 'Create a Landing Page',
subTitle: 'This is not handled by Typebot',
icon: <Text fontWeight="bold">1</Text>,
content: (
<Text>
You create a personalized landing page for the customers you are
targeting for this campaign.
</Text>
),
isActivated: false,
},
{
title: 'Create a lead generation form',
icon: <Text fontWeight="bold">2</Text>,
content: (
<Stack>
<Text>You need to create a form in order to qualify your lead</Text>
<Text>
Typebot allows you to create a{' '}
<chakra.span fontWeight="bold">high-converting</chakra.span> form in a
few minutes with a{' '}
<chakra.span fontWeight="bold">
dead simple building experience
</chakra.span>
</Text>
</Stack>
),
},
{
title: 'Connect the form to your existing tools',
icon: <Text fontWeight="bold">3</Text>,
content: (
<Stack>
<Text>
You need to collect your generated leads in your CRM (Hubspot,
Pipedrive) or in a Google Sheets for example.
</Text>
<Text fontWeight="bold">
With Typebot, you connect your form to your existing tools in a few
clicks thanks to our native integrations.
</Text>
</Stack>
),
},
{
title: 'Embed the form in your landing page',
icon: <Text fontWeight="bold">4</Text>,
content: (
<Stack>
<Text>
Your form needs to be embedded in your landing page. Most of the time,
it is painful when you're not a coder.
</Text>
<Text>
Typebot helps you easily embed your form with a dedicated library that
handles everything.
</Text>
</Stack>
),
},
{
title: 'Run your campaign',
subTitle: 'This is not handled by Typebot',
icon: <Text fontWeight="bold">5</Text>,
content: <Text>This is not handled by Typebot</Text>,
isActivated: false,
},
{
title: 'Iterate & improve your conversion',
icon: <Text fontWeight="bold">6</Text>,
content: (
<Stack>
<Text>
When a marketing campaign is launched you don't sit and wait for the
results. You have to analyse the results and potentially improve
things in order to increase the conversion rate.
</Text>
<Text>
Typebot comes with tools to analyse your typebot performance in real
time and helps you iterate quickly on improvements so that you
optimise your conversion rate and your campaign budget.{' '}
</Text>
</Stack>
),
},
]

View File

@ -0,0 +1,55 @@
import React from 'react'
import { Box, Flex, Heading, Stack, Text } from '@chakra-ui/react'
import { EyeDropIcon } from 'assets/icons/EyeDropIcon'
import Image from 'next/image'
import nativeFeelingSrc from 'public/images/homepage/native-feeling.png'
export const NativeFeeling = () => {
return (
<Flex justify="center">
<Stack
style={{ maxWidth: '1200px' }}
pt={32}
w="full"
px="4"
spacing={6}
direction={['column', 'row']}
>
<Stack spacing="6">
<Flex
boxSize="50px"
bgColor="blue.500"
rounded="lg"
color="white"
justify="center"
align="center"
shadow="lg"
>
<EyeDropIcon boxSize="30px" />
</Flex>
<Stack>
<Heading as="h1">Native feeling for a higher conversion</Heading>
<Text color="gray.500" size="lg">
As if you spent time crafting this form by hand
</Text>
</Stack>
<Text>
A form that doesn't feel native to your landing page will impact
dramatically its conversion potential
<br />
Typebot allows you to integrate the form in your landing page as if
it were specifically designed for it. You can customize pretty much
anything.
</Text>
</Stack>
<Box rounded="md" shadow="lg" maxW="700px">
<Image
src={nativeFeelingSrc}
alt="native feeling illustration"
placeholder="blur"
/>
</Box>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1,59 @@
import React from 'react'
import { Box, chakra, Flex, Heading, Stack, Text } from '@chakra-ui/react'
import incompleteResultsSrc from 'public/images/homepage/incomplete-results.png'
import Image from 'next/image'
import { AlbumsIcon } from 'assets/icons/AlbumsIcon'
export const DontLooseData = () => {
return (
<Flex justify="center">
<Stack
style={{ maxWidth: '1200px' }}
pt={32}
w="full"
px="4"
spacing={6}
direction={['column', 'row']}
>
<Stack spacing="6">
<Flex
boxSize="50px"
bgColor="blue.500"
rounded="lg"
color="white"
justify="center"
align="center"
shadow="lg"
>
<AlbumsIcon boxSize="30px" />
</Flex>
<Stack>
<Heading as="h1">Stop losing data from your forms</Heading>
<Text color="gray.500" size="lg">
Each answered question has a huge value
</Text>
</Stack>
<Text>
nstead of collecting it only when it is fully submitted, with a
Typebot form,{' '}
<chakra.span fontWeight="bold">
you collect the result as soon as the user answers the first
question.
</chakra.span>
<br />
You have access to all the incomplete results in your dashboard so
that it helps you figure out how you can properly improve your form
</Text>
</Stack>
<Box rounded="md" shadow="lg" maxW="700px">
<Image
src={incompleteResultsSrc}
alt="incomplete results illustration"
placeholder="blur"
/>
</Box>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1,62 @@
import React from 'react'
import { Box, Flex, Heading, Stack, Text } from '@chakra-ui/react'
import ConversionGraderSrc from 'public/images/homepage/conversion-grader.png'
import Image from 'next/image'
import { BuildIcon } from 'assets/icons/BuildIcon'
export const StopSpendingTimeOnBuilding = () => {
return (
<Flex justifyContent="center">
<Stack
style={{ maxWidth: '1200px' }}
pt={32}
w="full"
px="4"
spacing={6}
direction={['column', 'row']}
justifyContent="space-between"
alignItems="center"
>
<Stack spacing="6" maxW="500px">
<Flex
boxSize="50px"
bgColor="blue.500"
rounded="lg"
color="white"
justify="center"
align="center"
shadow="lg"
>
<BuildIcon boxSize="30px" />
</Flex>
<Stack>
<Heading as="h1">
Stop wasting your time on building the form
</Heading>
<Text color="gray.500" size="lg">
Easy building experience and a grader to make your life easier
</Text>
</Stack>
<Text>
A form should be improved over time based on its performance. You
shouldn't spend time working on the "perfect" first version.
<br />
Typebot comes with multiple verified templates to choose from.
<br />
And it offers a grader tool that gives a score your form in
real-time based on best practices we collected from high-performing
forms
</Text>
</Stack>
<Box rounded="md" shadow="lg" maxW="400px">
<Image
src={ConversionGraderSrc}
alt="conversion grader illustration"
placeholder="blur"
/>
</Box>
</Stack>
</Flex>
)
}

View File

@ -0,0 +1,13 @@
import { Button, ButtonProps } from '@chakra-ui/react'
import * as React from 'react'
export const ActionButton = (props: ButtonProps) => (
<Button
colorScheme="blue"
size="lg"
w="full"
fontWeight="extrabold"
py={{ md: '8' }}
{...props}
/>
)

View File

@ -0,0 +1,28 @@
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"
pb="6"
pt="16"
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,79 @@
import {
Flex,
Heading,
List,
ListIcon,
ListItem,
Text,
useColorModeValue,
VStack,
} from '@chakra-ui/react'
import * as React from 'react'
import { CheckIcon } from '../../../assets/icons/CheckIcon'
import { Card, CardProps } from './Card'
export interface PricingCardData {
features: string[]
name: string
price: string
}
interface PricingCardProps extends CardProps {
data: PricingCardData
icon?: JSX.Element
beforeButtonLabel?: string
button: React.ReactElement
}
export const PricingCard = (props: PricingCardProps) => {
const { data, icon, button, beforeButtonLabel, ...rest } = props
const { features, price, name } = data
const accentColor = useColorModeValue('blue.500', 'blue.200')
return (
<Card rounded="xl" {...rest}>
<VStack spacing={6}>
{icon}
<Heading size="md" fontWeight="extrabold">
{name}
</Heading>
</VStack>
<Flex
align="flex-end"
justify="center"
fontWeight="extrabold"
color={accentColor}
my="8"
>
<Heading size="2xl" fontWeight="inherit" lineHeight="0.9em">
{price}
</Heading>
{(price.includes('$') || price.includes('€')) && (
<Text fontWeight="inherit" fontSize="xl">
/ mo
</Text>
)}
</Flex>
<List spacing="4" mb="8" maxW="30ch" mx="auto">
{features.map((feature, index) => (
<ListItem fontWeight="medium" key={index}>
<ListIcon
fontSize="xl"
as={CheckIcon}
marginEnd={2}
color={accentColor}
fill="#0042da"
/>
{feature}
</ListItem>
))}
</List>
{beforeButtonLabel && (
<Text textAlign="center" mb="4" color="gray.600">
{beforeButtonLabel}
</Text>
)}
{button}
</Card>
)
}

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/signup"
>
Create a typebot
</Button>
<Text fontSize="sm" fontStyle="italic" color="gray.600">
It&apos;s free!
</Text>
</VStack>
)

View File

@ -0,0 +1,73 @@
import React, { ReactNode } from 'react'
import { Box, Container, Heading, SimpleGrid, Stack } from '@chakra-ui/react'
import { NextChakraLink } from './nextChakraAdapters/NextChakraLink'
import { Logo } from 'assets/icons/Logo'
const facebookGroupUrl = 'https://www.facebook.com/groups/typebot'
const typebotLinkedInUrl = 'https://www.linkedin.com/company/typebot'
const typebotTwitterUrl = 'https://twitter.com/Typebot_io'
export const contactUrl = 'https://bot.typebot.io/landing-page-bubble-en'
export const roadmapLink = 'https://feedback.typebot.io/roadmap'
export const Footer = () => {
return (
<Box w="full" bgColor="gray.50">
<Container as={Stack} maxW={'1000px'} py={10}>
<SimpleGrid columns={[1, 2, 5]} spacing={8} px={2}>
<Stack spacing={6}>
<Box>
<Logo boxSize="30px" />
</Box>
</Stack>
<Stack align={'flex-start'}>
<ListHeader>Product</ListHeader>
<NextChakraLink href={roadmapLink} isExternal>
Roadmap
</NextChakraLink>
<NextChakraLink href={'/blog'}>Blog</NextChakraLink>
<NextChakraLink href={'/pricing'}>Pricing</NextChakraLink>
</Stack>
<Stack align={'flex-start'}>
<ListHeader>Comparisons</ListHeader>
<NextChakraLink href="/vs-typeform">VS Typeform</NextChakraLink>
<NextChakraLink href="/vs-landbot">VS Landbot</NextChakraLink>
<NextChakraLink href="/vs-tally">VS Tally</NextChakraLink>
</Stack>
<Stack align={'flex-start'}>
<ListHeader>Community</ListHeader>
<NextChakraLink href={facebookGroupUrl} isExternal>
Facebook Group
</NextChakraLink>
<NextChakraLink href={typebotTwitterUrl} isExternal>
Twitter
</NextChakraLink>
<NextChakraLink href={typebotLinkedInUrl} isExternal>
LinkedIn
</NextChakraLink>
</Stack>
<Stack align={'flex-start'}>
<ListHeader>Company</ListHeader>
<NextChakraLink href="mailto:baptiste@typebot.io">
Contact
</NextChakraLink>
<NextChakraLink href={'/terms-of-service'}>
Terms of Service
</NextChakraLink>
<NextChakraLink href={'/privacy-policies'}>
Privacy Policy
</NextChakraLink>
</Stack>
</SimpleGrid>
</Container>
</Box>
)
}
const ListHeader = ({ children }: { children: ReactNode }) => {
return (
<Heading fontWeight={'500'} fontSize={'lg'} mb={2}>
{children}
</Heading>
)
}

View File

@ -0,0 +1,5 @@
import { Box, BoxProps } from '@chakra-ui/react'
import { HTMLMotionProps, motion } from 'framer-motion'
export type MotionBoxProps = BoxProps & HTMLMotionProps<'div'>
export const MotionBox = motion<BoxProps>(Box)

View File

@ -0,0 +1,142 @@
import {
Box,
Button,
Flex,
FlexProps,
HStack,
useDisclosure,
useColorModeValue as mode,
Heading,
} from '@chakra-ui/react'
import * as React from 'react'
import { Logo } from 'assets/icons/Logo'
import { NextChakraLink } from '../nextChakraAdapters/NextChakraLink'
import { NavLink } from './NavLink'
import { NavMenu } from './NavMenu'
import { Submenu } from './Submenu'
import { ToggleButton } from './ToggleButton'
import { Link } from './_data'
const MobileNavContext = ({
links,
...props
}: { links: Link[] } & FlexProps) => {
const { isOpen, onToggle } = useDisclosure()
return (
<>
<Flex
align="center"
justify="space-between"
className="nav-content__mobile"
color={mode('white', 'white')}
{...props}
>
<HStack as={NextChakraLink} href="/" rel="home" ml="2">
<Logo boxSize="35px" />
<Heading as="p" fontSize="lg">
Typebot
</Heading>
</HStack>
<Box>
<ToggleButton isOpen={isOpen} onClick={onToggle} />
</Box>
</Flex>
<NavMenu animate={isOpen ? 'open' : 'closed'}>
{links.map((link, idx) =>
link.children ? (
<Submenu.Mobile key={idx} link={link} />
) : (
<NavLink.Mobile key={idx} href={link.href ?? '#'}>
{link.label}
</NavLink.Mobile>
)
)}
<Button
as={NextChakraLink}
href="https://app.typebot.io/signin"
colorScheme="blue"
variant="outline"
w="full"
size="lg"
mt="5"
>
Sign in
</Button>
<Button
as={NextChakraLink}
href="https://app.typebot.io/signup"
colorScheme="blue"
w="full"
size="lg"
mt="5"
>
Create a typebot for free
</Button>
</NavMenu>
</>
)
}
const DesktopNavContent = ({
links,
...props
}: { links: Link[] } & FlexProps) => {
return (
<Flex
className="nav-content__desktop"
align="center"
justify="space-between"
{...props}
color={mode('bg.gray800', 'white')}
>
<HStack as={NextChakraLink} href="/" rel="home">
<Logo boxSize="35px" isDark={mode(false, true)} />
<Heading as="p" fontSize="lg">
Typebot
</Heading>
</HStack>
<HStack
as="ul"
id="nav__primary-menu"
aria-label="Main Menu"
listStyleType="none"
>
{links.map((link, idx) => (
<Box as="li" key={idx} id={`nav__menuitem-${idx}`}>
{link.children ? (
<Submenu.Desktop link={link} />
) : (
<NavLink.Desktop href={link.href ?? '#'}>
{link.label}
</NavLink.Desktop>
)}
</Box>
))}
</HStack>
<HStack spacing="8" minW="240px" justify="space-between">
<Box
as={NextChakraLink}
href="https://app.typebot.io/signin"
colorScheme="blue"
variant="ghost"
fontWeight="bold"
>
Sign in
</Box>
<Button
as={NextChakraLink}
href="https://app.typebot.io/signup"
colorScheme="blue"
fontWeight="bold"
>
Create a typebot
</Button>
</HStack>
</Flex>
)
}
export const NavContent = {
Mobile: MobileNavContext,
Desktop: DesktopNavContent,
}

View File

@ -0,0 +1,48 @@
import { LinkProps as ChakraLinkProps, Button } from '@chakra-ui/react'
import { LinkProps as NextLinkProps } from 'next/link'
import * as React from 'react'
import { NextChakraLink } from '../nextChakraAdapters/NextChakraLink'
type NavLinkProps = NextLinkProps &
Omit<ChakraLinkProps, 'as'> & {
active?: boolean
}
const DesktopNavLink = (props: NavLinkProps) => {
const { href, children } = props
return (
<Button
as={NextChakraLink}
href={href}
isExternal={href.startsWith('https') && !href.includes('app.typebot.io')}
variant="ghost"
colorScheme="gray"
>
{children}
</Button>
)
}
DesktopNavLink.displayName = 'DesktopNavLink'
export const MobileNavLink = (props: NavLinkProps) => {
const { href, children } = props
return (
<Button
as={NextChakraLink}
href={href ?? '#'}
isExternal={href.startsWith('https') && !href.includes('app.typebot.io')}
variant="ghost"
colorScheme="gray"
w="full"
h="3rem"
justifyContent="flex-start"
>
{children}
</Button>
)
}
export const NavLink = {
Mobile: MobileNavLink,
Desktop: DesktopNavLink,
}

View File

@ -0,0 +1,45 @@
import { useColorModeValue } from '@chakra-ui/react'
import { Variants } from 'framer-motion'
import * as React from 'react'
import { MotionBox, MotionBoxProps } from './MotionBox'
export const NavMenu = (props: MotionBoxProps) => (
<MotionBox
initial="init"
variants={variants}
outline="0"
opacity="0"
bg={useColorModeValue('white', 'gray.700')}
w="full"
shadow="lg"
px="4"
pos="absolute"
insetX="0"
pt="6"
pb="12"
{...props}
/>
)
const variants: Variants = {
init: {
opacity: 0,
y: -4,
display: 'none',
transition: { duration: 0 },
},
open: {
opacity: 1,
y: 0,
display: 'block',
transition: { duration: 0.15 },
},
closed: {
opacity: 0,
y: -4,
transition: { duration: 0.1 },
transitionEnd: {
display: 'none',
},
},
}

View File

@ -0,0 +1,30 @@
import { Box } from '@chakra-ui/react'
import * as React from 'react'
import { NavContent } from './NavContent'
import { links } from './_data'
export const Navbar = () => {
return (
<Box w="full">
<Box as="header" position="relative" zIndex="10">
<Box
as="nav"
aria-label="Main navigation"
maxW="7xl"
mx="auto"
px={{ base: '6', md: '8' }}
py="4"
>
<NavContent.Mobile
display={{ base: 'flex', lg: 'none' }}
links={links}
/>
<NavContent.Desktop
display={{ base: 'none', lg: 'flex' }}
links={links}
/>
</Box>
</Box>
</Box>
)
}

View File

@ -0,0 +1,95 @@
import { useNavMenu } from './useNavMenu'
import {
Box,
Collapse,
SimpleGrid,
useDisclosure,
Button,
} from '@chakra-ui/react'
import * as React from 'react'
import { Link } from './_data'
import { NavLink } from './NavLink'
import { NavMenu } from './NavMenu'
import { SubmenuItem as DesktopMenuItem } from './SubmenuItem'
import { ChevronDownIcon } from '../../../assets/icons/ChevronDownIcon'
interface SubmenuProps {
link: Link
}
const DesktopSubmenu = (props: SubmenuProps) => {
const { link } = props
const { isOpen, getMenuProps, getTriggerProps } = useNavMenu()
return (
<>
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
{/* @ts-ignore */}
<Button
rightIcon={<ChevronDownIcon />}
variant="ghost"
colorScheme="gray"
{...getTriggerProps()}
>
{link.label}
</Button>
<NavMenu {...getMenuProps()} animate={isOpen ? 'open' : 'closed'}>
<Box maxW="7xl" mx="auto" px="8">
<SimpleGrid spacing="10" columns={2}>
{link.children?.map((item, idx) => (
<DesktopMenuItem
key={idx}
title={item.label}
href={item.href ?? '#'}
icon={item.icon}
>
{item.description}
</DesktopMenuItem>
))}
</SimpleGrid>
</Box>
</NavMenu>
</>
)
}
const MobileSubMenu = (props: SubmenuProps) => {
const { link } = props
const { isOpen, onToggle } = useDisclosure()
return (
<Box>
<Button
textAlign="start"
type="button"
cursor="pointer"
onClick={onToggle}
paddingEnd="4"
variant="ghost"
colorScheme="gray"
h="3rem"
w="full"
justifyContent="flex-start"
>
<Box mr="4">{link.label}</Box>
<Box
as={ChevronDownIcon}
transform={`rotate(${isOpen ? '180deg' : '0deg'})`}
/>
</Button>
<Collapse in={isOpen}>
<Box pl="5">
{link.children?.map((item, idx) => (
<NavLink.Mobile key={idx} href={item.href ?? '#'}>
{item.label}
</NavLink.Mobile>
))}
</Box>
</Collapse>
</Box>
)
}
export const Submenu = {
Mobile: MobileSubMenu,
Desktop: DesktopSubmenu,
}

View File

@ -0,0 +1,75 @@
import {
Box,
Center,
HStack,
Text,
useColorModeValue as mode,
LinkProps as ChakraLinkProps,
} from '@chakra-ui/react'
import { LinkProps } from 'next/link'
import * as React from 'react'
import { ChevronRightIcon } from '../../../assets/icons/ChevronRightIcon'
import { NextChakraLink } from '../nextChakraAdapters/NextChakraLink'
type SubmenuItemProps = LinkProps &
Omit<ChakraLinkProps, 'as'> & {
title: string
icon?: React.ReactElement
children: React.ReactNode
href: string
}
export const SubmenuItem = (props: SubmenuItemProps) => {
const { title, icon, children, href, ...rest } = props
return (
<NextChakraLink
className="group"
href={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' }}
isExternal={href.startsWith('https') && !href.includes('app.typebot.io')}
{...rest}
>
<Center
aria-hidden
as="span"
flexShrink={0}
w="10"
h="10"
fontSize="3xl"
color={mode('blue.600', 'blue.400')}
>
{icon}
</Center>
<Box marginStart="3" as="dl">
<HStack as="dt">
<Text
fontWeight="semibold"
color={mode('gray.900', 'white')}
_groupHover={{ color: mode('blue.600', 'inherit') }}
>
{title}
</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')}>
{children}
</Text>
</Box>
</NextChakraLink>
)
}

View File

@ -0,0 +1,65 @@
import { Box, Center, chakra, VisuallyHidden } from '@chakra-ui/react'
import React from 'react'
const Bar = chakra('span', {
baseStyle: {
display: 'block',
pos: 'absolute',
w: '1.25rem',
h: '0.125rem',
rounded: 'full',
bg: 'currentcolor',
mx: 'auto',
insetStart: '0.125rem',
transition: 'all 0.12s',
},
})
const ToggleIcon = (props: { active: boolean }) => {
const { active } = props
return (
<Box
className="group"
data-active={active ? '' : undefined}
as="span"
display="block"
w="1.5rem"
h="1.5rem"
pos="relative"
aria-hidden
pointerEvents="none"
>
<Bar
top="0.4375rem"
_groupActive={{ top: '0.6875rem', transform: 'rotate(45deg)' }}
/>
<Bar
bottom="0.4375rem"
_groupActive={{ bottom: '0.6875rem', transform: 'rotate(-45deg)' }}
/>
</Box>
)
}
interface ToggleButtonProps {
isOpen: boolean
onClick(): void
}
export const ToggleButton = (props: ToggleButtonProps) => {
const { isOpen, onClick } = props
return (
<Center
marginStart="-6"
px="4"
py="4"
as="button"
color="gray.400"
_active={{ color: 'blue.600' }}
onClick={onClick}
>
<ToggleIcon active={isOpen} />
<VisuallyHidden>Toggle Menu</VisuallyHidden>
</Center>
)
}

View File

@ -0,0 +1,53 @@
import { BookIcon } from 'assets/icons/BookIcon'
import { DocIcon } from 'assets/icons/DocIcon'
import { MapIcon } from 'assets/icons/MapIcon'
import { PeopleCircleIcon } from 'assets/icons/PeopleCircleIcon'
import * as React from 'react'
export interface Link {
label: string
href?: string
children?: Array<{
label: string
description?: string
href: string
icon?: React.ReactElement
}>
}
export const links = [
{
label: 'Resources',
children: [
{
label: 'Blog',
description:
"Content about high-performing forms and guides on how to leverage Typebot's power",
href: '/blog',
icon: <BookIcon />,
},
{
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 our facebook community and get insights on how to create high performing surveys',
href: 'https://www.facebook.com/groups/262165102257585',
icon: <PeopleCircleIcon />,
},
],
},
{ label: 'Pricing', href: '/pricing' },
]

View File

@ -0,0 +1,127 @@
import { useDisclosure } from '@chakra-ui/react'
import { isFocusable, getOwnerDocument, isRightClick } from '@chakra-ui/utils'
import * as React from 'react'
const getTarget = (event: React.FocusEvent) =>
(event.relatedTarget || document.activeElement) as HTMLElement
type OmitMotionProps<T> = Omit<
T,
'onAnimationStart' | 'onDragStart' | 'onDragEnd' | 'onDrag'
>
export function useNavMenu() {
const { isOpen, onClose, onToggle, onOpen } = useDisclosure()
const menuRef = React.useRef<HTMLDivElement>(null)
const triggerRef = React.useRef<HTMLAnchorElement>(null)
const timeoutRef = React.useRef<number>()
React.useEffect(() => {
return () => {
if (timeoutRef.current) {
window.clearTimeout(timeoutRef.current)
}
}
}, [])
const focusMenu = () => {
timeoutRef.current = window.setTimeout(() => {
menuRef.current?.focus({ preventScroll: true })
}, 100)
}
const getTriggerProps = () => {
const triggerProps: React.ComponentPropsWithRef<'a'> = {
ref: triggerRef,
'aria-expanded': isOpen,
'aria-controls': 'menu',
'aria-haspopup': 'true',
}
triggerProps.onClick = (event: React.MouseEvent) => {
if (isRightClick(event)) return
onToggle()
if (!isOpen) {
focusMenu()
}
}
triggerProps.onBlur = (event: React.FocusEvent) => {
const target = getTarget(event)
if (isOpen && !menuRef.current?.contains(target)) {
onClose()
}
}
triggerProps.onKeyDown = (event: React.KeyboardEvent) => {
if (isOpen && event.key === 'Escape') {
onClose()
triggerRef.current?.focus({ preventScroll: true })
}
if (event.key === 'ArrowDown') {
if (!isOpen) onOpen()
focusMenu()
}
}
return triggerProps
}
const getMenuProps = () => {
const menuProps: OmitMotionProps<React.ComponentPropsWithRef<'div'>> = {
ref: menuRef,
id: 'menu',
tabIndex: -1,
}
menuProps.onKeyDown = (event: React.KeyboardEvent) => {
if (!isOpen) return
switch (event.key) {
case 'Escape': {
onClose()
return triggerRef.current?.focus()
}
case 'ArrowDown': {
const doc = getOwnerDocument(menuRef.current)
const next = doc?.activeElement
?.nextElementSibling as HTMLAnchorElement | null
return next?.focus()
}
case 'ArrowUp': {
const doc = getOwnerDocument(menuRef.current)
const prev = doc?.activeElement
?.previousElementSibling as HTMLAnchorElement | null
const el = (prev ?? triggerRef.current) as HTMLElement
return el.focus()
}
default:
break
}
}
menuProps.onBlur = (event: React.FocusEvent) => {
const target = getTarget(event)
const shouldBlur =
isOpen &&
!target.isSameNode(triggerRef.current) &&
!menuRef.current?.contains(target)
if (shouldBlur) {
onClose()
if (!isFocusable(target)) {
triggerRef.current?.focus({ preventScroll: true })
}
}
}
return menuProps
}
return {
isOpen,
onClose,
getTriggerProps,
getMenuProps,
}
}

View File

@ -0,0 +1,34 @@
import Head from 'next/head'
import React from 'react'
export const SocialMetaTags = ({
title,
description,
currentUrl,
imagePreviewUrl,
}: {
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" />
</Head>
)

View File

@ -0,0 +1,26 @@
import { CheckIcon } from 'assets/icons/CheckIcon'
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' : ''}>
<CheckIcon 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,50 @@
import { PropsWithChildren } from 'react'
import NextLink from 'next/link'
import { LinkProps as NextLinkProps } from 'next/dist/client/link'
import {
Link as ChakraLink,
LinkProps as ChakraLinkProps,
} from '@chakra-ui/react'
import React from 'react'
export type NextChakraLinkProps = PropsWithChildren<
NextLinkProps & Omit<ChakraLinkProps, 'as'>
>
// Has to be a new component because both chakra and next share the `as` keyword
// eslint-disable-next-line react/display-name
export const NextChakraLink = React.forwardRef(
(
{
href,
as,
replace,
scroll,
shallow,
prefetch,
children,
locale,
...chakraProps
}: NextChakraLinkProps,
ref
) => {
return (
<NextLink
passHref={true}
href={href}
as={as}
replace={replace}
scroll={scroll}
shallow={shallow}
prefetch={prefetch}
locale={locale}
>
{/*eslint-disable-next-line @typescript-eslint/ban-ts-comment*/}
{/*@ts-ignore*/}
<ChakraLink ref={ref} {...chakraProps}>
{children}
</ChakraLink>
</NextLink>
)
}
)

View File

@ -0,0 +1,43 @@
import React from 'react'
import { Stack } from '@chakra-ui/react'
import Head from 'next/head'
import { Footer } from 'components/common/Footer'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
import { EndCta } from 'components/Homepage/EndCta'
import { Features } from 'components/Homepage/Features'
import { Hero } from 'components/Homepage/Hero'
import { IntegrateInYourWorkflow } from 'components/Homepage/IntegrateInYourWorkflow'
import { IterateQuickly } from 'components/Homepage/IterateQuickly'
import { MarketingCampaignsRecipe } from 'components/Homepage/MarketingCampaignRecipe'
import { NativeFeeling } from 'components/Homepage/NativeFeeling'
import { DontLooseData } from 'components/Homepage/StopLoosingData'
import { StopSpendingTimeOnBuilding } from 'components/Homepage/StopWastingTimeOnBuilding'
const Homepage = () => {
return (
<Stack w="full" overflowX="hidden">
<SocialMetaTags
title="Typebot: Conversational Form Builder"
description="Convert 4x more with beautiful conversational forms. Embed them directly in your applications without a line of code."
currentUrl={`https://www.typebot.io/`}
imagePreviewUrl={`https://www.typebot.io/images/previews/home.png`}
/>
<Head>
<link rel="alternate" hrefLang="en" href="https://www.typebot.io/" />
<link rel="alternate" hrefLang="fr" href="https://www.typebot.io/fr" />
</Head>
<Hero />
<MarketingCampaignsRecipe />
<DontLooseData />
<IterateQuickly />
<StopSpendingTimeOnBuilding />
<IntegrateInYourWorkflow />
<NativeFeeling />
<Features />
<EndCta />
<Footer />
</Stack>
)
}
export default Homepage

View File

@ -0,0 +1,78 @@
import { extendTheme } from '@chakra-ui/react'
const fonts = {
heading: 'Outfit',
body: 'Open Sans',
}
const colors = {
blue: {
50: '#e0edff',
100: '#b0caff',
200: '#7ea6ff',
300: '#4b83ff',
400: '#1a5fff',
500: '#0042da',
600: '#0036b4',
700: '#002782',
800: '#001751',
900: '#1a202c',
},
orange: {
50: '#fff1da',
100: '#ffd7ae',
200: '#ffbf7d',
300: '#ffa54c',
400: '#ff8b1a',
500: '#e67200',
600: '#b45800',
700: '#813e00',
800: '#4f2500',
900: '#200b00',
},
yellow: {
50: '#fff9da',
100: '#ffedad',
200: '#ffe17d',
300: '#ffd54b',
400: '#ffc91a',
500: '#e6b000',
600: '#b38800',
700: '#806200',
800: '#4e3a00',
900: '#1d1400',
},
}
const components = {
Button: {
defaultProps: {
colorScheme: 'blue',
},
},
NumberInput: {
defaultProps: {
focusBorderColor: 'blue.200',
},
},
Input: {
defaultProps: {
focusBorderColor: 'blue.200',
},
},
Popover: {
baseStyle: {
popper: {
width: 'fit-content',
maxWidth: 'fit-content',
},
},
},
Link: {
baseStyle: {
_hover: { textDecoration: 'none' },
},
},
}
export const theme = extendTheme({ fonts, components, colors })

View File

@ -0,0 +1,16 @@
const loadLandbot = (): Promise<void> =>
new Promise((resolve) => {
const existingScript = document.getElementById('landbot-lib')
if (!existingScript) {
const script = document.createElement('script')
script.src = 'https://static.landbot.io/landbot-3/landbot-3.0.0.js'
script.id = 'landbot-lib'
document.body.appendChild(script)
script.onload = () => {
resolve()
}
}
if (existingScript) resolve()
})
export default loadLandbot

View File

@ -0,0 +1,62 @@
import { Client } from '@notionhq/client'
const notion = new Client({
auth: process.env.NOTION_API_TOKEN,
})
export const getDatabase = async (databaseId: string) => {
const response = await notion.databases.query({
database_id: databaseId,
sorts: [
{
property: 'Created',
direction: 'descending',
},
],
filter: {
property: 'Published',
checkbox: {
equals: true,
},
},
})
return response.results
}
export const getFullDatabase = async (databaseId: string) => {
const response = await notion.databases.query({
database_id: databaseId,
sorts: [
{
property: 'Created',
direction: 'descending',
},
],
})
return response.results
}
export const getPage = async (databaseId: string, slug: string) => {
const { results } = await notion.databases.query({
database_id: databaseId,
filter: {
property: 'Slug',
text: {
equals: slug,
},
},
})
if (results.length === 0) return
const page_id = results.pop()?.id
if (!page_id) return
const response = await notion.pages.retrieve({ page_id })
return response
}
export const getBlocks = async (blockId: string) => {
const response = await notion.blocks.children.list({
block_id: blockId,
page_size: 50,
})
return response.results
}

View File

@ -0,0 +1,14 @@
const loadTypeform = (): Promise<void> =>
new Promise((resolve) => {
const existingScript = document.getElementById('typeform-lib')
if (!existingScript) {
const script = document.createElement('script')
script.innerHTML = `(function() { var qs,js,q,s,d=document, gi=d.getElementById, ce=d.createElement, gt=d.getElementsByTagName, id="typef_orm", b="https://embed.typeform.com/"; if(!gi.call(d,id)) { js=ce.call(d,"script"); js.id=id; js.src=b+"embed.js"; q=gt.call(d,"script")[0]; q.parentNode.insertBefore(js,q) } })()`
script.id = 'typeform-lib'
document.body.appendChild(script)
resolve()
}
if (existingScript) resolve()
})
export default loadTypeform

5
apps/landing-page/next-env.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@ -0,0 +1,40 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
})
const securityHeaders = [
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN',
},
]
module.exports = withBundleAnalyzer({
async headers() {
return [
{
source: '/(.*)',
headers: securityHeaders,
},
]
},
async redirects() {
return [
{
source: '/typebot-lib',
destination:
'https://unpkg.com/typebot-js@2.0.21/dist/index.umd.min.js',
permanent: true,
},
]
},
async rewrites() {
return [
{
source: '/:path*',
destination: `${process.env.VIEWER_HOST}/:path*`,
},
]
},
})

View File

@ -0,0 +1,35 @@
{
"name": "typebot.io",
"version": "1.0.0",
"scripts": {
"dev": "next dev -p 3002",
"start": "next start",
"build": "next build",
"analyze": "cross-env ANALYZE=true next build"
},
"dependencies": {
"@chakra-ui/react": "^1.8.3",
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"focus-visible": "^5.2.0",
"framer-motion": "^4",
"keen-slider": "^6.6.3",
"next": "^12.0.10",
"notion-blocks-chakra-ui": "^0.0.15",
"posthog-js": "1.17.8",
"react": "17.0.2",
"react-dom": "17.0.2",
"typebot-js": "^2.0.21",
"@notionhq/client": "^0.3.1"
},
"devDependencies": {
"@next/bundle-analyzer": "^12.0.10",
"@types/node": "^17.0.16",
"@types/react": "^17.0.39",
"autoprefixer": "^10.4.2",
"cross-env": "^7.0.3",
"eslint": "<8.0.0",
"prettier": "^2.5.1",
"typescript": "^4.5.5"
}
}

View File

@ -0,0 +1,14 @@
import React from 'react'
import 'assets/style.css'
import { ChakraProvider } from '@chakra-ui/react'
import 'focus-visible/dist/focus-visible'
import { theme } from '../lib/chakraTheme'
import { AppProps } from 'next/app'
const App = ({ Component, pageProps }: AppProps) => (
<ChakraProvider theme={theme}>
<Component {...pageProps} />
</ChakraProvider>
)
export default App

View File

@ -0,0 +1,23 @@
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
render() {
return (
<Html dir="ltr">
<Head>
<link rel="icon" type="image/png" href="/favicon.png" />
<link
href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&family=Open+Sans:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument

View File

@ -0,0 +1,202 @@
import { GetStaticPropsContext } from 'next'
import { NotionBlock, NotionText } from 'notion-blocks-chakra-ui'
import React from 'react'
import { getPage, getBlocks, getFullDatabase } from '../../lib/notion'
import Image from 'next/image'
import {
Stack,
Container,
Button,
VStack,
Heading,
HStack,
Text,
} from '@chakra-ui/react'
import {
Page,
Block,
TitlePropertyValue,
RichTextPropertyValue,
CheckboxPropertyValue,
} from '@notionhq/client/build/src/api-types'
import { Footer } from 'components/common/Footer'
import { Navbar } from 'components/common/Navbar/Navbar'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
export default function Post({
page,
blocks,
}: {
page: Page
blocks: Block[]
}) {
return (
<>
<Stack
alignItems="center"
w="full"
overflowX="hidden"
pb={20}
minH="calc(100vh - 267px)"
spacing={10}
>
{page && (
<SocialMetaTags
title={
(page.properties.Name as TitlePropertyValue).title[0]?.plain_text
}
description={
(page.properties.Description as RichTextPropertyValue)
.rich_text[0]?.plain_text
}
currentUrl={`https://www.typebot.io/blog/${
(page.properties.Slug as RichTextPropertyValue).rich_text[0]
?.plain_text
}`}
imagePreviewUrl={
(page.properties.Thumbnail as RichTextPropertyValue).rich_text[0]
?.plain_text
}
/>
)}
<Navbar />
<Container as="article" maxW="900px">
{((page?.properties?.Published as CheckboxPropertyValue | undefined)
?.checkbox ||
!page) && (
<Button
as={NextChakraLink}
href="/blog"
colorScheme="gray"
variant="outline"
size="sm"
>
{'<'} Blog
</Button>
)}
{page ? (
<>
<VStack>
<Heading as="h1" fontSize="5xl" textAlign="center" mt={6}>
<NotionText
text={(page.properties.Name as TitlePropertyValue).title}
/>
</Heading>
<Heading
fontSize="md"
fontWeight="normal"
textAlign="center"
textColor="gray.500"
>
<NotionText
text={
(page.properties.Description as RichTextPropertyValue)
.rich_text
}
/>
</Heading>
{(page.properties.Author as RichTextPropertyValue | undefined)
?.rich_text[0]?.plain_text && (
<Author
author={
(page.properties.Author as RichTextPropertyValue)
.rich_text[0]?.plain_text
}
/>
)}
</VStack>
<Stack mt={6} spacing={4} maxW="700px" mx="auto">
{blocks.map((block) => (
<NotionBlock key={block.id} block={block} />
))}
</Stack>
</>
) : (
<Text textAlign="center">Blog post not found</Text>
)}
</Container>
</Stack>
<Footer />
</>
)
}
export const getStaticPaths = async () => {
if (!process.env.NOTION_DATABASE_ID)
throw new Error("Couldn't find NOTION_DATABASE_ID")
const database = await getFullDatabase(process.env.NOTION_DATABASE_ID)
return {
paths: database.filter(pageWithSlugAndId).map((page) => ({
params: {
slug: (page.properties.Slug as RichTextPropertyValue).rich_text[0]
.plain_text,
id: page.id,
},
})),
fallback: true,
}
}
const pageWithSlugAndId = (page: Page) =>
(page.properties.Slug as RichTextPropertyValue).rich_text[0]?.plain_text &&
page.id
const Author = ({ author }: { author: string }) => {
return (
<HStack>
<Image
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
src={/\(([^)]+)\)/.exec(author)![0].slice(1, -1)}
width="30px"
height="30px"
className="rounded-full"
alt="Author's picture"
/>
<Text>{author.split(' (')[0]}</Text>
</HStack>
)
}
export const getStaticProps = async (
context: GetStaticPropsContext<{ slug: string; locale: 'fr' | 'en' }>
) => {
if (!process.env.NOTION_DATABASE_ID)
throw new Error("Couldn't find NOTION_DATABASE_ID")
if (!context.params) throw new Error("Couldn't find params")
const { slug } = context.params
const page = await getPage(process.env.NOTION_DATABASE_ID, slug)
if (!page?.id) return
const blocks = await getBlocks(page?.id)
const childBlocks = await Promise.all(
blocks
.filter((block) => block.has_children)
.map(async (block) => {
return {
id: block.id,
children: await getBlocks(block.id),
}
})
)
const blocksWithChildren = blocks.map((block) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
if (block.has_children && !block[block.type].children) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
block[block.type]['children'] = childBlocks.find(
(x) => x.id === block.id
)?.children
}
return block
})
return {
props: {
page,
blocks: blocksWithChildren,
},
revalidate: 1,
}
}

View File

@ -0,0 +1,155 @@
import React from 'react'
import {
Box,
Heading,
Image,
Text,
Container,
VStack,
SimpleGrid,
Flex,
} from '@chakra-ui/react'
import { getDatabase } from '../../lib/notion'
import {
DatePropertyValue,
Page,
RichText,
RichTextPropertyValue,
TitlePropertyValue,
} from '@notionhq/client/build/src/api-types'
import { NotionText } from 'notion-blocks-chakra-ui'
import { Footer } from 'components/common/Footer'
import { Navbar } from 'components/common/Navbar/Navbar'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
const ArticleList = ({ posts }: { posts: Page[] }) => {
return (
<>
<Flex
alignItems="center"
justifyContent="space-between"
w="full"
flexDir="column"
>
<SocialMetaTags
title="Blog"
description="Keep up to date with the latest news related to Typebot. Learn
about conversationnal forms and how to convert more."
currentUrl={`https://www.typebot.io/blog`}
imagePreviewUrl={`https://www.typebot.io/images/previews/blog.png`}
/>
<Navbar />
<VStack maxW="1200px" mt={20} pb={56}>
<VStack maxW="700px">
<Heading as="h1" fontSize="5xl">
Blog
</Heading>
<Heading
fontSize="md"
fontWeight="normal"
textAlign="center"
textColor="gray.500"
>
Keep up to date with the latest news related to Typebot. Learn
about conversationnal forms and how to convert more.
</Heading>
</VStack>
<Container maxW="1200px">
<SimpleGrid columns={[1, 2, 3]} mt={6} py={4} spacing={10}>
{posts.map((post) => (
<BlogPost
key={post.id}
slug={`/${
(post.properties.Slug as RichTextPropertyValue).rich_text[0]
?.plain_text
}`}
title={
(post.properties.Name as TitlePropertyValue).title[0]
?.plain_text
}
description={
(post.properties.Description as RichTextPropertyValue)
.rich_text
}
imageSrc={
(post.properties.Thumbnail as RichTextPropertyValue)
.rich_text[0]?.plain_text
}
date={
new Date(
(post.properties.Created as DatePropertyValue)?.date
?.start ?? ''
)
}
/>
))}
</SimpleGrid>
</Container>
</VStack>
</Flex>
<Footer />
</>
)
}
type BlogPostProps = {
slug: string
title: string
description: RichText[]
imageSrc: string
date: Date
}
const BlogPost = ({
slug,
title,
description,
imageSrc,
date,
}: BlogPostProps) => (
<NextChakraLink
href={'/blog' + slug}
w="100%"
shadow="lg"
p={4}
rounded="lg"
_hover={{ textDecoration: 'none' }}
>
<Box borderRadius="lg" overflow="hidden">
<Image
transform="scale(1.0)"
src={imageSrc}
objectFit="contain"
width="100%"
transition="0.3s ease-in-out"
_hover={{
transform: 'scale(1.05)',
}}
alt="title thumbnail"
/>
</Box>
<Heading fontSize="xl" marginTop="4">
{title}
</Heading>
<NotionText text={description} as="p" fontSize="md" marginTop="2" />
<Text textColor="gray.400" fontSize="sm" mt={2}>
{date.toDateString()}
</Text>
</NextChakraLink>
)
export const getStaticProps = async () => {
if (!process.env.NOTION_DATABASE_ID)
throw new Error("Couldn't find NOTION_DATABASE_ID")
const database = await getDatabase(process.env.NOTION_DATABASE_ID)
return {
props: {
posts: database,
},
revalidate: 1,
}
}
export default ArticleList

View File

@ -0,0 +1,5 @@
import Homepage from '../layouts/Homepage'
const App = Homepage
export default App

View File

@ -0,0 +1,120 @@
import { VStack } from '@chakra-ui/layout'
import { DarkMode, Flex, Stack } from '@chakra-ui/react'
import { Footer } from 'components/common/Footer'
import { Navbar } from 'components/common/Navbar/Navbar'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
import { BackgroundPolygons } from 'components/Homepage/Hero/BackgroundPolygons'
import { PricingCard } from 'components/PricingPage/PricingCard'
import { ActionButton } from 'components/PricingPage/PricingCard/ActionButton'
import Head from 'next/head'
import { useRouter } from 'next/router'
const Pricing = () => {
const router = useRouter()
return (
<Stack overflowX="hidden">
<Flex
pos="relative"
flexDir="column"
bgColor="blue.500"
minHeight="100vh"
alignItems="center"
pb={40}
>
<SocialMetaTags
title={'Pricing'}
description={
"99% of Typebot's features are available to all users for free."
}
currentUrl={`https://www.typebot.io/${
router.locale === 'fr' ? 'fr/' : ''
}pricing`}
imagePreviewUrl={`https://www.typebot.io/images/previews/pricing${
router.locale === 'fr' ? '-fr' : ''
}.png`}
/>
<Head>
<link
rel="alternate"
hrefLang="en"
href="https://www.typebot.io/pricing"
/>
<link
rel="alternate"
hrefLang="fr"
href="https://www.typebot.io/fr/pricing"
/>
</Head>
<BackgroundPolygons />
<DarkMode>
<Navbar />
</DarkMode>
<VStack spacing={40} w="full">
<Stack
direction={['column', 'row']}
alignItems={['stretch', 'flex-start']}
spacing={10}
px={[4, 0]}
mt={[20, 32]}
w="full"
maxW="900px"
>
<PricingCard
data={{
price: 'Free',
name: 'Basic',
features: [
'Unlimited typebots',
'Unlimited responses',
'Conditional branching and computations',
'Native integrations (Google Sheets, Webhooks, Zapier...)',
'Basic analytics (sessions, time, completion...)',
],
}}
button={
<NextChakraLink
href="https://app.typebot.io/signup"
_hover={{ textDecor: 'none' }}
>
<ActionButton variant="outline">Try now</ActionButton>
</NextChakraLink>
}
/>
<PricingCard
data={{
price: '$30',
name: 'Pro',
features: [
'Everything in Basic',
'Branding removed',
'View incomplete submissions',
'In-depth drop off analytics',
'Custom domains',
'Organize typebots in folders',
'Unlimited uploads',
'Custom Google Analytics events',
],
}}
beforeButtonLabel={"The only form builder you'll need"}
button={
<NextChakraLink
href="https://app.typebot.io/signup?chosen_plan=scale"
_hover={{ textDecor: 'none' }}
>
<ActionButton>Subscribe now</ActionButton>
</NextChakraLink>
}
/>
</Stack>
</VStack>
</Flex>
<Footer />
</Stack>
)
}
export default Pricing

View File

@ -0,0 +1,228 @@
import { Heading } from '@chakra-ui/layout'
import { Stack } from '@chakra-ui/react'
import { Navbar } from 'components/common/Navbar/Navbar'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
import React from 'react'
const PrivacyPolicies = () => {
return (
<div className="flex flex-col items-center w-full overflow-x-hidden ">
<Navbar />
<SocialMetaTags
title="Privacy Policies for Typebot"
description="Create beautiful conversational forms"
currentUrl={`https://www.typebot.io/privacy-policies`}
imagePreviewUrl={`https://www.typebot.io/images/previews/home.png`}
/>
<Stack spacing={10} mx="auto" maxW="3xl" my="20">
<Heading as="h1">Privacy Policy for Typebot</Heading>
<p>
At typebot.io, accessible from https://www.typebot.io, one of our main
priorities is the privacy of our visitors. This Privacy Policy
document contains types of information that is collected and recorded
by typebot.io and how we use it.
</p>
<p>
If you have additional questions or require more information about our
Privacy Policy, do not hesitate to contact us.
</p>
<p>
This Privacy Policy applies only to our online activities and is valid
for visitors to our website with regards to the information that they
shared and/or collect in typebot.io. This policy is not applicable to
any information collected offline or via channels other than this
website. Our Privacy Policy was created with the help of the{' '}
<a href="https://www.privacypolicyonline.com/privacy-policy-generator/">
Online Generator of Privacy Policy
</a>
.
</p>
<Heading>Consent</Heading>
<p>
By using our website, you hereby consent to our Privacy Policy and
agree to its terms.
</p>
<Heading>Information we collect</Heading>
<p>
The personal information that you are asked to provide, and the
reasons why you are asked to provide it, will be made clear to you at
the point we ask you to provide your personal information.
</p>
<p>
If you contact us directly, we may receive additional information
about you such as your name, email address, phone number, the contents
of the message and/or attachments you may send us, and any other
information you may choose to provide.
</p>
<p>
When you register for an Account, we may ask for your contact
information, including items such as name, company name, address,
email address, and telephone number.
</p>
<Heading>How we use your information</Heading>
<p>We use the information we collect in various ways, including to:</p>
<ul>
<li>Provide, operate, and maintain our website</li>
<li>Improve, personalize, and expand our website</li>
<li>Understand and analyze how you use our website</li>
<li>Develop new products, services, features, and functionality</li>
<li>
Communicate with you, either directly or through one of our
partners, including for customer service, to provide you with
updates and other information relating to the website, and for
marketing and promotional purposes
</li>
<li>Send you emails</li>
<li>Find and prevent fraud</li>
</ul>
<Heading>Log Files</Heading>
<p>
typebot.io follows a standard procedure of using log files. These
files log visitors when they visit websites. All hosting companies do
this and a part of hosting services analytics. The information
collected by log files include internet protocol (IP) addresses,
browser type, Internet Service Provider (ISP), date and time stamp,
referring/exit pages, and possibly the number of clicks. These are not
linked to any information that is personally identifiable. The purpose
of the information is for analyzing trends, administering the site,
tracking users movement on the website, and gathering demographic
information.
</p>
<Heading>Advertising Partners Privacy Policies</Heading>
<p>
You may consult this list to find the Privacy Policy for each of the
advertising partners of typebot.io.
</p>
<p>
Third-party ad servers or ad networks uses technologies like cookies,
JavaScript, or Web Beacons that are used in their respective
advertisements and links that appear on typebot.io, which are sent
directly to users browser. They automatically receive your IP address
when this occurs. These technologies are used to measure the
effectiveness of their advertising campaigns and/or to personalize the
advertising content that you see on websites that you visit.
</p>
<p>
Note that typebot.io has no access to or control over these cookies
that are used by third-party advertisers.
</p>
<Heading>Third Party Privacy Policies</Heading>
<p>
typebot.io&apos;s Privacy Policy does not apply to other advertisers
or websites. Thus, we are advising you to consult the respective
Privacy Policies of these third-party ad servers for more detailed
information. It may include their practices and instructions about how
to opt-out of certain options.{' '}
</p>
<p>
You can choose to disable cookies through your individual browser
options. To know more detailed information about cookie management
with specific web browsers, it can be found at the browsers&apos;
respective websites.
</p>
<Heading>
CCPA Privacy Rights (Do Not Sell My Personal Information)
</Heading>
<p>
Under the CCPA, among other rights, California consumers have the
right to:
</p>
<p>
Request that a business that collects a consumer&apos;s personal data
disclose the categories and specific pieces of personal data that a
business has collected about consumers.
</p>
<p>
Request that a business delete any personal data about the consumer
that a business has collected.
</p>
<p>
Request that a business that sells a consumer&apos;s personal data,
not sell the consumer&apos;s personal data.
</p>
<p>
If you make a request, we have one month to respond to you. If you
would like to exercise any of these rights, please contact us.
</p>
<Heading>GDPR Data Protection Rights</Heading>
<p>
We would like to make sure you are fully aware of all of your data
protection rights. Every user is entitled to the following:
</p>
<p>
The right to access You have the right to request copies of your
personal data. We may charge you a small fee for this service.
</p>
<p>
The right to rectification You have the right to request that we
correct any information you believe is inaccurate. You also have the
right to request that we complete the information you believe is
incomplete.
</p>
<p>
The right to erasure You have the right to request that we erase
your personal data, under certain conditions.
</p>
<p>
The right to restrict processing You have the right to request that
we restrict the processing of your personal data, under certain
conditions.
</p>
<p>
The right to object to processing You have the right to object to
our processing of your personal data, under certain conditions.
</p>
<p>
The right to data portability You have the right to request that we
transfer the data that we have collected to another organization, or
directly to you, under certain conditions.
</p>
<p>
If you make a request, we have one month to respond to you. If you
would like to exercise any of these rights, please contact us.
</p>
<Heading>Children&apos;s Information</Heading>
<p>
Another part of our priority is adding protection for children while
using the internet. We encourage parents and guardians to observe,
participate in, and/or monitor and guide their online activity.
</p>
<p>
typebot.io does not knowingly collect any Personal Identifiable
Information from children under the age of 13. If you think that your
child provided this kind of information on our website, we strongly
encourage you to contact us immediately and we will do our best
efforts to promptly remove such information from our records.
</p>
</Stack>
</div>
)
}
export default PrivacyPolicies

View File

@ -0,0 +1,140 @@
import { Stack, Heading } from '@chakra-ui/react'
import { Navbar } from 'components/common/Navbar/Navbar'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
const PrivacyPolicies = () => {
return (
<div className="flex flex-col items-center w-full overflow-x-hidden ">
<SocialMetaTags
title="Website Terms and Conditions of Use"
description="Create beautiful conversational forms"
currentUrl={`https://www.typebot.io/terms-of-service`}
imagePreviewUrl={`https://www.typebot.io/images/previews/home.png`}
/>
<Navbar />
<Stack spacing={10} mx="auto" maxW="3xl" my="20">
<Heading as="h1">Website Terms and Conditions of Use</Heading>
<Heading>1. Terms</Heading>
<p>
By accessing this Website, accessible from https://www.typebot.io, you
are agreeing to be bound by these Website Terms and Conditions of Use
and agree that you are responsible for the agreement with any
applicable local laws. If you disagree with any of these terms, you
are prohibited from accessing this site. The materials contained in
this Website are protected by copyright and trade mark law.
</p>
<Heading>2. Use License</Heading>
<p>
Permission is granted to temporarily download one copy of the
materials on Typebot&apos;s Website for personal, non-commercial
transitory viewing only. This is the grant of a license, not a
transfer of title, and under this license you may not:
</p>
<ul>
<li>modify or copy the materials;</li>
<li>
use the materials for any commercial purpose or for any public
display;
</li>
<li>
attempt to reverse engineer any software contained on Typebot&apos;s
Website;
</li>
<li>
remove any copyright or other proprietary notations from the
materials; or
</li>
<li>
transferring the materials to another person or &quot;mirror&quot;
the materials on any other server.
</li>
</ul>
<p>
This will let Typebot to terminate upon violations of any of these
restrictions. Upon termination, your viewing right will also be
terminated and you should destroy any downloaded materials in your
possession whether it is printed or electronic format. These Terms of
Service has been created with the help of the{' '}
<a href="https://www.termsofservicegenerator.net">
Terms Of Service Generator
</a>{' '}
and the{' '}
<a href="https://www.generateprivacypolicy.com">
Privacy Policy Generator
</a>
.
</p>
<Heading>3. Disclaimer</Heading>
<p>
All the materials on Typebots Website are provided &quot;as is&quot;.
Typebot makes no warranties, may it be expressed or implied, therefore
negates all other warranties. Furthermore, Typebot does not make any
representations concerning the accuracy or reliability of the use of
the materials on its Website or otherwise relating to such materials
or any sites linked to this Website.
</p>
<Heading>4. Limitations</Heading>
<p>
Typebot or its suppliers will not be hold accountable for any damages
that will arise with the use or inability to use the materials on
Typebots Website, even if Typebot or an authorize representative of
this Website has been notified, orally or written, of the possibility
of such damage. Some jurisdiction does not allow limitations on
implied warranties or limitations of liability for incidental damages,
these limitations may not apply to you.
</p>
<Heading>5. Revisions and Errata</Heading>
<p>
The materials appearing on Typebots Website may include technical,
typographical, or photographic errors. Typebot will not promise that
any of the materials in this Website are accurate, complete, or
current. Typebot may change the materials contained on its Website at
any time without notice. Typebot does not make any commitment to
update the materials.
</p>
<Heading>6. Links</Heading>
<p>
Typebot has not reviewed all of the sites linked to its Website and is
not responsible for the contents of any such linked site. The presence
of any link does not imply endorsement by Typebot of the site. The use
of any linked website is at the users own risk.
</p>
<Heading>7. Site Terms of Use Modifications</Heading>
<p>
Typebot may revise these Terms of Use for its Website at any time
without prior notice. By using this Website, you are agreeing to be
bound by the current version of these Terms and Conditions of Use.
</p>
<Heading>8. Your Privacy</Heading>
<p>Please read our Privacy Policy.</p>
<Heading>9. Governing Law</Heading>
<p>
Any claim related to Typebot&apos;s Website shall be governed by the
laws of fr without regards to its conflict of law provisions.
</p>
</Stack>
</div>
)
}
export default PrivacyPolicies

View File

@ -0,0 +1,299 @@
import React, { useEffect } from 'react'
import {
Heading,
VStack,
Stack,
Text,
Table,
Thead,
Tbody,
Tr,
Td,
Th,
Box,
Flex,
} from '@chakra-ui/react'
import loadLandbot from '../lib/landbot'
import Image from 'next/image'
import Typebot from 'typebot-js'
import { ArticleCallToAction } from 'components/common/ArticleCta'
import { Footer } from 'components/common/Footer'
import { Navbar } from 'components/common/Navbar/Navbar'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
import { Yes, No } from 'components/common/TableCells'
// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare const Landbot: any
const VsTypebot = () => {
useEffect(() => {
loadLandbot().then(() => {
new Landbot.Container({
container: '#myLandbot',
configUrl:
'https://chats.landbot.io/v3/H-937813-ZLZEY720UH1TWN5S/index.json',
})
})
Typebot.initContainer('typebot-container', {
publishId: 'example-vs-other-tools',
})
}, [])
return (
<>
<Stack
alignItems="center"
justifyContent="space-between"
w="full"
overflowX="hidden"
mb="20"
>
<SocialMetaTags
title="Typebot vs Landbot"
description="Get to know the main differences between Typebot and Landbot"
currentUrl={`https://www.typebot.io/vs-landbot`}
imagePreviewUrl={`https://www.typebot.io/vs-landbot`}
/>
<Navbar />
<VStack maxW="1200px" py={20} spacing={10} w="full">
<Heading as="h1" fontSize={['3xl', '5xl']} textAlign="center">
What makes Typebot a great Landbot alternative?
</Heading>
<Stack maxW="700px" spacing={6} textAlign="justify" w="full" px={4}>
<Text>
Both Landbot and Typebot offer the same output: beautiful
conversational forms. But Landbot is in fact a tool focused on
delivering customer service through chatbots while Typebot is
focused on getting the most out of forms.
</Text>
<Heading>User experience</Heading>
<Text>
Here is an example of the same form created with both tools:
</Text>
<Heading size="md" as="h3">
Landbot:
</Heading>
<div id="myLandbot" style={{ width: '100%', height: '500px' }} />
<Heading size="md" as="h3">
Typebot:
</Heading>
<div
id="typebot-container"
style={{ width: '100%', height: '500px' }}
/>
<Heading>Building experience</Heading>
<Text>
Landbot offers a &quot;visual flow&quot; building experience.
While it makes conditional logic more understandable. I think
it&apos;s hard to understand how the final result will look like
at a glance:
</Text>
<Box h="400px" pos="relative">
<Image
src="landbotVisualFlowSrc"
layout="fill"
objectFit="contain"
alt="Visual flow screenshot"
/>
</Box>
<Text>
The idea behind Typebot building experience is that you directly
modify the final result and you click on elements you want to
edit. Typebot also offer a &quot;visual flow&quot; building
experience when you start adding doing conditional logic
</Text>
<Heading>Pricing</Heading>
<Text>
Landbot offers a Free plan that isn&apos;t very generous as you
won&apos;t have access to advanced useful features and you will be
limited to 30 chats per month. You won&apos;t really know if your
forms are performing well with only 30 responses per month.
You&apos;ll be obligated to upgrade to at least their
&quot;PROFESSIONAL&quot; plan that offers up to 1,000 responses
for $95/month.
</Text>
<Text>
Landbot offers a human take-over feature that won&apos;t be
developed into Typebot. It won&apos;t be a live chat product
because Typebot is designed for marketers, not customer support
like Landbot. Typebot&apos;s main focus is to help marketers get
the most out of their online forms with exclusive features.
</Text>
<Text>
Landbot also offers Facebook and Whatsapp integrations. Typebot
has planned these integrations but it will be focused on helping
marketers distribute forms through Facebook and WhatsApp instead
of a focus on delivering customer service.
</Text>
<Heading as="h3" size="md">
Free plan comparison
</Heading>
<Flex overflowY="scroll">
<Table variant="simple">
<Thead>
<Tr>
<Th />
<Th>Typebot (Free plan)</Th>
<Th>Landbot (Free plan)</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Unlimited forms</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Unlimited conversations</Td>
<Yes />
<No>(30 / month)</No>
</Tr>
<Tr>
<Td>Zapier integration</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Slack integration</Td>
<No>Zapier, Integromat</No>
<Yes />
</Tr>
<Tr>
<Td>Sendgrid integration</Td>
<No>Zapier, Integromat</No>
<Yes />
</Tr>
<Tr>
<Td>Stripe integration</Td>
<Yes />
<No>starts at $35</No>
</Tr>
<Tr>
<Td>Google Sheets integration</Td>
<Yes />
<No>starts at $90</No>
</Tr>
<Tr>
<Td>Human take over</Td>
<No />
<Yes />
</Tr>
<Tr>
<Td>Priority Support</Td>
<Yes />
<No>(only enterprise)</No>
</Tr>
<Tr>
<Td>Webhooks</Td>
<Yes />
<No>starts at $95</No>
</Tr>
<Tr>
<Td>Hidden fields</Td>
<Yes />
<No>starts at $35</No>
</Tr>
<Tr>
<Td>Conditional logic</Td>
<Yes />
<No>starts at $35</No>
</Tr>
<Tr>
<Td>Formulas</Td>
<Yes />
<No>starts at $95</No>
</Tr>
<Tr>
<Td>Custom error messages</Td>
<Yes />
<No>starts at $35</No>
</Tr>
<Tr>
<Td>Custom typing emulation</Td>
<Yes />
<No>starts at $35</No>
</Tr>
</Tbody>
</Table>
</Flex>
<Heading as="h3" size="md">
Paid plan comparison
</Heading>
<Flex overflowY="scroll">
<Table variant="simple">
<Thead>
<Tr>
<Th />
<Th>Typebot Pro ($30/month)</Th>
<Th>Landbot ($35+/month)</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Access to incomplete submissions</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Remove branding</Td>
<Yes />
<Yes>$95/month</Yes>
</Tr>
<Tr>
<Td>Custom domain</Td>
<Yes />
<No />
</Tr>
<Tr>
<Td>Facebook messenger</Td>
<No />
<Yes />
</Tr>
<Tr>
<Td>Whatsapp</Td>
<No />
<Yes>$95+/month</Yes>
</Tr>
<Tr>
<Td>In-depth analytics</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Google analytics events</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Team collaboration</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Organize forms in folders</Td>
<Yes />
<No />
</Tr>
</Tbody>
</Table>
</Flex>
<Text>
Landbot offers other very cool features.{' '}
<NextChakraLink
href="https://landbot.io/pricing"
color="blue.400"
>
Here is an exhausting list.
</NextChakraLink>
</Text>
</Stack>
</VStack>
<ArticleCallToAction />
</Stack>
<Footer />
</>
)
}
export default VsTypebot

View File

@ -0,0 +1,254 @@
import React, { useEffect } from 'react'
import {
Heading,
VStack,
Stack,
Text,
Table,
Thead,
Tbody,
Tr,
Td,
Th,
Flex,
} from '@chakra-ui/react'
import Typebot from 'typebot-js'
import { ArticleCallToAction } from 'components/common/ArticleCta'
import { roadmapLink, Footer } from 'components/common/Footer'
import { Navbar } from 'components/common/Navbar/Navbar'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
import { Yes, No } from 'components/common/TableCells'
const VsTypebot = () => {
useEffect(() => {
Typebot.initContainer('typebot-container', {
publishId: 'example-vs-other-tools',
})
}, [])
return (
<>
<Stack
alignItems="center"
justifyContent="space-between"
w="full"
overflowX="hidden"
mb="20"
>
<SocialMetaTags
title="Tally vs Typebot"
description="Get to know the main differences between Typebot and Tally"
currentUrl={`https://www.typebot.io/vs-typeform`}
imagePreviewUrl={`https://www.typebot.io/vs-typeform`}
/>
<Navbar />
<VStack maxW="1200px" py={20} spacing={10} w="full">
<Heading as="h1" fontSize={['3xl', '5xl']} textAlign="center">
What makes Typebot a great Tally alternative?
</Heading>
<Stack maxW="700px" spacing={6} textAlign="justify" w="full" px={4}>
<Text>
Tally user experience is quite unique and is similar to Notion. I
love the simplicity of its building experience. Tally and Typebot
seem to have the same vision for the building experience: what you
edit is the final result. They also offer similar generous pricing
where the majority of the features are available for free.
</Text>
<Text>
But these tools differ in the end-user experience: Tally offers
one-page or multi-step forms whereas Typebot offers a
conversational experience. Let&apos;s take a look at it:
</Text>
<Heading>User experience</Heading>
<Text>
Here is an example of the same form created with both tools:
</Text>
<Heading size="md" as="h3">
Tally:
</Heading>
<div
className="typeform-widget"
data-url="https://form.typeform.com/to/mKiSR43i?typeform-medium=embed-snippet"
style={{ width: '100%', height: '500px' }}
>
<iframe
src="https://tally.so/embed/nP9Gbm?hideTitle=1&alignLeft=1"
width="100%"
height="100%"
title="Request a class"
/>
</div>
<Heading size="md" as="h3">
Typebot:
</Heading>
<div
id="typebot-container"
style={{ width: '100%', height: '500px' }}
/>
<Heading>Conversion increased</Heading>
<Text>
I built Typebot because I know conversational experience allows
you to increase your conversion rate and ultimately offer a more
comfortable experience on mobile.
</Text>
<Heading as="h3" size="md">
Chat experience is comfortable on mobile
</Heading>
<Text>
Tally looks great on mobile but it still feels like a classic form
with lots of questions you have to fill. Whereas with a
conversational experience, your mind shift and it feels like
you&apos;re talking to someone.
</Text>
<Heading>Roadmap Ceiling</Heading>
<Text>
Because Tally is offering traditional formatting of its forms,
they won&apos;t be able to implement advanced features such as
drop-off rates on a question basis. This feature (available on
Typebot) is a game-changer for marketers who need to know in
real-time how their questions perform and where users tend to quit
the form.
</Text>
<Heading>Pricing</Heading>
<Text>
Both tools offer similar pricing. Everything is unlimited and for
free. You&apos;ll need to subscribe only if you need advanced
features and remove the branding.
</Text>
<Heading as="h3" size="md">
Free plan comparison
</Heading>
<Flex overflowY="scroll">
<Table variant="simple">
<Thead>
<Tr>
<Th />
<Th>Typebot (Free plan)</Th>
<Th>Tally (Free plan)</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Unlimited forms</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Unlimited responses</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Collect payments</Td>
<Yes />
<Yes>5% commission</Yes>
</Tr>
<Tr>
<Td>File upload</Td>
<No>
<NextChakraLink href={roadmapLink} color="blue.400">
Roadmap
</NextChakraLink>
</No>
<Yes />
</Tr>
<Tr>
<Td>Calculator</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Hidden fields</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Zapier</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Integromat</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Google Sheets</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Redirect</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Custom subdomain</Td>
<Yes />
<No />
</Tr>
</Tbody>
</Table>
</Flex>
<Heading as="h3" size="md">
Paid plan comparison
</Heading>
<Flex overflowY="scroll">
<Table variant="simple">
<Thead>
<Tr>
<Th />
<Th>Typebot Pro ($30/month)</Th>
<Th>Tally ($29/month)</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Collaboration</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Remove branding</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Custom domains</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Workspaces</Td>
<Yes />
<Yes />
</Tr>
<Tr>
<Td>Access to incomplete submissions</Td>
<Yes />
<No />
</Tr>
<Tr>
<Td>In-depth analytics</Td>
<Yes />
<No />
</Tr>
<Tr>
<Td>Google analytics events</Td>
<Yes />
<No />
</Tr>
</Tbody>
</Table>
</Flex>
</Stack>
</VStack>
<ArticleCallToAction />
</Stack>
<Footer />
</>
)
}
export default VsTypebot

View File

@ -0,0 +1,449 @@
import React, { useEffect } from 'react'
import {
Heading,
VStack,
Stack,
Text,
Table,
Thead,
Tbody,
Tr,
Td,
Th,
Flex,
} from '@chakra-ui/react'
import Typebot from 'typebot-js'
import { CheckIcon } from 'assets/icons/CheckIcon'
import { CloseIcon } from 'assets/icons/CloseIcon'
import { ArticleCallToAction } from 'components/common/ArticleCta'
import { Footer } from 'components/common/Footer'
import { Navbar } from 'components/common/Navbar/Navbar'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
import { Yes, No } from 'components/common/TableCells'
import loadTypeform from 'lib/typeform'
const VsTypebot = () => {
useEffect(() => {
loadTypeform().then()
Typebot.initContainer('typebot-container', {
publishId: 'example-vs-other-tools',
})
}, [])
return (
<>
<Stack
alignItems="center"
justifyContent="space-between"
w="full"
overflowX="hidden"
mb="20"
>
<SocialMetaTags
title="Typebot vs Typeform"
description="Get to know the main differences between Typebot and Typeform"
currentUrl={`https://www.typebot.io/vs-typeform`}
imagePreviewUrl={`https://www.typebot.io/vs-typeform`}
/>
<Navbar />
<VStack maxW="1200px" py={20} spacing={10} w="full">
<Heading as="h1" fontSize={['3xl', '5xl']} textAlign="center">
What makes Typebot a great Typeform alternative?
</Heading>
<Stack maxW="700px" spacing={6} textAlign="justify" w="full" px={4}>
<Text>
I am a big fan of Typeform user experience. This is probably what
motivated me to create an alternative that keeps Typeform slick
design but also offers a unique conversational experience that
would make my forms convert more.
</Text>
<Text>
Along the journey, I figured that a conversational experience also
unlocks many possibilities in terms of conversion rate
optimization for marketers. That&apos;s exactly where Typebot is
headed.
</Text>
<Heading>User experience</Heading>
<Text>
Here is an example of the same form created with both tools:
</Text>
<Heading size="md" as="h3">
Typeform:
</Heading>
<div
className="typeform-widget"
data-url="https://form.typeform.com/to/mKiSR43i?typeform-medium=embed-snippet"
style={{ width: '100%', height: '500px' }}
/>
<Heading size="md" as="h3">
Typebot:
</Heading>
<div
id="typebot-container"
style={{ width: '100%', height: '500px' }}
/>
<Heading>Conversion increased</Heading>
<Text>
Typebot&apos;s users report a better conversion rate compared to
Typeform forms. All of this is thanks to a conversation :
</Text>
<Heading as="h3" size="md">
Collect real-time results
</Heading>
<Text>
With a Typeform, you collect the answer only when your user clicks
on the &quot;Submit&quot; button located at end of the form. If
your users are leaving the form at a specific question, you
won&apos;t even know this. With Typebot, if a user answers only
one question, you will still collect the answer and will never
lose any valuable information.
</Text>
<Text>
What&apos;s the powerful math behind this feature? Imagine 300
users are interacting with your form but only 100 of them fully
completed it. With Typebot, you&apos;ll still see responses from
300 users while with Typeform, you&apos;ll only see responses from
the 100 people that clicked on &quot;submit&quot;.
</Text>
<Heading as="h3" size="md">
Chat experience is comfortable on mobile
</Heading>
<Text>
Typeform is responsive and looks good on mobile but it still feels
like a form you need to fill. Whereas with a conversational
experience, your mind shift and it feels like you&apos;re talking
to someone.
</Text>
<Heading>Pricing</Heading>
<Text>
Typeform recently changed its pricing and now offers a Free plan
that includes meaningful features without limits (logic jumps,
ending screens, and the number of typeforms you can create). But
they instead limited the number of responses you can collect per
month to only 10 and the questions per typeform to 10 as well.
</Text>
<Text>
The problem with these limitations is that you won&apos;t know if
your forms are actually performing well with only 10 responses per
month. You&apos;ll be obligated to upgrade to at least their
&quot;Plus&quot; plan that offers up to 1,000 responses for
$55/month
</Text>
<Heading as="h3" size="md">
Free plan comparison
</Heading>
<Flex overflowY="scroll">
<Table variant="simple">
<Thead>
<Tr>
<Th />
<Th>Typebot (Free plan)</Th>
<Th>Typeform (Free plan)</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Unlimited forms</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
</Tr>
<Tr>
<Td>Unlimited logic</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
</Tr>
<Tr>
<Td>Unlimited responses</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(10 / month)
</Text>
</Td>
</Tr>
<Tr>
<Td>Unlimited questions</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(10 / form)
</Text>
</Td>
</Tr>
<Tr>
<Td>Hidden fields</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
</Tr>
<Tr>
<Td>Calculator</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
</Tr>
<Tr>
<Td>Templates</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
</Tr>
<Tr>
<Td>Download your data</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
</Tr>
<Tr>
<Td>Native integrations</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
</Tr>
<Tr>
<Td>Collect payments</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $30)
</Text>
</Td>
</Tr>
<Tr>
<Td>Redirect</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $60)
</Text>
</Td>
</Tr>
<Tr>
<Td>File upload</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $30)
</Text>
</Td>
</Tr>
<Tr>
<Td>Webhooks</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $30)
</Text>
</Td>
</Tr>
<Tr>
<Td>Custom link preview</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $30)
</Text>
</Td>
</Tr>
<Tr>
<Td>Custom subdomain</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $50)
</Text>
</Td>
</Tr>
<Tr>
<Td>Google analytics integration</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $108)
</Text>
</Td>
</Tr>
<Tr>
<Td>Facebook pixel</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $108)
</Text>
</Td>
</Tr>
<Tr>
<Td>Google Tag Manager</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $108)
</Text>
</Td>
</Tr>
<Tr>
<Td>Priority support</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td display="flex">
<CloseIcon width="25px" />
<Text ml={1} fontSize="sm">
(starts at $108)
</Text>
</Td>
</Tr>
</Tbody>
</Table>
</Flex>
<Heading as="h3" size="md">
Paid plan comparison
</Heading>
<Flex overflowY="scroll">
<Table variant="simple">
<Thead>
<Tr>
<Th />
<Th>Typebot Pro ($30/month)</Th>
<Th>Typeform ($30+/month)</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Access to incomplete submissions</Td>
<Yes />
<No />
</Tr>
<Tr>
<Td>Remove branding</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>$66/month</Td>
</Tr>
<Tr>
<Td>Unlimited file upload</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>$108/month (4GB)</Td>
</Tr>
<Tr>
<Td>Team collaboration</Td>
<Td display="flex">
<CheckIcon fill="#0042da" width="25px" />
<Text ml="1" fontSize="sm">
(unlimited)
</Text>
</Td>
<Td>$66 for 3 users</Td>
</Tr>
<Tr>
<Td>Custom domains</Td>
<Td>
<CheckIcon fill="#0042da" width="25px" />
</Td>
<Td>
<CloseIcon width="25px" />
</Td>
</Tr>
<Tr>
<Td>Salesforce integration</Td>
<Td>
<CloseIcon width="25px" />
</Td>
<Td>$108/month</Td>
</Tr>
<Tr>
<Td>Schedule a close date</Td>
<Td>
<CloseIcon width="25px" />
</Td>
<Td>$108/month</Td>
</Tr>
<Tr>
<Td>Drop-off rates</Td>
<Yes />
<Td>$108/month</Td>
</Tr>
<Tr>
<Td>Google analytics events</Td>
<Yes />
<No />
</Tr>
<Tr>
<Td>Organize forms in folders</Td>
<Yes />
<No />
</Tr>
</Tbody>
</Table>
</Flex>
</Stack>
</VStack>
<ArticleCallToAction />
</Stack>
<Footer />
</>
)
}
export default VsTypebot

Some files were not shown because too many files have changed in this diff Show More