Blog: Join the FormTribe blog post

Blog: Join the FormTribe blog post
This commit is contained in:
Johannes
2023-10-01 15:14:39 +05:30
committed by GitHub
12 changed files with 211 additions and 91 deletions
+40 -38
View File
@@ -4,42 +4,44 @@ title: "[FEATURE]"
labels: enhancement
assignees: []
body:
- type: textarea
id: problem-description
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
id: solution-description
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
id: alternate-solution-description
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request here.
validations:
required: false
- type: markdown
id: formbricks-info
attributes:
value: |
### How we code at Formbricks 🤓
- type: textarea
id: problem-description
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
id: solution-description
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
id: alternate-solution-description
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request here.
validations:
required: false
- type: markdown
id: formbricks-info
attributes:
value: |
### How we code at Formbricks 🤓
- Everything is type-safe
- All UI components are in the package `formbricks/ui`
- Run `pnpm dev` to find a demo app to test in-app surveys at `localhost:3002`
- We use **chatGPT** to help refactor code. Use our [Formbricks ✨ megaprompt ✨](https://github.com/formbricks/formbricks/blob/main/megaprompt.md) to create the right
context before you write your prompt.
- Follow Best Practices lined out in our [Contributor Docs](https://formbricks.com/docs/contributing/how-we-code)
- First time: Please read our [introductory blog post](https://formbricks.com/blog/join-the-formtribe)
- All UI components are in the package `formbricks/ui`
- Run `pnpm go` to find a demo app to test in-app surveys at `localhost:3002`
- Everything is type-safe
- We use **chatGPT** to help refactor code. Use our [Formbricks ✨ megaprompt ✨](https://github.com/formbricks/formbricks/blob/main/megaprompt.md) to create the right
context before you write your prompt.
@@ -0,0 +1,15 @@
import Image from "next/image";
export const meta = {
title: "Gitpod Setup",
description:
"With one click, you can setup the Formbricks developer environment in your browser using Gitpod",
};
### One Click Setup
1. Click the button below to open this project in Gitpod.
2. This will open a fully configured workspace in your browser with all the necessary dependencies already installed.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/formbricks/formbricks)
@@ -1,16 +1,16 @@
"use client";
import { useRef } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import clsx from "clsx";
import { AnimatePresence, motion, useIsPresent } from "framer-motion";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useRef } from "react";
import { remToPx } from "@/lib/remToPx";
import { Button } from "./Button";
import { useIsInsideMobileNavigation } from "./MobileNavigation";
import { useSectionStore } from "./SectionProvider";
import { Tag } from "./Tag";
import { remToPx } from "@/lib/remToPx";
interface NavGroup {
title: string;
@@ -255,6 +255,7 @@ export const navigation: Array<NavGroup> = [
{ title: "Introduction", href: "/docs/contributing/introduction" },
{ title: "How we code at Formbricks", href: "/docs/contributing/how-we-code" },
{ title: "Setup Dev Environment", href: "/docs/contributing/setup" },
{ title: "Gitpod", href: "/docs/contributing/gitpod" },
{ title: "Demo App", href: "/docs/contributing/demo" },
{ title: "Troubleshooting", href: "/docs/contributing/troubleshooting" },
],
@@ -3,26 +3,24 @@ import { Button } from "@formbricks/ui";
export const OpenSourceInfo = () => {
return (
<div className="my-8 md:my-20">
<div className="px-4 md:px-16">
<div className=" rounded-xl bg-slate-100 px-4 py-4 dark:bg-slate-800 md:px-12">
<div className="px-8 md:px-16">
<div className=" rounded-xl bg-slate-100 px-4 py-8 dark:bg-slate-800 md:px-12">
<h2 className="text-lg font-semibold leading-7 tracking-tight text-slate-800 dark:text-slate-200 md:text-2xl">
Open Source
</h2>
<p className=" text-slate-800 dark:text-slate-200">
<p className=" my-2 text-slate-600 dark:text-slate-300">
Formbricks is an open source project. You can self-host it for free. We provide multiple easy
deployment options as per your customisation needs. We have documented the process of self-hosting
Formbricks on your own server using Docker, Bash Scripting, and Building from Source.
</p>
<div className="flex items-center justify-center">
<div className="mt-4 space-x-2">
<Button
className="mr-4 mt-4 justify-center px-8 text-xs shadow-sm md:text-lg"
variant="highlight"
variant="darkCTA"
onClick={() => window.open("https://github.com/formbricks/formbricks", "_blank")}>
Star us on GitHub
</Button>
<Button
className="ml-4 mt-4 justify-center px-8 text-xs shadow-sm md:text-lg"
onClick={() => window.open("/docs/self-hosting/deployment", "_blank")}
variant="secondary">
Read our Docs on Self Hosting
@@ -6,17 +6,17 @@ export const GetStartedWithPricing = ({ showDetailed }: { showDetailed: boolean
<div className="flex items-center gap-x-4 px-4 pb-4 md:gap-4 md:px-16">
<div className="w-1/3"></div>
<div className="w-1/3 text-left text-sm text-slate-800 dark:text-slate-100">
<p className="font-semibold">Free</p>
<p className="text-base font-semibold">Free</p>
{showDetailed && (
<p className="text-xs md:text-base">
<p className="leading text-xs text-slate-500 dark:text-slate-400 md:text-base">
General free usage on every product. Best for early stage startups and hobbyists
</p>
)}
<Button
className="mt-4 w-full justify-center bg-slate-300 px-4 text-xs shadow-sm hover:bg-slate-200 dark:bg-slate-600 dark:hover:bg-slate-500 md:text-lg"
variant={"secondary"}
className="mt-4 w-full justify-center"
variant="secondary"
onClick={() => {
window.open("https://app.formbricks.com/", "_blank");
}}>
@@ -24,16 +24,16 @@ export const GetStartedWithPricing = ({ showDetailed }: { showDetailed: boolean
</Button>
</div>
<div className="w-1/3 text-left text-sm text-slate-800 dark:text-slate-100">
<p className="font-semibold"> Paid</p>
<p className="text-base font-semibold"> Paid</p>
{showDetailed && (
<p className="text-xs md:text-base">
<p className="leading text-xs text-slate-500 dark:text-slate-400 md:text-base">
Formbricks with the next-generation features, Pay only for the tracked users.
</p>
)}
<Button
className="mt-4 w-full justify-center px-4 text-xs shadow-sm md:text-lg"
variant={"highlight"}
className="mt-4 w-full justify-center"
variant="highlight"
onClick={() => {
window.open("https://app.formbricks.com/", "_blank");
}}>
@@ -1,9 +1,9 @@
import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from "@formbricks/ui";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@formbricks/ui";
import { CheckIcon, XMarkIcon } from "@heroicons/react/24/outline";
export const PricingTable = ({ leadRow, pricing, endRow }) => {
return (
<div className="-mt-16 grid grid-cols-1 px-4 md:gap-4 md:px-16 ">
<div className="grid grid-cols-1 px-4 md:gap-4 md:px-16 ">
<div className="rounded-xl px-4 md:px-12">
<div className="flex items-center gap-x-4">
<div className="w-1/3 text-left font-semibold text-slate-700 dark:text-slate-200 md:text-xl">
@@ -11,7 +11,7 @@ export const PricingTable = ({ leadRow, pricing, endRow }) => {
</div>
<div
className="flex w-1/3 items-center justify-center text-center text-sm font-semibold
text-slate-700 dark:text-slate-200 md:text-lg">
text-slate-500 dark:text-slate-200 md:text-lg">
{leadRow.free}
</div>
@@ -34,7 +34,7 @@ export const PricingTable = ({ leadRow, pricing, endRow }) => {
</div>
<div className="flex w-1/3 items-center justify-center text-center text-sm text-slate-800 dark:text-slate-100">
{feature.addOnText ? (
<TooltipProvider>
<TooltipProvider delayDuration={50}>
<Tooltip>
<TooltipTrigger>
<u>{feature.free}</u>
Binary file not shown.

After

Width:  |  Height:  |  Size: 818 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 KiB

@@ -0,0 +1,107 @@
import Image from "next/image";
import LayoutMdx from "@/components/shared/LayoutMdx";
import MonorepoImage from "./formbricks-monorepo-folder-structure.png";
import HeaderImage from "./create-a-new-survey-with-formbricks.png";
import GitpodImage from "./setup-formbricks-via-gitpod.png";
import PackagesFolderImage from "./formbricks-packages-folder.png";
import AuthorBox from "@/components/shared/AuthorBox";
export const meta = {
title: "Join the FormTribe 🔥",
description: "Here is everything you need to know about joining the Formbricks community",
date: "2023-10-01",
publishedTime: "2023-10-01T00:00:00",
authors: ["Johannes"],
section: "Open-Source",
tags: ["Open-Source", "No-Code", "Formbricks", "Geting started", "Welcome guide"],
};
<AuthorBox name="Johannes" title="Co-Founder" date="October 1st, 2023" duration="4" />
<Image src={HeaderImage} alt="Title Image" className="w-full rounded-lg" />
_Get a quick intro to the Formbricks community, also known as FormTribe, and learn all the deets about making awesome contributions to the project._
## Welcome to the Formbricks community!
We are so excited to have you with us 😊
In this post we will be helping you get familiar with the Formbricks codebase and get you up to speed contributing in no time. If you want to learn about Formbricks check out our [docs intro](https://formbricks.com/docs/introduction/what-is-formbricks), for more info about our founding story and why we're building open source checkout out our [blog](https://formbricks.com/blog).
### Prerequisites
Our codebase is written fully in Typescript and we love it 😍. To power our the experience management solution, here is the stack behind it all:
[Next.js](https://nextjs.org/) - React Framework
[Prisma](https://www.prisma.io/) - ORM
[Typescript](https://www.typescriptlang.org/) - Language
[Lucide React](https://lucide.dev/guide/packages/lucide-react) - Icons
[TalwindCSS](https://tailwindcss.com/) - Styling
[Zod](https://zod.dev/) - Validation
[Auth.js](https://authjs.dev/) - Authentication
### 😎 Installation and Setup
To get up and running we have 2 options: Gitpod and local.
#### Get started with Gitpod
With Gitpod you can run all of Formbricks in the cloud. With one click you can start coding right away in your browser:
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/formbricks/formbricks)
<Image src={GitpodImage} alt="Setup Formbricks via Gitpod" className="w-full rounded-lg" />
#### Run on a local machine
If you choose to get setup locally, we also have a well documented guide to hold you through the process, you can find it [here](https://formbricks.com/docs/contributing/setup)
### 👩🏽‍💻 Codebase Overview
Our codebase is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) which means we have different projects in one repository. At moment we have 3 different projects:
1. **demo** `apps/demo` - It's a simple React app that you can run locally and use to trigger actions and set **[Attributes](https://formbricks.com/docs/attributes/why)**. It allows you to test your setup easily.
2. **formbricks-com** `apps/formbricks-com` - The landing page of [Formbricks](https://formbricks.com)
3. **web** `apps/web` - Our [cloud offering](https://app.formbricks.com/) for Formbricks.
<Image src={MonorepoImage} alt="Formbricks monorepo folder structure" className="w-full rounded-lg" />
#### TurboRepo and our own packages
To manage all of these projects in one repository we use [turborepo](https://turbo.build/repo/docs/core-concepts/monorepos). Depending on what part of the codebase you need to contribute in, now you know where to begin 😃
We also have a set of packages which we manage: They are located in the `packages` folder. There we keep our styling library, components, database migrations and connection, a couple of configurations and much more. We do this to use any of these packages seamlessly between our mono repos.
<Image src={PackagesFolderImage} alt="Formbricks packages folder" className="w-full rounded-lg" />
### ⚖️ Contribution Guidelines
You want to get started contributing? Amazing! Checkout our must-read post on [How we Code at Formbricks](https://formbricks.com/docs/contributing/how-we-code). This will give you everything you need to know about successfully contributing to our codebase in no time.
### 🤗 Our Community
We really value our community. It might be small but it is close to our hearts. Join our [Discord](https://formbricks.com/discord) to learn from other contributors and meet the Formbricks community.
### Conclusion
Contributing to open source projects like Formbricks can be a rewarding experience. By contributing, you have the opportunity to make a meaningful impact on a project used by many and gain valuable experience in the process.
Whether you are a seasoned developer or just starting out, your contributions are appreciated. We might not always have to onboard everyone but try our best. You can help improve the codebase, fix bugs, add new features, or even contribute to the documentation. Every contribution, no matter how small, can make a difference.
Not only will you be able to showcase your skills and build your portfolio, but you will also have the chance to collaborate with other talented designers and developers in the Formbricks community. You can learn from their expertise and share your own knowledge.
### So, why wait?
Join the Formbricks community today and start contributing to an up and coming open source project. Your contributions can help shape the future of Formbricks and make a positive impact on the lives of tens of thousands of users worldwide.
We look forward to seeing your contributions and welcoming you to the Formbricks community!
### [Say Hi 👋](https://formbricks.com/discord)
export default ({ children }) => <LayoutMdx meta={meta}>{children}</LayoutMdx>;
Binary file not shown.

After

Width:  |  Height:  |  Size: 594 KiB

+27 -30
View File
@@ -1,9 +1,9 @@
import HeroTitle from "@/components/shared/HeroTitle";
import Layout from "@/components/shared/Layout";
import { PricingTable } from "../components/shared/PricingTable";
import { PricingCalculator } from "../components/shared/PricingCalculator";
import { GetStartedWithPricing } from "@/components/shared/PricingGetStarted";
import { OpenSourceInfo } from "@/components/shared/OpenSourceInfo";
import { GetStartedWithPricing } from "@/components/shared/PricingGetStarted";
import { PricingCalculator } from "../components/shared/PricingCalculator";
import { PricingTable } from "../components/shared/PricingTable";
const inProductSurveys = {
leadRow: {
@@ -110,36 +110,33 @@ const PricingPage = () => {
headingTeal="Pricing"
subheading="Choose what's best for you! All our plans start free."
/>
<div className="space-y-24">
<div>
<GetStartedWithPricing showDetailed={true} />
<GetStartedWithPricing showDetailed={true} />
<PricingTable
leadRow={inProductSurveys.leadRow}
pricing={inProductSurveys.features}
endRow={inProductSurveys.endRow}
/>
</div>
<PricingTable
leadRow={inProductSurveys.leadRow}
pricing={inProductSurveys.features}
endRow={inProductSurveys.endRow}
/>
<div className="my-12 md:my-20"></div>
<PricingTable
leadRow={linkSurveys.leadRow}
pricing={linkSurveys.features}
endRow={linkSurveys.endRow}
/>
<PricingTable
leadRow={linkSurveys.leadRow}
pricing={linkSurveys.features}
endRow={linkSurveys.endRow}
/>
<div className="my-12 md:my-20"></div>
<PricingTable
leadRow={integrations.leadRow}
pricing={integrations.features}
endRow={integrations.endRow}
/>
<div className="my-4"></div>
<GetStartedWithPricing showDetailed={false} />
<PricingCalculator />
<OpenSourceInfo />
<PricingTable
leadRow={integrations.leadRow}
pricing={integrations.features}
endRow={integrations.endRow}
/>
<div>
<PricingCalculator />
<OpenSourceInfo />
</div>
</div>
</Layout>
);
};