Compare commits

..

1 Commits

Author SHA1 Message Date
Piyush Gupta
9833ba6b26 fix: license restores 2024-11-18 18:22:20 +05:30
1766 changed files with 41689 additions and 51281 deletions

View File

@@ -46,9 +46,6 @@ SMTP_SECURE_ENABLED=0
SMTP_USER=smtpUser
SMTP_PASSWORD=smtpPassword
# If set to 0, the server will not require SMTP_USER and SMTP_PASSWORD(default is 1)
# SMTP_AUTHENTICATED=
# If set to 0, the server will accept connections without requiring authorization from the list of supplied CAs (default is 1).
# SMTP_REJECT_UNAUTHORIZED_TLS=0
@@ -104,11 +101,6 @@ PASSWORD_RESET_DISABLED=1
PRIVACY_URL=
TERMS_URL=
IMPRINT_URL=
IMPRINT_ADDRESS=
# Configure Turnstile in signup flow
# NEXT_PUBLIC_TURNSTILE_SITE_KEY=
# TURNSTILE_SECRET_KEY=
# Configure Github Login
GITHUB_ID=
@@ -193,7 +185,4 @@ UNSPLASH_ACCESS_KEY=
# AI_AZURE_RESSOURCE_NAME=
# AI_AZURE_API_KEY=
# AI_AZURE_EMBEDDINGS_DEPLOYMENT_ID=
# AI_AZURE_LLM_DEPLOYMENT_ID=
# NEXT_PUBLIC_INTERCOM_APP_ID=
# INTERCOM_SECRET_KEY=
# AI_AZURE_LLM_DEPLOYMENT_ID=

View File

@@ -1,6 +1,7 @@
name: Bug report
description: "Found a bug? Please fill out the sections below. \U0001F44D"
type: bug
labels:
- bug
body:
- type: textarea
id: issue-summary

View File

@@ -1,6 +1,7 @@
name: Feature request
description: "Suggest an idea for this project \U0001F680"
type: feature
labels:
- enhancement
body:
- type: textarea
id: problem-description
@@ -29,4 +30,4 @@ body:
### Additional resources 🤓
- Check out our [Contributor Docs](https://formbricks.com/docs/developer-docs/contributing/get-started)
- Anything unclear? [Ask in Github Discussions](https://github.com/formbricks/formbricks/discussions)
- Anything unclear? [Ask in Discord](https://formbricks.com/discord)

View File

@@ -1,11 +0,0 @@
name: Task (internal)
description: "Template for creating a task. Used by the Formbricks Team only \U0001f4e5"
type: task
body:
- type: textarea
id: task-summary
attributes:
label: Task description
description: A clear detailed-rich description of the task.
validations:
required: true

View File

@@ -1,10 +1,6 @@
name: Build Docs
on:
workflow_call:
permissions:
contents: read
jobs:
build:
name: Build Docs

View File

@@ -1,10 +1,6 @@
name: Build Web
on:
workflow_call:
permissions:
contents: read
jobs:
build:
name: Build Formbricks-web

92
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,92 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Advanced"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '17 1 * * 1'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@@ -7,10 +7,6 @@ on:
schedule:
# Runs "At 00:00." (see https://crontab.guru)
- cron: "0 0 * * *"
permissions:
contents: read
jobs:
cron-weeklySummary:
env:

View File

@@ -9,8 +9,6 @@ on:
- cron: "0 8 * * 1"
jobs:
cron-weeklySummary:
permissions:
contents: read
env:
APP_URL: ${{ secrets.APP_URL }}
CRON_SECRET: ${{ secrets.CRON_SECRET }}

View File

@@ -1,55 +0,0 @@
name: Draft release
run-name: Draft release ${{ inputs.next_version }}
on:
workflow_dispatch:
inputs:
next_version:
required: true
type: string
description: "Version name"
permissions:
contents: write
jobs:
draft_release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: ./.github/actions/dangerous-git-checkout
- name: Configure git
run: |
git config --local user.email "github-actions@github.com"
git config --local user.name "GitHub Actions"
- name: Setup Node.js 20.x
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
with:
node-version: 20.x
- name: Install pnpm
uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2
- name: Install dependencies
run: pnpm install --config.platform=linux --config.architecture=x64
- name: Bump version
run: |
cd apps/web
pnpm version ${{ inputs.next_version }} --no-workspaces-update
- name: Commit changes
run: |
git add .
git commit -m "chore: release v${{ inputs.next_version }}"
git push
- name: Draft release
run: gh release create v${{ inputs.next_version }} --generate-notes --draft
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.next_version }}

View File

@@ -2,11 +2,6 @@ name: E2E Tests
on:
workflow_call:
workflow_dispatch:
permissions:
contents: read
actions: read
checks: write
env:
TELEMETRY_DISABLED: 1
jobs:
@@ -65,8 +60,7 @@ jobs:
- name: Apply Prisma Migrations
run: |
# pnpm prisma migrate deploy
pnpm db:migrate:dev
pnpm prisma migrate deploy
- name: Run App
run: |
@@ -92,7 +86,7 @@ jobs:
run: |
pnpm test:e2e
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report

View File

@@ -1,10 +1,6 @@
name: Lint
on:
workflow_call:
permissions:
contents: read
jobs:
build:
name: Linters
@@ -12,16 +8,16 @@ jobs:
timeout-minutes: 15
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@v3
- uses: ./.github/actions/dangerous-git-checkout
- name: Setup Node.js 20.x
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
uses: actions/setup-node@v3
with:
node-version: 20.x
- name: Install pnpm
uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2
uses: pnpm/action-setup@v4
- name: Install dependencies
run: pnpm install --config.platform=linux --config.architecture=x64

View File

@@ -1,12 +1,5 @@
name: PR Update
# Update permissions to include all necessary ones
permissions:
contents: read
pull-requests: read
actions: read
checks: write
on:
pull_request:
branches:
@@ -22,6 +15,8 @@ jobs:
changes:
name: Detect changes
runs-on: ubuntu-latest
permissions:
pull-requests: read
outputs:
has-files-requiring-all-checks: ${{ steps.filter.outputs.has-files-requiring-all-checks }}
steps:
@@ -74,10 +69,6 @@ jobs:
needs: [lint, test, build, e2e-test, docs]
if: always()
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
statuses: write
steps:
- name: fail if conditional jobs failed
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped') || contains(needs.*.result, 'cancelled')

View File

@@ -6,11 +6,6 @@ on:
# branches:
# - main
permissions:
contents: write
pull-requests: write
packages: write
concurrency: ${{ github.workflow }}-${{ github.ref }}
env:

View File

@@ -0,0 +1,62 @@
name: Docker for Data Migrations
on:
workflow_dispatch:
push:
tags:
- "v*"
env:
REGISTRY: ghcr.io
IMAGE_NAME: formbricks/data-migrations
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/formbricks?schema=public"
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@v3.5.0
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=tag
type=raw,value=${{ github.ref_name }}
type=raw,value=latest
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: ./packages/database/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
DATABASE_URL=${{ env.DATABASE_URL }}
- name: Sign the published Docker image
if: ${{ github.event_name != 'pull_request' }}
run: |
cosign sign --yes ghcr.io/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
cosign sign --yes ghcr.io/${{ env.IMAGE_NAME }}:latest

View File

@@ -8,8 +8,6 @@ on:
jobs:
release-image-on-dockerhub:
name: Release on Dockerhub
permissions:
contents: read
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}

View File

@@ -1,23 +0,0 @@
name: SonarQube
on:
workflow_dispatch:
# push:
# branches:
# - main
# pull_request:
# types: [opened, synchronize, reopened]
permissions:
contents: read
jobs:
sonarqube:
name: SonarQube
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@bfd4e558cda28cda6b5defafb9232d191be8c203
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

View File

@@ -6,8 +6,6 @@ jobs:
name: Unit Tests
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- uses: actions/checkout@v3

View File

