mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-29 18:00:26 -06:00
Merge branch 'main' of github.com:formbricks/formbricks into feature/new-docs
This commit is contained in:
@@ -4,7 +4,7 @@ import { HeroPattern } from "@/components/docs/HeroPattern";
|
||||
import { Button } from "@/components/docs/Button";
|
||||
|
||||
export const metadata = {
|
||||
title: "Formbricks – Experience Management for B2B SaaS",
|
||||
title: "Formbricks – Open Source Experience Management",
|
||||
description:
|
||||
"Natively embed qualitative user research into your B2B SaaS. Leverage Best Practices for user discovery to increase Product-Market Fit",
|
||||
};
|
||||
@@ -16,7 +16,7 @@ export const sections = [
|
||||
|
||||
<HeroPattern />
|
||||
|
||||
# Formbricks – Experience Management for B2B SaaS
|
||||
# Formbricks – Open Source Experience Management
|
||||
|
||||
Welcome to Formbricks, your go-to solution for in-product micro-surveys that will supercharge your product experience! 🚀 {{ className: 'lead' }}
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ import glob from "fast-glob";
|
||||
import { Providers } from "@/app/providers";
|
||||
import { Layout } from "@/components/docs/Layout";
|
||||
|
||||
import { type Metadata } from "next";
|
||||
import { type Section } from "@/components/docs/SectionProvider";
|
||||
import { type Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
template: "Formbricks – Experience Management for B2B SaaS",
|
||||
template: "Formbricks – Open Source Experience Management",
|
||||
default: "Formbricks Docs",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import SlideInBanner from "@/components/shared/SlideInBanner";
|
||||
import { useEffect } from "react";
|
||||
import Footer from "./Footer";
|
||||
import Header from "./Header";
|
||||
@@ -60,6 +61,7 @@ export default function LayoutMdx({ meta, children }: Props) {
|
||||
)}
|
||||
<Prose className="">{children}</Prose>
|
||||
</article>
|
||||
<SlideInBanner delay={5000} scrollPercentage={10} UTMSource="learnArticle" />
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function MetaInformation({
|
||||
section,
|
||||
tags,
|
||||
}: Props) {
|
||||
const pageTitle = `${title} | Open-Source Experience Management, Privacy-first`;
|
||||
const pageTitle = `${title}`;
|
||||
return (
|
||||
<Head>
|
||||
<title>{pageTitle}</title>
|
||||
@@ -27,7 +27,7 @@ export default function MetaInformation({
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content={`https://${process.env.VERCEL_URL}/social-image.png`} />
|
||||
<meta property="og:image:alt" content="Formbricks - Open Source Experience Management, Privacy-first" />
|
||||
<meta property="og:image:alt" content="Open Source Experience Management, Privacy-first" />
|
||||
<meta property="og:image:type" content="image/png" />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
|
||||
57
apps/formbricks-com/components/shared/SlideInBanner.tsx
Normal file
57
apps/formbricks-com/components/shared/SlideInBanner.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import LFGLuigi from "@/images/blog/lfg-luigi-200px.webp";
|
||||
import { Button } from "@formbricks/ui";
|
||||
import Image from "next/image";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
interface Props {
|
||||
delay?: number; // in milliseconds, optional
|
||||
scrollPercentage?: number; // optional
|
||||
UTMSource: string; // required
|
||||
}
|
||||
|
||||
const SlideInBanner: React.FC<Props> = ({ delay = 5000, scrollPercentage = 10, UTMSource }) => {
|
||||
const [showBanner, setShowBanner] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setShowBanner(true);
|
||||
}, delay);
|
||||
|
||||
const handleScroll = () => {
|
||||
let currentScrollPercentage =
|
||||
(window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100;
|
||||
if (currentScrollPercentage > scrollPercentage) {
|
||||
setShowBanner(true);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
};
|
||||
}, [delay, scrollPercentage]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`sticky bottom-4 grid grid-cols-7 rounded-lg bg-slate-700 bg-opacity-70 p-4 text-white backdrop-blur-sm transition-all duration-500 ease-out ${
|
||||
showBanner ? "visible translate-y-0 opacity-100" : "invisible translate-y-full opacity-0"
|
||||
}`}>
|
||||
<div className="relative col-span-1 hidden lg:block">
|
||||
<Image src={LFGLuigi} height={150} className="absolute -bottom-16 left-8" alt="LFG Luigi" />
|
||||
</div>
|
||||
<div className="col-span-7 flex items-center space-x-3 lg:col-span-6">
|
||||
<p>
|
||||
Did you know? Formbricks is the only open source Experience Management solution: free &
|
||||
privacy-first!
|
||||
</p>
|
||||
<Button size="sm" href={`https://formbricks.com?utm_source=${UTMSource}`}>
|
||||
Learn more
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SlideInBanner;
|
||||
BIN
apps/formbricks-com/images/blog/lfg-luigi-200px.webp
Normal file
BIN
apps/formbricks-com/images/blog/lfg-luigi-200px.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -1,14 +1,13 @@
|
||||
import HeroTitle from "@/components/shared/HeroTitle";
|
||||
import Layout from "@/components/shared/Layout";
|
||||
import Cal, { getCalApi } from "@calcom/embed-react";
|
||||
import { useEffect } from "react";
|
||||
import { CheckBadgeIcon } from "@heroicons/react/24/solid";
|
||||
import { Button } from "@formbricks/ui";
|
||||
import { useEffect } from "react";
|
||||
|
||||
const XMOffer = [
|
||||
{
|
||||
step: "1",
|
||||
header: "Kick-off call (FREE)",
|
||||
header: "Kick-off call",
|
||||
description: "Share with our seasoned PMs which areas of customer experience need improvement.",
|
||||
},
|
||||
{
|
||||
@@ -48,10 +47,10 @@ const ConciergePage = () => {
|
||||
|
||||
return (
|
||||
<Layout
|
||||
title="Community | Formbricks Open Source Forms & Surveys"
|
||||
description="You're building open source forms and surveys? So are we! Get support for anything your building - or just say hi!">
|
||||
title="Concierge | Formbricks Open Source Experience Management"
|
||||
description="We help you get started! Get the worry-free setup with our guidance.">
|
||||
<HeroTitle
|
||||
headingPt1="XM"
|
||||
headingPt1=""
|
||||
headingTeal="Concierge"
|
||||
headingPt2="Service"
|
||||
subheading="Let's set up your system for continuous user discovery together."
|
||||
@@ -69,10 +68,10 @@ const ConciergePage = () => {
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="border-b border-t border-slate-300 p-6 text-4xl font-semibold text-slate-800">
|
||||
{/* <div className="border-b border-t border-slate-300 p-6 text-4xl font-semibold text-slate-800">
|
||||
<p className="mr-2 font-light">$1.290</p>
|
||||
</div>
|
||||
<div className="p-6 text-sm text-slate-800">
|
||||
{ <div className="border-t border-slate-300 p-6 text-sm text-slate-800">
|
||||
<p>
|
||||
<CheckBadgeIcon className="mr-1 inline h-5 w-5 text-slate-800" />
|
||||
100% Risk-free: Pay after the kick-off call, if you liked it.
|
||||
@@ -81,14 +80,14 @@ const ConciergePage = () => {
|
||||
<CheckBadgeIcon className="mr-1 inline h-5 w-5 text-slate-800" />
|
||||
Money-back: If you're not happy, get a full refund.
|
||||
</p>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="px-6">
|
||||
<Button
|
||||
variant="darkCTA"
|
||||
className="w-full justify-center"
|
||||
href="https://cal.com/johannes/kick-off"
|
||||
target="_blank">
|
||||
Book free Kick-Off call
|
||||
Schedule free Kick-Off call
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import LayoutMdx from "@/components/shared/LayoutMdx";
|
||||
import { FAQPageJsonLd } from "next-seo";
|
||||
import Head from "next/head";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import fetch from "node-fetch";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
|
||||
@@ -89,8 +91,12 @@ export async function getStaticProps({ params }) {
|
||||
}
|
||||
|
||||
export default function ArticlePage({ article = {} }: ArticlePageProps) {
|
||||
const router = useRouter();
|
||||
if (!article || !article.attributes) return <div>Loading...</div>;
|
||||
|
||||
// Generate canonical URL
|
||||
const canonicalURL = `https://formbricks.com${router.asPath}`;
|
||||
|
||||
// Use next/image to render images in markdown
|
||||
const renderers = {
|
||||
img: (image) => {
|
||||
@@ -134,6 +140,9 @@ export default function ArticlePage({ article = {} }: ArticlePageProps) {
|
||||
<LayoutMdx meta={meta}>
|
||||
<>
|
||||
<ReactMarkdown components={renderers}>{text as any}</ReactMarkdown>
|
||||
<Head>
|
||||
<link rel="canonical" href={canonicalURL} />
|
||||
</Head>
|
||||
<FAQPageJsonLd mainEntity={faqEntities} />
|
||||
</>
|
||||
</LayoutMdx>
|
||||
|
||||
@@ -116,7 +116,7 @@ Let’s go through it in detail:
|
||||
| Multiple Choice / Radio | ✅ | ✅ |
|
||||
| Checkbox | ✅ | ✅ |
|
||||
| Dropdown / Select | ✅ | ✅ |
|
||||
| File Upload | ✅ | ✅ |
|
||||
| File Upload | ✅ | ⚙️ |
|
||||
| Linear Scale | ✅ | ⚙️ |
|
||||
| Multiple Choice Grid | ✅ | ⚙️ |
|
||||
| Checkbox Grid | ✅ | ⚙️ |
|
||||
|
||||
Reference in New Issue
Block a user