From d7a72a293c19d78a654b3db72d2f4117dcdd0472 Mon Sep 17 00:00:00 2001 From: Donnie Flood Date: Fri, 16 Oct 2026 12:04:10 -0600 Subject: [PATCH] fix: align signup messaging with monthly free PR pricing --- README.md | 6 ++++-- src/report/web/App.browser.test.tsx | 22 +++++++++++++--------- src/report/web/acts/AutomatedStory.tsx | 9 +++------ src/report/web/acts/CallToAction.tsx | 8 ++++---- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 741d492..8311e73 100644 --- a/README.md +++ b/README.md @@ -70,9 +70,11 @@ The report covers: ## What is PatchWave? -PatchWave is a GitHub app that automatically analyzes, fixes and merges your Dependabot PRs. It's free for 30 days, up to 100 PRs, no credit card. +PatchWave is a GitHub app that automatically analyzes, fixes and merges your Dependabot PRs. Everyone gets 25 free PRs every month. No credit card required. -- [Join the public beta](https://app.patchwave.ai/join?utm_source=patchwave-analysis&utm_medium=readme) +Paid plans start at $10 a month for 35 PRs total, including your 25 free PRs. All plans include analysis, fixing, and unlimited repositories and users. Only unused paid PRs roll over for one month. See [pricing](https://patchwave.ai/pricing) for larger allowances and volume discounts. + +- [Sign up for free](https://app.patchwave.ai/join?utm_source=patchwave-analysis&utm_medium=readme) - [Learn more at patchwave.ai](https://patchwave.ai/?utm_source=patchwave-analysis&utm_medium=readme) ## What it reads from GitHub diff --git a/src/report/web/App.browser.test.tsx b/src/report/web/App.browser.test.tsx index 862ce10..5a06bfe 100644 --- a/src/report/web/App.browser.test.tsx +++ b/src/report/web/App.browser.test.tsx @@ -11,7 +11,7 @@ import { personActivity, prBacklog, } from '../testFactories.ts'; -import { automatedStoryCopy, automatedStorySectionId, automatedStoryTestIds } from './acts/AutomatedStory.tsx'; +import { automatedStorySectionId, automatedStoryTestIds } from './acts/AutomatedStory.tsx'; import { callToActionCopy, callToActionTestIds } from './acts/CallToAction.tsx'; import { costStoryCopy, costStoryTestIds } from './acts/CostStory.tsx'; import { methodologyAppendixTestIds } from './acts/MethodologyAppendix.tsx'; @@ -552,24 +552,28 @@ describe('sections and calls to action', () => { expect(cta).toHaveAttribute('href', href); }); - it('labels the automation CTA with the savings shown above it', () => { + it('offers free signup with monthly PR terms in both signup sections', () => { renderReport(); - const savings = screen.getByTestId(automatedStoryTestIds.patchwaveCost).textContent ?? ''; - const cta = screen.getByTestId(automatedStoryTestIds.primaryCta); - expect(cta).toHaveTextContent(automatedStoryCopy.ctaLabel(savings)); - expect(cta).toHaveAttribute('href', reportCtaUrls.automation); + expect(screen.getByTestId(automatedStoryTestIds.primaryCta)).toHaveTextContent('Sign up for free'); + expect(screen.getByTestId(automatedStoryTestIds.primaryCta)).toHaveAttribute('href', reportCtaUrls.automation); + expect(screen.getByTestId(automatedStoryTestIds.section)).toHaveTextContent( + '25 free PRs every month. No credit card required.', + ); + expect(screen.getByTestId(callToActionTestIds.cta)).toHaveTextContent('Sign up for free'); + expect(screen.getByTestId(callToActionTestIds.section)).toHaveTextContent('25 free PRs every month.'); + expect(screen.getByTestId(callToActionTestIds.section)).toHaveTextContent('No credit card required.'); }); - it('drops the savings from the automation CTA when there is nothing to save', () => { + it('offers free signup even when there is nothing to save', () => { renderReport({ costEstimate: costEstimate.build({ humanMergeCount: 0, humanReviewCount: 0 }), }); - expect(screen.getByTestId(automatedStoryTestIds.primaryCta)).toHaveTextContent(automatedStoryCopy.ctaFallbackLabel); + expect(screen.getByTestId(automatedStoryTestIds.primaryCta)).toHaveTextContent('Sign up for free'); }); - it('sends trial CTAs to sign-up and the header to the homepage, tagged with UTM parameters', () => { + it('sends signup CTAs to sign-up and the header to the homepage, tagged with UTM parameters', () => { expect(reportCtaUrls.automation).toBe( 'https://app.patchwave.ai/join?utm_source=patchwave-analysis&utm_medium=report&utm_content=automation', ); diff --git a/src/report/web/acts/AutomatedStory.tsx b/src/report/web/acts/AutomatedStory.tsx index 325e5e7..d6e3000 100644 --- a/src/report/web/acts/AutomatedStory.tsx +++ b/src/report/web/acts/AutomatedStory.tsx @@ -23,9 +23,8 @@ export const automatedStoryTestIds = { export const automatedStorySectionId = 'patchwave'; export const automatedStoryCopy = { - ctaLabel: (savings: string) => `Start saving ${savings}`, - ctaFallbackLabel: 'Join the public beta', - ctaNote: 'Free for 30 days. No credit card.', + ctaLabel: 'Sign up for free', + ctaNote: '25 free PRs every month. No credit card required.', } as const; const SHARE_MIN = 50; @@ -114,9 +113,7 @@ export function AutomatedStory() {

{automatedStoryCopy.ctaNote}

diff --git a/src/report/web/acts/CallToAction.tsx b/src/report/web/acts/CallToAction.tsx index 2cce4a8..8b54e3e 100644 --- a/src/report/web/acts/CallToAction.tsx +++ b/src/report/web/acts/CallToAction.tsx @@ -12,9 +12,9 @@ export const callToActionTestIds = { export const callToActionCopy = { heading: 'Wave goodbye to (most) dependency update work.', pitch: 'PatchWave is a GitHub app that automatically analyzes, fixes and merges your Dependabot PRs.', - trialTerms: 'Free for 30 days, up to 100 PRs.', - ctaLabel: 'Join the public beta', - ctaNote: 'No credit card. The 30 days start when you install the GitHub App.', + freeTerms: '25 free PRs every month.', + ctaLabel: 'Sign up for free', + ctaNote: 'No credit card required.', howItWorksLabel: 'See how it works', } as const; @@ -36,7 +36,7 @@ export function CallToAction() {

{callToActionCopy.pitch}

- {callToActionCopy.trialTerms} + {callToActionCopy.freeTerms}