@@ -22,6 +22,6 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pr-message: |-
Thank you so much for making your first Pull Request and taking the time to improve Formbricks! 🚀🙏❤️
Feel free to join the conversation on [Github Discussions](https://github.com/formbricks/formbricks/discussions) if you need any help or have any questions. 😊
Feel free to join the conversation at [Discord](https://formbricks.com/discord)
issue-message: |
Thank you for opening your first issue! 🙏❤️ One of our team members will review it and get back to you as soon as it possible. 😊

5
.gitignore vendored
View File

@@ -35,6 +35,9 @@ yarn-error.log*
!packages/database/.env
!apps/web/.env
# Prisma generated files
packages/database/zod
# turbo
.turbo
@@ -57,5 +60,3 @@ packages/lib/uploads
# js compiled assets
apps/web/public/js
packages/database/migrations

2
.nvmrc
View File

@@ -1 +1 @@
22.1.0
20.18.0

View File

@@ -24,7 +24,7 @@ Ready to dive into the code and make a real impact? Here's your path:
1. **Pull Request Act:** If you're ready to go, craft a new pull request closely following our PR template 🙏
Would you prefer a chat before you dive into a lot of work? [Github Discussions](https://github.com/formbricks/formbricks/discussions) is your harbor. Share your thoughts, and we'll meet you there with open arms. We're responsive and friendly, promise!
Would you prefer a chat before you dive into a lot of work? Our [Discord server](https://formbricks.com/discord) is your harbor. Share your thoughts, and we'll meet you there with open arms. We're responsive and friendly, promise!
## 🚀 Aspiring Features

View File

@@ -2,7 +2,7 @@ Copyright (c) 2024 Formbricks GmbH
Portions of this software are licensed as follows:
- All content that resides under the "apps/web/modules/ee" directory of this repository, if these directories exist, is licensed under the license defined in "apps/web/modules/ee/LICENSE".
- All content that resides under the "packages/ee/", "apps/web/modules/ee" & "apps/web/app/(ee)" directories of this repository, if these directories exist, is licensed under the license defined in "packages/ee/LICENSE".
- All content that resides under the "packages/js/", "packages/react-native/" and "packages/api/" directories of this repository, if that directories exist, is licensed under the "MIT" license as defined in the "LICENSE" files of these packages.
- All third party components incorporated into the Formbricks Software are licensed under the original license provided by the owner of the applicable component.
- Content outside of the above mentioned directories or restrictions above is available under the "AGPLv3" license as defined below.

View File

@@ -15,12 +15,12 @@
<p align="center">
Harvest user-insights, build irresistible experiences.
<br />
<a href="https://formbricks.com/">Website</a>
<a href="https://formbricks.com/">Website</a> | <a href="https://formbricks.com/discord">Join Discord community</a>
</p>
</p>
<p align="center">
<a href="https://github.com/formbricks/formbricks/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-AGPL-purple" alt="License"></a> <a href="https://github.com/formbricks/formbricks/stargazers"><img src="https://img.shields.io/github/stars/formbricks/formbricks?logo=github" alt="Github Stars"></a>
<a href="https://github.com/formbricks/formbricks/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-AGPL-purple" alt="License"></a> <a href="https://formbricks.com/discord"><img src="https://img.shields.io/discord/979077669410979880?label=Discord&logo=discord&logoColor=%23fff" alt="Join Formbricks Discord"></a> <a href="https://github.com/formbricks/formbricks/stargazers"><img src="https://img.shields.io/github/stars/formbricks/formbricks?logo=github" alt="Github Stars"></a>
<a href="https://news.ycombinator.com/item?id=32303986"><img src="https://img.shields.io/badge/Hacker%20News-122-%23FF6600" alt="Hacker News"></a>
<a href="[https://www.producthunt.com/products/formbricks](https://www.producthunt.com/posts/formbricks)"><img src="https://img.shields.io/badge/Product%20Hunt-455-orange?logo=producthunt&logoColor=%23fff" alt="Product Hunt"></a>
<a href="https://github.blog/2023-04-12-github-accelerator-our-first-cohort-and-whats-next/"><img src="https://img.shields.io/badge/2023-blue?logo=github&label=Github%20Accelerator" alt="Github Accelerator"></a>
@@ -228,14 +228,14 @@ The Formbricks core application is licensed under the [AGPLv3 Open Source Licens
### The Enterprise Edition
Additional to the AGPL licensed Formbricks core, this repository contains code licensed under an Enterprise license. The [code](https://github.com/formbricks/formbricks/tree/main/apps/web/modules/ee) and [license](https://github.com/formbricks/formbricks/blob/main/apps/web/modules/ee/LICENSE) for the enterprise functionality can be found in the `/apps/web/modules/ee` folder of this repository. This additional functionality is not part of the AGPLv3 licensed Formbricks core and is designed to meet the needs of larger teams and enterprises. This advanced functionality is already included in the Docker images, but you need an [Enterprise License Key](https://formbricks.com/docs/self-hosting/enterprise) to unlock it.
Additional to the AGPL licensed Formbricks core, this repository contains code licensed under an Enterprise license. The [code](https://github.com/formbricks/formbricks/tree/main/packages/ee) and [license](https://github.com/formbricks/formbricks/blob/main/packages/ee/LICENSE) for the enterprise functionality can be found in the `/packages/ee` folder of this repository. This additional functionality is not part of the AGPLv3 licensed Formbricks core and is designed to meet the needs of larger teams and enterprises. This advanced functionality is already included in the Docker images, but you need an [Enterprise License Key](https://formbricks.com/docs/self-hosting/enterprise) to unlock it.
### White-Labeling Formbricks and Other Licensing Needs
We currently do not offer Formbricks white-labeled. That means that we don't sell a license which let's other companies resell Formbricks to third parties under their name nor take parts (like the survey editor) out of Formbricks to add to their own software products. Any other needs? [Send us an email](mailto:hola@formbricks.com).
We currently do not offer Formbricks white-labeled. Any other needs? [Send us an email](mailto:hola@formbricks.com).
### Why charge for Enterprise Features?
The Enterprise Edition allows us to fund the development of Formbricks sustainably. It guarantees that the free and open-source surveying infrastructure we're building will be around for decades to come.
The Enterprise Edition and White-Label Licenses allow us to fund the development of Formbricks sustainably. It guarantees that the open-source surveying infrastructure we're building will be around for decades to come.
<p align="right"><a href="#top">🔼 Back to top</a></p>

View File

@@ -1,7 +1,7 @@
# Security Policy of Formbricks
This is Formbrick's security policy. Please reach out to us
on Github or, if privately, via <security@formbricks.com>
on our Discord or, if privately, via <security@formbricks.com>
## Introduction
@@ -40,7 +40,7 @@ We invite you to report if:
Avoid reporting if:
- Assistance is needed to optimize Formbricks for security please engage on Github Discussions for this.
- Assistance is needed to optimize Formbricks for security please engage on our Discord for this.
- Help is required for applying security-related updates.
- The concern is not related to security.

View File

@@ -13,17 +13,17 @@
"dependencies": {
"@formbricks/js": "workspace:*",
"@formbricks/react-native": "workspace:*",
"expo": "52.0.18",
"expo-status-bar": "2.0.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "0.76.5",
"react-native-webview": "13.12.5"
"expo": "51.0.26",
"expo-status-bar": "1.12.1",
"react": "19.0.0-rc-ed15d500-20241110",
"react-dom": "19.0.0-rc-ed15d500-20241110",
"react-native": "0.74.4",
"react-native-webview": "13.8.6"
},
"devDependencies": {
"@babel/core": "7.26.0",
"@types/react": "19.0.1",
"typescript": "5.7.2"
"@babel/core": "7.25.2",
"@types/react": "18.3.11",
"typescript": "5.3.3"
},
"private": true
}

View File

@@ -1,5 +1,5 @@
import { StatusBar } from "expo-status-bar";
import React, { type JSX } from "react";
import type { JSX } from "react";
import { Button, LogBox, StyleSheet, Text, View } from "react-native";
import Formbricks, { track } from "@formbricks/react-native";
@@ -15,8 +15,8 @@ export default function App(): JSX.Element {
}
const config = {
environmentId: process.env.EXPO_PUBLIC_FORMBRICKS_ENVIRONMENT_ID as string,
apiHost: process.env.EXPO_PUBLIC_API_HOST as string,
environmentId: process.env.EXPO_PUBLIC_FORMBRICKS_ENVIRONMENT_ID,
apiHost: process.env.EXPO_PUBLIC_API_HOST,
userId: "random-user-id",
attributes: {
language: "en",

View File

@@ -1,7 +1,3 @@
module.exports = {
extends: ["@formbricks/eslint-config/next.js"],
parserOptions: {
project: "tsconfig.json",
tsconfigRootDir: __dirname,
},
extends: ["@formbricks/eslint-config/legacy-next.js"],
};

View File

@@ -1,6 +1,6 @@
import { Sidebar } from "./sidebar";
import { Sidebar } from "./Sidebar";
export function LayoutApp({ children }: { children: React.ReactNode }): React.JSX.Element {
export const LayoutApp = ({ children }: { children: React.ReactNode }) => {
return (
<div className="min-h-full">
{/* Static sidebar for desktop */}
@@ -10,4 +10,4 @@ export function LayoutApp({ children }: { children: React.ReactNode }): React.JS
<div className="flex flex-1 flex-col lg:pl-64">{children}</div>
</div>
);
}
};

View File

@@ -25,7 +25,7 @@ const secondaryNavigation = [
{ name: "Privacy", href: "#", icon: ShieldCheckIcon },
];
export function Sidebar(): React.JSX.Element {
export const Sidebar = () => {
return (
<div className="flex flex-grow flex-col overflow-y-auto bg-cyan-700 pb-4 pt-5">
<nav
@@ -62,4 +62,4 @@ export function Sidebar(): React.JSX.Element {
</nav>
</div>
);
}
};

View File

@@ -1,3 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -1,3 +1,3 @@
export function classNames(...classes: string[]): string {
export const classNames = (...classes: any) => {
return classes.filter(Boolean).join(" ");
}
};

View File

@@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.

View File

@@ -4,21 +4,22 @@
"private": true,
"scripts": {
"clean": "rimraf .turbo node_modules .next",
"dev": "next dev -p 3002 --turbopack",
"go": "next dev -p 3002 --turbopack",
"dev": "next dev -p 3002 --turbo",
"go": "next dev -p 3002 --turbo",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@formbricks/js": "workspace:*",
"lucide-react": "0.468.0",
"next": "15.1.2",
"react": "19.0.0",
"react-dom": "19.0.0"
"@formbricks/ui": "workspace:*",
"lucide-react": "0.452.0",
"next": "15.0.3",
"react": "19.0.0-rc-ed15d500-20241110",
"react-dom": "19.0.0-rc-ed15d500-20241110"
},
"devDependencies": {
"@formbricks/config-typescript": "workspace:*",
"@formbricks/eslint-config": "workspace:*"
"@formbricks/eslint-config": "workspace:*",
"@formbricks/config-typescript": "workspace:*"
}
}

View File

@@ -1,8 +1,8 @@
import type { AppProps } from "next/app";
import Head from "next/head";
import "../globals.css";
import "@formbricks/ui/globals.css";
export default function App({ Component, pageProps }: AppProps): React.JSX.Element {
const App = ({ Component, pageProps }: AppProps) => {
return (
<>
<Head>
@@ -17,4 +17,6 @@ export default function App({ Component, pageProps }: AppProps): React.JSX.Eleme
<Component {...pageProps} />
</>
);
}
};
export default App;

View File

@@ -1,6 +1,6 @@
import { Head, Html, Main, NextScript } from "next/document";
export default function Document(): React.JSX.Element {
const Document = () => {
return (
<Html lang="en" className="h-full bg-slate-50">
<Head />
@@ -10,4 +10,6 @@ export default function Document(): React.JSX.Element {
</body>
</Html>
);
}
};
export default Document;

View File

@@ -4,9 +4,9 @@ import { useEffect, useState } from "react";
import formbricks from "@formbricks/js";
import fbsetup from "../public/fb-setup.png";
declare const window: Window;
declare const window: any;
export default function AppPage(): React.JSX.Element {
const AppPage = ({}) => {
const [darkMode, setDarkMode] = useState(false);
const router = useRouter();
@@ -19,53 +19,44 @@ export default function AppPage(): React.JSX.Element {
}, [darkMode]);
useEffect(() => {
const initFormbricks = () => {
// enable Formbricks debug mode by adding formbricksDebug=true GET parameter
const addFormbricksDebugParam = (): void => {
const urlParams = new URLSearchParams(window.location.search);
if (!urlParams.has("formbricksDebug")) {
urlParams.set("formbricksDebug", "true");
const newUrl = `${window.location.pathname}?${urlParams.toString()}`;
window.history.replaceState({}, "", newUrl);
}
};
addFormbricksDebugParam();
if (process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID && process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST) {
const userId = "THIS-IS-A-VERY-LONG-USER-ID-FOR-TESTING";
const userInitAttributes = {
language: "de",
"Init Attribute 1": "eight",
"Init Attribute 2": "two",
};
void formbricks.init({
environmentId: process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID,
apiHost: process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST,
userId,
attributes: userInitAttributes,
});
}
// Connect next.js router to Formbricks
if (process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID && process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST) {
const handleRouteChange = formbricks.registerRouteChange;
router.events.on("routeChangeComplete", () => {
void handleRouteChange();
});
return () => {
router.events.off("routeChangeComplete", () => {
void handleRouteChange();
});
};
// enable Formbricks debug mode by adding formbricksDebug=true GET parameter
const addFormbricksDebugParam = () => {
const urlParams = new URLSearchParams(window.location.search);
if (!urlParams.has("formbricksDebug")) {
urlParams.set("formbricksDebug", "true");
const newUrl = `${window.location.pathname}?${urlParams.toString()}`;
window.history.replaceState({}, "", newUrl);
}
};
initFormbricks();
}, [router.events]);
addFormbricksDebugParam();
if (process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID && process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST) {
const userId = "THIS-IS-A-VERY-LONG-USER-ID-FOR-TESTING";
const userInitAttributes = {
language: "de",
"Init Attribute 1": "eight",
"Init Attribute 2": "two",
};
formbricks.init({
environmentId: process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID,
apiHost: process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST,
userId,
attributes: userInitAttributes,
});
}
// Connect next.js router to Formbricks
if (process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID && process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST) {
const handleRouteChange = formbricks?.registerRouteChange;
router.events.on("routeChangeComplete", handleRouteChange);
return () => {
router.events.off("routeChangeComplete", handleRouteChange);
};
}
}, []);
return (
<div className="min-h-screen bg-white px-12 py-6 dark:bg-slate-800">
@@ -83,11 +74,8 @@ export default function AppPage(): React.JSX.Element {
</div>
<button
type="button"
className="mt-2 rounded-lg bg-slate-200 px-6 py-1 dark:bg-slate-700 dark:text-slate-100"
onClick={() => {
setDarkMode(!darkMode);
}}>
onClick={() => setDarkMode(!darkMode)}>
{darkMode ? "Toggle Light Mode" : "Toggle Dark Mode"}
</button>
</div>
@@ -108,8 +96,8 @@ export default function AppPage(): React.JSX.Element {
{process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID}
</strong>
<span className="relative ml-2 flex h-3 w-3">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-500 opacity-75" />
<span className="relative inline-flex h-3 w-3 rounded-full bg-green-500" />
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-500 opacity-75"></span>
<span className="relative inline-flex h-3 w-3 rounded-full bg-green-500"></span>
</span>
</div>
</div>
@@ -120,6 +108,9 @@ export default function AppPage(): React.JSX.Element {
Look at the logs to understand how the widget works.{" "}
<strong className="dark:text-white">Open your browser console</strong> to see the logs.
</p>
{/* <div className="max-h-[40vh] overflow-y-auto py-4">
<LogsContainer />
</div> */}
</div>
</div>
@@ -134,9 +125,8 @@ export default function AppPage(): React.JSX.Element {
</p>
<button
className="my-4 rounded-lg bg-slate-500 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600"
type="button"
onClick={() => {
void formbricks.reset();
formbricks.reset();
}}>
Reset
</button>
@@ -148,9 +138,7 @@ export default function AppPage(): React.JSX.Element {
<div className="p-6">
<div>
<button
type="button"
className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600">
<button className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600">
No-Code Action
</button>
</div>
@@ -159,7 +147,6 @@ export default function AppPage(): React.JSX.Element {
This button sends a{" "}
<a
href="https://formbricks.com/docs/actions/no-code"
rel="noopener noreferrer"
className="underline dark:text-blue-500"
target="_blank">
No Code Action
@@ -167,7 +154,6 @@ export default function AppPage(): React.JSX.Element {
as long as you created it beforehand in the Formbricks App.{" "}
<a
href="https://formbricks.com/docs/actions/no-code"
rel="noopener noreferrer"
target="_blank"
className="underline dark:text-blue-500">
Here are instructions on how to do it.
@@ -178,9 +164,8 @@ export default function AppPage(): React.JSX.Element {
<div className="p-6">
<div>
<button
type="button"
onClick={() => {
void formbricks.setAttribute("Plan", "Free");
formbricks.setAttribute("Plan", "Free");
}}
className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600">
Set Plan to &apos;Free&apos;
@@ -192,7 +177,6 @@ export default function AppPage(): React.JSX.Element {
<a
href="https://formbricks.com/docs/attributes/custom-attributes"
target="_blank"
rel="noopener noreferrer"
className="underline dark:text-blue-500">
attribute
</a>{" "}
@@ -203,9 +187,8 @@ export default function AppPage(): React.JSX.Element {
<div className="p-6">
<div>
<button
type="button"
onClick={() => {
void formbricks.setAttribute("Plan", "Paid");
formbricks.setAttribute("Plan", "Paid");
}}
className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600">
Set Plan to &apos;Paid&apos;
@@ -217,7 +200,6 @@ export default function AppPage(): React.JSX.Element {
<a
href="https://formbricks.com/docs/attributes/custom-attributes"
target="_blank"
rel="noopener noreferrer"
className="underline dark:text-blue-500">
attribute
</a>{" "}
@@ -228,9 +210,8 @@ export default function AppPage(): React.JSX.Element {
<div className="p-6">
<div>
<button
type="button"
onClick={() => {
void formbricks.setEmail("test@web.com");
formbricks.setEmail("test@web.com");
}}
className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600">
Set Email
@@ -242,7 +223,6 @@ export default function AppPage(): React.JSX.Element {
<a
href="https://formbricks.com/docs/attributes/identify-users"
target="_blank"
rel="noopener noreferrer"
className="underline dark:text-blue-500">
user email
</a>{" "}
@@ -254,4 +234,6 @@ export default function AppPage(): React.JSX.Element {
</div>
</div>
);
}
};
export default AppPage;

View File

@@ -1,20 +1,3 @@
module.exports = {
root: true,
extends: ["@formbricks/eslint-config/next.js"],
parserOptions: {
project: "tsconfig.json",
tsconfigRootDir: __dirname,
},
rules: {
"@typescript-eslint/restrict-template-expressions": "off",
"import/no-cycle": "off",
},
settings: {
"import/resolver": {
typescript: {
project: "tsconfig.json",
},
caseSensitive: false,
},
},
extends: ["@formbricks/eslint-config/legacy-next.js"],
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,48 +0,0 @@
import { MdxImage } from "@/components/mdx-image";
import EmailCustomizationSettings from "./email-customization-card.webp";
import EmailSample from "./email-sample.webp";
import UpdatedLogo from "./updated-logo.webp";
export const metadata = {
title: "Email Customization",
description: "Customize the email that is sent to your users!",
};
# Email Customization
Email customization is a white-label feature that allows you to customize the email that is sent to your users. You can upload a logo of your company and use it in the email.
<Note>
This feature is a white-label feature. It is only available for users on paid plans or have an enterprise license.
</Note>
## How to Upload a Logo
1. Go to the Organization Settings page.
2. You will see a card called **Email Customization** under the **General** section.
<MdxImage
src={EmailCustomizationSettings}
alt="Email Customization Settings"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
3. Upload a logo of your company.
4. Click on the **Save** button.
<MdxImage src={UpdatedLogo} alt="Updated Logo" quality="100" className="max-w-full rounded-lg sm:max-w-3xl" />
## Viewing the Logo in the Email
You can click on the **Send test email** button to get a test email with the logo.
<MdxImage src={EmailSample} alt="Email Sample" quality="100" className="max-w-full rounded-lg sm:max-w-3xl" />
<Note>Only the owner and managers of the organization can modify the logo.</Note>
## Use Cases
- **White-labeling**: You can use this feature to white-label your emails to your users.
- **Branding**: You can use this feature to add your logo to your emails to increase brand recognition.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -1,88 +0,0 @@
import { MdxImage } from "@/components/mdx-image";
import CreatedVariables from "./images/created-variables.webp";
import InputVariables from "./images/input-variables.webp";
import LogicWithVariables from "./images/logic-with-variables.webp";
import VariablesCard from "./images/variables-card.webp";
import VariablesUsage from "./images/variables-usage.webp";
export const metadata = {
title: "Variables",
description: "Add variabeles to your surveys to transform your survey into a quiz",
};
# Variables
Variables are a powerful feature in Formbricks that allows you to keep track of data variables when user fills a form. This feature is especially useful when you want to use your survey as a quiz.
## Types of Variables
There are two types of variables you can add to your survey:
1. **Text**: You can add text variables to your survey to capture text data.
2. **Number**: You can add number variables to your survey to capture number data.
## How to Add Variables
1. Edit the survey you want to add variables to & switch to the Questions tab and scroll down to the bottom of the page. You will see a section called **Variables**.
<MdxImage
src={VariablesCard}
alt="Variables card"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
2. Now click on it to add a new variable ID. You can add as many variables as you want. You can also choose the type of variable you want to add along with the default value.
<MdxImage
src={InputVariables}
alt="add variables"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
<MdxImage
src={CreatedVariables}
alt="created variables"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
## Use case:
- **Quiz**: You can use variables to create a quiz. For example, you can add a variable `score` and update it every time a user answers a question. You can also use the variable for recall to show the final score to the user.
- **Personalisation**: You can use variables to store user data and personalise the survey experience. For example, you can add a variable `full_name` and update it every time a user fills in their first name and last name. You can use the variable to personalise the survey experience by addressing the user with their full name.
## How is it different from Hidden Fields?
Variables are different from hidden fields in the following ways:
1. **Setting**: Hidden fields can be set through query parameters or `formbricks.init`, but the variables can only be set either during creation or dynamically by using logic actions.
2. **Updating**: Hidden fields cannot be set again, but the value of variables can be updated while the user fills the survey.
3. **Type**: Hidden fields can only store text data, but variables can store both text and number data.
## How to use Variables
1. Once you have added the variables to your survey, you'll be able to access them in the logic editor. You can use the variables to create logic actions and conditions.
<MdxImage
src={VariablesUsage}
alt="Variables usage"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
2. You can create logic based on the variables and questions in your survey and can update the variables based on the user's response.
<MdxImage
src={LogicWithVariables}
alt="Logic with variables"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
<Note>
To know more about how to use logic in Formbricks, check out the [Conditional Logic](/global/conditional-logic).
</Note>

View File

@@ -1,68 +0,0 @@
"use client";
import { useTheme } from "next-themes";
import { useState } from "react";
import { RedocStandalone } from "redoc";
import { LoadingSpinner } from "@/components/icons/loading-spinner";
import { Button } from "@/components/button";
import "./style.css";
export function ApiDocs() {
const { resolvedTheme } = useTheme();
const redocTheme = {
hideDownloadButton: true,
hideLoading: true,
nativeScrollbars: true,
theme: {
sidebar: {
backgroundColor: "transparent",
textColor: resolvedTheme === "dark" ? "rgb(203, 213, 225)" : "rgb(51, 51, 51)",
activeTextColor: "#2dd4bf",
},
rightPanel: {
backgroundColor: "transparent",
},
colors: {
primary: { main: "#2dd4bf" },
text: {
primary: resolvedTheme === "dark" ? "#ffffff" : "rgb(51, 51, 51)",
},
responses: {
success: { color: "#22c55e" },
error: { color: "#ef4444" },
info: { color: "#3b82f6" },
},
},
typography: {
fontSize: "16px",
lineHeight: "2rem",
fontFamily: "Jost, system-ui, -apple-system, sans-serif",
headings: {
fontFamily: "Jost, system-ui, -apple-system, sans-serif",
fontWeight: "600",
},
code: {
fontSize: "16px",
fontFamily: "ui-monospace, monospace",
},
},
codeBlock: {
backgroundColor: "rgb(24, 35, 58)",
},
spacing: { unit: 5 },
},
};
const [loading, setLoading] = useState(true);
return (
<div className="px-4">
<Button href="/developer-docs/rest-api" arrow="left" className="mb-4 mt-8">
Back to docs
</Button>
<RedocStandalone specUrl="/docs/openapi.yaml" onLoaded={() => { setLoading(false); }} options={redocTheme} />
{loading ? <LoadingSpinner /> : null}
</div>
);
}

View File

@@ -1,86 +0,0 @@
:root[data-theme="light"] {
--text-color: rgb(51, 65, 85);
}
:root[data-theme="dark"] {
--text-color: rgb(203, 213, 225);
}
h5,
.sc-dhCplO,
.sc-dpBQxM {
color: var(--text-color) !important;
}
.tab-success,
.react-tabs__tab,
.tab-error {
background-color: transparent !important;
border: 1px solid var(--text-color) !important;
margin: 10px 5px !important;
}
.sc-dwGkES,
.sc-ePpfBx {
background-color: rgb(24, 24, 27) !important;
border: 1px solid var(--text-color) !important;
}
.sc-ePpfBx,
.corVrN {
background-color: rgb(24, 24, 27) !important;
border: none !important;
}
.cqdCbT {
display: none !important;
}
.kiMaJz, .iZNUDY {
align-items: center !important;
}
.react-tabs__tab-panel > div {
padding: 0 !important;
border-radius: 8px !important;
overflow: hidden !important;
}
.sc-Rjrgp {
background-color: rgb(15, 23, 42) !important;
display: flex !important;
justify-content: center !important;
flex-direction: column !important;
padding: 8px 16px !important;
}
.cugBNu {
position: static !important;
}
.daIHdK {
padding: 0 !important;
}
.kqHNPM {
margin-top: 0px !important;
}
.sc-iwXfZk,
.redoc-json {
padding: 1rem !important;
background-color: rgb(24, 35, 58) !important;
}
.sc-uYFMi {
background-color: rgb(24, 35, 58) !important;
padding: 0.5rem 0 !important;
color: #2dd4bf !important;
font-weight: 600 !important;
}
.token {
color: #2dd4bf !important;
}
.property {
color: rgb(203, 213, 225) !important;
}
.sc-iPHsxv {
background-color: rgb(15, 23, 42) !important;
border-radius: 8px !important;
}
.sc-hSyjfr {
background-color: rgb(15, 23, 42) !important;
}

View File

@@ -1,5 +0,0 @@
import { ApiDocs } from "./components/api-docs";
export default function ApiDocsPage() {
return <ApiDocs />;
}

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

@@ -1,7 +1,7 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import I1 from "./images/i1.webp";
import I2 from "./images/i2.webp";
import I1 from "./images/I1.webp";
import I2 from "./images/I2.webp";
export const metadata = {
title: "Using Actions in Formbricks",

View File

@@ -8,7 +8,7 @@ export const metadata = {
Advanced Targeting allows you to show surveys to the right group of people. You can target surveys based on user attributes, device type, and more instead of spraying and praying. This helps you get more relevant feedback and make data-driven decisions. All of this without writing a single line of code.
## How to setup Advanced Targeting
# How to setup Advanced Targeting
<Note>Advanced Targeting is only available on the Pro plan!</Note>

View File

@@ -1,45 +1,45 @@
import Image from "next/image";
import { Button } from "@/components/button";
import { Button } from "@/components/Button";
import logoHtml from "@/images/frameworks/html5.svg";
import logoNextjs from "@/images/frameworks/nextjs.svg";
import logoReactJs from "@/images/frameworks/reactjs.svg";
import logoVueJs from "@/images/frameworks/vuejs.svg";
import Image from "next/image";
const libraries = [
{
href: "#html",
name: "HTML",
description: "All you need to do is add 3 lines of code to your HTML script and thats it, you're done!",
logo: logoHtml as string,
logo: logoHtml,
},
{
href: "#react-js",
name: "React.js",
description: "Load the our Js library with your environment ID and you're ready to go!",
logo: logoReactJs as string,
logo: logoReactJs,
},
{
href: "#next-js",
name: "Next.js",
description:
"Natively add us to your NextJs project with support for both App as well as Pages project structure!",
logo: logoNextjs as string,
logo: logoNextjs,
},
{
href: "#vue-js",
name: "Vue.js",
description: "Simply add us to your router change and sit back!",
logo: logoVueJs as string,
logo: logoVueJs,
},
{
href: "#react-native",
name: "React Native",
description: "Easily integrate our SDK with your React Native app for seamless survey support!",
logo: logoReactJs as string,
logo: logoReactJs,
},
];
export function Libraries() {
export const Libraries = () => {
return (
<div className="my-16 xl:max-w-none">
<div className="not-prose mt-4 grid grid-cols-1 gap-x-6 gap-y-10 border-slate-900/5 xl:max-w-none xl:grid-cols-2 2xl:grid-cols-3 dark:border-white/5">
@@ -63,4 +63,4 @@ export function Libraries() {
</div>
</div>
);
}
};

View File

@@ -1,6 +1,6 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import { Libraries } from "./components/libraries";
import { Libraries } from "./components/Libraries";
import ReactApp from "./images/react-in-app-survey-app-popup-form.webp";
import WidgetConnected from "./images/widget-connected.webp";
@@ -15,7 +15,7 @@ export const metadata = {
# Framework Guides
One can integrate Formbricks App Survey SDK into their app using multiple options! Checkout the options below that we provide! If you are looking
for something else, please [open a new Github Discussion](https://github.com/formbricks/formbricks/discussions) and we would be glad to help.
for something else, please [join our Discord!](https://formbricks.com/discord) and we would be glad to help.
<Libraries />
@@ -360,7 +360,7 @@ import Formbricks from "@formbricks/react-native";
const config = {
environmentId: "<environment-id>",
apiHost: "<api-host>",
userId: "<user-id>", // optional
userId: "<user-id>",
};
export default function App() {
@@ -448,6 +448,6 @@ Debug log messages provide insights into:
- Event tracking, survey triggers and form interactions.
- Initialization errors.
**Cant figure it out?**: **[Get help in Github Discussions](https://github.com/formbricks/formbricks/discussions)**
**Cant figure it out? [Join our Discord!](https://formbricks.com/discord)**
---

View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1,14 +1,14 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import I1 from "./images/i1.webp";
import I2 from "./images/i2.webp";
import I3 from "./images/i3.webp";
import I3_1 from "./images/i3_1.webp";
import I4 from "./images/i4.webp";
import I5 from "./images/i5.webp";
import I6 from "./images/i6.webp";
import I7 from "./images/i7.webp";
import I8 from "./images/i8.webp";
import I1 from "./images/I1.webp";
import I2 from "./images/I2.webp";
import I3 from "./images/I3.webp";
import I3_1 from "./images/I3_1.webp";
import I4 from "./images/I4.webp";
import I5 from "./images/I5.webp";
import I6 from "./images/I6.webp";
import I7 from "./images/I7.webp";
import I8 from "./images/I8.webp";
export const metadata = {
title: "Formbricks Quickstart Guide: App Surveys Made Easier & Faster",
@@ -29,11 +29,11 @@ App surveys have 6-10x better conversion rates than emailed surveys. This tutori
className="max-w-full rounded-lg sm:max-w-3xl"
/>
2. **Choose your Project Channel**: On this step, you have to choose between the various channels that you want your project to be created in, you can create both app and link surveys from all the channels, but for the onboarding, please choose between the app surveys or the public website options, upon doing this, you'll be prompted to connect your app / website to formbricks.
2. **Choose your Product Channel**: On this step, you have to choose between the various channels that you want your product to be created in, you can create both app and link surveys from all the channels, but for the onboarding, please choose between the app surveys or the public website options, upon doing this, you'll be prompted to connect your app / website to formbricks.
<MdxImage
src={I2}
alt="Choose between app and website surveys project channels"
alt="Choose between app and website surveys product channels"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
@@ -112,4 +112,4 @@ Pick the Survey Type as **App Survey**.
- We offer framework guides for various frontend tech, head over to the the [App Survey Framework Guides](/app-surveys/framework-guides) to get started with your app survey.
- Head over to our JS SDK documentation to get started with the [JS SDK](/developer-docs/js-sdk).
Still struggling or something not working as expected? [Join us in Github Discussions](https://github.com/formbricks/formbricks/discussions) and we'd be glad to assist you!
Still struggling or something not working as expected? [Join our Discord!](https://formbricks.com/discord) and we'd be glad to assist you!

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import AppSurvey from "./app-survey.webp";
import GlobalWaitTime from "./global-wait-time.webp";
@@ -62,7 +62,7 @@ Available Recontact Options include:
className="max-w-full rounded-lg sm:max-w-3xl"
/>
## Project-wide Global Waiting Time
## Product-wide Global Waiting Time
The Global Waiting Time is a universal blocker to make sure that no user sees too many surveys. This is particularly helpful when several teams of large organisations use Formbricks at the same time.
@@ -71,13 +71,13 @@ The Global Waiting Time is a universal blocker to make sure that no user sees to
To adjust the Global Waiting Time:
1. Visit Formbricks Settings
2. Go to Project Settings
2. Go to Product Settings
3. Find the **Recontact Waiting Time** section
4. Modify the interval (in days) as needed.
<MdxImage
src={GlobalWaitTime}
alt="Formbricks Project-Wide Wait Time"
alt="Formbricks Product-Wide Wait Time"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
@@ -102,4 +102,4 @@ For specific surveys, you may need to override the default waiting time. Below i
---
Still struggling or something not working as expected? [Join us in Github Discussions](https://github.com/formbricks/formbricks/discussions) and we'd be glad to assist you!
Still struggling or something not working as expected? [Join our Discord!](https://formbricks.com/discord) and we'd be glad to assist you!

View File

@@ -74,7 +74,8 @@ formbricks.init({
You can use the setAttribute function to set any custom attribute for the user (e.g. name, plan, etc.):
<Note>
Please note that the number of different attribute classes (e.g., "Plan," "First Name," etc.) is currently limited to 150 attributes per environment.
Please note that the number of different attribute classes (e.g., "Plan," "First Name," etc.) is currently
limited to 150 attributes per environment.
</Note>
<Col>

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import ChangeText from "./change-text.webp";
import CreateChurnFlow from "./create-cancel-flow.webp";
@@ -68,7 +68,7 @@ Youre free to update the question and answer options. However, based on our e
className="max-w-full rounded-lg sm:max-w-3xl"
/>
_Want to change the button color? You can do so in the project settings._
_Want to change the button color? You can do so in the product settings._
Save, and move over to the “Audience” tab.
@@ -112,7 +112,9 @@ Whenever a user visits this page, matches the filter conditions above and the re
Here is our complete [Actions manual](/app-surveys/actions/) covering [No-Code](/app-surveys/actions#setting-up-no-code-actions) and [Code](/app-surveys/actions#setting-up-code-actions) Actions.
<Note>
## Pre-churn flow coming soon Were currently building full-screen survey pop-ups. Youll be able to prevent users from closing the survey unless they respond to it. Its certainly debatable if you want that but you could force them to click through the survey before letting them cancel 🤷
## Pre-churn flow coming soon Were currently building full-screen survey pop-ups. Youll be able to prevent
users from closing the survey unless they respond to it. Its certainly debatable if you want that but you
could force them to click through the survey before letting them cancel 🤷
</Note>
### 5. Select Action in the “When to ask” card
@@ -147,7 +149,8 @@ These settings make sure the survey is always displayed, when a user wants to Ca
/>
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Churn Survey in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Churn Survey
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
</Note>
###

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import AddQuestion from "./images/add-question.webp";
import EmailField from "./images/email-field.webp";
import EmbedImage from "./images/embed.webp";
@@ -21,7 +21,6 @@ Welcome to this comprehensive guide on creating a contact form using Formbricks.
## What Well Build
By the end of this tutorial, you'll have created a simple contact form featuring:
1. A welcoming introduction.
2. Fields for collecting the user's name and email.
3. A question to find out why theyre contacting you.
@@ -45,7 +44,9 @@ First, let's lay the groundwork for your form:
4. Add a welcoming statement to greet your users and explain the form's purpose.
5. Personalize the greeting to make it inviting and encourage engagement.
<Note>A warm welcome sets the tone for your form. Make it friendly to encourage users to participate.</Note>
<Note>
A warm welcome sets the tone for your form. Make it friendly to encourage users to participate.
</Note>
### Adding the Name Field
@@ -144,8 +145,7 @@ Once your form is complete, follow these final steps:
After publishing the form, follow these steps to integrate it into your site:
1. **Copy the Shareable Link**
1. **Copy the Shareable Link**
- Find your form in the Formbricks dashboard, and click Share.
- Select Embed in a Web Page.
@@ -156,19 +156,16 @@ After publishing the form, follow these steps to integrate it into your site:
className="max-w-full rounded-lg sm:max-w-3xl"
/>
2. **Embed the Code**
2. **Embed the Code**
- Copy the provided code and paste it into your website where you want the form to appear.
<Note>
Note: There is an options toggle button called "Embed Mode." When enabled, it updates the `src` to `"?embed=true"` and displays your survey in a minimalist design, removing padding and background for a cleaner look.
</Note>
<Note>Note: There is an options toggle button called "Embed Mode." When enabled, it updates the `src` to `"?embed=true"` and displays your survey in a minimalist design, removing padding and background for a cleaner look.</Note>
3. **Test the Integration**
3. **Test the Integration**
- Check if the form displays correctly on your site.
- Submit a test entry to ensure everything works and notifications are received.
## Conclusion
Congratulations! Youve successfully created and integrated a professional contact form using Formbricks. This form will help you collect valuable information from your visitors in an efficient, user-friendly way.
A great contact form strikes the balance between collecting necessary details and being simple enough to encourage submissions. **Youve achieved just that!**
A great contact form strikes the balance between collecting necessary details and being simple enough to encourage submissions. **Youve achieved just that!**

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import AddAction from "./add-action.webp";
import ChangeId from "./change-id.webp";
@@ -69,7 +69,8 @@ To get this running, you'll need a bit of time. Here are the steps we're going t
5. In the same way, you can change the Internal Question ID of the _Please elaborate_ question to **“additionalFeedback”** and the one of the _Page URL_ question to **“pageUrl”**.
<Note>
Answers need to be identical If you want different answers than “Yes 👍” and “No 👎” you need to update the choices accordingly. They have to be identical to the frontend we're building in the next step.
Answers need to be identical If you want different answers than “Yes 👍” and “No 👎” you need to update the
choices accordingly. They have to be identical to the frontend we're building in the next step.
</Note>
6. Click on “Continue to Settings or select the audience tab manually. Scroll down to “Survey Trigger” and create a new Action:
@@ -99,7 +100,8 @@ To get this running, you'll need a bit of time. Here are the steps we're going t
## 2. Build the frontend
<Note>
Your frontend might work differently Your frontend likely looks and works differently. This is an example specific to our tech stack. We want to illustrate what you should consider building yours 😊
Your frontend might work differently Your frontend likely looks and works differently. This is an example
specific to our tech stack. We want to illustrate what you should consider building yours 😊
</Note>
Before we start, lets talk about the widget. It works like this:
@@ -125,10 +127,10 @@ Locate that file. We are using the [Tailwind Template “Syntax”](https://tail
<CodeGroup title="Entire Widget">
```tsx
import { Button } from "@/modules/ui/components/Button";
import { Popover, PopoverContent, PopoverTrigger } from "@/modules/ui/popover";
import { useRouter } from "next/router";
import { useState } from "react";
import { Button } from "@formbricks/ui/components/Button";
import { Popover, PopoverContent, PopoverTrigger } from "@formbricks/ui/components/Popover";
import { handleFeedbackSubmit, updateFeedback } from "../../lib/handleFeedbackSubmit";
export const DocsFeedback = () => {
@@ -436,4 +438,4 @@ And lastly, in the `updateFeedback` function
Something doesnt work? Check your browser console for the error.
**Cant figure it out?**: **[Get help in Github Discussions](https://github.com/formbricks/formbricks/discussions)**
Cant figure it out? [Join our Discord!](https://formbricks.com/discord)

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import ActionCSS from "./action-css.webp";
import ActionText from "./action-innertext.webp";
@@ -38,7 +38,10 @@ To run the Feature Chaser survey in your app you want to proceed as follows:
2. Setup a user action to display survey at the right point in time
<Note>
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (takes 15mins max.)](/app-surveys/quickstart)
## Formbricks Widget running?
We assume that you have already installed the Formbricks Widget in your web
wapp. Its required to display messages and surveys in your app. If not, please follow the [Quick Start
Guide (takes 15mins max.)](/app-surveys/quickstart)
</Note>
### 1. Create new Feature Chaser
@@ -120,7 +123,8 @@ Lastly, scroll down to “Recontact Options”. Here you have full freedom to de
<MdxImage src={Publish} alt="Publish survey" quality="100" className="max-w-full rounded-lg sm:max-w-3xl" />
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feature Chaser in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feature Chaser
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
</Note>
###

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import Link from "next/link";
import ActionCSS from "./action-css.webp";
@@ -110,7 +110,8 @@ Scroll down to “Recontact Options”. Here you have to choose the right settin
## Setting up the Widget
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
</Note>
### &nbsp;

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import NewsletterSurveyType from "./choose-survey-type.webp";
import NewsletterSurveyEmbedCode from "./embed-survey-code-in-your-email.webp";
@@ -100,7 +100,9 @@ And you're done! Send a test email to yourself and try it out 🤓
## Learn about data prefilling
<Note>
## How does data prefilling work? Learn about how link prefilling and user identification maximize your insights in [this detailed guide](/blog/how-smart-writers-use-formbricks-open-source-tool-to-measure-the-quality-of-their-newsletter-content).
## How does data prefilling work? Learn about how link prefilling and user identification maximize your
insights in [this detailed
guide](/blog/how-smart-writers-use-formbricks-open-source-tool-to-measure-the-quality-of-their-newsletter-content).
</Note>
### &nbsp;

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import ActionText from "./action-innertext.webp";
import ActionPageurl from "./action-pageurl.webp";
@@ -38,7 +38,8 @@ To display the Trial Conversion Survey in your app you want to proceed as follow
3. Print that 💸
<Note>
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (takes 15mins max.)](/app-surveys/quickstart)
## Formbricks Widget running?
We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (takes 15mins max.)](/app-surveys/quickstart)
</Note>
### 1. Create new Trial Conversion Survey
@@ -65,14 +66,15 @@ Youre free to update the questions and answer options. However, based on our
className="max-w-full rounded-lg sm:max-w-3xl"
/>
_Want to change the button color? You can do so in the project settings!_
_Want to change the button color? You can do so in the product settings!_
Save, and move over to the “Audience” tab.
### 3. Pre-segment your audience (coming soon)
<Note>
## Filter by attribute coming soon We're working on pre-segmenting users by attributes. We will update this manual in the next days.
## Filter by attribute coming soon We're working on pre-segmenting users by attributes. We will update this
manual in the next days.
</Note>
Pre-segmentation isn't relevant for this survey because you likely want to solve all people who cancel their trial. You probably have a specific user action e.g. clicking on "Cancel Trial" you can use to only display the survey to users trialing your product.
@@ -128,7 +130,8 @@ Lastly, scroll down to “Recontact Options”. Here you have to choose the corr
<MdxImage src={Publish} alt="Publish survey" quality="100" className="max-w-full rounded-lg sm:max-w-3xl" />
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
</Note>
###

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import ActionCSS from "./action-css.webp";
import ActionInner from "./action-innertext.webp";
@@ -43,7 +43,8 @@ To display an Interview Prompt in your app you want to proceed as follows:
3. Thats it! 🎉
<Note>
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (15mins)](/app-surveys/quickstart)
## Formbricks Widget running?
We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (15mins).](/app-surveys/quickstart)
</Note>
### 1. Create new Interview Prompt
@@ -61,7 +62,7 @@ Click on "Create Survey" and choose the template “Interview Prompt”:
### 2. Update prompt and CTA
Update the prompt, description and button text to match your products tonality. You can also update the button color in the Project Settings.
Update the prompt, description and button text to match your products tonality. You can also update the button color in the Product Settings.
<MdxImage
src={ChangeText}

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import ActionCSS from "./action-css.webp";
import ActionPageurl from "./action-pageurl.webp";
@@ -37,7 +37,9 @@ To display the Product-Market Fit survey in your app you want to proceed as foll
3. Setup the user action to display survey at good point in time
<Note>
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (15mins)](/app-surveys/quickstart)
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web
app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide
(15mins).](/app-surveys/quickstart)
</Note>
### 1. Create new PMF survey
@@ -64,7 +66,7 @@ Youre free to update the question and answer options. However, based on our e
className="max-w-full rounded-lg sm:max-w-3xl"
/>
_Want to change the button color? You can do so in the project settings!_
_Want to change the button color? You can do so in the product settings!_
Save, and move over to where the magic happens: The “Audience” tab.
@@ -120,7 +122,8 @@ Lastly, scroll down to “Recontact Options”. Here you have to choose the corr
<MdxImage src={Publish} alt="Publish survey" quality="100" className="max-w-full rounded-lg sm:max-w-3xl" />
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
</Note>
###

View File

@@ -1,125 +1,178 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import SingleSelect from "./single-select.webp";
import Quiz from "./quiz.webp";
import Score from "./score.webp"
import AddLogic from "./conditional-logic.webp";
import WhenThen from "./when-then.webp";
import EndingLogic from "./ending-logic.webp";
import PassFail from "./pass-fail.webp";
import Quiz from "./quiz.webp";
import Score from "./score.webp";
import SingleSelect from "./single-select.webp";
import WhenThen from "./when-then.webp";
export const metadata = {
title: "How to Create a Quiz Using Formbricks - Step-by-Step Guide",
description:
"Learn to leverage Formbricks to create Quizzes. Follow our detailed step-by-step guide to build quizzes with custom logic and multiple endings.",
title: "How to Create a Quiz Using Formbricks - Step-by-Step Guide",
description:
"Learn to leverage Formbricks to create Quizzes. Follow our detailed step-by-step guide to build quizzes with custom logic and multiple endings.",
};
# Creating a quiz with Formbricks - Step-by-step Guide
Welcome to this guide on creating engaging quizzes with Formbricks! Quizzes help you capture customer insights, explore user personalities, or simply add fun for your team. With Formbricks, you can personalize quizzes in minutes add scores, customize backgrounds, and more, all without any technical skills!
## What we'll build
By the end of this tutorial, you'll have created a simple trivia Quiz featuring:
1. Score calculations.
2. Multiple endings depending on the score.
## Setting up the form
First, make sure you have a Formbricks account. If not, you can create one [here](https://app.formbricks.com):
1. Head to the Surveys page and click on **New Survey**.
2. Select Start from Scratch to create a new form.
3. Go to the settings and select form type as **Link Survey**
4. In the form editor, click the three dots next to a question, then select Change Question Type and choose **Single-Select**.
<MdxImage
src={SingleSelect}
alt="Change Question type to Single-Select"
quality="100"
className="max-w-full rounded-lg sm:max-w-2xl"
src={SingleSelect}
alt="Change Question type to Single-Select"
quality="100"
className="max-w-full rounded-lg sm:max-w-2xl"
/>
5. Add a welcoming statement to greet your users and explain the Quiz's purpose.
6. Personalize the greeting to make it inviting and encourage engagement.
**Note:** While were creating a Link Survey here, the process is similar for Web and App surveys.
## Adding the questions
Next, let's create a question for example with multiple options:
What country has the longest coastline in the world?
A) Canada
B) Japan
C) India
D) Nepal
<MdxImage src={Quiz} alt="Sample Question" quality="100" className="max-w-full rounded-lg sm:max-w-xl" />
<MdxImage
src={Quiz}
alt="Sample Question"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
/>
## Calculate Score
Now that we have our question ready, lets add the logic to calculate scores.
1. Scroll down in the editor and click on variables.
2. Create a new variable named `score` with a default value of 0
<MdxImage
src={Score}
alt="Create Variable named Score image"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
src={Score}
alt="Create Variable named Score image"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
/>
3. Now go back to the question and expand the advanced settings by clicking on `> Show Advanced Settings`.
4. Under the conditional logic you should see the option to `Add Logic`. Click on that.
<MdxImage src={AddLogic} alt="Add Logic Button" quality="100" className="max-w-full rounded-lg sm:max-w-xl" />
<MdxImage
src={AddLogic}
alt="Add Logic Button"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
/>
5. Now you should see conditional logic. Customize the logic to match your needs for example:
**When** `question` equals `YOUR_ANSWER_HERE` **Then** `Calculate` `score` `Add +` `01`. So it should look something like this.
<MdxImage
src={WhenThen}
alt="When-Then Conditional Logic"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
src={WhenThen}
alt="When-Then Conditional Logic"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
/>
6. Let's duplicate and customize these questions. Click on the duplicate icon at the top of the question.
7. Now edit the questions, options, and answers in the **conditional logic**
## Creating Multiple Endings Based on Scores
Once you have all the questions and the calculation logic in place, its time to customize the endings. Scroll down to the Ending Card section. We will create two cards for this quiz: one for when the user fails the quiz and another for when the user passes.
1. Customize the ending card.
2. Display the score by typing `@score`. ( You can address all the variables or questions by just typing @ ).
3. Add logic to the last question. ( this is necessary to redirect the user based on the score ). Kind of like this:
**When** `score` >= `03` **Then** `Jump to` `Pass`. So it should look something like this.
<MdxImage
src={EndingLogic}
alt="Conditional Logic for ending card"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
src={EndingLogic}
alt="Conditional Logic for ending card"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
/>
4. Ensure that the Fail card is positioned above the Pass card. This allows any condition that does not meet the criteria of being greater than or equal to 3 to jump to the Fail card.
<MdxImage
src={PassFail}
alt="Pass or Fail ending Cards"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
src={PassFail}
alt="Pass or Fail ending Cards"
quality="100"
className="max-w-full rounded-lg sm:max-w-xl"
/>
5. That's it! Now you can save and publish the quiz.
# Wrapping Up
Congratulations! Youve successfully created a Quiz with Formbricks. You can play around with the quiz that we just created [here](https://app.formbricks.com/s/cm2wwt3vu0001ir8o7ys0bezz).
A great quiz can serve as an excellent lead generator, a job fit checker, or just a fun icebreaker for your team. You now have the skills to build that! If you want to read more about building quizzes and how you can create a Job Fit Quiz check this article [here](https://www.harshbhat.me/blog/formbricks-quiz).
A great quiz can serve as an excellent lead generator, a job fit checker, or just a fun icebreaker for your team. You now have the skills to build that! If you want to read more about building quizzes and how you can create a Job Fit Quiz check this article [here](https://www.harshbhat.me/blog/formbricks-quiz).

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
export const metadata = {
title: "Formbricks API SDK",
@@ -10,6 +10,11 @@ export const metadata = {
# SDK: Formbricks API
<Note>
The API SDK is currently in beta and APIs are subject to change. We will do our best to notify you of any
changes.
</Note>
### Overview
The Formbricks Client API Wrapper is a lightweight package designed to simplify the integration of Formbricks API endpoints into your JavaScript (JS) or TypeScript (TS) projects. With this wrapper, you can easily interact with Formbricks API endpoints without the need for complex setup or manual HTTP requests.
@@ -221,4 +226,4 @@ Promise<fileUrl>
---
If you have any questions or need help, feel free to reach out to us in **[Github Discussions](https://github.com/formbricks/formbricks/discussions)**
If you have any questions or need help, feel free to reach out to us on our **[Discord](https://formbricks.com/discord)**

View File

@@ -1,13 +1,15 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import GithubCodespaceLoading from "./images/loading.webp";
import GithubCodespaceNew from "./images/new.webp";
import GithubCodespacePorts from "./images/ports.webp";
export const metadata = {
title: "Formbricks Open Source Contribution Guide: How to Enhance yourself and Contribute to Formbricks",
description:
"Join the Formbricks community and learn how to effectively contribute. From raising issues and feature requests to creating PRs, discover the best practices and communicate with our responsive team on Github Discussions",
"Join the Formbricks community and learn how to effectively contribute. From raising issues and feature requests to creating PRs, discover the best practices and communicate with our responsive team on Discord",
};
#### Contributing
@@ -61,4 +63,4 @@ export const metadata = {
className="max-w-full rounded-lg sm:max-w-3xl"
/>
Now make the changes you want to and see them live in action!
Now make the changes you want to and see them live in action!

View File

@@ -0,0 +1,83 @@
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@formbricks/ui/components/Accordion";
import { FaqJsonLdComponent } from "./FAQPageJsonLd";
const FAQ_DATA = [
{
question: "What is an environment ID?",
answer: () => (
<>
The environment ID is a unique identifier associated with each Environment in Formbricks,
distinguishing between different setups like production, development, etc.
</>
),
},
{
question: "How can I implement authentication for the Formbricks API?",
answer: () => (
<>
Formbricks provides 2 types of API keys for each environment ie development and production. You can
generate, view, and manage these keys in the Settings section on the Admin dashboard. Include the API
key in your requests to authenticate and gain access to Formbricks functionalities.
</>
),
},
{
question: "Can I run the deployment shell script on any server?",
answer: () => (
<>
You can run it on any machine you own as long as its running a <b> Linux Ubuntu </b> distribution. And
to forward the requests, make sure you have an <b>A record</b> setup for your domain pointing to the
server.
</>
),
},
{
question: "Can I self-host Formbricks?",
answer: () => (
<>
Absolutely! We provide an option for users to host Formbricks on their own server, ensuring even more
control over data and compliance. And the best part? Self-hosting is available for free, always. For
documentation on self hosting, click{" "}
<a href="/self-hosting/deployment" className="text-brand-dark dark:text-brand-light">
here
</a>
.
</>
),
},
{
question: "How can I change Button texts in my survey?",
answer: () => (
<>
For the question that you want to change the button text, click on the <b>Show Advanced Settings</b>{" "}
toggle and change the button label in the <b>Button Text</b> field.
</>
),
},
];
export const faqJsonLdData = FAQ_DATA.map((faq) => ({
questionName: faq.question,
acceptedAnswerText: faq.answer(),
}));
export const FAQ = () => {
return (
<>
<FaqJsonLdComponent data={faqJsonLdData} />
<Accordion type="single" collapsible>
{FAQ_DATA.map((faq, index) => (
<AccordionItem key={`item-${index}`} value={`item-${index + 1}`} className="not-prose mb-0 mt-0">
<AccordionTrigger>{faq.question}</AccordionTrigger>
<AccordionContent>{faq.answer()}</AccordionContent>
</AccordionItem>
))}
</Accordion>
</>
);
};

View File

@@ -0,0 +1,12 @@
"use client";
import { FAQPageJsonLd } from "next-seo";
export const FaqJsonLdComponent = ({ data }) => {
const faqEntities = data.map(({ question, answer }) => ({
questionName: question,
acceptedAnswerText: answer,
}));
return <FAQPageJsonLd mainEntity={faqEntities} />;
};

View File

@@ -1,9 +1,9 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
export const metadata = {
title: "Formbricks Open Source Contribution Guide: How to Enhance yourself and Contribute to Formbricks",
description:
"Join the Formbricks community and learn how to effectively contribute. From raising issues and feature requests to creating PRs, discover the best practices and communicate with our responsive team on Github Discussions",
"Join the Formbricks community and learn how to effectively contribute. From raising issues and feature requests to creating PRs, discover the best practices and communicate with our responsive team on Discord",
};
#### Contributing
@@ -18,7 +18,7 @@ We are so happy that you are interested in contributing to Formbricks 🤗 There
## Talk to us first
We highly recommend connecting with us on [Github Discussions](https://github.com/formbricks/formbricks/discussions) before you ship a contribution. This will increase the likelihood of your PR being merged. And it will decrease the likelihood of you wasting your time :)
We highly recommend connecting with us on [Discord server](https://formbricks.com/discord) before you ship a contribution. This will increase the likelihood of your PR being merged. And it will decrease the likelihood of you wasting your time :)
## Contributor License Agreement (CLA)
@@ -149,7 +149,8 @@ pnpm go
<Note>
**WSL2 users**: If you encounter connection issues with Prisma, ensure your WSL2 instance's PostgreSQL
service is stopped before running `pnpm go`. Use the command `sudo systemctl stop postgresql` to stop the service.
service is stopped before running `pnpm go`. Use the command `sudo systemctl stop postgresql` to stop the
service.
</Note>
**You can now access the Formbricks app on [http://localhost:3000](http://localhost:3000)**. You will be automatically redirected to the login. To use your local installation of formbricks, create a new account.

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import ClearAppData from "./images/clear-app-data.webp";
import Logout from "./images/logout.webp";
@@ -7,7 +7,7 @@ import UncaughtPromise from "./images/uncaught-promise.webp";
export const metadata = {
title: "Formbricks Open Source Contribution Guide: How to Enhance yourself and Contribute to Formbricks",
description:
"Join the Formbricks community and learn how to effectively contribute. From raising issues and feature requests to creating PRs, discover the best practices and communicate with our responsive team on Github Discussions",
"Join the Formbricks community and learn how to effectively contribute. From raising issues and feature requests to creating PRs, discover the best practices and communicate with our responsive team on Discord",
};
#### Contributing

View File

@@ -1,9 +1,9 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import AirtableConnected from "./airtable-connected.webp";
import ConnectWithAirtable from "./connect-with-airtable.webp";
import CreateNewIntegration from "./create-new-integration.webp";
import DeleteIntegration from "./delete-integration.webp";
import DeleteIntegration from "./deleteIntegration.webp";
import IntegrationTab from "./integrations-tab.webp";
import LinkSurveyWithTable from "./link-survey-with-table.webp";
import LinkWithQuestions from "./link-with-questions.webp";
@@ -24,7 +24,7 @@ export const metadata = {
The Airtable integration allows you to automatically send responses to an Airtable of your choice.
<Note>
If you are on a self-hosted instance, you will need to configure this integration separately. Please follow the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
If you are on a self-hosted instance, you will need to configure this integration separately. Please follow the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
</Note>
## Formbricks Cloud
@@ -101,7 +101,7 @@ Before the next step, make sure that you have a Formbricks Survey with at least
Congratulations! You have successfully linked an Airtable with Formbricks. Now whenever a response is submitted for the linked survey, it will be automatically added to the linked Airtable.
Still struggling or something not working as expected? [Join us on Github Discussions](https://github.com/formbricks/formbricks/discussions) and we'd be glad to assist you!
Still struggling or something not working as expected? [Join our Discord!](https://formbricks.com/discord) and we'd be glad to assist you!
## Remove Integration with Airtable
@@ -120,7 +120,8 @@ To remove the integration with Airtable,
/>
<Note>
We do not store any other information of yours! We value Privacy more than you and rest assured you're safe with us!
We do not store any other information of yours! We value Privacy more than you and rest assured you're safe
with us!
</Note>
Still struggling or something not working as expected? [Join our Github Discussions](https://github.com/formbricks/formbricks/discussions) and we'd be glad to assist you!
Still struggling or something not working as expected? [Join our Discord!](https://formbricks.com/discord) and we'd be glad to assist you!

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import ConnectWithGoogle from "./connect-with-google.webp";
import DeleteConnection from "./delete-connection.webp";
@@ -21,7 +21,8 @@ export const metadata = {
The Google Sheets integration allows you to automatically send responses to a Google Sheet of your choice.
<Note>
If you are on a self-hosted instance, you will need to configure this integration separately. Please follow the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
If you are on a self-hosted instance, you will need to configure this integration separately. Please follow
the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
</Note>
## Connect Google Sheets
@@ -119,4 +120,4 @@ For the above, we ask for:
<Note>We store as little personal information as possible.</Note>
Still struggling or something not working as expected? [Join our Github Discussions](https://github.com/formbricks/formbricks/discussions) and we'd be glad to assist you!
Still struggling or something not working as expected? [Join our Discord!](https://formbricks.com/discord) and we'd be glad to assist you!

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import AddModule from "./add-module.webp";
import CreateNewScenario from "./create-new-scenario.webp";
@@ -27,7 +27,8 @@ export const metadata = {
Make is a powerful tool to send information between Formbricks and thousands of apps. Here's how to set it up.
<Note>
Nailed down your survey?? Any changes in the survey cause additional work in the _Scenario_. It makes sense to first settle on the survey you want to run and then get to setting up Make.
Nailed down your survey?? Any changes in the survey cause additional work in the _Scenario_. It makes sense
to first settle on the survey you want to run and then get to setting up Make.
</Note>
## Step 1: Setup your survey incl. `questionId` for every question
@@ -44,7 +45,8 @@ Set up the `questionId`s of your survey questions before publishing.
_Update the Question ID field in every question card under Advanced Settings._
<Note>
### Already published? Duplicate survey You can only update the questionId before publishing the survey. If already published, simply duplicate it.
### Already published? Duplicate survey You can only update the questionId before publishing the survey. If
already published, simply duplicate it.
<MdxImage
src={DuplicateSurvey}
alt="Duplicate Survey"

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import AddApiKey from "./add-api-key.webp";
import AddDiscord from "./add-discord.webp";
@@ -27,7 +27,8 @@ export const metadata = {
# n8n Setup
<Note>
The Formbricks n8n node is currently only available in the n8n self-hosted version as a community node. To install it go to "Settings" -> "Community Nodes" and install @formbricks/n8n-nodes-formbricks.
The Formbricks n8n node is currently only available in the n8n self-hosted version as a community node. To
install it go to "Settings" -> "Community Nodes" and install @formbricks/n8n-nodes-formbricks.
</Note>
n8n allows you to build flexible workflows focused on deep data integration. And with sharable templates and a user-friendly UI, the less technical people on your team can collaborate on them too. Unlike other tools, complexity is not a limitation. So you can build whatever you want — without stressing over budget. Hook up Formbricks with n8n and you can send your data to 350+ other apps. Here is how to do it.
@@ -35,7 +36,8 @@ n8n allows you to build flexible workflows focused on deep data integration. And
## Step 1: Setup your survey incl. `questionId` for every question
<Note>
Nailed down your survey? Any changes in the survey cause additional work in the n8n node. It makes sense to first settle on the survey you want to run and then get to setting up n8n.
Nailed down your survey? Any changes in the survey cause additional work in the n8n node. It makes sense to
first settle on the survey you want to run and then get to setting up n8n.
</Note>
When setting up the node your life will be easier when you change the `questionId`s of your survey questions. You can only do so **before** you publish your survey.

View File

@@ -1,4 +1,4 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import ConnectWithNotion from "./images/connect-with-notion.webp";
import DeleteConnection from "./images/delete-connection.webp";
@@ -21,7 +21,7 @@ export const metadata = {
The notion integration allows you to automatically send responses to a Notion database of your choice.
<Note>
If you are on a self-hosted instance, you will need to configure this integration separately. Please follow the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
If you are on a self-hosted instance, you will need to configure this integration separately. Please follow the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
</Note>
## Formbricks Cloud
@@ -56,7 +56,8 @@ The notion integration allows you to automatically send responses to a Notion da
/>
<Note>
Before the next step, make sure that you have a Formbricks Survey with at least one question and a Notion database in the Notion account you integrated.
Before the next step, make sure that you have a Formbricks Survey with at least one question and a Notion
database in the Notion account you integrated.
</Note>
5. Now click on the "Link New Database" button to link a Notion database with Formbricks and a modal will open up.
@@ -122,4 +123,4 @@ To remove the integration with Slack Workspace,
className="max-w-full rounded-lg sm:max-w-3xl"
/>
Still struggling or something not working as expected? [Join our Github Discussions](https://github.com/formbricks/formbricks/discussions) and we'd be glad to assist you!
Still struggling or something not working as expected? [Join our Discord!](https://formbricks.com/discord) and we'd be glad to assist you!

View File

@@ -10,7 +10,7 @@ export const metadata = {
At Formbricks, we understand the importance of integrating with third-party applications. We have step-by-step guides to configure our third-party integrations with a your Formbricks instance. We currently support the below integrations, click on them to see their individual guides:
<Note>
If you are on a self-hosted instance, you will need to configure these integrations manually. Please follow the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
If you are on a self-hosted instance, you will need to configure these integrations manually. Please follow the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
</Note>
- [Airtable](/developer-docs/integrations/airtable): Automatically send responses to an Airtable of your choice.
@@ -24,4 +24,4 @@ At Formbricks, we understand the importance of integrating with third-party appl
---
If you have any questions or need help with any of the integrations or even want a new integration, please reach out to us on [Github Discussions](https://github.com/formbricks/formbricks/discussions).
If you have any questions or need help with any of the integrations or even want a new integration, please reach out to us on [Discord](https://formbricks.com/discord).

View File

@@ -1,9 +1,5 @@
import { MdxImage } from "@/components/mdx-image";
import { MdxImage } from "@/components/MdxImage";
import AddSlackBot1 from "./images/add-slack-bot-1.webp";
import AddSlackBot2 from "./images/add-slack-bot-2.webp";
import AddSlackBot3 from "./images/add-slack-bot-3.webp";
import AddSlackBot4 from "./images/add-slack-bot-4.webp";
import ConnectWithSlack from "./images/connect-with-slack.webp";
import DeleteConnection from "./images/delete-connection.webp";
import IntegrationsTab from "./images/integrations-tab.webp";
@@ -12,7 +8,10 @@ import LinkWithQuestions from "./images/link-with-questions.webp";
import ListLinkedSurveys from "./images/list-linked-surveys.webp";
import SlackAuth from "./images/slack-auth.webp";
import SlackConnected from "./images/slack-connected.webp";
import AddSlackBot1 from "./images/add-slack-bot-1.webp";
import AddSlackBot2 from "./images/add-slack-bot-2.webp";
import AddSlackBot3 from "./images/add-slack-bot-3.webp";
import AddSlackBot4 from "./images/add-slack-bot-4.webp";
export const metadata = {
title: "Slack",
description:
@@ -26,7 +25,8 @@ export const metadata = {
The slack integration allows you to automatically send responses to a Slack channel of your choice.
<Note>
If you are on a self-hosted instance, you will need to configure this integration separately. Please follow the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
If you are on a self-hosted instance, you will need to configure this integration separately. Please follow
the guides [here](/self-hosting/integrations) to configure integrations on your self-hosted instance.
</Note>
## Formbricks Cloud
@@ -68,13 +68,14 @@ The slack integration allows you to automatically send responses to a Slack chan
/>
<Note>
Before the next step, make sure that you have a Formbricks Survey with at least one question and a Slack channel in the Slack workspace you integrated.
Before the next step, make sure that you have a Formbricks Survey with at least one question and a Slack
channel in the Slack workspace you integrated.
</Note>
5. In order to make your channel available in channel dropdown, you need to add formbricks integration bot to the channel you want to link. You can do this by going to channel settings -> Integrations -> Add apps -> Search for "Formbricks" -> Select the bot -> Add.
<MdxImage
src={AddSlackBot1}
src={AddSlackBot1}
alt="Click on three dot at top right of the channel"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
@@ -94,7 +95,7 @@ The slack integration allows you to automatically send responses to a Slack chan
<MdxImage
src={AddSlackBot4}
alt="Add Formbricks Bot"
quality="100"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
@@ -195,4 +196,4 @@ To remove the integration with Slack Workspace,
className="max-w-full rounded-lg sm:max-w-3xl"
/>
Still struggling or something not working as expected? [Join our Github Discussions](https://github.com/formbricks/formbricks/discussions) and we'd be glad to assist you!
Still struggling or something not working as expected? [Join our Discord!](https://formbricks.com/discord) and we'd be glad to assist you!

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