docs(nx-dev): add click tracking on pricing plans (#28902)

This commit is contained in:
Benjamin Cabanes 2024-11-12 10:33:15 -05:00 committed by GitHub
parent 06af0ee53b
commit f3d5787f97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 188 additions and 62 deletions

View File

@ -1,5 +1,11 @@
import type { Metadata } from 'next';
import { Faq, Oss, ResourceClasses, PlansDisplay } from '@nx/nx-dev/ui-pricing';
import {
Faq,
Oss,
ResourceClasses,
PlansDisplay,
TrialCallout,
} from '@nx/nx-dev/ui-pricing';
import {
CallToAction,
DefaultLayout,
@ -30,13 +36,16 @@ export const metadata: Metadata = {
},
};
export default function PricingPageV2() {
export default function PricingPage() {
return (
<DefaultLayout>
<PlansDisplay />
<div className="mt-18 lg:mt-32">
<TrustedBy utmSource="pricingpage" utmCampaign="pricing" />
</div>
<div className="mt-32 lg:mt-56">
<TrialCallout pageId="pricing" />
</div>
<div className="mt-32 lg:mt-56">
<ResourceClasses />
</div>

View File

@ -12,6 +12,7 @@ import {
TrustedBy,
SolveYourCi,
} from '@nx/nx-dev/ui-enterprise';
import { TrialCallout } from '@nx/nx-dev/ui-pricing';
export function Enterprise(): JSX.Element {
const router = useRouter();
@ -46,6 +47,9 @@ export function Enterprise(): JSX.Element {
<div className="mt-32 lg:mt-40">
<MetricsAndCustomers />
</div>
<div className="mt-32 lg:mt-40">
<TrialCallout pageId="enterprise" />
</div>
<div className="mt-32 lg:mt-56">
<ScaleYourPeople />
</div>

View File

@ -86,7 +86,10 @@ export function AgentNumberOverTime(): JSX.Element {
};
return (
<section id="agent-number-over-time" className="overflow-hidden">
<section
id="agent-number-over-time"
className="scroll-mt-24 overflow-hidden"
>
<div className="mx-auto max-w-7xl md:px-6 lg:px-8">
<div className="mx-auto max-w-2xl text-center">
<SectionHeading

View File

@ -48,7 +48,7 @@ export function AutomatedAgentsManagement(): JSX.Element {
};
return (
<section id="competitive-compute" className="overflow-hidden">
<section id="competitive-compute" className="scroll-mt-24 overflow-hidden">
<div className="mx-auto max-w-7xl md:px-6 lg:px-8">
<div className="grid grid-cols-1 gap-x-8 gap-y-16 sm:gap-y-20 lg:grid-cols-2 lg:items-start">
<div className="px-6 md:px-0 lg:pr-4 lg:pt-4">

View File

@ -6,6 +6,7 @@ import {
} from '@heroicons/react/24/outline';
import { SectionHeading } from '@nx/nx-dev/ui-common';
import Link from 'next/link';
import { ReactElement } from 'react';
const features = [
{
@ -41,9 +42,9 @@ const features = [
},
];
export function EnhancedWithAi(): JSX.Element {
export function EnhancedWithAi(): ReactElement {
return (
<section id="ai-for-your-ci">
<section id="ai-for-your-ci" className="scroll-mt-24">
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-3xl text-center">
<SectionHeading as="h2" variant="title" id="deep-understanding">

View File

@ -1,9 +1,10 @@
'use client';
import { Variants, motion } from 'framer-motion';
import { motion, Variants } from 'framer-motion';
import { Spotlight } from './elements/spotlight';
import { AnimateValue } from '@nx/nx-dev/ui-animations';
import { ReactElement } from 'react';
export function FasterAndCheaper(): JSX.Element {
export function FasterAndCheaper(): ReactElement {
const spotlight: Variants = {
offscreen: {
display: 'none',
@ -14,7 +15,7 @@ export function FasterAndCheaper(): JSX.Element {
};
return (
<section>
<section id="faster-and-cheaper" className="scroll-mt-24">
<motion.div
initial="offscreen"
whileInView="onscreen"

View File

@ -1,6 +1,6 @@
'use client';
import { motion } from 'framer-motion';
import { useEffect, useState } from 'react';
import { ReactElement, useEffect, useState } from 'react';
import { SectionHeading } from '@nx/nx-dev/ui-common';
import { usePrefersReducedMotion } from '@nx/nx-dev/ui-animations';
@ -71,7 +71,7 @@ const stats = [
{ id: 4, name: 'Runs daily', value: 100, suffix: 'k+' },
];
export function Statistics(): JSX.Element {
export function Statistics(): ReactElement {
const shouldReduceMotion = usePrefersReducedMotion();
const variants = {

View File

@ -8,9 +8,11 @@ import {
StorybookIcon,
VmwareIcon,
} from '@nx/nx-dev/ui-icons';
export function TrustedBy(): JSX.Element {
import { ReactElement } from 'react';
export function TrustedBy(): ReactElement {
return (
<section className="">
<section id="trust" className="scroll-mt-24">
<div className="mx-auto max-w-7xl px-4 pb-12 sm:px-6 lg:px-8 lg:pb-16">
<h2 className="text-center text-lg font-medium leading-8 text-slate-400">
Startups and Fortune 500 companies trust Nx Cloud

View File

@ -13,15 +13,15 @@ import { SectionHeading } from '@nx/nx-dev/ui-common';
import { BentoGrid, BentoGridItem } from './elements/bento-grid';
import { cx } from '@nx/nx-dev/ui-primitives';
import { animate, motion, useMotionValue, useTransform } from 'framer-motion';
import { useEffect } from 'react';
import { ReactElement, useEffect } from 'react';
import { usePrefersReducedMotion } from '@nx/nx-dev/ui-animations';
export function UnderstandWorkspace(): JSX.Element {
export function UnderstandWorkspace(): ReactElement {
return (
<section>
<section id="deep-understanding" className="scroll-mt-24">
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-2xl text-center">
<SectionHeading as="h2" variant="title" id="deep-understanding">
<SectionHeading as="h2" variant="title">
Deep understanding of your workspace
</SectionHeading>
<SectionHeading as="p" variant="subtitle" className="mt-6">

View File

@ -4,6 +4,7 @@ import { ChevronDownIcon } from '@heroicons/react/24/outline';
import { SectionHeading } from '@nx/nx-dev/ui-common';
import { cx } from '@nx/nx-dev/ui-primitives';
import { FAQPageJsonLd } from 'next-seo';
import Link from 'next/link';
import { ReactElement } from 'react';
export function Faq(): ReactElement {
@ -89,11 +90,11 @@ export function Faq(): ReactElement {
{
question: 'What if I need help picking the right plan?',
answer:
'We have a helpful comparison above. If you have additional questions, or these plans dont fit your needs please reach out to cloud-support@nrwl.io and we will do our best to help.',
'We have a helpful comparison above. If you have additional questions, or these plans dont fit your needs please reach out to https://nx.dev/contact/sales and we will do our best to help.',
},
{
question: 'What if I need more than 70 active contributors?',
answer: 'Please reach out to cloud-support@nrwl.io.',
answer: 'Please reach out to https://nx.dev/contact/sales',
},
{
question: 'What payment methods do you accept?',
@ -108,22 +109,20 @@ export function Faq(): ReactElement {
<div className="lg:grid lg:grid-cols-3 lg:gap-8">
<header>
<SectionHeading as="h2" variant="title">
Not sure yet? <br /> Have questions?
Have questions?
</SectionHeading>
<SectionHeading as="p" variant="subtitle" className="mt-6">
Here are the most asked question we condensed for your to get you
setup quickly.
Check out our most commonly asked questions.
</SectionHeading>
<p className="text-md mt-4 text-slate-400 dark:text-slate-600">
Cant find the answer youre looking for? Reach out to our{' '}
<a
href="mailto:cloud-support@nrwl.io"
className="font-medium underline"
<Link
href="/contact"
title="Reach out to the team"
className="font-semibold"
>
customer support
</a>{' '}
team.
Cant find the answer youre looking for?
</Link>
</p>
</header>
<FAQPageJsonLd

View File

@ -1,13 +1,14 @@
'use client';
import { ReactElement } from 'react';
import { PlusIcon } from '@heroicons/react/24/outline';
import { CheckCircleIcon } from '@heroicons/react/24/solid';
import { ButtonLink, SectionHeading } from '@nx/nx-dev/ui-common';
import { TrialCallout } from './trial-callout';
import Link from 'next/link';
import { sendCustomEvent } from '@nx/nx-dev/feature-analytics';
export function PlansDisplay(): ReactElement {
return (
<section>
<section id="plans" className="scroll-mt-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<header className="mx-auto max-w-4xl text-center">
<SectionHeading as="h2" variant="display">
@ -19,7 +20,7 @@ export function PlansDisplay(): ReactElement {
</SectionHeading>
</header>
<div className="mt-20 flow-root">
<div className="isolate -mt-16 grid max-w-full grid-cols-1 gap-6 sm:mx-auto lg:mt-0 lg:grid-cols-3 xl:-mx-4 xl:gap-12">
<div className="isolate -mt-16 grid max-w-full grid-cols-1 gap-6 sm:mx-auto lg:mt-0 lg:grid-cols-3 xl:-mx-4 xl:gap-8">
{/*HOBBY*/}
<div>
<div className="rounded-lg border-2 border-blue-500 bg-white p-6 dark:border-sky-500 dark:bg-slate-950">
@ -47,6 +48,13 @@ export function PlansDisplay(): ReactElement {
title="Start now"
size="default"
variant="primary"
onClick={() =>
sendCustomEvent(
'start-hobby-plan-click',
'plans-table',
'pricing-plans'
)
}
className="w-full"
>
Get started
@ -74,6 +82,13 @@ export function PlansDisplay(): ReactElement {
href="/ci/features/remote-cache"
target="_blank"
title="Learn how Nx Replay easily reduces CI execution time"
onClick={() =>
sendCustomEvent(
'learn-nx-replay-click',
'plans-table',
'pricing-plans'
)
}
className="font-medium underline decoration-dotted"
>
Nx Replay
@ -91,6 +106,13 @@ export function PlansDisplay(): ReactElement {
href="/ci/features/distribute-task-execution"
target="_blank"
title="Learn how Nx Agents easily scale your CI pipelines"
onClick={() =>
sendCustomEvent(
'learn-nx-agents-click',
'plans-table',
'pricing-plans'
)
}
className="font-medium underline decoration-dotted"
>
Nx Agents
@ -109,14 +131,16 @@ export function PlansDisplay(): ReactElement {
</h4>
</div>
<p className="mt-2 text-sm">
Scales with your team's needs. Billed on the first of each
month.
Start free, pay as you grow. Billed on the first of each month.
</p>
<p className="mt-4 leading-5">
<span className="text-3xl font-semibold text-slate-950 dark:text-white">
$19
</span>
<span className="text-lg"> per Active Contributor¹</span>
<span className="text-lg"> per Active Contributor¹</span>{' '}
<span className="text-sm font-semibold italic">
(first 5 free)
</span>
<br />
<span className="text-sm">+ usage overages</span>
</p>
@ -128,6 +152,13 @@ export function PlansDisplay(): ReactElement {
title="Get started"
size="default"
variant="secondary"
onClick={() =>
sendCustomEvent(
'start-team-plan-click',
'plans-table',
'pricing-plans'
)
}
className="w-full"
>
Get started
@ -167,6 +198,13 @@ export function PlansDisplay(): ReactElement {
href="/nx-cloud#ai-for-your-ci"
target="_blank"
title="Check our AI integrations and how to use them"
onClick={() =>
sendCustomEvent(
'learn-ai-integrations-click',
'plans-table',
'pricing-plans'
)
}
className="font-medium underline decoration-dotted"
>
AI integrations
@ -218,8 +256,8 @@ export function PlansDisplay(): ReactElement {
</h4>
</div>
<p className="mt-2 text-sm">
The ultimate Nx toolchain, tailored to your needs of speed.
Flexible billing & payment options available.
The ultimate Nx toolchain, tailored for speed. Flexible billing
& payment options available.
</p>
<p className="mt-4 pb-5 leading-5">
<span className="text-3xl font-semibold text-slate-950 dark:text-white">
@ -233,6 +271,13 @@ export function PlansDisplay(): ReactElement {
title="Enterprise"
size="default"
variant="secondary"
onClick={() =>
sendCustomEvent(
'learn-enterprise-click',
'plans-table',
'pricing-plans'
)
}
className="w-full"
>
Learn more
@ -266,6 +311,13 @@ export function PlansDisplay(): ReactElement {
href="/powerpack"
target="_blank"
title="Check our AI integrations and how to use them"
onClick={() =>
sendCustomEvent(
'learn-nx-powerpack-click',
'plans-table',
'pricing-plans'
)
}
className="font-medium underline decoration-dotted"
>
Nx Powerpack
@ -317,10 +369,6 @@ export function PlansDisplay(): ReactElement {
</p>
</div>
</div>
<div className="mt-20">
<TrialCallout />
</div>
</div>
</section>
);

View File

@ -17,7 +17,7 @@ const linuxAmd64 = [
},
{
icon: <LinuxIcon aria-hidden="true" className="size-6" />,
name: 'Medium plus',
name: 'Medium +',
description: '3 vCPU, 6GB RAM',
creditCost: 15,
},

View File

@ -1,37 +1,96 @@
import { ButtonLink } from '@nx/nx-dev/ui-common';
'use client';
import { ReactElement } from 'react';
import Image from 'next/image';
import { ButtonLink } from '@nx/nx-dev/ui-common';
import Link from 'next/link';
import { sendCustomEvent } from '@nx/nx-dev/feature-analytics';
export function TrialCallout(): ReactElement {
export function TrialCallout({
pageId,
}: {
pageId: 'enterprise' | 'pricing';
}): ReactElement {
return (
<section id="trial" className="isolate mx-auto max-w-xl">
<div className="border border-slate-100 bg-white shadow-lg sm:rounded-lg dark:border-slate-800/60 dark:bg-slate-950">
<div className="px-4 py-5 sm:p-6">
<h3 className="text-base font-semibold leading-6 text-slate-900 dark:text-slate-100">
Looking for a trial?
</h3>
<div className="mt-2 sm:flex sm:items-start sm:justify-between">
<div className="max-w-xl text-sm">
<p>
<section id="start-trial" className="scroll-mt-24">
<div className="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div className="relative isolate overflow-hidden bg-white px-6 pt-16 shadow-2xl ring-1 ring-slate-200 sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0 dark:bg-slate-900 dark:ring-slate-800">
<svg
viewBox="0 0 1024 1024"
aria-hidden="true"
className="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-y-1/2 [mask-image:radial-gradient(closest-side,white,transparent)] sm:left-full sm:-ml-80 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2 lg:translate-y-0"
>
<circle
r={512}
cx={512}
cy={512}
fill="url(#1e3c1415-dh10-454c-aa3c-9a8019d0ap09d)"
fillOpacity="0.7"
/>
<defs>
<radialGradient id="1e3c1415-dh10-454c-aa3c-9a8019d0ap09d">
<stop stopColor="#9333ea" />
<stop offset={1} stopColor="#3b82f6" />
</radialGradient>
</defs>
</svg>
<div className="mx-auto max-w-md text-center lg:mx-0 lg:flex-auto lg:py-32 lg:text-left">
<h2 className="texxt-slate-950 text-balance text-3xl font-semibold tracking-tight sm:text-4xl dark:text-white">
Start a Trial
</h2>
<p className="mt-6 text-pretty text-lg/8">
Start with our Hobby Plan - free forever for teams of any size.
Perfect for proof of concept testing with up to 50,000 credits
per month.
Perfect for proof of concept testing with up to 50,000 credits per
month.
</p>
</div>
<div className="mt-5 sm:ml-6 sm:mt-0 sm:flex sm:flex-shrink-0 sm:items-center">
<div className="mt-4 flex items-center justify-center gap-x-6 lg:justify-start">
<ButtonLink
href="https://cloud.nx.app"
title="Start with Hobby"
variant="primary"
target="_blank"
size="default"
title="Start free trial"
onClick={() =>
sendCustomEvent(
'start-trial-click',
'trial-callout-' + pageId,
'trial-callout'
)
}
>
Start for free
</ButtonLink>
</div>
<p className="mt-8 text-pretty text-base/8 leading-normal">
Need a bit more? For larger teams we offer personalized support,{' '}
<Link
href="/contact-us/sales"
title="Reach out to us"
onClick={() =>
sendCustomEvent(
'contact-click',
'trial-callout-' + pageId,
'trial-callout'
)
}
className="font-semibold text-blue-500 dark:text-sky-500"
>
reach out to us and we'll help you get started with a trial
</Link>{' '}
that suites your team's needs.{' '}
</p>
</div>
<div className="relative mt-16 h-80 lg:mt-8">
<Image
src="/images/cloud/nrwl-ocean.avif"
alt="App screenshot: overview"
width={2550}
height={1622}
loading="eager"
priority
className="absolute left-0 top-0 w-[57rem] max-w-none rounded-md bg-white/5 ring-1 ring-slate-950/10"
/>
</div>
</div>
</div>
{/*</motion.div>*/}
</section>
);
}