Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 3 additions & 30 deletions packages/frontend/src/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
cardTrialEligible,
parsePlanIntent,
readCardTrialPrompt,
saveAuthorizationReturn,
savePlanIntent,
parsePromoCode,
savePromoCode,
Expand Down Expand Up @@ -178,31 +177,6 @@
return true;
};

/**
* Cloud only: someone who signed up from "Connect" in an AI client (the
* redirect is the pending authorization) is offered the card trial before
* approving, once. Every way out of /start-trial (skip, a cancelled or a
* completed checkout) returns to this authorization, which the backend
* keeps for 30 minutes. Resolves true when it has navigated.
*/
const offerCardTrialBeforeAuthorization = async (
u: { id?: string; role?: string } | null | undefined,
token: string,
): Promise<boolean> => {
if (!isCloudMode || !returningToAuthorization || !u?.id || u.role !== 'ADMIN') return false;
if (readCardTrialPrompt(u.id) !== null) return false;
try {
const lic = await license.getStatus(token);
if (!cardTrialEligible({ isCloud: true, role: u.role, license: lic })) return false;
} catch {
return false;
}
writeCardTrialPrompt(u.id, 'shown');
saveAuthorizationReturn(redirectTo);
router.push('/start-trial');
return true;
};

// Surface a failure the SSO callback redirected back with.
useEffect(() => {
if (errorParam) setError(errorParam);
Expand Down Expand Up @@ -331,7 +305,6 @@
login(result.accessToken, result.user);
if (isCloudMode && needsLicenseSetup && returningToAuthorization) {
await license.activateTrial(result.accessToken).catch(() => undefined);
if (await offerCardTrialBeforeAuthorization(result.user, result.accessToken)) return;
goTo(redirectTo);
} else if (isCloudMode && needsLicenseSetup) {
// Cloud mode: auto-activate trial for verified users
Expand Down Expand Up @@ -379,9 +352,9 @@

if (isCloudMode && returningToAuthorization) {
// Verification already created the trial; the user is in the middle
// of connecting an AI client: offer the card trial once, then back
// to approve.
if (await offerCardTrialBeforeAuthorization(verifiedUser, authToken)) return;
// of connecting an AI client, so take them straight back to approve.
// No card-trial offer here: put before Approve it halved the share of
// directory sign-ups that connected Claude (3 Oct 2026).
goTo(redirectTo);
} else if (isCloudMode) {
// Cloud mode: auto-activate trial
Expand All @@ -390,7 +363,7 @@
if (offerCardTrial(storedUser, trialResult)) return;
setTrialDaysLeft(trialResult.trialDaysLeft);
setSetupStep('trial-activated');
} catch (trialErr: any) {

Check warning on line 366 in packages/frontend/src/app/login/page.tsx

View workflow job for this annotation

GitHub Actions / Frontend (lint, typecheck, build)

'trialErr' is defined but never used
// Trial may already exist (e.g. returning user) — go to dashboard
goTo(redirectTo);
}
Expand Down
149 changes: 0 additions & 149 deletions packages/frontend/tests/e2e/card-trial-claude-signup.spec.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,8 @@ test.describe('sign-up from an AI client (Claude "Connect")', () => {
// The MCP authorization page links "Create an account" with
// redirect=/auth/login. After verifying, the new user must land back on that
// page (still inside the pending authorization) to approve with one click,
// not on the welcome wizard, which used to strand the connection half way.
// The card-trial offer may come first, but only with a guaranteed way back
// (card-trial-claude-signup.spec.ts); here there is no trial to convert.
// not on the welcome wizard or the card-trial offer, which strand the connection half way.
// Nor the card-trial offer: before Approve it cost half the connections.
test('after verifying the email, goes straight back to the authorization page', async ({ page }) => {
const calls: string[] = [];
await page.route(/\/(api|health)\//, async (route) => {
Expand Down
Loading