diff --git a/apps/formbricks-com-old/.env.example b/apps/formbricks-com-old/.env.example deleted file mode 100644 index 26b2ce211f..0000000000 --- a/apps/formbricks-com-old/.env.example +++ /dev/null @@ -1,6 +0,0 @@ -NEXT_PUBLIC_FORMBRICKS_COM_API_HOST=http://localhost:3000 -NEXT_PUBLIC_FORMBRICKS_COM_ENVIRONMENT_ID= -NEXT_PUBLIC_FORMBRICKS_COM_DOCS_FEEDBACK_SURVEY_ID= - -# Strapi API Key -STRAPI_API_KEY= diff --git a/apps/formbricks-com-old/.eslintrc.js b/apps/formbricks-com-old/.eslintrc.js deleted file mode 100644 index bcf4aad3a3..0000000000 --- a/apps/formbricks-com-old/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: ["formbricks"], -}; diff --git a/apps/formbricks-com-old/.gitignore b/apps/formbricks-com-old/.gitignore deleted file mode 100644 index 25374c573c..0000000000 --- a/apps/formbricks-com-old/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts - -public/sitemap*.xml \ No newline at end of file diff --git a/apps/formbricks-com-old/components/docs/DocsFeedback.tsx b/apps/formbricks-com-old/components/docs/DocsFeedback.tsx deleted file mode 100644 index a12363a109..0000000000 --- a/apps/formbricks-com-old/components/docs/DocsFeedback.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { Button, Popover, PopoverContent, PopoverTrigger } from "@formbricks/ui"; -import { useRouter } from "next/router"; -import { useState } from "react"; -import { handleFeedbackSubmit, updateFeedback } from "../../lib/handleFeedbackSubmit"; - -export const DocsFeedback: React.FC = () => { - const router = useRouter(); - const [isOpen, setIsOpen] = useState(false); - const [sharedFeedback, setSharedFeedback] = useState(false); - const [responseId, setResponseId] = useState(null); - const [freeText, setFreeText] = useState(""); - - if ( - !process.env.NEXT_PUBLIC_FORMBRICKS_COM_DOCS_FEEDBACK_SURVEY_ID || - !process.env.NEXT_PUBLIC_FORMBRICKS_COM_API_HOST || - !process.env.NEXT_PUBLIC_FORMBRICKS_COM_ENVIRONMENT_ID - ) { - return null; - } - - return ( -
- {!sharedFeedback ? ( -
- Is everything on this page clear? - -
- {["Yes πŸ‘", "No πŸ‘Ž"].map((option) => ( - { - const id = await handleFeedbackSubmit(option, router.asPath); - setResponseId(id); - }}> - {option} - - ))} -
- -
- -
-
-
- -
- - ); -} diff --git a/apps/formbricks-com-old/components/dummyUI/PreviewModal.tsx b/apps/formbricks-com-old/components/dummyUI/PreviewModal.tsx deleted file mode 100644 index 0bdcf5e568..0000000000 --- a/apps/formbricks-com-old/components/dummyUI/PreviewModal.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import clsx from "clsx"; -import { ReactNode, useEffect, useState } from "react"; - -export const Modal: React.FC<{ children: ReactNode; isOpen: boolean }> = ({ children, isOpen }) => { - const [show, setShow] = useState(false); - - useEffect(() => { - setShow(isOpen); - }, [isOpen]); - return ( -
-
-
- {children} -
-
-
- ); -}; - -export default Modal; diff --git a/apps/formbricks-com-old/components/dummyUI/PreviewSurvey.tsx b/apps/formbricks-com-old/components/dummyUI/PreviewSurvey.tsx deleted file mode 100644 index 7fba2a5986..0000000000 --- a/apps/formbricks-com-old/components/dummyUI/PreviewSurvey.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { useState } from "react"; -import Modal from "./Modal"; -import QuestionConditional from "./QuestionConditional"; -import type { Question } from "@formbricks/types/questions"; -import { Survey } from "@formbricks/types/surveys"; -import ThankYouCard from "./ThankYouCard"; - -interface PreviewSurveyProps { - localSurvey?: Survey; - setActiveQuestionId: (id: string | null) => void; - activeQuestionId?: string | null; - questions: Question[]; - brandColor: string; -} - -export default function PreviewSurvey({ - localSurvey, - setActiveQuestionId, - activeQuestionId, - questions, - brandColor, -}: PreviewSurveyProps) { - const [isModalOpen, setIsModalOpen] = useState(true); - - const gotoNextQuestion = () => { - const currentIndex = questions.findIndex((q) => q.id === activeQuestionId); - if (currentIndex < questions.length - 1) { - setActiveQuestionId(questions[currentIndex + 1].id); - } else { - if (localSurvey?.thankYouCard?.enabled) { - setActiveQuestionId("thank-you-card"); - } else { - setIsModalOpen(false); - setTimeout(() => { - setActiveQuestionId(questions[0].id); - setIsModalOpen(true); - }, 500); - if (localSurvey?.thankYouCard?.enabled) { - setActiveQuestionId("thank-you-card"); - } else { - setIsModalOpen(false); - setTimeout(() => { - setActiveQuestionId(questions[0].id); - setIsModalOpen(true); - }, 500); - } - } - } - }; - - const resetPreview = () => { - setIsModalOpen(false); - setTimeout(() => { - setActiveQuestionId(questions[0].id); - setIsModalOpen(true); - }, 500); - }; - - if (!activeQuestionId) { - return null; - } - - return ( - <> - - {activeQuestionId == "thank-you-card" ? ( - - ) : ( - questions.map( - (question, idx) => - activeQuestionId === question.id && ( - - ) - ) - )} - - - ); -} diff --git a/apps/formbricks-com-old/components/dummyUI/Progress.tsx b/apps/formbricks-com-old/components/dummyUI/Progress.tsx deleted file mode 100644 index 16f75f378f..0000000000 --- a/apps/formbricks-com-old/components/dummyUI/Progress.tsx +++ /dev/null @@ -1,11 +0,0 @@ -export const Progress: React.FC<{ progress: number; brandColor: string }> = ({ progress, brandColor }) => { - return ( -
-
-
- ); -}; - -export default Progress; diff --git a/apps/formbricks-com-old/components/dummyUI/QuestionConditional.tsx b/apps/formbricks-com-old/components/dummyUI/QuestionConditional.tsx deleted file mode 100644 index 207421dbc4..0000000000 --- a/apps/formbricks-com-old/components/dummyUI/QuestionConditional.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { QuestionType, type Question } from "@formbricks/types/questions"; -import OpenTextQuestion from "./OpenTextQuestion"; -import MultipleChoiceSingleQuestion from "./MultipleChoiceSingleQuestion"; -import MultipleChoiceMultiQuestion from "./MultipleChoiceMultiQuestion"; -import NPSQuestion from "./NPSQuestion"; -import CTAQuestion from "./CTAQuestion"; -import RatingQuestion from "./RatingQuestion"; - -interface QuestionConditionalProps { - question: Question; - onSubmit: (data: { [x: string]: any }) => void; - lastQuestion: boolean; - brandColor: string; -} - -export default function QuestionConditional({ - question, - onSubmit, - lastQuestion, - brandColor, -}: QuestionConditionalProps) { - return question.type === QuestionType.OpenText ? ( - - ) : question.type === QuestionType.MultipleChoiceSingle ? ( - - ) : question.type === QuestionType.MultipleChoiceMulti ? ( - - ) : question.type === QuestionType.NPS ? ( - - ) : question.type === QuestionType.CTA ? ( - - ) : question.type === QuestionType.Rating ? ( - - ) : null; -} diff --git a/apps/formbricks-com-old/components/dummyUI/RatingQuestion.tsx b/apps/formbricks-com-old/components/dummyUI/RatingQuestion.tsx deleted file mode 100644 index ddbccfd1e8..0000000000 --- a/apps/formbricks-com-old/components/dummyUI/RatingQuestion.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import type { RatingQuestion } from "@formbricks/types/questions"; -import { useState } from "react"; -import { cn } from "@formbricks/lib/cn"; -import Headline from "./Headline"; -import Subheader from "./Subheader"; - -interface RatingQuestionProps { - question: RatingQuestion; - onSubmit: (data: { [x: string]: any }) => void; - lastQuestion: boolean; - brandColor: string; -} - -export default function RatingQuestion({ - question, - onSubmit, - lastQuestion, - brandColor, -}: RatingQuestionProps) { - const [selectedChoice, setSelectedChoice] = useState(null); - - const handleSelect = (number: number) => { - setSelectedChoice(number); - if (question.required) { - onSubmit({ - [question.id]: number, - }); - setSelectedChoice(null); // reset choice - } - }; - - return ( -
{ - e.preventDefault(); - - const data = { - [question.id]: selectedChoice, - }; - - setSelectedChoice(null); // reset choice - - onSubmit(data); - }}> - - -
-
- Options -
- {Array.from({ length: question.range }, (_, i) => i + 1).map((number) => ( - - ))} -
-
-

{question.lowerLabel}

-

{question.upperLabel}

-
-
-
- {!question.required && ( -
-
- -
- )} - - ); -} diff --git a/apps/formbricks-com-old/components/dummyUI/Subheader.tsx b/apps/formbricks-com-old/components/dummyUI/Subheader.tsx deleted file mode 100644 index 2fa4c32353..0000000000 --- a/apps/formbricks-com-old/components/dummyUI/Subheader.tsx +++ /dev/null @@ -1,14 +0,0 @@ -export const Subheader: React.FC<{ subheader?: string; questionId: string }> = ({ - subheader, - questionId, -}) => { - return ( - - ); -}; - -export default Subheader; diff --git a/apps/formbricks-com-old/components/dummyUI/TemplateList.tsx b/apps/formbricks-com-old/components/dummyUI/TemplateList.tsx deleted file mode 100644 index 9e96545f0d..0000000000 --- a/apps/formbricks-com-old/components/dummyUI/TemplateList.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import type { Template } from "@formbricks/types/templates"; -import { useEffect, useState } from "react"; -import { cn } from "@formbricks/lib/cn"; -import { templates } from "./templates"; - -type TemplateList = { - onTemplateClick: (template: Template) => void; - activeTemplate: Template | null; -}; - -const ALL_CATEGORY_NAME = "All"; - -export default function TemplateList({ onTemplateClick, activeTemplate }: TemplateList) { - const [selectedFilter, setSelectedFilter] = useState(ALL_CATEGORY_NAME); - - const [categories, setCategories] = useState>([]); - - useEffect(() => { - const defaultCategories = [ - /* ALL_CATEGORY_NAME, */ - ...(Array.from(new Set(templates.map((template) => template.category))) as string[]), - ]; - - const fullCategories = [ALL_CATEGORY_NAME, ...defaultCategories]; - - setCategories(fullCategories); - - const activeFilter = ALL_CATEGORY_NAME; - setSelectedFilter(activeFilter); - }, []); - - return ( -
-
- {categories.map((category) => ( - - ))} -
-
- {templates - .filter((template) => selectedFilter === ALL_CATEGORY_NAME || template.category === selectedFilter) - .map((template: Template) => ( - - ))} -
-
- ); -} diff --git a/apps/formbricks-com-old/components/dummyUI/ThankYouCard.tsx b/apps/formbricks-com-old/components/dummyUI/ThankYouCard.tsx deleted file mode 100644 index 9d34466083..0000000000 --- a/apps/formbricks-com-old/components/dummyUI/ThankYouCard.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import Headline from "./Headline"; -import Subheader from "./Subheader"; - -interface ThankYouCardProps { - headline: string; - subheader: string; - brandColor: string; -} - -export default function ThankYouCard({ headline, subheader, brandColor }: ThankYouCardProps) { - return ( -
-
- - - -
- - - -
- - -
- - {/* - -
-

- Powered by{" "} - - - Formbricks - - -

-
*/} -
- ); -} diff --git a/apps/formbricks-com-old/components/dummyUI/templates.ts b/apps/formbricks-com-old/components/dummyUI/templates.ts deleted file mode 100644 index 91822c2409..0000000000 --- a/apps/formbricks-com-old/components/dummyUI/templates.ts +++ /dev/null @@ -1,1102 +0,0 @@ -import { - AppPieChartIcon, - ArrowRightCircleIcon, - ArrowUpRightIcon, - BaseballIcon, - CancelSubscriptionIcon, - CashCalculatorIcon, - CheckMarkIcon, - CodeBookIcon, - DashboardIcon, - DogChaserIcon, - DoorIcon, - FeedbackIcon, - GaugeSpeedFastIcon, - HeartCommentIcon, - InterviewPromptIcon, - LoadingBarIcon, - OnboardingIcon, - PMFIcon, - TaskListSearchIcon, - UserSearchGlasIcon, - VideoTabletAdjustIcon, -} from "@formbricks/ui"; - -import { createId } from "@paralleldrive/cuid2"; -import type { Template } from "@formbricks/types/templates"; -import { QuestionType } from "@formbricks/types/questions"; - -const thankYouCardDefault = { - enabled: true, - headline: "Thank you!", - subheader: "We appreciate your feedback.", -}; - -export const customSurvey: Template = { - name: "Start from scratch", - description: "Create a survey without template.", - icon: null, - preset: { - name: "New Survey", - questions: [ - { - id: createId(), - type: QuestionType.OpenText, - headline: "Custom Survey", - subheader: "This is an example survey.", - placeholder: "Type your answer here...", - longAnswer: true, - required: true, - }, - ], - thankYouCard: thankYouCardDefault, - }, -}; - -export const templates: Template[] = [ - { - name: "Product Market Fit (Superhuman)", - icon: PMFIcon, - category: "Product Experience", - - description: "Measure PMF by assessing how disappointed users would be if your product disappeared.", - preset: { - name: "Product Market Fit (Superhuman)", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "How disappointed would you be if you could no longer use Formbricks?", - subheader: "Please select one of the following options:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Not at all disappointed", - }, - { - id: createId(), - label: "Somewhat disappointed", - }, - { - id: createId(), - label: "Very disappointed", - }, - ], - }, - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "What is your role?", - subheader: "Please select one of the following options:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Founder", - }, - { - id: createId(), - label: "Executive", - }, - { - id: createId(), - label: "Product Manager", - }, - { - id: createId(), - label: "Product Owner", - }, - { - id: createId(), - label: "Software Engineer", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "What type of people do you think would most benefit from Formbricks?", - longAnswer: true, - required: true, - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "What is the main benefit your receive from Formbricks?", - longAnswer: true, - required: true, - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "How can we improve our service for you?", - subheader: "Please be as specific as possible.", - longAnswer: true, - required: true, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - - { - name: "Onboarding Segmentation", - icon: OnboardingIcon, - category: "Product Experience", - description: "Learn more about who signed up to your product and why.", - preset: { - name: "Onboarding Segmentation", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "What is your role?", - subheader: "Please select one of the following options:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Founder", - }, - { - id: createId(), - label: "Executive", - }, - { - id: createId(), - label: "Product Manager", - }, - { - id: createId(), - label: "Product Owner", - }, - { - id: createId(), - label: "Software Engineer", - }, - ], - }, - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "What's your company size?", - subheader: "Please select one of the following options:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "only me", - }, - { - id: createId(), - label: "1-5 employees", - }, - { - id: createId(), - label: "6-10 employees", - }, - { - id: createId(), - label: "11-100 employees", - }, - { - id: createId(), - label: "over 100 employees", - }, - ], - }, - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "How did you hear about us first?", - subheader: "Please select one of the following options:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Recommendation", - }, - { - id: createId(), - label: "Social Media", - }, - { - id: createId(), - label: "Ads", - }, - { - id: createId(), - label: "Google Search", - }, - { - id: createId(), - label: "In a Podcast", - }, - ], - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Uncover Strengths & Weaknesses", - icon: TaskListSearchIcon, - category: "Growth", - description: "Find out what users like and don't like about your product or offering.", - preset: { - name: "Uncover Strengths & Weaknesses", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "What do you value most about our service?", - subheader: "Please select one of the following options:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Ease of use", - }, - { - id: createId(), - label: "Good value for money", - }, - { - id: createId(), - label: "It's open-source", - }, - { - id: createId(), - label: "The founders are pretty", - }, - ], - }, - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "What should we improve on?", - subheader: "Please select one of the following options:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Documentation", - }, - { - id: createId(), - label: "Customizability", - }, - { - id: createId(), - label: "Pricing", - }, - { - id: createId(), - label: "Humbleness of founders", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "Would you like to add something?", - subheader: "Feel free to speak your mind, we do too.", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Marketing Attribution", - icon: AppPieChartIcon, - category: "Growth", - description: "How did you first hear about us?", - preset: { - name: "Marketing Attribution", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "How did you hear about us first?", - subheader: "Please select one of the following options:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Recommendation", - }, - { - id: createId(), - label: "Social Media", - }, - { - id: createId(), - label: "Ads", - }, - { - id: createId(), - label: "Google Search", - }, - { - id: createId(), - label: "In a Podcast", - }, - ], - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Churn Survey", - icon: CancelSubscriptionIcon, - category: "Increase Revenue", - description: "Find out why people cancel their subscriptions. These insights are pure gold!", - preset: { - name: "Churn Survey", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "Why did you cancel your subscription?", - subheader: "We're sorry to see you leave. Please help us do better:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "I didn't get much value out of it", - }, - { - id: createId(), - label: "It's too expensive", - }, - { - id: createId(), - label: "I am missing a feature", - }, - { - id: createId(), - label: "Poor customer service", - }, - { - id: createId(), - label: "I just didn't need it anymore", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "How can we win you back?", - subheader: "Feel free to speak your mind, we do too.", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Improve Trial Conversion", - icon: BaseballIcon, - category: "Increase Revenue", - description: "Find out why people stopped their trial. These insights help you improve your funnel.", - preset: { - name: "Improve Trial Conversion", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "Why did you stop your trial?", - subheader: "Help us understand you better:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "I didn't get much value out of it", - }, - { - id: createId(), - label: "I expected something else", - }, - { - id: createId(), - label: "It's too expensive for what it does", - }, - { - id: createId(), - label: "I am missing a feature", - }, - { - id: createId(), - label: "I was just looking around", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "Any details to share?", - longAnswer: true, - required: false, - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "How are you solving your problem instead?", - subheader: "Please name alternative tools:", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Changing subscription experience", - icon: CashCalculatorIcon, - category: "Increase Revenue", - description: "Find out what goes through peoples minds when changing their subscriptions.", - preset: { - name: "Changing subscription experience", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "How easy was it to change your plan?", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Extremely difficult", - }, - { - id: createId(), - label: "It took a while, but I got it", - }, - { - id: createId(), - label: "It was alright", - }, - { - id: createId(), - label: "Quite easy", - }, - { - id: createId(), - label: "Very easy, love it!", - }, - ], - }, - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "Is the pricing information easy to understand?", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Yes, very clear.", - }, - { - id: createId(), - label: "I was confused at first, but found what I needed.", - }, - { - id: createId(), - label: "Quite complicated.", - }, - ], - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Measure Task Accomplishment", - icon: CheckMarkIcon, - category: "Product Experience", - description: "See if people get their 'Job To Be Done' done. Successful people are better customers.", - preset: { - name: "Measure Task Accomplishment", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "Were you able to accomplish what you came here to do today?", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Yes", - }, - { - id: createId(), - label: "Working on it, boss", - }, - { - id: createId(), - label: "No", - }, - ], - }, - { - id: createId(), - type: QuestionType.Rating, - headline: "How easy was it to achieve your goal?", - required: true, - lowerLabel: "Very difficult", - upperLabel: "Very easy", - range: 5, - scale: "number", - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "What did you come here to do today?", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Identify Customer Goals", - icon: ArrowRightCircleIcon, - category: "Product Experience", - description: - "Better understand if your messaging creates the right expectations of the value your product provides.", - preset: { - name: "Identify Customer Goals", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "What's your primary goal for using Formbricks?", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Understand my user base deeply", - }, - { - id: createId(), - label: "Identify upselling opportunities", - }, - { - id: createId(), - label: "Build the best possible product", - }, - { - id: createId(), - label: "Rule the world to make everyone breakfast brussels sprouts.", - }, - ], - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Feature Chaser", - icon: DogChaserIcon, - category: "Product Experience", - description: "Follow up with users who just used a specific feature.", - preset: { - name: "Feature Chaser", - questions: [ - { - id: createId(), - type: QuestionType.Rating, - headline: "How easy was it to achieve your goal?", - required: true, - lowerLabel: "Very difficult", - upperLabel: "Very easy", - range: 5, - scale: "number", - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "Wanna add something?", - subheader: "This really helps us do better!", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Fake Door Follow-Up", - icon: DoorIcon, - category: "Exploration", - description: "Follow up with users who ran into one of your Fake Door experiments.", - preset: { - name: "Fake Door Follow-Up", - questions: [ - { - id: createId(), - type: QuestionType.Rating, - headline: "How important is this feature for you?", - required: true, - lowerLabel: "Not important", - upperLabel: "Very important", - range: 5, - scale: "number", - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Product Market Fit Survey (short)", - icon: PMFIcon, - category: "Product Experience", - - description: "Measure PMF by assessing how disappointed users would be if your product disappeared.", - preset: { - name: "Product Market Fit Survey (short)", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "How disappointed would you be if you could no longer use Formbricks?", - subheader: "Please select one of the following options:", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Not at all disappointed", - }, - { - id: createId(), - label: "Somewhat disappointed", - }, - { - id: createId(), - label: "Very disappointed", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "How can we improve our service for you?", - subheader: "Please be as specific as possible.", - longAnswer: true, - required: true, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Feedback Box", - icon: FeedbackIcon, - category: "Product Experience", - description: "Give your users the chance to seamlessly share what's on their minds.", - preset: { - name: "Feedback Box", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "What's on your mind, boss?", - subheader: "Thanks for sharing. We'll get back to you asap.", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Bug report 🐞", - }, - { - id: createId(), - label: "Feature Request πŸ’‘", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "Give us the juicy details:", - longAnswer: true, - required: true, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Integration usage survey", - icon: DashboardIcon, - category: "Product Experience", - description: "Evaluate how easily users can add integrations to your product. Find blind spots.", - preset: { - name: "Integration Usage Survey", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "How easy was it to set this integration up?", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Extremely difficult", - }, - { - id: createId(), - label: "It took a while, but I got it", - }, - { - id: createId(), - label: "It was alright", - }, - { - id: createId(), - label: "Quite easy", - }, - { - id: createId(), - label: "Very easy, love it!", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "Which product would you like to integrate next?", - subheader: "We keep building integrations. Yours can be next:", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "New integration survey", - icon: DashboardIcon, - category: "Exploration", - description: "Find out which integrations your users would like to see next.", - preset: { - name: "New integration survey", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "Which other tools are you using?", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "PostHog", - }, - { - id: createId(), - label: "Segment", - }, - { - id: createId(), - label: "Hubspot", - }, - { - id: createId(), - label: "Twilio", - }, - { - id: createId(), - label: "Other", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "If you chose other, please clarify:", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Docs Feedback", - icon: CodeBookIcon, - category: "Product Experience", - description: "Measure how clear each page of your developer documentation is.", - preset: { - name: "Formbricks Docs Feedback", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "Was this page helpful?", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Yes πŸ‘", - }, - { - id: createId(), - label: "No πŸ‘Ž", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "Please elaborate:", - longAnswer: true, - required: false, - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "Page URL", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Interview Prompt", - icon: InterviewPromptIcon, - category: "Exploration", - description: "Invite a specific subset of your users to schedule an interview with your product team.", - preset: { - name: "Interview Prompt", - questions: [ - { - id: createId(), - type: QuestionType.CTA, - headline: "Do you have 15 min to talk to us? πŸ™", - html: "You're one of our power users. We would love to interview you briefly!", - buttonLabel: "Book interview", - buttonUrl: "https://cal.com/johannes/onboarding?duration=25", - buttonExternal: true, - required: false, - dismissButtonLabel: "Maybe later", - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Review Prompt", - icon: HeartCommentIcon, - category: "Growth", - description: "Invite users who love your product to review it publicly.", - preset: { - name: "Review Prompt", - questions: [ - { - id: createId(), - type: QuestionType.CTA, - headline: "You're one of our most valued customers! Please write a review for us.", - buttonLabel: "Write review", - buttonUrl: "https://formbricks.com/github", - buttonExternal: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Net Promoter Score (NPS)", - icon: GaugeSpeedFastIcon, - category: "Customer Success", - description: "Measure the Net Promoter Score of your product.", - preset: { - name: "Formbricks NPS", - questions: [ - { - id: createId(), - type: QuestionType.NPS, - headline: "How likely are you to recommend Formbricks to a friend or colleague?", - required: false, - lowerLabel: "Not likely", - upperLabel: "Very likely", - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Identify upsell opportunities", - icon: ArrowUpRightIcon, - category: "Increase Revenue", - description: "Find out how much time your product saves your user. Use it to upsell.", - preset: { - name: "Identify upsell opportunities", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "How many hours does your team save per week by using Formbricks?", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Less than 1 hour", - }, - { - id: createId(), - label: "1 to 2 hours", - }, - { - id: createId(), - label: "3 to 5 hours", - }, - { - id: createId(), - label: "5+ hours", - }, - ], - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Build Product Roadmap", - icon: LoadingBarIcon, - category: "Product Experience", - description: "Ask how users rate your product. Identify blind spots to build your roadmap.", - preset: { - name: "Build Product Roadmap", - questions: [ - { - id: createId(), - type: QuestionType.Rating, - headline: "How satisfied are you with the features of Formbricks?", - required: true, - lowerLabel: "Not satisfied", - upperLabel: "Very satisfied", - scale: "number", - range: 5, - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "What's the #1 thing you'd like to change in Formbricks?", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Gauge Feature Satisfaction", - icon: UserSearchGlasIcon, - category: "Product Experience", - description: "Evaluate the satisfaction of specific features of your product.", - preset: { - name: "Gauge Feature Satisfaction", - questions: [ - { - id: createId(), - type: QuestionType.Rating, - headline: "How easy was it to achieve ... ?", - required: true, - lowerLabel: "Not easy", - upperLabel: "Very easy", - scale: "number", - range: 5, - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "What is one thing we could do better?", - longAnswer: true, - required: false, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, - { - name: "Marketing Site Clarity", - icon: VideoTabletAdjustIcon, - category: "Growth", - description: "Identify users dropping off your marketing site. Improve your messaging.", - preset: { - name: "Marketing Site Clarity", - questions: [ - { - id: createId(), - type: QuestionType.MultipleChoiceSingle, - headline: "Do you have all the info you need to give Formbricks a try?", - required: true, - shuffleOption: "none", - choices: [ - { - id: createId(), - label: "Yes, totally", - }, - { - id: createId(), - label: "Kind of...", - }, - { - id: createId(), - label: "No, not at all", - }, - ], - }, - { - id: createId(), - type: QuestionType.OpenText, - headline: "What’s missing or unclear to you about Formbricks?", - longAnswer: true, - required: false, - }, - { - id: createId(), - type: QuestionType.CTA, - headline: "Thanks for your answer! Get 25% off your first 6 months:", - required: false, - buttonLabel: "Get discount", - buttonUrl: "https://app.formbricks.com/auth/signup", - buttonExternal: true, - }, - ], - thankYouCard: thankYouCardDefault, - }, - }, -]; - -export const findTemplateByName = (name: string): Template | undefined => { - return templates.find((template) => template.name === name); -}; diff --git a/apps/formbricks-com-old/components/home/Features.tsx b/apps/formbricks-com-old/components/home/Features.tsx deleted file mode 100644 index 6ef45f9657..0000000000 --- a/apps/formbricks-com-old/components/home/Features.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { CodeFileIcon, EyeIcon, HandPuzzleIcon } from "@formbricks/ui"; -import HeadingCentered from "../shared/HeadingCentered"; - -const features = [ - { - id: "compliance", - name: "Smoothly Compliant", - description: "Use our GDPR-compliant Cloud or self-host the entire solution.", - icon: EyeIcon, - }, - { - id: "customizable", - name: "Fully Customizable", - description: "Full customizability and extendability. Integrate with your stack easily.", - icon: HandPuzzleIcon, - }, - { - id: "independent", - name: "Stay independent", - description: "The code is open-source. Do with it what your organization needs.", - icon: CodeFileIcon, - }, -]; -export const Features: React.FC = () => { - return ( -
-
- - -
    - {features.map((feature) => { - const IconComponent: React.ElementType = feature.icon; - - return ( -
  • -
    -
    - -
    -
    -
    -

    - {feature.name} -

    -
    -
    Description
    -
    {feature.description}
    -
    -
    -
  • - ); - })} -
-
-
- ); -}; - -export default Features; diff --git a/apps/formbricks-com-old/components/home/GitHubSponsorship.tsx b/apps/formbricks-com-old/components/home/GitHubSponsorship.tsx deleted file mode 100644 index a089c5b7dd..0000000000 --- a/apps/formbricks-com-old/components/home/GitHubSponsorship.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import GitHubMarkWhite from "@/images/github-mark-white.svg"; -import GitHubMarkDark from "@/images/github-mark.svg"; -import Image from "next/image"; -import Link from "next/link"; - -export const GitHubSponsorship: React.FC = () => { - return ( -
- -
- GitHub Sponsors Formbricks badge - GitHub Sponsors Formbricks badge -
-

- Proudly Open-Source 🀍 -

-

- We're proud to to be supported by GitHubs Open-Source Program!{" "} - - - Read more. - - -

-
- ); -}; - -export default GitHubSponsorship; diff --git a/apps/formbricks-com-old/components/home/Hero.tsx b/apps/formbricks-com-old/components/home/Hero.tsx deleted file mode 100644 index 2b06350668..0000000000 --- a/apps/formbricks-com-old/components/home/Hero.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import CalLogoDark from "@/images/clients/cal-logo-dark.svg"; -import CalLogoLight from "@/images/clients/cal-logo-light.svg"; -import ClovyrLogo from "@/images/clients/clovyr-logo.svg"; -import CrowdLogoDark from "@/images/clients/crowd-logo-dark.svg"; -import CrowdLogoLight from "@/images/clients/crowd-logo-light.svg"; -import NILogoDark from "@/images/clients/niLogoDark.svg"; -import NILogoLight from "@/images/clients/niLogoWhite.svg"; -import AnimationFallback from "@/public/animations/opensource-xm-platform-formbricks-fallback.png"; -import { Button } from "@formbricks/ui"; -import { ChevronRightIcon } from "@heroicons/react/24/outline"; -import { usePlausible } from "next-plausible"; -import Image from "next/image"; -import { useRouter } from "next/router"; -import HeroAnimation from "./HeroAnimation"; - -export const Hero: React.FC = ({}) => { - const plausible = usePlausible(); - const router = useRouter(); - return ( -
-
- - We're Open-Source | Star us on GitHub{" "} - - -

- Open-source Experience Management -

- -

- Understand what customers think & feel about your product. -
- - Natively integrate user research with minimal dev attention,{" "} - privacy-first. - -

- -
-

- Trusted by -

-
- Cal Logo - Cal Logo - Crowd.dev Logo - Crowd.dev Logo - Clovyr Logo - Neverinstall Logo - Neverinstall Logo -
-
-
- - -
-
-
- -
-
- ); -}; - -export default Hero; diff --git a/apps/formbricks-com-old/components/home/HeroAnimation.tsx b/apps/formbricks-com-old/components/home/HeroAnimation.tsx deleted file mode 100644 index 163cf9a29b..0000000000 --- a/apps/formbricks-com-old/components/home/HeroAnimation.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { useEffect, useRef, useState } from "react"; -import type { LottiePlayer } from "lottie-web"; -import Image from "next/image"; - -export const HeroAnimation: React.FC = ({ fallbackImage, ...props }) => { - const [loaded, setLoaded] = useState(false); - const ref = useRef(null); - const [lottie, setLottie] = useState(null); - - useEffect(() => { - import("lottie-web").then((Lottie) => setLottie(Lottie.default)); - }, []); - - useEffect(() => { - if (lottie && ref.current) { - const animation = lottie.loadAnimation({ - container: ref.current, - renderer: "svg", - loop: true, - autoplay: true, - // path to your animation file, place it inside public folder - path: "/animations/opensource-xm-platform-formbricks.json", - }); - - animation.addEventListener("DOMLoaded", () => { - setLoaded(true); - }); - - return () => animation.destroy(); - } - }, [lottie]); - - return ( -
-
- {!loaded && ( -
- Fallback Image -
- )} -
- ); -}; - -export default HeroAnimation; diff --git a/apps/formbricks-com-old/components/home/Highlights.tsx b/apps/formbricks-com-old/components/home/Highlights.tsx deleted file mode 100644 index cea8820ad1..0000000000 --- a/apps/formbricks-com-old/components/home/Highlights.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import ImageAttributesDark from "@/images/attributes-dark.svg"; -import ImageAttributesLight from "@/images/attributes-light.svg"; -import ImageEventTriggerDark from "@/images/event-trigger-dark.svg"; -import ImageEventTriggerLight from "@/images/event-trigger-light.svg"; -import Image from "next/image"; - -export const Highlights: React.FC = ({}) => { - return ( - <> -
-
-
-
-

- Ask at the right moment, -
- get the data you need. -

-

- Follow up emails are so 2010. Ask users as they experience your product - and leverage a - significantly higher conversion rate. -

-
-
- react library - react library -
-
-
-
-
-
-
-
- react library - react library -
-
-

- Dont' β€˜Spray and pray’. -
- Pre-segment granularly. -

-

- Pre-segment who sees your survey based on custom attributes. Keep the signal, cancel out the - noise. -

-
-
-
-
- - ); -}; - -export default Highlights; diff --git a/apps/formbricks-com-old/components/home/SetupTabs.tsx b/apps/formbricks-com-old/components/home/SetupTabs.tsx deleted file mode 100644 index c753ae245a..0000000000 --- a/apps/formbricks-com-old/components/home/SetupTabs.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import clsx from "clsx"; -import { useState } from "react"; -import { IoLogoHtml5, IoLogoNpm } from "react-icons/io5"; -import CodeBlock from "../shared/CodeBlock"; - -interface SecondNavbarProps { - tabs: { id: string; label: string; icon?: React.ReactNode }[]; - activeId: string; - setActiveId: (id: string) => void; -} - -export const TabBar: React.FC = ({ tabs, activeId, setActiveId }) => { - return ( -
- -
- ); -}; - -const tabs = [ - { id: "npm", label: "NPM", icon: }, - { id: "html", label: "HTML", icon: }, -]; - -export const SetupInstructions: React.FC = ({}) => { - const [activeTab, setActiveTab] = useState(tabs[0].id); - - return ( -
- -
- {activeTab === "npm" ? ( - <> - npm install @formbricks/js - - {`import formbricks from "@formbricks/js"; - -if (typeof window !== "undefined") { - formbricks.init({ - environmentId: "claV2as2kKAqF28fJ8", - apiHost: "https://app.formbricks.com", - }); -}`} - - ) : activeTab === "html" ? ( - {``} - ) : null} -
-
- ); -}; - -export default SetupInstructions; diff --git a/apps/formbricks-com-old/components/home/Steps.tsx b/apps/formbricks-com-old/components/home/Steps.tsx deleted file mode 100644 index 93ee57a091..0000000000 --- a/apps/formbricks-com-old/components/home/Steps.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import DemoPreview from "@/components/dummyUI/DemoPreview"; -import DashboardMockupDark from "@/images/dashboard-mockup-dark.png"; -import DashboardMockup from "@/images/dashboard-mockup.png"; -import { Button } from "@formbricks/ui"; -import { CursorArrowRaysIcon } from "@heroicons/react/24/solid"; -import Image from "next/image"; -import { useState } from "react"; -import AddEventDummy from "../dummyUI/AddEventDummy"; -import AddNoCodeEventModalDummy from "../dummyUI/AddNoCodeEventModalDummy"; -import HeadingCentered from "../shared/HeadingCentered"; -import SetupTabs from "./SetupTabs"; - -export const Steps: React.FC = () => { - const [isAddEventModalOpen, setAddEventModalOpen] = useState(false); - - return ( - <> - -
-
-
-
-

Step 1

-

- Copy + Paste -

-

- Simply copy a <script> tag to your HTML head - that’s about it. Or use NPM to install - Formbricks for React, Vue, Svelte, etc. -

-
-
- -
-
-
-
-
-
-
-
-
- -
-
-
-

Step 2

-

- No-Code: Track User Actions -

-

- Set up user actions which can trigger your survey without writing a single line of code. - Surveys can be triggered on specific pages or after an element is clicked. -

-
-
-
-
-
-
-
-
-

Step 3

-

- Create your survey -

-

- Start from a template - or from scratch. Ask what you want, in any language. You can also - adjust the look and feel of your survey. -

-
-
- -
-
-
-
-
-
-
-
-
- -
-
-
-

Step 4

-

- Set segment and trigger -

-

- Create a custom segment for each survey. Use attributes and past user actions to only survey - the people who have answers. Trigger your survey on any user action in your app. -

-
-
-
-
-
-
-
-
-

Step 5

-

- Make better decisions -

-

- Gather all insights you can - including partial submissions. Build conviction for the next - product decision. Better data, better business. -

-
-
- Data Pipelines - Data Pipelines -
-
-
-
- - - - ); -}; - -export default Steps; diff --git a/apps/formbricks-com-old/components/home/VideoWalkThrough.tsx b/apps/formbricks-com-old/components/home/VideoWalkThrough.tsx deleted file mode 100644 index 10259215e3..0000000000 --- a/apps/formbricks-com-old/components/home/VideoWalkThrough.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { ResponsiveVideo } from "@formbricks/ui"; -import Modal from "../shared/Modal"; - -interface VideoWalkThroughProps { - open: boolean; - setOpen: (v: boolean) => void; -} - -export const VideoWalkThrough: React.FC = ({ open, setOpen }) => { - return ( - -
- -
-
- ); -}; diff --git a/apps/formbricks-com-old/components/shared/APILayout.tsx b/apps/formbricks-com-old/components/shared/APILayout.tsx deleted file mode 100644 index d910c67f88..0000000000 --- a/apps/formbricks-com-old/components/shared/APILayout.tsx +++ /dev/null @@ -1,214 +0,0 @@ -import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/24/solid"; -import clsx from "clsx"; -import { useState } from "react"; - -interface APICallProps { - method: "GET" | "POST"; - url: string; - description: string; - headers: { - label: string; - type: string; - description: string; - required?: boolean; - }[]; - bodies: { - label: string; - type: string; - description: string; - required?: boolean; - }[]; - responses: { - color: string; - statusCode: string; - description: string; - example?: string; - }[]; - example?: string; -} - -export function APILayout({ method, url, description, headers, bodies, responses, example }: APICallProps) { - const [switchState, setSwitchState] = useState(true); - function handleOnChange() { - setSwitchState(!switchState); - } - - return ( -
- {switchState ? ( -
- ); -} - -interface ParaProps { - label: string; - type: string; - description: string; - required?: boolean; -} - -function Parameter({ label, type, description, required }: ParaProps) { - return ( - <> -
-
- {label} - {required &&

*

} -
-
{type}
-
{description}
-
- - ); -} - -interface RespProps { - color: string; - statusCode: string; - description: string; - example?: string; -} - -function Response({ color, statusCode, description, example }: RespProps) { - const [toggleExample, setSwitchState] = useState(false); - function handleOnChange() { - setSwitchState(!toggleExample); - } - return ( -
-
-
-   -
-
{statusCode}
-
-
-
{description}
-
- {example && - (toggleExample ? ( -
-
- {example && toggleExample && ( -
- {example} -
- )} -
- ); -} diff --git a/apps/formbricks-com-old/components/shared/AuthorBox.tsx b/apps/formbricks-com-old/components/shared/AuthorBox.tsx deleted file mode 100644 index f818fe9159..0000000000 --- a/apps/formbricks-com-old/components/shared/AuthorBox.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import Image from "next/image"; -import AuthorJohannes from "@/images/blog/johannes-co-founder-formbricks-small.jpg"; - -interface AuthorBoxProps { - name: string; - title: string; - date: string; - duration: string; -} - -export default function AuthorBox({ name, title, date, duration }: AuthorBoxProps) { - return ( -
- {name} -
-
-

{name}

-

{title}

-
-
-

{duration} Minutes

-

{date}

-
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/BestPracticeNavigation.tsx b/apps/formbricks-com-old/components/shared/BestPracticeNavigation.tsx deleted file mode 100644 index 054cbebdbd..0000000000 --- a/apps/formbricks-com-old/components/shared/BestPracticeNavigation.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { - CancelSubscriptionIcon, - DogChaserIcon, - FeedbackIcon, - InterviewPromptIcon, - OnboardingIcon, - PMFIcon, - BaseballIcon, - CodeBookIcon, -} from "@formbricks/ui"; -import clsx from "clsx"; -import Link from "next/link"; - -export default function BestPracticeNavigation() { - const BestPractices = [ - { - name: "Interview Prompt", - href: "/interview-prompt", - status: true, - icon: InterviewPromptIcon, - description: "Ask only power users users to book a time in your calendar. Get those juicy details.", - category: "Understand Users", - }, - { - name: "Product-Market Fit Survey", - href: "/measure-product-market-fit", - status: true, - icon: PMFIcon, - description: "Find out how disappointed people would be if they could not use your service any more.", - category: "Understand Users", - }, - { - name: "Onboarding Segments", - href: "/onboarding-segmentation", - status: false, - icon: OnboardingIcon, - description: - "Get to know your users right from the start. Ask a few questions early, let us enrich the profile.", - category: "Understand Users", - }, - { - name: "Learn from Churn", - href: "/learn-from-churn", - status: true, - icon: CancelSubscriptionIcon, - description: "Churn is hard, but insightful. Learn from users who changed their mind.", - category: "Increase Revenue", - }, - { - name: "Improve Trial CR", - href: "/improve-trial-conversion", - status: true, - icon: BaseballIcon, - description: "Take guessing out, convert more trials to paid users with insights.", - category: "Increase Revenue", - }, - { - name: "Docs Feedback", - href: "/docs-feedback", - status: true, - icon: CodeBookIcon, - description: "Clear docs lead to more adoption. Understand granularly what's confusing.", - category: "Boost Retention", - }, - { - name: "Feature Chaser", - href: "/feature-chaser", - status: true, - icon: DogChaserIcon, - description: "Show a survey about a new feature shown only to people who used it.", - category: "Boost Retention", - }, - { - name: "Feedback Box", - href: "/feedback-box", - status: true, - icon: FeedbackIcon, - description: "Give users the chance to share feedback in a single click.", - category: "Boost Retention", - }, - ]; - - return ( -
- {BestPractices.map((bestPractice) => ( - -
-
- {bestPractice.category} -
-
- -
-

- {bestPractice.name} -

-

{bestPractice.description}

-
- - ))} -
- ); -} diff --git a/apps/formbricks-com-old/components/shared/BestPractices.tsx b/apps/formbricks-com-old/components/shared/BestPractices.tsx deleted file mode 100644 index 5d33601f7c..0000000000 --- a/apps/formbricks-com-old/components/shared/BestPractices.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { Button } from "@formbricks/ui"; -import { usePlausible } from "next-plausible"; -import { useRouter } from "next/router"; -import BestPracticeNavigation from "./BestPracticeNavigation"; - -export default function InsightOppos() { - const plausible = usePlausible(); - const router = useRouter(); - return ( -
-
-

- Get started with{" "} - - Best Practices - -

-

- Run battle-tested approaches for qualitative user research in minutes. -

-
- - - -
- -
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/BreakerCTA.tsx b/apps/formbricks-com-old/components/shared/BreakerCTA.tsx deleted file mode 100644 index c518b7e69a..0000000000 --- a/apps/formbricks-com-old/components/shared/BreakerCTA.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { Button } from "@formbricks/ui"; -import clsx from "clsx"; -import { usePlausible } from "next-plausible"; -import { useRouter } from "next/router"; - -interface Props { - teaser: string; - headline: string; - subheadline: string; - cta: string; - href: string; - inverted?: boolean; -} - -export default function BreakerCTA({ inverted = false, teaser, headline, subheadline, cta, href }: Props) { - const router = useRouter(); - const plausible = usePlausible(); - return ( -
-
-
- -
-

- {teaser} -

-

- {headline} -

-

- {subheadline} -

-
- -
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/CTA.tsx b/apps/formbricks-com-old/components/shared/CTA.tsx deleted file mode 100644 index 64029e23b0..0000000000 --- a/apps/formbricks-com-old/components/shared/CTA.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Button } from "@formbricks/ui"; -import { useRouter } from "next/router"; -import HeadingCentered from "./HeadingCentered"; - -export default function CTA() { - const router = useRouter(); - return ( - <> -
- - -
-
-

Self-hosted

-

Run locally e.g. with docker-compose.

- -
-
-

Cloud

-

Use our free managed service.

- -
-
-
- - ); -} diff --git a/apps/formbricks-com-old/components/shared/Callout.tsx b/apps/formbricks-com-old/components/shared/Callout.tsx deleted file mode 100644 index 99be002ec5..0000000000 --- a/apps/formbricks-com-old/components/shared/Callout.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import clsx from "clsx"; -import { Icon } from "@/components/shared/Icon"; - -const styles = { - note: { - container: "bg-slate-100 dark:bg-slate-800/60 dark:ring-1 dark:ring-slate-300/10", - title: "text-slate-900 dark:text-slate-400", - body: "text-slate-800 [--tw-prose-background:theme(colors.slate.50)] prose-a:text-slate-900 prose-code:text-slate-900 dark:text-slate-300 dark:prose-code:text-slate-300", - }, - warning: { - container: "bg-amber-50 dark:bg-slate-800/60 dark:ring-1 dark:ring-slate-300/10", - title: "text-amber-900 dark:text-amber-500", - body: "text-amber-800 [--tw-prose-underline:theme(colors.amber.400)] [--tw-prose-background:theme(colors.amber.50)] prose-a:text-amber-900 prose-code:text-amber-900 dark:text-slate-300 dark:[--tw-prose-underline:theme(colors.slate.700)] dark:prose-code:text-slate-300", - }, -}; - -const icons = { - note: (props: any) => , - warning: (props: any) => , -}; - -interface CalloutProps { - type: "note" | "warning"; - title: string; - children: React.ReactNode; -} - -export function Callout({ type = "note", title, children }: CalloutProps) { - let IconComponent = icons[type]; - - return ( -
- -
-

{title}

-
{children}
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/Card.jsx b/apps/formbricks-com-old/components/shared/Card.jsx deleted file mode 100644 index 46daeb69d7..0000000000 --- a/apps/formbricks-com-old/components/shared/Card.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import Link from "next/link"; -import clsx from "clsx"; - -function ChevronRightIcon(props) { - return ( - - ); -} - -export function Card({ as: Component = "div", className, children }) { - return ( - {children} - ); -} - -Card.Link = function CardLink({ children, ...props }) { - return ( - <> -
- - - {children} - - - ); -}; - -Card.Title = function CardTitle({ as: Component = "h2", href, children }) { - return ( - - {href ? {children} : children} - - ); -}; - -Card.Description = function CardDescription({ children }) { - return

{children}

; -}; - -Card.Cta = function CardCta({ children }) { - return ( - - ); -}; - -Card.Eyebrow = function CardEyebrow({ - as: Component = "p", - decorate = false, - className, - children, - ...props -}) { - return ( - - {decorate && ( - - ); -}; diff --git a/apps/formbricks-com-old/components/shared/CodeBlock.tsx b/apps/formbricks-com-old/components/shared/CodeBlock.tsx deleted file mode 100644 index d64b394a25..0000000000 --- a/apps/formbricks-com-old/components/shared/CodeBlock.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// components/ui/CodeBlock.tsx -import Prism from "prismjs"; -import "prismjs/themes/prism.css"; -import React, { useEffect } from "react"; - -interface CodeBlockProps { - children: React.ReactNode; -} - -const CodeBlock: React.FC = ({ children }) => { - useEffect(() => { - Prism.highlightAll(); - }, [children]); - - return ( -
-
-        {children}
-      
-
- ); -}; - -export default CodeBlock; diff --git a/apps/formbricks-com-old/components/shared/EarlyBirdDeal.tsx b/apps/formbricks-com-old/components/shared/EarlyBirdDeal.tsx deleted file mode 100644 index b3916c5eee..0000000000 --- a/apps/formbricks-com-old/components/shared/EarlyBirdDeal.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import EarlyBird from "@/images/early bird deal for open source jotform alternative typeform and surveymonkey_v2.svg"; -import { Button } from "@formbricks/ui"; -import { usePlausible } from "next-plausible"; -import Image from "next/image"; - -export default function EarlyBirdDeal() { - const plausible = usePlausible(); - return ( -
-
-

- 50% off for Early Birds. -

-

- Limited deal: Only{" "} - 14 left. -

- -
- -
-

- This saves you $588 every year. -

-
- formbricks favicon open source forms typeform alternative -
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/FeatureHighlight.tsx b/apps/formbricks-com-old/components/shared/FeatureHighlight.tsx deleted file mode 100644 index f5c3d99f61..0000000000 --- a/apps/formbricks-com-old/components/shared/FeatureHighlight.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { Button } from "@formbricks/ui"; -import { useRouter } from "next/router"; -import clsx from "clsx"; - -interface Props { - featureTitle: string; - text: string; - img: React.ReactNode; - isImgLeft?: boolean; - cta?: string; - href?: string; - disabled?: boolean; -} - -export default function FeatureHighlights({ - featureTitle, - text, - img, - isImgLeft, - cta, - href, - disabled, -}: Props) { - const router = useRouter(); - - return ( -
-
-
-
-

- {featureTitle} -

-
- {text} -
-
- {cta && href && ( - - )} -
-
- {img} -
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/Fence.jsx b/apps/formbricks-com-old/components/shared/Fence.jsx deleted file mode 100644 index dab11c6b8e..0000000000 --- a/apps/formbricks-com-old/components/shared/Fence.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Fragment } from "react"; -import { Highlight } from "prism-react-renderer"; - -export function Fence({ children, language }) { - return ( - - {({ className, style, tokens, getTokenProps }) => ( -
-          
-            {tokens.map((line, lineIndex) => (
-              
-                {line
-                  .filter((token) => !token.empty)
-                  .map((token, tokenIndex) => (
-                    
-                  ))}
-                {"\n"}
-              
-            ))}
-          
-        
- )} -
- ); -} diff --git a/apps/formbricks-com-old/components/shared/Footer.tsx b/apps/formbricks-com-old/components/shared/Footer.tsx deleted file mode 100644 index 34c49e030c..0000000000 --- a/apps/formbricks-com-old/components/shared/Footer.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import Link from "next/link"; -import { FooterLogo } from "./Logo"; - -const navigation = { - other: [ - { name: "Community", href: "/community", status: true }, - { name: "Blog", href: "/blog", status: true }, - { name: "OSS Friends", href: "/oss-friends", status: true }, - { name: "GDPR FAQ", href: "/gdpr", status: true }, - { name: "GDPR Guide", href: "/gdpr-guide", status: true }, - ], - social: [ - { - name: "Twitter", - href: "https://twitter.com/formbricks", - icon: (props: any) => ( - - - - ), - }, - { - name: "GitHub", - href: "https://github.com/formbricks/formbricks", - icon: (props: any) => ( - - - - ), - }, - ], -}; - -export default function Footer() { - return ( -
- -
- - Formbricks - - -

Privacy-first Experience Management

-
-

- Formbricks GmbH © 2022. All rights reserved. -
- Imprint | Privacy Policy |{" "} - Terms | OSS Friends -

-
-
- {navigation.social.map((item) => ( - - {item.name} -
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/Header.tsx b/apps/formbricks-com-old/components/shared/Header.tsx deleted file mode 100644 index 000b1e84fb..0000000000 --- a/apps/formbricks-com-old/components/shared/Header.tsx +++ /dev/null @@ -1,396 +0,0 @@ -import GitHubMarkWhite from "@/images/github-mark-white.svg"; -import GitHubMarkDark from "@/images/github-mark.svg"; -import { - BaseballIcon, - Button, - CancelSubscriptionIcon, - CodeBookIcon, - DogChaserIcon, - FeedbackIcon, - InterviewPromptIcon, - OnboardingIcon, - PMFIcon, -} from "@formbricks/ui"; -import { Popover, Transition } from "@headlessui/react"; -import { Bars3Icon, ChevronDownIcon, ChevronRightIcon, XMarkIcon } from "@heroicons/react/24/outline"; -import clsx from "clsx"; -import { usePlausible } from "next-plausible"; -import Image from "next/image"; -import Link from "next/link"; -import { useRouter } from "next/router"; -import { Fragment, useState } from "react"; -import { FooterLogo } from "./Logo"; -import { ThemeSelector } from "./ThemeSelector"; - -function GitHubIcon(props: any) { - return ( - - ); -} - -const UnderstandUsers = [ - { - name: "Interview Prompt", - href: "/interview-prompt", - status: true, - icon: InterviewPromptIcon, - description: "Interview invites on auto-pilot", - }, - { - name: "Measure PMF", - href: "/measure-product-market-fit", - status: true, - icon: PMFIcon, - description: "Improve Product-Market Fit", - }, - { - name: "Onboarding Segments", - href: "/onboarding-segmentation", - status: true, - icon: OnboardingIcon, - description: "Get it right from the start", - }, -]; - -const IncreaseRevenue = [ - { - name: "Learn from Churn", - href: "/learn-from-churn", - status: true, - icon: CancelSubscriptionIcon, - description: "Churn is hard, but insightful", - }, - { - name: "Improve Trial CR", - href: "/improve-trial-conversion", - status: true, - icon: BaseballIcon, - description: "Take guessing out, hit it right", - }, -]; - -const BoostRetention = [ - { - name: "Feedback Box", - href: "/feedback-box", - status: true, - icon: FeedbackIcon, - description: "Always keep an ear open", - }, - { - name: "Docs Feedback", - href: "/docs-feedback", - status: true, - icon: CodeBookIcon, - description: "Clear docs, more adoption", - }, - { - name: "Feature Chaser", - href: "/feature-chaser", - status: true, - icon: DogChaserIcon, - description: "Follow up, improve", - }, -]; - -export default function Header() { - const [mobileSubOpen, setMobileSubOpen] = useState(false); - const plausible = usePlausible(); - const router = useRouter(); - return ( - -
-
- - Formbricks - - -
-
- - Open menu - -
- - - {({ open }) => ( - <> - - Best Practices - - - - -
-
-
-

- Understand Users -

- {UnderstandUsers.map((brick) => ( - -
-
-
-

- {brick.name} -

-

{brick.description}

-
- - ))} -
-
-

- Increase Revenue -

- {IncreaseRevenue.map((brick) => ( - -
-
-
-

- {brick.name} -

-

{brick.description}

-
- - ))} -
-
-

- Boost Retention -

- {BoostRetention.map((brick) => ( - -
-
-
-

- {brick.name} -

-

{brick.description}

-
- - ))} -
-
-
-
-
- - )} -
- {/* - Community - - */} - - Pricing - - - Docs - - - Blog {/*

1

*/} - - {/* - Careers

2

- */} - - - Concierge - -
-
- - - {/* */} - - -
-
- - - -
-
-
-
- -
-
- - Close menu - -
-
-
-
-
-
- {mobileSubOpen ? ( - - ) : ( - - )} - -
- {mobileSubOpen && ( -
- {UnderstandUsers.map((brick) => ( - - {brick.name} - - ))} - {IncreaseRevenue.map((brick) => ( - - {brick.name} - - ))} - {BoostRetention.map((brick) => ( - - {brick.name} - - ))} -
-
- )} - Concierge - Pricing - Docs - Blog - {/* Careers */} - - -
-
-
-
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/HeaderLight.tsx b/apps/formbricks-com-old/components/shared/HeaderLight.tsx deleted file mode 100644 index cffc8b27e0..0000000000 --- a/apps/formbricks-com-old/components/shared/HeaderLight.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Button } from "@formbricks/ui"; -import { Popover } from "@headlessui/react"; -import { usePlausible } from "next-plausible"; -import Link from "next/link"; -import { useRouter } from "next/router"; -import { FooterLogo } from "./Logo"; - -export default function HeaderLight() { - const plausible = usePlausible(); - const router = useRouter(); - return ( - -
-
- - Formbricks - - -
- -
- - -
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/HeadingCentered.tsx b/apps/formbricks-com-old/components/shared/HeadingCentered.tsx deleted file mode 100644 index d7c74aef8e..0000000000 --- a/apps/formbricks-com-old/components/shared/HeadingCentered.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import clsx from "clsx"; - -interface Props { - teaser?: string; - heading: string; - subheading?: string; - closer?: boolean; -} - -export default function HeadingCentered({ teaser, heading, subheading, closer }: Props) { - return ( -
-

- {teaser} -

-

- {heading} -

-

- {subheading} -

-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/HeroAnimation.tsx b/apps/formbricks-com-old/components/shared/HeroAnimation.tsx deleted file mode 100644 index 8556664838..0000000000 --- a/apps/formbricks-com-old/components/shared/HeroAnimation.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { useEffect, useRef, useState } from "react"; -import type { LottiePlayer } from "lottie-web"; - -export default function HeroAnimation(props: any) { - const ref = useRef(null); - const [lottie, setLottie] = useState(null); - - useEffect(() => { - import("lottie-web").then((Lottie) => setLottie(Lottie.default)); - }, []); - - useEffect(() => { - if (lottie && ref.current) { - const animation = lottie.loadAnimation({ - container: ref.current, - renderer: "svg", - loop: true, - autoplay: true, - // path to your animation file, place it inside public folder - path: "/animations/xm-hero-v1.json", - }); - - return () => animation.destroy(); - } - }, [lottie]); - - return
; -} diff --git a/apps/formbricks-com-old/components/shared/HeroTitle.tsx b/apps/formbricks-com-old/components/shared/HeroTitle.tsx deleted file mode 100644 index 6f6c26177f..0000000000 --- a/apps/formbricks-com-old/components/shared/HeroTitle.tsx +++ /dev/null @@ -1,25 +0,0 @@ -interface Props { - headingPt1: string; - headingTeal?: string; - headingPt2?: string; - subheading?: string; - children?: React.ReactNode; -} - -export default function HeroTitle({ headingPt1, headingTeal, headingPt2, subheading, children }: Props) { - return ( -
-

- {headingPt1}{" "} - - {headingTeal} - {" "} - {headingPt2} -

-

- {subheading} -

-
{children}
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/Icon.jsx b/apps/formbricks-com-old/components/shared/Icon.jsx deleted file mode 100644 index acde8da647..0000000000 --- a/apps/formbricks-com-old/components/shared/Icon.jsx +++ /dev/null @@ -1,69 +0,0 @@ -import { useId } from "react"; -import clsx from "clsx"; - -import { InstallationIcon } from "@/components/shared/icons/InstallationIcon"; -import { LightbulbIcon } from "@/components/shared/icons/LightbulbIcon"; -import { PluginsIcon } from "@/components/shared/icons/PluginsIcon"; -import { PresetsIcon } from "@/components/shared/icons/PresetsIcon"; -import { ThemingIcon } from "@/components/shared/icons/ThemingIcon"; -import { WarningIcon } from "@/components/shared/icons/WarningIcon"; - -const icons = { - installation: InstallationIcon, - presets: PresetsIcon, - plugins: PluginsIcon, - theming: ThemingIcon, - lightbulb: LightbulbIcon, - warning: WarningIcon, -}; - -const iconStyles = { - slate: "[--icon-foreground:theme(colors.slate.900)] [--icon-background:theme(colors.white)]", - amber: "[--icon-foreground:theme(colors.amber.900)] [--icon-background:theme(colors.amber.100)]", -}; - -export function Icon({ color = "slate", icon, className, ...props }) { - let id = useId(); - let IconComponent = icons[icon]; - - return ( - - ); -} - -const gradients = { - slate: [ - { stopColor: "#0EA5E9" }, - { stopColor: "#22D3EE", offset: ".527" }, - { stopColor: "#818CF8", offset: 1 }, - ], - amber: [ - { stopColor: "#FDE68A", offset: ".08" }, - { stopColor: "#F59E0B", offset: ".837" }, - ], -}; - -export function Gradient({ color = "slate", ...props }) { - return ( - - {gradients[color].map((stop, stopIndex) => ( - - ))} - - ); -} - -export function LightMode({ className, ...props }) { - return ; -} - -export function DarkMode({ className, ...props }) { - return ; -} diff --git a/apps/formbricks-com-old/components/shared/Layout.tsx b/apps/formbricks-com-old/components/shared/Layout.tsx deleted file mode 100644 index 9a039fadc5..0000000000 --- a/apps/formbricks-com-old/components/shared/Layout.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import Footer from "./Footer"; -import Header from "./Header"; -import MetaInformation from "./MetaInformation"; - -interface LayoutProps { - children: React.ReactNode; - title: string; - description: string; -} - -export default function Layout({ title, description, children }: LayoutProps) { - return ( -
- -
- { -
- {children} -
- } -
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/LayoutLight.tsx b/apps/formbricks-com-old/components/shared/LayoutLight.tsx deleted file mode 100644 index 252544cbd4..0000000000 --- a/apps/formbricks-com-old/components/shared/LayoutLight.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import Footer from "./Footer"; -import MetaInformation from "./MetaInformation"; -import HeaderLight from "./HeaderLight"; - -interface LayoutProps { - children: React.ReactNode; - title: string; - description: string; -} - -export default function Layout({ title, description, children }: LayoutProps) { - return ( -
- - - { -
- {children} -
- } -
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/LayoutMdx.tsx b/apps/formbricks-com-old/components/shared/LayoutMdx.tsx deleted file mode 100644 index 585f9d2107..0000000000 --- a/apps/formbricks-com-old/components/shared/LayoutMdx.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { useEffect } from "react"; -import Footer from "./Footer"; -import Header from "./Header"; -import MetaInformation from "./MetaInformation"; -import { Prose } from "./Prose"; - -const useExternalLinks = (selector: string) => { - useEffect(() => { - const links = document.querySelectorAll(selector); - - links.forEach((link) => { - link.setAttribute("target", "_blank"); - link.setAttribute("rel", "noopener noreferrer"); - }); - - return () => { - links.forEach((link) => { - link.removeAttribute("target"); - link.removeAttribute("rel"); - }); - }; - }, [selector]); -}; - -interface Props { - meta: { - title: string; - description: string; - publishedTime: string; - authors: string[]; - section: string; - tags: string[]; - }; - children: JSX.Element; -} - -export default function LayoutMdx({ meta, children }: Props) { - useExternalLinks(".prose a"); - return ( -
- -
-
-
- {meta.title && ( -
- {meta.title && ( -

- {meta.title} -

- )} -
- )} - {children} -
-
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/Logo.tsx b/apps/formbricks-com-old/components/shared/Logo.tsx deleted file mode 100644 index 3f45009ea6..0000000000 --- a/apps/formbricks-com-old/components/shared/Logo.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import Image from "next/image"; -import logomark from "@/images/logo/logomark.svg"; -import logo from "@/images/logo/logo.svg"; -import logoDark from "@/images/logo/logo_dark.svg"; -import footerLogo from "@/images/logo/footerlogo.svg"; -import footerLogoDark from "@/images/logo/footerlogo-dark.svg"; - -export function Logomark(props: any) { - return Formbricks Open source Forms & Surveys Logomark; -} - -export function Logo(props: any) { - return ( -
-
- Formbricks Open source Forms & Surveys Logo -
-
- Formbricks Open source Forms & Surveys Logo -
-
- ); -} - -export function FooterLogo(props: any) { - return ( -
-
- Formbricks Open source Forms & Surveys Logo -
-
- Formbricks Open source Forms & Surveys Logo -
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/MdxCTA.tsx b/apps/formbricks-com-old/components/shared/MdxCTA.tsx deleted file mode 100644 index f189dd66a0..0000000000 --- a/apps/formbricks-com-old/components/shared/MdxCTA.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Button } from "@formbricks/ui"; -import { useRouter } from "next/router"; - -export default function CTA() { - const router = useRouter(); - return ( - <> -
-

- It's free & open-source -

-

- Try Formbricks right now! -

-
-
-

Self-hosted

-

Run locally with docker-compose.

- -
-
-

Cloud

-

Use our free managed service.

- -
-
-
- - ); -} diff --git a/apps/formbricks-com-old/components/shared/MdxTryItCTA.tsx b/apps/formbricks-com-old/components/shared/MdxTryItCTA.tsx deleted file mode 100644 index 786c29fe8d..0000000000 --- a/apps/formbricks-com-old/components/shared/MdxTryItCTA.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Button } from "@formbricks/ui"; -import { DocumentDuplicateIcon } from "@heroicons/react/24/outline"; -import { useRouter } from "next/router"; - -export default function HeadingCentered() { - const router = useRouter(); - return ( -
-
-

- What are you waiting for? -

-

- Try it right now! -

-

- Dive right in or browse docs for examples. Questions? Join our Discord, we’re happy to help -

- - -
-
-
-

npm install @formbricks/react

- -
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/MetaInformation.tsx b/apps/formbricks-com-old/components/shared/MetaInformation.tsx deleted file mode 100644 index 39961f3c52..0000000000 --- a/apps/formbricks-com-old/components/shared/MetaInformation.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import Head from "next/head"; - -interface Props { - title: string; - description: string; - publishedTime?: string; - updatedTime?: string; - authors?: string[]; - section?: string; - tags?: string[]; -} - -export default function MetaInformation({ - title, - description, - publishedTime, - updatedTime, - authors, - section, - tags, -}: Props) { - const pageTitle = `${title} | Open-Source Experience Management, Privacy-first`; - return ( - - {pageTitle} - - - - - - - - - - - - - {publishedTime && } - {updatedTime && } - {authors && } - {section && } - {tags && } - - - - - - ); -} diff --git a/apps/formbricks-com-old/components/shared/MobileNavigation.jsx b/apps/formbricks-com-old/components/shared/MobileNavigation.jsx deleted file mode 100644 index a5d8766116..0000000000 --- a/apps/formbricks-com-old/components/shared/MobileNavigation.jsx +++ /dev/null @@ -1,69 +0,0 @@ -import { useEffect, useState } from "react"; -import Link from "next/link"; -import { useRouter } from "next/router"; -import { Dialog } from "@headlessui/react"; - -import { Logomark } from "@/components/shared/Logo"; -import { Navigation } from "@/components/shared/Navigation"; - -function MenuIcon(props) { - return ( - - ); -} - -function CloseIcon(props) { - return ( - - ); -} - -export function MobileNavigation({ navigation }) { - let router = useRouter(); - let [isOpen, setIsOpen] = useState(false); - - useEffect(() => { - if (!isOpen) return; - - function onRouteChange() { - setIsOpen(false); - } - - router.events.on("routeChangeComplete", onRouteChange); - router.events.on("routeChangeError", onRouteChange); - - return () => { - router.events.off("routeChangeComplete", onRouteChange); - router.events.off("routeChangeError", onRouteChange); - }; - }, [router, isOpen]); - - return ( - <> - - - -
- - - - -
- -
-
- - ); -} diff --git a/apps/formbricks-com-old/components/shared/Modal.tsx b/apps/formbricks-com-old/components/shared/Modal.tsx deleted file mode 100644 index 2e565bd7f6..0000000000 --- a/apps/formbricks-com-old/components/shared/Modal.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { Dialog, Transition } from "@headlessui/react"; -import { XMarkIcon } from "@heroicons/react/24/solid"; -import { Fragment } from "react"; -import clsx from "clsx"; - -type Modal = { - open: boolean; - setOpen: (v: boolean) => void; - children: React.ReactNode; - title?: string; - noPadding?: boolean; - closeOnOutsideClick?: boolean; -}; - -const Modal: React.FC = ({ - open, - setOpen, - children, - title, - noPadding, - closeOnOutsideClick = true, -}) => { - return ( - <> - - closeOnOutsideClick && setOpen(false)}> - -
- - -
-
- - -
- -
- {title &&

{title}

} - - {children} -
-
-
-
-
-
- - ); -}; - -export default Modal; diff --git a/apps/formbricks-com-old/components/shared/Navigation.tsx b/apps/formbricks-com-old/components/shared/Navigation.tsx deleted file mode 100644 index 0befd0b566..0000000000 --- a/apps/formbricks-com-old/components/shared/Navigation.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import Link from "next/link"; -import { useRouter } from "next/router"; -import clsx from "clsx"; - -interface NavigationProps { - navigation: { - title: string; - links: { - title: string; - href: string; - }[]; - }[]; - className: string; - preserveScroll: () => void; - linkRef: React.RefObject; -} - -export function Navigation({ navigation, className, preserveScroll, linkRef }: NavigationProps) { - let router = useRouter(); - - return ( - - ); -} diff --git a/apps/formbricks-com-old/components/shared/NewsletterSignup.tsx b/apps/formbricks-com-old/components/shared/NewsletterSignup.tsx deleted file mode 100644 index 49ed550042..0000000000 --- a/apps/formbricks-com-old/components/shared/NewsletterSignup.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import Friends from "@/images/newsletter-signup-gif.gif"; -import { Button } from "@formbricks/ui"; -import Image from "next/image"; - -export default function WaitlistForm() { - return ( -
-

Build in public

- Get all the juicy details of our journey building Formbricks in public πŸ‘‡ -
-
-
-
- -
-
- - -
-
- - -
-
- - -
- -
-
- - Sign up to newsletter -
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/Pricing.tsx b/apps/formbricks-com-old/components/shared/Pricing.tsx deleted file mode 100644 index dacb32dd4b..0000000000 --- a/apps/formbricks-com-old/components/shared/Pricing.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import { Button } from "@formbricks/ui"; -import clsx from "clsx"; -import HeadingCentered from "./HeadingCentered"; -import { CheckIcon } from "@heroicons/react/24/outline"; -import { usePlausible } from "next-plausible"; -import { useRouter } from "next/router"; - -const tiers = [ - { - name: "Self-hosting", - priceMonthly: "free", - paymentRythm: "/always", - button: "secondary", - discounted: false, - highlight: false, - description: "Host Formbricks on your own server.", - features: [ - "All Free features", - "Easy self-hosting (Docker)", - "Unlimited surveys", - "Unlimited responses", - "Unlimited team members", - ], - ctaName: "Read docs", - plausibleGoal: "Pricing_CTA_SelfHosting", - href: "/docs/self-hosting/deployment", - }, - { - name: "Cloud", - href: "https://app.formbricks.com/auth/signup", - priceMonthly: "$0", - paymentRythm: "/month", - button: "highlight", - discounted: false, - highlight: true, - description: "Start with the 'Free forever' plan.", - features: [ - "Unlimited surveys", - "In-product surveys", - "Link surveys", - "Remove branding", - "Granular targeting", - "30+ templates", - "API access", - "Integrations (Zapier, Make, ...)", - "Unlimited team members", - "100 responses per survey", - ], - ctaName: "Get started", - plausibleGoal: "Pricing_CTA_FreePlan", - }, - { - name: "Cloud Pro", - href: "https://app.formbricks.com/auth/signup", - priceMonthly: "$99", - paymentRythm: "/month", - button: "secondary", - discounted: false, - highlight: false, - description: "All features, unlimited usage.", - features: ["Everything in 'Cloud'", "Unlimited responses per survey"], - ctaName: "Start for free", - plausibleGoal: "Pricing_CTA_ProPlan", - }, -]; - -export default function Pricing() { - const plausible = usePlausible(); - const router = useRouter(); - - return ( -
-
- - -
- {tiers.map((tier) => ( -
-
-

- {tier.name} -

-

- {tier.description} -

-
    - {tier.features.map((feature, index) => ( -
  • -
    - -
    - {feature} -
  • - ))} -
-

- - {tier.priceMonthly} - {" "} - - {tier.discounted && "$49"} - - - {tier.paymentRythm} - -

- - - - {tier.name == "Cloud Pro" && ( -

No Creditcard required.

- )} - {tier.name == "Cloud" && ( -

Free forever 🀍

- )} -
-
- ))} -
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/Prose.jsx b/apps/formbricks-com-old/components/shared/Prose.jsx deleted file mode 100644 index 6a816f2419..0000000000 --- a/apps/formbricks-com-old/components/shared/Prose.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import clsx from "clsx"; - -export function Prose({ as: Component = "div", className, ...props }) { - return ( - - ); -} diff --git a/apps/formbricks-com-old/components/shared/Search.tsx b/apps/formbricks-com-old/components/shared/Search.tsx deleted file mode 100644 index 679185b068..0000000000 --- a/apps/formbricks-com-old/components/shared/Search.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import { createPortal } from "react-dom"; -import Link from "next/link"; -import Router from "next/router"; -import { DocSearchModal, useDocSearchKeyboardEvents } from "@docsearch/react"; - -const docSearchConfig = { - appId: process.env.NEXT_PUBLIC_DOCSEARCH_APP_ID || "", - apiKey: process.env.NEXT_PUBLIC_DOCSEARCH_API_KEY || "", - indexName: process.env.NEXT_PUBLIC_DOCSEARCH_INDEX_NAME || "", -}; - -interface HitProps { - hit: { url: string }; - children: React.ReactNode; -} - -function Hit({ hit, children }: HitProps) { - return {children}; -} - -function SearchIcon(props: any) { - return ( - - ); -} - -export function Search() { - let [isOpen, setIsOpen] = useState(false); - let [modifierKey, setModifierKey] = useState(); - - const onOpen = useCallback(() => { - setIsOpen(true); - }, [setIsOpen]); - - const onClose = useCallback(() => { - setIsOpen(false); - }, [setIsOpen]); - - useDocSearchKeyboardEvents({ isOpen, onOpen, onClose }); - - useEffect(() => { - setModifierKey(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ? "⌘" : "Ctrl "); - }, []); - - return ( - <> - - {isOpen && - createPortal( - , - document.body - )} - - ); -} diff --git a/apps/formbricks-com-old/components/shared/ThemeSelector.jsx b/apps/formbricks-com-old/components/shared/ThemeSelector.jsx deleted file mode 100644 index 5506c70bf5..0000000000 --- a/apps/formbricks-com-old/components/shared/ThemeSelector.jsx +++ /dev/null @@ -1,111 +0,0 @@ -import { useEffect, useState } from "react"; -import { Listbox } from "@headlessui/react"; -import clsx from "clsx"; - -const themes = [ - { name: "Light", value: "light", icon: LightIcon }, - { name: "Dark", value: "dark", icon: DarkIcon }, - { name: "System", value: "system", icon: SystemIcon }, -]; - -function LightIcon(props) { - return ( - - ); -} - -function DarkIcon(props) { - return ( - - ); -} - -function SystemIcon(props) { - return ( - - ); -} - -export function ThemeSelector(props) { - let [selectedTheme, setSelectedTheme] = useState(); - - useEffect(() => { - if (selectedTheme) { - document.documentElement.setAttribute("data-theme", selectedTheme.value); - } else { - setSelectedTheme( - themes.find((theme) => theme.value === document.documentElement.getAttribute("data-theme")) - ); - } - }, [selectedTheme]); - - useEffect(() => { - let handler = () => - setSelectedTheme(themes.find((theme) => theme.value === (window.localStorage.theme ?? "system"))); - - window.addEventListener("storage", handler); - - return () => window.removeEventListener("storage", handler); - }, []); - - return ( - - Theme - - - - - - - - {themes.map((theme) => ( - - clsx("flex cursor-pointer select-none items-center rounded-[0.625rem] p-1", { - "text-brand-dark dark:text-brand-light": selected, - "text-slate-800 dark:text-slate-100": active && !selected, - "text-slate-700 dark:text-slate-400": !active && !selected, - "bg-slate-100 dark:bg-slate-900/40": active, - }) - }> - {({ selected }) => ( - <> -
- -
-
{theme.name}
- - )} -
- ))} -
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/TryItCTA.tsx b/apps/formbricks-com-old/components/shared/TryItCTA.tsx deleted file mode 100644 index 21dda175e7..0000000000 --- a/apps/formbricks-com-old/components/shared/TryItCTA.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Button } from "@formbricks/ui"; -import { DocumentDuplicateIcon } from "@heroicons/react/24/outline"; -import { useRouter } from "next/router"; - -export default function HeadingCentered() { - const router = useRouter(); - return ( -
-
-

- What are you waiting for? -

-

- Try it right now! -

-

- Dive right in or browse docs for examples. -
- Questions? Join our Discord, we’re happy to help! -

- - -
-
-
-

npm install @formbricks/react

- -
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/UseCaseCTA.tsx b/apps/formbricks-com-old/components/shared/UseCaseCTA.tsx deleted file mode 100644 index e753afddcf..0000000000 --- a/apps/formbricks-com-old/components/shared/UseCaseCTA.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { Button } from "@formbricks/ui"; -import { useRouter } from "next/router"; - -interface UseCaseCTAProps { - href: string; -} - -export default function UseCaseHeader({ href }: UseCaseCTAProps) { - /* const plausible = usePlausible(); */ - const router = useRouter(); - return ( -
- -
- -

It's free

-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/UseCaseHeader.tsx b/apps/formbricks-com-old/components/shared/UseCaseHeader.tsx deleted file mode 100644 index 8fe2c14c2e..0000000000 --- a/apps/formbricks-com-old/components/shared/UseCaseHeader.tsx +++ /dev/null @@ -1,26 +0,0 @@ -interface UseCaseHeaderProps { - title: string; - - difficulty: string; - setupMinutes: string; -} - -export default function UseCaseHeader({ title, difficulty, setupMinutes }: UseCaseHeaderProps) { - return ( -
-
-

- {title} -

-
-
- {difficulty} -
-
- {setupMinutes} minutes -
-
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/WhyFormbricks.tsx b/apps/formbricks-com-old/components/shared/WhyFormbricks.tsx deleted file mode 100644 index 78d29c8d65..0000000000 --- a/apps/formbricks-com-old/components/shared/WhyFormbricks.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { - UsersIcon, - CubeTransparentIcon, - UserGroupIcon, - CommandLineIcon, - SwatchIcon, - SquaresPlusIcon, -} from "@heroicons/react/24/outline"; - -const features = [ - { - name: "Futureproof", - description: "Form needs change. With Formbricks you’ll avoid island solutions right from the start.", - icon: CubeTransparentIcon, - }, - { - name: "Privacy by design", - description: "Self-host the entire product and fly through privacy compliance reviews.", - icon: UsersIcon, - }, - { - name: "Community driven", - description: "We're building for you. If you need something specific, we’re happy to build it!", - icon: UserGroupIcon, - }, - { - name: "Great DX", - description: "We love a solid developer experience. We felt your pain and do our best to avoid it.", - icon: CommandLineIcon, - }, - { - name: "Customizable", - description: "We have to build opinionated. If it doesn't suit your need, just change it up.", - icon: SwatchIcon, - }, - { - name: "Extendable", - description: "Even though we try, we cannot build every single integration. With Formbricks, you can.", - icon: SquaresPlusIcon, - }, -]; - -export default function FeatureTable({}) { - return ( -
-
-

- Why Formbricks? -

-

- The only complete open source option. -

-

- We experienced how form needs develop as companies grow. We could'nt find a solution which ticked - all of the boxes. Now we're building it. -

-
- {features.map((feature) => ( -
-
- - -
-
-

{feature.name}

-

- {feature.description} -

-
-
- ))} -
-
-
- ); -} diff --git a/apps/formbricks-com-old/components/shared/icons/InstallationIcon.jsx b/apps/formbricks-com-old/components/shared/icons/InstallationIcon.jsx deleted file mode 100644 index b36601e0d3..0000000000 --- a/apps/formbricks-com-old/components/shared/icons/InstallationIcon.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import { DarkMode, Gradient, LightMode } from "@/components/shared/Icon"; - -export function InstallationIcon({ id, color }) { - return ( - <> - - - - - - - - - - - - - ); -} diff --git a/apps/formbricks-com-old/components/shared/icons/LightbulbIcon.jsx b/apps/formbricks-com-old/components/shared/icons/LightbulbIcon.jsx deleted file mode 100644 index 1f6ab70d23..0000000000 --- a/apps/formbricks-com-old/components/shared/icons/LightbulbIcon.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import { DarkMode, Gradient, LightMode } from "@/components/shared/Icon"; - -export function LightbulbIcon({ id, color }) { - return ( - <> - - - - - - - - - - - - - - - ); -} diff --git a/apps/formbricks-com-old/components/shared/icons/PluginsIcon.jsx b/apps/formbricks-com-old/components/shared/icons/PluginsIcon.jsx deleted file mode 100644 index ae8f05e78c..0000000000 --- a/apps/formbricks-com-old/components/shared/icons/PluginsIcon.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import { DarkMode, Gradient, LightMode } from "@/components/shared/Icon"; - -export function PluginsIcon({ id, color }) { - return ( - <> - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/apps/formbricks-com-old/components/shared/icons/PresetsIcon.jsx b/apps/formbricks-com-old/components/shared/icons/PresetsIcon.jsx deleted file mode 100644 index 2464ddc913..0000000000 --- a/apps/formbricks-com-old/components/shared/icons/PresetsIcon.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import { DarkMode, Gradient, LightMode } from "@/components/shared/Icon"; - -export function PresetsIcon({ id, color }) { - return ( - <> - - - - - - - - - - - - - - - - - - - ); -} diff --git a/apps/formbricks-com-old/components/shared/icons/ThemingIcon.jsx b/apps/formbricks-com-old/components/shared/icons/ThemingIcon.jsx deleted file mode 100644 index 476c9f022b..0000000000 --- a/apps/formbricks-com-old/components/shared/icons/ThemingIcon.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import { DarkMode, Gradient, LightMode } from "@/components/shared/Icon"; - -export function ThemingIcon({ id, color }) { - return ( - <> - - - - - - - - - - - - - - - - ); -} diff --git a/apps/formbricks-com-old/components/shared/icons/WarningIcon.jsx b/apps/formbricks-com-old/components/shared/icons/WarningIcon.jsx deleted file mode 100644 index aa5108664a..0000000000 --- a/apps/formbricks-com-old/components/shared/icons/WarningIcon.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import { DarkMode, Gradient, LightMode } from "@/components/shared/Icon"; - -export function WarningIcon({ id, color }) { - return ( - <> - - - - - - - - - - - - - - - ); -} diff --git a/apps/formbricks-com-old/lib/articles.ts b/apps/formbricks-com-old/lib/articles.ts deleted file mode 100644 index 4390a66ef9..0000000000 --- a/apps/formbricks-com-old/lib/articles.ts +++ /dev/null @@ -1,21 +0,0 @@ -import glob from "fast-glob"; -import * as path from "path"; - -async function importArticle(articleFilename: string) { - let { meta, default: component } = await import(`../pages/blog/${articleFilename}`); - return { - slug: articleFilename.replace(/(\/index)?\.mdx$/, ""), - ...meta, - component, - }; -} - -export async function getAllArticles() { - let articleFilenames = await glob(["*.mdx", "*/index.mdx"], { - cwd: path.join(process.cwd(), "pages/blog"), - }); - - let articles = await Promise.all(articleFilenames.map(importArticle)); - - return articles.sort((a, z) => new Date(z.date).valueOf() - new Date(a.date).valueOf()); -} diff --git a/apps/formbricks-com-old/lib/cleanHtml.ts b/apps/formbricks-com-old/lib/cleanHtml.ts deleted file mode 100644 index c7b47ba052..0000000000 --- a/apps/formbricks-com-old/lib/cleanHtml.ts +++ /dev/null @@ -1,79 +0,0 @@ -/*! - * Sanitize an HTML string - * (c) 2021 Chris Ferdinandi, MIT License, https://gomakethings.com - * @param {String} str The HTML string to sanitize - * @return {String} The sanitized string - */ -export function cleanHtml(str: string): string { - /** - * Convert the string to an HTML document - * @return {Node} An HTML document - */ - function stringToHTML() { - let parser = new DOMParser(); - let doc = parser.parseFromString(str, "text/html"); - return doc.body || document.createElement("body"); - } - - /** - * Remove