11import {
2- ArrowUpRightIcon ,
32 CheckIcon ,
43 ExclamationTriangleIcon ,
54 ShieldCheckIcon ,
@@ -37,6 +36,7 @@ import { Header2 } from "~/components/primitives/Headers";
3736import { Paragraph } from "~/components/primitives/Paragraph" ;
3837import { Spinner } from "~/components/primitives/Spinner" ;
3938import { TextArea } from "~/components/primitives/TextArea" ;
39+ import { TextLink } from "~/components/primitives/TextLink" ;
4040import { SimpleTooltip } from "~/components/primitives/Tooltip" ;
4141import { prisma } from "~/db.server" ;
4242import { 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
242247type 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({
809868export 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-
954992function 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+
12091272function Branches ( { limits, children } : { limits : Limits ; children ?: React . ReactNode } ) {
12101273 return (
12111274 < FeatureItem checked = { limits . branches . number > 0 } >
0 commit comments