2
0

docs: 📝 Update env var and write Configuration doc

This commit is contained in:
Baptiste Arnaud
2022-03-13 08:56:10 +01:00
parent b37db3cee3
commit 69248f94d4
35 changed files with 455 additions and 260 deletions

View File

@ -1,60 +1,14 @@
DATABASE_URL=postgresql://postgres:@localhost:5432/typebot
ENCRYPTION_SECRET=q3t6v9y$B&E)H@McQfTjWnZr4u7x!z%C #256-bits secret (can be generated here: https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx)
ENCRYPTION_SECRET=SgVkYp2s5v8y/B?E(H+MbQeThWmZq4t6 #256-bits secret (can be generated here: https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx)
NEXTAUTH_URL=http://localhost:3000
NEXT_PUBLIC_VIEWER_URL=http://localhost:3001
# Used for email auth and email notifications
AUTH_EMAIL_SERVER_USERNAME=username
AUTH_EMAIL_SERVER_PASSWORD=password
AUTH_EMAIL_SERVER_HOST=smtp.example.com
AUTH_EMAIL_SERVER_PORT=587
AUTH_EMAIL_FROM_EMAIL=noreply@example.com
AUTH_EMAIL_FROM_NAME="John Smith"
NEXT_PUBLIC_EMAIL_NOTIFICATIONS_FROM_EMAIL=
# Storage
# Used for uploading images, videos, etc...
S3_ACCESS_KEY=minio
S3_SECRET_KEY=minio123
S3_BUCKET=typebot
S3_PORT=9000
S3_ENDPOINT=localhost
S3_SSL=false
# S3_REGION=
# Auth
# (Optional) Used to login using GitHub
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
# (Optional) Used to login using Google AND Google Sheets integration
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# (Optional) Used to login using Facebook
FACEBOOK_CLIENT_ID=
FACEBOOK_CLIENT_SECRET=
# (Optional) Subscription Payment
NEXT_PUBLIC_STRIPE_PUBLIC_KEY=
STRIPE_SECRET_KEY=
STRIPE_PRICE_USD_ID=
STRIPE_PRICE_EUR_ID=
STRIPE_WEBHOOK_SECRET=
# (Optional) Used for GIF search
NEXT_PUBLIC_GIPHY_API_KEY=
NEXT_PUBLIC_VIEWER_HOST=http://localhost:3001
# (Optional) Error tracking with Sentry
NEXT_PUBLIC_SENTRY_DSN=
SENTRY_AUTH_TOKEN=
SENTRY_PROJECT=
SENTRY_ORG=
# Vercel
VERCEL_TOKEN=
VERCEL_VIEWER_PROJECT_NAME=
VERCEL_TEAM_ID=
# For more configuration options check out:
https://docs.typebot.io/self-hosting/configuration

View File

@ -52,6 +52,8 @@ export const SignInForm = ({
return (
<Stack spacing="4">
<SocialLoginButtons />
{process.env.NEXT_PUBLIC_SMTP_FROM && (
<>
<DividerWithText mt="6">Or with your email</DividerWithText>
<HStack as="form" onSubmit={handleEmailSubmit}>
<Input
@ -72,6 +74,8 @@ export const SignInForm = ({
Submit
</Button>
</HStack>
</>
)}
</Stack>
)
}

View File

@ -36,6 +36,7 @@ export const SocialLoginButtons = () => {
>
Continue with GitHub
</Button>
{process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID && (
<Button
leftIcon={<GoogleLogo />}
onClick={handleGoogleClick}
@ -45,6 +46,8 @@ export const SocialLoginButtons = () => {
>
Continue with Google
</Button>
)}
{process.env.NEXT_PUBLIC_FACEBOOK_CLIENT_ID && (
<Button
leftIcon={<FacebookLogo />}
onClick={handleFacebookClick}
@ -54,6 +57,7 @@ export const SocialLoginButtons = () => {
>
Continue with Facebook
</Button>
)}
</Stack>
)
}

View File

@ -54,7 +54,7 @@ export const ShareContent = () => {
{typebot && (
<EditableUrl
hostname={
process.env.NEXT_PUBLIC_VIEWER_HOST ?? 'https://typebot.io'
process.env.NEXT_PUBLIC_VIEWER_URL ?? 'https://typebot.io'
}
pathname={publicId}
onPathnameChange={handlePublicIdChange}

View File

@ -20,7 +20,9 @@ export const SpreadsheetsDropdown = ({
})
const { spreadsheets, isLoading } = useSpreadsheets({
credentialsId,
onError: (e) => toast({ title: e.name, description: e.message }),
onError: (e) =>
!toast.isActive('spreadsheets') &&
toast({ id: 'spreadsheets', title: e.name, description: e.message }),
})
const currentSpreadsheet = useMemo(
() => spreadsheets?.find((s) => s.id === spreadsheetId),

View File

@ -69,9 +69,9 @@ export const SendEmailSettings = ({ options, onOptionsChange }: Props) => {
currentCredentialsId={options.credentialsId}
onCredentialsSelect={handleCredentialsSelect}
onCreateNewClick={onOpen}
defaultCredentialLabel={
process.env.NEXT_PUBLIC_EMAIL_NOTIFICATIONS_FROM_EMAIL
}
defaultCredentialLabel={process.env.NEXT_PUBLIC_SMTP_FROM?.match(
/\<(.*)\>/
)?.pop()}
refreshDropdownKey={refreshCredentialsKey}
/>
</Stack>

View File

@ -78,7 +78,6 @@ export const SmtpConfigModal = ({
<ModalFooter>
<Button
colorScheme="blue"
mr={3}
onClick={handleCreateClick}
isDisabled={
isNotDefined(smtpConfig.from.email) ||
@ -91,7 +90,6 @@ export const SmtpConfigModal = ({
>
Create
</Button>
<Button variant="ghost">Close</Button>
</ModalFooter>
</ModalContent>
</Modal>

View File

@ -2,6 +2,7 @@ import { useTypebot } from 'contexts/TypebotContext'
import { useUser } from 'contexts/UserContext'
import { Plan } from 'db'
import React, { useEffect } from 'react'
import { isCloudProdInstance } from 'services/utils'
import { initBubble } from 'typebot-js'
export const SupportBubble = () => {
@ -9,9 +10,10 @@ export const SupportBubble = () => {
const { user } = useUser()
useEffect(() => {
if (isCloudProdInstance())
initBubble({
publishId: 'typebot-support',
viewerHost: process.env.NEXT_PUBLIC_VIEWER_HOST,
viewerHost: process.env.NEXT_PUBLIC_VIEWER_URL,
backgroundColor: '#ffffff',
button: { color: '#0042DA' },
hiddenVariables: {

View File

@ -5,7 +5,7 @@ import { decrypt, encrypt } from 'utils'
import prisma from './prisma'
export const oauth2Client = new OAuth2Client(
process.env.GOOGLE_CLIENT_ID,
process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
`${process.env.NEXTAUTH_URL}/api/credentials/google-sheets/callback`
)

View File

@ -23,11 +23,6 @@ class MyDocument extends Document {
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"
/>
<script
defer
data-domain="app.typebot.io"
src="https://plausible.baptistearno.com/js/plausible.js"
/>
</Head>
<body>
<Main />

View File

@ -10,40 +10,51 @@ import { withSentry } from '@sentry/nextjs'
import { CustomAdapter } from './adapter'
import { User } from 'db'
const providers: Provider[] = [
EmailProvider({
server: {
host: process.env.AUTH_EMAIL_SERVER_HOST,
port: Number(process.env.AUTH_EMAIL_SERVER_PORT),
auth: {
user: process.env.AUTH_EMAIL_SERVER_USER,
pass: process.env.AUTH_EMAIL_SERVER_PASSWORD,
},
},
from: `"${process.env.AUTH_EMAIL_FROM_NAME}" <${process.env.AUTH_EMAIL_FROM_EMAIL}>`,
}),
]
const providers: Provider[] = []
if (process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET)
providers.push(
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
clientId:
process.env.NEXT_PUBLIC_GITHUB_CLIENT_ID ?? '534b549dd17709a743a2',
clientSecret:
process.env.GITHUB_CLIENT_SECRET ??
'7adb03507504fb1a54422f6c3c697277cfd000a9',
})
)
if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET)
if (process.env.NEXT_PUBLIC_SMTP_FROM)
providers.push(
EmailProvider({
server: {
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT ? Number(process.env.SMTP_PORT) : 25,
auth: {
user: process.env.SMTP_USERNAME,
pass: process.env.SMTP_PASSWORD,
},
},
from: process.env.NEXT_PUBLIC_SMTP_FROM,
})
)
if (
process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID &&
process.env.GOOGLE_CLIENT_SECRET
)
providers.push(
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
})
)
if (process.env.FACEBOOK_CLIENT_ID && process.env.FACEBOOK_CLIENT_SECRET)
if (
process.env.NEXT_PUBLIC_FACEBOOK_CLIENT_ID &&
process.env.FACEBOOK_CLIENT_SECRET
)
providers.push(
FacebookProvider({
clientId: process.env.FACEBOOK_CLIENT_ID,
clientId: process.env.NEXT_PUBLIC_FACEBOOK_CLIENT_ID,
clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
})
)

View File

@ -19,12 +19,11 @@ const handler = async (
if (
!process.env.S3_ENDPOINT ||
!process.env.S3_ACCESS_KEY ||
!process.env.S3_SECRET_KEY ||
!process.env.S3_BUCKET
!process.env.S3_SECRET_KEY
)
return res.send({
message:
'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_ACCESS_KEY, S3_BUCKET',
'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY',
})
const s3 = new Client({
@ -40,7 +39,7 @@ const handler = async (
const filePath = req.query.filePath as string | undefined
if (!filePath) return badRequest(res)
const presignedUrl = await s3.presignedPutObject(
process.env.S3_BUCKET as string,
process.env.S3_BUCKET ?? 'typebot',
filePath
)

View File

@ -14,6 +14,7 @@ import { NextPageContext } from 'next/types'
const DashboardPage = () => {
const [isLoading, setIsLoading] = useState(false)
const [showBanner, setShowBanner] = useState(false)
const { query, isReady } = useRouter()
const { user } = useUser()
const toast = useToast({
@ -37,6 +38,9 @@ const DashboardPage = () => {
const couponCode = query.coupon?.toString()
const stripeStatus = query.stripe?.toString()
if (document.location.hostname.includes('app.typebot.io'))
setShowBanner(true)
if (stripeStatus === 'success')
toast({
title: 'Typebot Pro',
@ -53,6 +57,7 @@ const DashboardPage = () => {
return (
<Stack minH="100vh">
{showBanner && (
<Banner id={'v1-navigation'}>
<Text>
You are on Typebot 2.0. To access the old version, navigate to
@ -61,6 +66,7 @@ const DashboardPage = () => {
https://old.typebot.io
</Link>
</Banner>
)}
<Seo title="My typebots" />
<DashboardHeader />
<TypebotDndContext>

View File

@ -29,7 +29,7 @@ test.describe('Send email step', () => {
await page.goto(`/typebots/${typebotId}/edit`)
await page.click('text=Configure...')
await page.click(
`text=${process.env.NEXT_PUBLIC_EMAIL_NOTIFICATIONS_FROM_EMAIL}`
`text=${process.env.NEXT_PUBLIC_SMTP_FROM?.match(/\<(.*)\>/)?.pop()}`
)
await page.click('text=Connect new')
const createButton = page.locator('button >> text=Create')

View File

@ -10,16 +10,16 @@ export const sendEmailNotification = ({
content: string
}) => {
const transporter = createTransport({
host: process.env.AUTH_EMAIL_SERVER_HOST,
port: Number(process.env.AUTH_EMAIL_SERVER_PORT),
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
auth: {
user: process.env.AUTH_EMAIL_SERVER_USER,
pass: process.env.AUTH_EMAIL_SERVER_PASSWORD,
user: process.env.SMTP_USERNAME,
pass: process.env.SMTP_PASSWORD,
},
})
return transporter.sendMail({
from: `"${process.env.AUTH_EMAIL_FROM_NAME}" <${process.env.AUTH_EMAIL_FROM_EMAIL}>`,
from: process.env.NEXT_PUBLIC_SMTP_FROM,
to,
subject,
html: content,

View File

@ -77,7 +77,7 @@ export const executeWebhook = (
{ blockId, stepId }: { blockId: string; stepId: string }
) =>
sendRequest<WebhookResponse>({
url: `${process.env.NEXT_PUBLIC_VIEWER_HOST}/api/typebots/${typebotId}/blocks/${blockId}/steps/${stepId}/executeWebhook`,
url: `${process.env.NEXT_PUBLIC_VIEWER_URL}/api/typebots/${typebotId}/blocks/${blockId}/steps/${stepId}/executeWebhook`,
method: 'POST',
body: {
variables,

View File

@ -135,3 +135,6 @@ export const timeSince = (date: string) => {
}
return Math.floor(seconds) + ' seconds'
}
export const isCloudProdInstance = () =>
window.location.hostname === 'app.typebot.io'

View File

@ -1,4 +1,4 @@
{
"label": "Self hosting",
"label": "Self-Hosting",
"position": 6
}

View File

@ -0,0 +1,177 @@
---
sidebar_position: 2
---
# Configuration
:::note
The easiest way to get started with Typebot is with [the official managed service in the Cloud](https://app.typebot.io). It takes 1 minute to try out the tool for free. You'll have high availability, backups, security, and maintenance all managed for you by me, Baptiste, Typebot's founder.
That's also the best way to support my work, open-source software, and you'll get great service!
:::
When running a Typebot on your machine, the following configuration parameters can be supplied as environment variables.
## Builder & Viewer
These variables are shared between builder and viewer. If you host them in a different environments then it needs to be set in both environments.
### Global
| Parameter | Default | Description |
| ---------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DATABASE_URL | -- | The database URL, i.e. for external db server `postgres://user:password@ip.or.domain.to.server/database_name` |
| ENCRYPTION_SECRET | SgVkYp2s5v8y/B?E(H+MbQeThWmZq4t6 | A 256-bit key used to encrypt sensitive data. It is strongly recommended to [generate](https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx) a new one. |
| ADMIN_EMAIL | -- | The email that will get a "Pro" plan on user creation |
| NEXTAUTH_URL | http://localhost:3000 | The builder base URL |
| NEXT_PUBLIC_VIEWER_URL | http://localhost:3001 | The viewer base URL |
### SMTP (optional)
Used for sending email notifications and authentication
| Parameter | Default | Description |
| --------------------- | ------- | ------------------------------------------------------------------------------- |
| SMTP_USERNAME | -- | SMTP username |
| SMTP_PASSWORD | -- | SMTP password |
| SMTP_HOST | -- | SMTP host. (i.e. `smtp.host.com`) |
| SMTP_PORT | 25 | SMTP port |
| NEXT_PUBLIC_SMTP_FROM | - | From name and email (i.e. `"Typebot Notifications" <notifications@typebot.io>`) |
### Google (optional)
Used authentication in the builder and for the Google Sheets integration step. Make sure to set the required scopes (`userinfo.email`, `spreadsheets`, `drive.readonly`) in your console
| Parameter | Default | Description |
| ---------------------------- | ------- | --------------------------------------------- |
| NEXT_PUBLIC_GOOGLE_CLIENT_ID | -- | The Client ID from the Google API Console |
| GOOGLE_CLIENT_SECRET | -- | The Client secret from the Google API Console |
## Builder
The following variables are only used for the builder.
### GitHub (optional)
Used for authenticating with GitHub. By default, it uses the credentials of a Typebot-dev app.
You can create your own GitHub OAuth app [here](https://github.com/settings/developers).
| Parameter | Default | Description |
| ---------------------------- | ---------------------------------------- | --------------------------------------------------------------------------- |
| NEXT_PUBLIC_GITHUB_CLIENT_ID | 534b549dd17709a743a2 | Application client ID. Also used to check if it is enabled in the front-end |
| GITHUB_CLIENT_SECRET | 7adb03507504fb1a54422f6c3c697277cfd000a9 | Application secret |
### Facebook (optional)
You can create your own Facebook OAuth app [here](https://developers.facebook.com/apps/create/).
| Parameter | Default | Description |
| ------------------------------ | ------- | --------------------------------------------------------------------------- |
| NEXT_PUBLIC_FACEBOOK_CLIENT_ID | -- | Application client ID. Also used to check if it is enabled in the front-end |
| FACEBOOK_CLIENT_SECRET | -- | Application secret |
### S3 Storage (optional)
Used for uploading images, videos, etc... It can be any S3 compatible object storage service (Minio, Digital Oceans Space, AWS S3...)
| Parameter | Default | Description |
| ------------- | ------- | -------------------------------------------------------------- |
| S3_ACCESS_KEY | -- | S3 access key. Also used to check if upload feature is enabled |
| S3_SECRET_KEY | -- | S3 secret key. |
| S3_BUCKET | typebot | Name of the bucket where assets will be uploaded in. |
| S3_PORT | -- | S3 Host port number |
| S3_ENDPOINT | -- | S3 secret key. |
| S3_SSL | true | Use SSL when establishing the connection. |
| S3_REGION | -- | S3 region. |
Your bucket must have the following policy that tells S3 to allow public read when an object is located under the public folder:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<BUCKET_NAME>/public/*"
}
]
}
```
You also need to configure CORS so that an object can be uploaded from the browser:
```json
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["PUT", "POST"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["ETag"]
}
]
```
### Giphy (optional)
Used to search for GIF. You can create a Giphy app [here](https://developers.giphy.com/dashboard/)
| Parameter | Default | Description |
| ------------------------- | ------- | ------------- |
| NEXT_PUBLIC_GIPHY_API_KEY | -- | Giphy API key |
### Others (optional)
The [official Typebot managed service](https://app.typebot.io/) uses other services such as [Stripe](https://stripe.com/) for processing payments, [Sentry](https://sentry.io/) for tracking bugs and [Sleekplan](https://sleekplan.com/) for user feedbacks.
The related environment variables are listed here but you are probably not interested in these if you self-host Typebot.
<details><summary>Stripe</summary>
<p>
| Parameter | Default | Description |
| ----------------------------- | ------- | --------------------- |
| NEXT_PUBLIC_STRIPE_PUBLIC_KEY | -- | Stripe public key |
| STRIPE_SECRET_KEY | -- | Stripe secret key |
| STRIPE_PRICE_USD_ID | -- | Pro plan USD price id |
| STRIPE_PRICE_EUR_ID | -- | Pro plan EUR price id |
| STRIPE_WEBHOOK_SECRET | -- | Stripe Webhook secret |
</p></details>
<details><summary>Sentry</summary>
<p>
| Parameter | Default | Description |
| ---------------------- | ------- | -------------------------------------- |
| NEXT_PUBLIC_SENTRY_DSN | -- | Sentry DSN |
| SENTRY_AUTH_TOKEN | -- | Used to upload sourcemaps on app build |
| SENTRY_PROJECT | -- | Sentry project name |
| SENTRY_ORG | -- | Sentry organization name |
These can also be added to the `viewer` environment
</p></details>
<details><summary>Vercel (custom domains)</summary>
<p>
| Parameter | Default | Description |
| -------------------------- | ------- | ----------------------------------------------- |
| VERCEL_TOKEN | -- | Vercel API token |
| VERCEL_VIEWER_PROJECT_NAME | -- | The name of the viewer project in Vercel |
| VERCEL_TEAM_ID | -- | Vercel team ID that contains the viewer project |
</p></details>
<details><summary>Sleekplan</summary>
<p>
| Parameter | Default | Description |
| ----------------- | ------- | ------------------------------------------------------------------------ |
| SLEEKPLAN_SSO_KEY | -- | Sleekplan SSO key used to automatically authenticate a user in Sleekplan |
</p></details>

View File

@ -0,0 +1,44 @@
---
sidebar_position: 2
---
# Docker
:::note
The easiest way to get started with Typebot is with [the official managed service in the Cloud](https://app.typebot.io). It takes 1 minute to try out the tool for free. You'll have high availability, backups, security, and maintenance all managed for you by me, Baptiste, Typebot's founder.
That's also the best way to support my work, open-source software, and you'll get great service!
:::
## Requirements
You need a server with Docker installed. If your server doesn't come with Docker pre-installed, you can follow [their docs](https://docs.docker.com/get-docker/) to install it.
## Getting started
1. Fork the repository
On your server:
2. Clone the forked repo:
```sh
git clone https://github.com/<your-fork>/typebot.io.git
```
3. Edit the `typebot-config.env` file. ([Check out the configuration guide](/self-hosting/configuration))
4. Start the applications:
```sh
docker-compose up -d
```
It does the following:
- Create a database
- Run the migrations
- Start the builder on port 8080
- Start the viewer on port 8081
You should see the login screen if you navigate to `http://{hostname}:8080`. Login with the `${ADMIN_EMAIL}` in order to have access to a Pro account automatically.

View File

@ -0,0 +1,22 @@
---
sidebar_position: 1
slug: /self-hosting
---
# Getting started
:::note
The easiest way to get started with Typebot is with [the official managed service in the Cloud](https://app.typebot.io). It takes 1 minute to try out the tool for free. You'll have high availability, backups, security, and maintenance all managed for you by me, Baptiste, Typebot's founder.
That's also the best way to support my work, open-source software, and you'll get great service!
:::
Typebot is composed of 2 Next.js applications you need to deploy:
- the builder, where you build your typebots
- the viewer, where your user answer the typebot
I've written guides on how to deploy Typebot using:
- [Docker](/self-hosting/docker)
- [Vercel](/self-hosting/vercel)

View File

@ -1,53 +0,0 @@
# Self hosting
:::note
The easiest way to get started with Typebot is with [our official managed service in the Cloud](https://app.typebot.io). It takes 1 minute to create your free account. You'll have high availability, backups, security, and maintenance all managed for you by Typebot. The section below is for self-hosting Typebot on your server and managing your infrastructure.
:::
Typebot is composed of 2 Next.js applications you need to deploy:
- the builder, where you build your typebots
- the viewer, where your user answer the typebot
They are connected to a Database and an S3 bucket
## S3
Paste this bucket policy after replacing `<BUCKET_NAME>` with your bucket name:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<BUCKET_NAME>/public/*"
}
]
}
```
CORS config:
```json
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["PUT", "POST"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["ETag"]
}
]
```
```
S3_ACCESS_KEY=minio
S3_SECRET_KEY=minio123
S3_BUCKET=typebot
S3_PORT=9000
S3_ENDPOINT=localhost
S3_SSL=false
```

View File

@ -0,0 +1,49 @@
---
sidebar_position: 2
---
# Vercel
:::note
The easiest way to get started with Typebot is with [the official managed service in the Cloud](https://app.typebot.io). It takes 1 minute to try out the tool for free. You'll have high availability, backups, security, and maintenance all managed for you by me, Baptiste, Typebot's founder.
That's also the best way to support my work, open-source software, and you'll get great service!
:::
## Requirements
You need a PostgresDB database hosted somewhere. [Supabase](https://supabase.com/) and [Heroku](https://www.heroku.com/) offer great free options.
## Getting Started
Fork the repository
### Deploy the builder
1. Create a new Vercel project and import the forked repo
2. Change the project name to: `typebot-builder` (or anything else)
3. Choose Next.js framework
4. Change the root directory to: `apps/builder`
5. Change the build command to:
```sh
cd ../.. && yarn db:migrate && yarn turbo run build --scope=builder --include-dependencies
```
6. Add the required environment variables ([Check out the configuration guide](/self-hosting/configuration))
7. Hit "Deploy"
### Deploy the viewer
1. Create a new Vercel project and import the forked repo
2. Change the project name to: `typebot-viewer` (or anything else)
3. Choose Next.js framework
4. Change the root directory to: `apps/viewer`
5. Change the build command to:
```sh
cd ../.. && yarn db:migrate && yarn turbo run build --scope=viewer --include-dependencies
```
6. Add the required environment variables ([Check out the configuration guide](/self-hosting/configuration))
7. Hit "Deploy"

View File

@ -80,7 +80,8 @@ module.exports = {
],
},
colorMode: {
disableSwitch: true,
disableSwitch: false,
respectPrefersColorScheme: true,
},
},
presets: [

View File

@ -21,17 +21,6 @@ h4 {
img {
border-radius: 0.5rem;
}
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #0042da;
--ifm-color-primary-dark: #003bc4;
--ifm-color-primary-darker: #0038b9;
--ifm-color-primary-darkest: #002e99;
--ifm-color-primary-light: #0049f0;
--ifm-color-primary-lighter: #004cfb;
--ifm-color-primary-lightest: #1c61ff;
--ifm-code-font-size: 95%;
}
.docusaurus-highlight-code-line {
background-color: rgba(0, 0, 0, 0.1);

View File

@ -1,4 +1,4 @@
NOTION_API_TOKEN=
NOTION_DATABASE_ID=
NEXT_PUBLIC_VIEWER_HOST=http://localhost:3001
NEXT_PUBLIC_VIEWER_URL=http://localhost:3001
LANDING_PAGE_HOST=http://localhost:3002

View File

@ -35,7 +35,7 @@ module.exports = withBundleAnalyzer({
{
source: '/_next/static/:static*',
destination:
process.env.NEXT_PUBLIC_VIEWER_HOST + '/_next/static/:static*',
process.env.NEXT_PUBLIC_VIEWER_URL + '/_next/static/:static*',
has: [
{
type: 'header',
@ -52,11 +52,11 @@ module.exports = withBundleAnalyzer({
fallback: [
{
source: '/:typebotId*',
destination: process.env.NEXT_PUBLIC_VIEWER_HOST + '/:typebotId*',
destination: process.env.NEXT_PUBLIC_VIEWER_URL + '/:typebotId*',
},
{
source: '/api/:path*',
destination: process.env.NEXT_PUBLIC_VIEWER_HOST + '/api/:path*',
destination: process.env.NEXT_PUBLIC_VIEWER_URL + '/api/:path*',
},
],
}

View File

@ -1,16 +1,6 @@
ENCRYPTION_SECRET=
NEXT_PUBLIC_VIEWER_HOST=http://localhost:3001
ENCRYPTION_SECRET=SgVkYp2s5v8y/B?E(H+MbQeThWmZq4t6 #256-bits secret (can be generated here: https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx)
NEXT_PUBLIC_VIEWER_URL=http://localhost:3001
DATABASE_URL=postgresql://postgres:@localhost:5432/typebot
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# (Optional) Used for email notifications
EMAIL_NOTIFICATIONS_SERVER_USER=username
EMAIL_NOTIFICATIONS_SERVER_PASSWORD=password
EMAIL_NOTIFICATIONS_SERVER_HOST=smtp.example.com
EMAIL_NOTIFICATIONS_SERVER_PORT=587
NEXT_PUBLIC_EMAIL_NOTIFICATIONS_FROM_EMAIL=noreply@example.com
NEXT_PUBLIC_EMAIL_NOTIFICATIONS_FROM_NAME="John Smith"
NEXT_PUBLIC_SENTRY_DSN=
# For more configuration options check out:
https://docs.typebot.io/self-hosting/configuration

View File

@ -17,7 +17,7 @@ export const getAuthenticatedGoogleClient = async (
) as GoogleSheetsCredentialsData
const oauth2Client = new OAuth2Client(
process.env.GOOGLE_CLIENT_ID,
process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
`${process.env.NEXTAUTH_URL}/api/credentials/google-sheets/callback`
)

View File

@ -14,7 +14,7 @@ export const getServerSideProps: GetServerSideProps = async (
try {
if (!context.req.headers.host) return { props: {} }
typebot = context.req.headers.host.includes(
(process.env.NEXT_PUBLIC_VIEWER_HOST ?? '').split('//')[1]
(process.env.NEXT_PUBLIC_VIEWER_URL ?? '').split('//')[1]
)
? await getTypebotFromPublicId(context.query.publicId?.toString())
: await getTypebotFromCustomDomain(

View File

@ -10,18 +10,18 @@ import { withSentry } from '@sentry/nextjs'
const cors = initMiddleware(Cors())
const defaultTransportOptions = {
host: process.env.EMAIL_NOTIFICATIONS_SERVER_HOST,
port: Number(process.env.EMAIL_NOTIFICATIONS_SERVER_PORT),
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure: false,
auth: {
user: process.env.EMAIL_NOTIFICATIONS_SERVER_USER,
pass: process.env.EMAIL_NOTIFICATIONS_SERVER_PASSWORD,
user: process.env.SMTP_USERNAME,
pass: process.env.SMTP_PASSWORD,
},
}
const defaultFrom = {
name: process.env.NEXT_PUBLIC_EMAIL_NOTIFICATIONS_FROM_NAME,
email: process.env.NEXT_PUBLIC_EMAIL_NOTIFICATIONS_FROM_EMAIL,
name: process.env.NEXT_PUBLIC_SMTP_FROM?.split(' <')[0].replace(/"/g, ''),
email: process.env.NEXT_PUBLIC_SMTP_FROM?.match(/\<(.*)\>/)?.pop(),
}
const handler = async (req: NextApiRequest, res: NextApiResponse) => {

View File

@ -17,7 +17,7 @@ const config: PlaywrightTestConfig = {
maxFailures: process.env.CI ? 10 : undefined,
use: {
actionTimeout: 0,
baseURL: process.env.NEXT_PUBLIC_VIEWER_HOST,
baseURL: process.env.NEXT_PUBLIC_VIEWER_URL,
storageState: path.join(__dirname, 'playwright/proUser.json'),
trace: 'on-first-retry',
video: 'retain-on-failure',

View File

@ -33,7 +33,7 @@ export type TypebotViewerProps = {
}
export const TypebotViewer = ({
typebot,
apiHost = process.env.NEXT_PUBLIC_VIEWER_HOST,
apiHost = process.env.NEXT_PUBLIC_VIEWER_URL,
isPreview = false,
onNewLog,
onNewBlockVisible,
@ -59,7 +59,7 @@ export const TypebotViewer = ({
const handleCompleted = () => onCompleted && onCompleted()
if (!apiHost)
return <p>process.env.NEXT_PUBLIC_VIEWER_HOST is missing in env</p>
return <p>process.env.NEXT_PUBLIC_VIEWER_URL is missing in env</p>
return (
<Frame
id="typebot-iframe"

View File

@ -1,7 +1,5 @@
# Typebot JS library
[![NPM](https://flat.badgen.net/npm/v/typebot-js)](https://www.npmjs.com/package/typebot-js) [![Bundle](https://flat.badgen.net/bundlephobia/minzip/typebot-js)](https://bundlephobia.com/result?p=typebot-js@latest) [![Build Status](https://travis-ci.com/plausible/typebot-js.svg?branch=master)](https://travis-ci.com/plausible/typebot-js)
Frontend library to embed typebots from [Typebot](https://www.typebot.io/).
## Installation
@ -19,9 +17,9 @@ yarn add typebot-js
It exposes 3 functions:
```ts
initContainer();
initPopup();
initBubble();
initContainer()
initPopup()
initBubble()
```
You can configure them directly in the "Share" tab of your typebot.
@ -29,9 +27,9 @@ You can configure them directly in the "Share" tab of your typebot.
Example:
```ts
import { initContainer } from "typebot-js";
import { initContainer } from 'typebot-js'
const plausible = initContainer("container-id", {
publishId: "my-app.com",
});
const plausible = initContainer('container-id', {
publishId: 'my-app.com',
})
```

View File

@ -1,7 +1,7 @@
# Shared
# MIGRATION_DATABASE_URL=
DATABASE_URL=postgresql://typebot:typebot@postgres:5432/typebot
NEXT_PUBLIC_VIEWER_HOST=http://localhost:8081
NEXT_PUBLIC_VIEWER_URL=http://localhost:8081
ENCRYPTION_SECRET=SgVkYp2s5v8y/B?E(H+MbQeThWmZq4t6
# Builder