Skip to content

Commit 533e083

Browse files
committed
feat(webapp): hipaa add-on row and credits copy on plan-selection tiers
1 parent d637fed commit 533e083

2 files changed

Lines changed: 146 additions & 77 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: feature
4+
---
5+
6+
Add a HIPAA BAA add-on row to the Hobby, Pro, and Enterprise tiers on the in-app pricing/plan-selection cards. Each row opens the existing Feedback dialog pre-filled with a new `hipaa` feedback type. Restructure `feedbackTypes` to match the marketing contact form (label / labelTypeId / threadTitle), so every supported inquiry type tags its Plain thread with the same label ID used by the marketing form and uses a consistent "Contact form: …" thread title. Also reformat the included-compute line on each tier ("$X / month free credits" / "$X / month credits included") and move it from the `TierLimit` block into a `FeatureItem` with a `DefinitionTip`, matching the marketing pricing page.

apps/webapp/app/routes/resources.orgs.$organizationSlug.select-plan.tsx

Lines changed: 140 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {
2-
ArrowUpRightIcon,
32
CheckIcon,
43
ExclamationTriangleIcon,
54
ShieldCheckIcon,
@@ -37,6 +36,7 @@ import { Header2 } from "~/components/primitives/Headers";
3736
import { Paragraph } from "~/components/primitives/Paragraph";
3837
import { Spinner } from "~/components/primitives/Spinner";
3938
import { TextArea } from "~/components/primitives/TextArea";
39+
import { TextLink } from "~/components/primitives/TextLink";
4040
import { SimpleTooltip } from "~/components/primitives/Tooltip";
4141
import { prisma } from "~/db.server";
4242
import { redirectWithErrorMessage } from "~/models/message.server";
@@ -237,6 +237,11 @@ const pricingDefinitions = {
237237
title: "Query period",
238238
content: "The maximum number of days a query can look back when analyzing your task data.",
239239
},
240+
hipaaBaa: {
241+
title: "HIPAA BAA",
242+
content:
243+
"A signed Business Associate Agreement (BAA) is required to run tasks that process Protected Health Information (PHI) on Trigger.dev Cloud.",
244+
},
240245
};
241246

242247
type PricingPlansProps = {
@@ -317,10 +322,7 @@ export function TierFree({
317322
<TierContainer>
318323
<div className="relative">
319324
<PricingHeader title={plan.title} cost={0} />
320-
<TierLimit href="https://trigger.dev/pricing#computePricing">
321-
${plan.limits.includedUsage / 100} free monthly usage
322-
</TierLimit>
323-
{showGithubVerificationBadge && status === "approved" && (
325+
{showGithubVerificationBadge && status === "approved" && (
324326
<SimpleTooltip
325327
buttonClassName="absolute right-1 top-1"
326328
button={
@@ -351,8 +353,7 @@ export function TierFree({
351353
</div>
352354
{status === "rejected" ? (
353355
<div>
354-
<hr className="my-6 border-grid-bright" />
355-
<div className="flex flex-col gap-2 rounded-sm border border-warning p-4">
356+
<div className="flex flex-col gap-2 rounded-sm border border-warning p-4">
356357
<ExclamationTriangleIcon className="size-6 text-warning" />
357358
<Paragraph variant="small/bright">
358359
Your Trigger.dev account failed to be verified for the Free plan because your GitHub
@@ -533,6 +534,16 @@ export function TierFree({
533534
</Form>
534535
)}
535536
<ul className="flex flex-col gap-2.5">
537+
<FeatureItem checked>
538+
<DefinitionTip
539+
title="Free credits"
540+
content={`You get $${
541+
plan.limits.includedUsage / 100
542+
} of compute each month for free. Requires a verified GitHub account.`}
543+
>
544+
${plan.limits.includedUsage / 100} / month free credits
545+
</DefinitionTip>
546+
</FeatureItem>
536547
<ConcurrentRuns limits={plan.limits} />
537548
<FeatureItem checked>
538549
Unlimited{" "}
@@ -584,9 +595,6 @@ export function TierHobby({
584595
return (
585596
<TierContainer isHighlighted={isHighlighted}>
586597
<PricingHeader title={plan.title} isHighlighted={isHighlighted} cost={plan.tierPrice} />
587-
<TierLimit href="https://trigger.dev/pricing#computePricing">
588-
${plan.limits.includedUsage / 100} usage included
589-
</TierLimit>
590598
<Form action={formAction} method="post" id="subscribe-hobby" className="py-6">
591599
<input type="hidden" name="type" value="paid" />
592600
<input type="hidden" name="planCode" value={plan.code} />
@@ -652,6 +660,23 @@ export function TierHobby({
652660
)}
653661
</Form>
654662
<ul className="flex flex-col gap-2.5">
663+
<FeatureItem checked>
664+
<DefinitionTip
665+
title="Credits included"
666+
content={
667+
<>
668+
This plan includes ${plan.tierPrice} of compute each month. After that's used, tasks
669+
keep running and you're billed per our{" "}
670+
<TextLink to="https://trigger.dev/pricing#computePricing">
671+
compute usage rates
672+
</TextLink>
673+
.
674+
</>
675+
}
676+
>
677+
${plan.limits.includedUsage / 100} / month credits included
678+
</DefinitionTip>
679+
</FeatureItem>
655680
<ConcurrentRuns limits={plan.limits} />
656681
<FeatureItem checked>
657682
Unlimited{" "}
@@ -672,6 +697,16 @@ export function TierHobby({
672697
<SupportLevel limits={plan.limits} />
673698
<Alerts limits={plan.limits} />
674699
<RealtimeConcurrency limits={plan.limits} />
700+
<HIPAAAddOn>
701+
<Feedback
702+
defaultValue="hipaa"
703+
button={
704+
<span className="cursor-pointer underline decoration-charcoal-500 underline-offset-4 transition hover:decoration-text-bright">
705+
Request a BAA
706+
</span>
707+
}
708+
/>
709+
</HIPAAAddOn>
675710
</ul>
676711
</TierContainer>
677712
);
@@ -701,9 +736,6 @@ export function TierPro({
701736
return (
702737
<TierContainer>
703738
<PricingHeader title={plan.title} cost={plan.tierPrice} />
704-
<TierLimit href="https://trigger.dev/pricing#computePricing">
705-
${plan.limits.includedUsage / 100} usage included
706-
</TierLimit>
707739
<Form action={formAction} method="post" id="subscribe-pro">
708740
<div className="py-6">
709741
<input type="hidden" name="type" value="paid" />
@@ -773,6 +805,23 @@ export function TierPro({
773805
</div>
774806
</Form>
775807
<ul className="flex flex-col gap-2.5">
808+
<FeatureItem checked>
809+
<DefinitionTip
810+
title="Credits included"
811+
content={
812+
<>
813+
This plan includes ${plan.tierPrice} of compute each month. After that's used, tasks
814+
keep running and you're billed per our{" "}
815+
<TextLink to="https://trigger.dev/pricing#computePricing">
816+
compute usage rates
817+
</TextLink>
818+
.
819+
</>
820+
}
821+
>
822+
${plan.limits.includedUsage / 100} / month credits included
823+
</DefinitionTip>
824+
</FeatureItem>
776825
<ConcurrentRuns limits={plan.limits}>
777826
{`Then ${formatCurrency(concurrencyAddOnPricing.centsPerStep / 100, true)}/month per ${
778827
concurrencyAddOnPricing.stepSize
@@ -801,6 +850,16 @@ export function TierPro({
801850
<RealtimeConcurrency limits={plan.limits}>
802851
{pricingDefinitions.additionalRealtimeConnections.content}
803852
</RealtimeConcurrency>
853+
<HIPAAAddOn>
854+
<Feedback
855+
defaultValue="hipaa"
856+
button={
857+
<span className="cursor-pointer underline decoration-charcoal-500 underline-offset-4 transition hover:decoration-text-bright">
858+
Request a BAA
859+
</span>
860+
}
861+
/>
862+
</HIPAAAddOn>
804863
</ul>
805864
</TierContainer>
806865
);
@@ -809,41 +868,12 @@ export function TierPro({
809868
export function TierEnterprise() {
810869
return (
811870
<TierContainer>
812-
<div className="flex w-full flex-col items-center justify-between gap-4 lg:flex-row">
813-
<div className="flex w-full flex-wrap items-center justify-between gap-2 lg:flex-nowrap">
814-
<div className="-mt-1 mb-2 flex w-full flex-col gap-2 lg:mb-0 lg:gap-0.5">
815-
<h2 className="text-xl font-medium text-text-dimmed">Enterprise</h2>
816-
<hr className="my-2 block border-grid-dimmed lg:hidden" />
817-
<p className="whitespace-nowrap font-sans text-lg font-normal text-text-bright lg:text-sm">
818-
Tailor a custom plan
819-
</p>
820-
</div>
821-
<ul className="flex w-full flex-col gap-y-3 lg:gap-y-1">
822-
<FeatureItem checked checkedColor="bright">
823-
All Pro plan features +
824-
</FeatureItem>
825-
<FeatureItem checked checkedColor="bright">
826-
Custom log retention
827-
</FeatureItem>
828-
</ul>
829-
<ul className="flex w-full flex-col gap-y-3 lg:gap-y-1">
830-
<FeatureItem checked checkedColor="bright">
831-
Priority support
832-
</FeatureItem>
833-
<FeatureItem checked checkedColor="bright">
834-
Role-based access control
835-
</FeatureItem>
836-
</ul>
837-
<ul className="flex w-full flex-col gap-y-3 lg:gap-y-1">
838-
<FeatureItem checked checkedColor="bright">
839-
SOC 2 report
840-
</FeatureItem>
841-
<FeatureItem checked checkedColor="bright">
842-
SSO
843-
</FeatureItem>
844-
</ul>
871+
<div className="mb-4 flex w-full flex-col items-start justify-between gap-4 lg:flex-row lg:items-center">
872+
<div className="flex flex-col gap-0.5">
873+
<h2 className="text-xl font-medium text-text-dimmed">Enterprise</h2>
874+
<p className="font-sans text-lg font-normal text-text-bright">Tailor a custom plan</p>
845875
</div>
846-
<div className="w-full lg:max-w-[16rem]">
876+
<div className="w-full lg:w-auto lg:max-w-[16rem]">
847877
<Feedback
848878
defaultValue="enterprise"
849879
button={
@@ -854,6 +884,44 @@ export function TierEnterprise() {
854884
/>
855885
</div>
856886
</div>
887+
<div className="flex w-full flex-wrap items-start justify-between gap-2 lg:flex-nowrap">
888+
<ul className="flex w-full flex-col gap-y-3 lg:gap-y-1">
889+
<FeatureItem checked checkedColor="bright">
890+
All Pro plan features +
891+
</FeatureItem>
892+
<FeatureItem checked checkedColor="bright">
893+
Custom log retention
894+
</FeatureItem>
895+
</ul>
896+
<ul className="flex w-full flex-col gap-y-3 lg:gap-y-1">
897+
<FeatureItem checked checkedColor="bright">
898+
Priority support
899+
</FeatureItem>
900+
<FeatureItem checked checkedColor="bright">
901+
Role-based access control
902+
</FeatureItem>
903+
</ul>
904+
<ul className="flex w-full flex-col gap-y-3 lg:gap-y-1">
905+
<FeatureItem checked checkedColor="bright">
906+
SOC 2 report
907+
</FeatureItem>
908+
<FeatureItem checked checkedColor="bright">
909+
SSO
910+
</FeatureItem>
911+
</ul>
912+
<ul className="flex w-full flex-col gap-y-3 lg:gap-y-1">
913+
<HIPAAAddOn checkedColor="bright">
914+
<Feedback
915+
defaultValue="hipaa"
916+
button={
917+
<span className="cursor-pointer underline decoration-charcoal-500 underline-offset-4 transition hover:decoration-text-bright">
918+
Request a BAA
919+
</span>
920+
}
921+
/>
922+
</HIPAAAddOn>
923+
</ul>
924+
</div>
857925
</TierContainer>
858926
);
859927
}
@@ -921,36 +989,6 @@ function PricingHeader({
921989
);
922990
}
923991

924-
function TierLimit({ children, href }: { children: React.ReactNode; href?: string }) {
925-
return (
926-
<>
927-
<hr className="my-6 border-grid-bright" />
928-
{href ? (
929-
<SimpleTooltip
930-
buttonClassName="text-left w-fit"
931-
disableHoverableContent
932-
button={
933-
<a
934-
href={href}
935-
className="text-left font-sans text-lg font-normal text-text-bright underline decoration-charcoal-500 underline-offset-4 transition hover:decoration-text-bright"
936-
>
937-
{children}
938-
</a>
939-
}
940-
content={
941-
<div className="flex items-center gap-1">
942-
<Paragraph variant="small">View compute pricing information</Paragraph>
943-
<ArrowUpRightIcon className="size-4 text-text-dimmed" />
944-
</div>
945-
}
946-
/>
947-
) : (
948-
<div className="font-sans text-lg font-normal text-text-bright">{children}</div>
949-
)}
950-
</>
951-
);
952-
}
953-
954992
function FeatureItem({
955993
checked,
956994
checkedColor = "primary",
@@ -1206,6 +1244,31 @@ function QueryPeriod({ limits }: { limits: Limits }) {
12061244
);
12071245
}
12081246

1247+
function HIPAAAddOn({
1248+
children,
1249+
checkedColor = "primary",
1250+
}: {
1251+
children?: React.ReactNode;
1252+
checkedColor?: "primary" | "bright";
1253+
}) {
1254+
return (
1255+
<FeatureItem checked checkedColor={checkedColor}>
1256+
<div className="flex flex-col gap-y-0.5">
1257+
<div>
1258+
<DefinitionTip
1259+
title={pricingDefinitions.hipaaBaa.title}
1260+
content={pricingDefinitions.hipaaBaa.content}
1261+
>
1262+
HIPAA BAA
1263+
</DefinitionTip>{" "}
1264+
add-on
1265+
</div>
1266+
{children && <span className="text-xs text-text-dimmed">{children}</span>}
1267+
</div>
1268+
</FeatureItem>
1269+
);
1270+
}
1271+
12091272
function Branches({ limits, children }: { limits: Limits; children?: React.ReactNode }) {
12101273
return (
12111274
<FeatureItem checked={limits.branches.number > 0}>

0 commit comments

Comments
 (0)