Skip to content

Commit 6892ccf

Browse files
committed
fix: update team pricing to reflect new rate
- Changed the team pricing per developer from $8 to $1 in the billing logic and related documentation. - Updated tests to ensure accurate display of the new pricing in various components, including the homepage and billing settings. - Adjusted marketing copy to reflect the updated pricing model, ensuring consistency across the application. These changes enhance the accuracy of billing information and improve user clarity regarding subscription costs.
1 parent 32c8d0c commit 6892ccf

7 files changed

Lines changed: 15 additions & 14 deletions

File tree

apps/admin/content/compare/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { ContentPage } from "@/content/types";
2+
import { TEAM_PRICE_PER_DEV_USD } from "@/lib/saas-billing/entitlements";
23

34
export const compareWakatime: ContentPage = {
45
kind: "compare",
@@ -356,7 +357,7 @@ export const compareJunctionPanel: ContentPage = {
356357
"AI coding spend management",
357358
"AI coding agent control plane",
358359
],
359-
updatedAt: "2026-08-05",
360+
updatedAt: "2026-09-04",
360361
answer:
361362
"UseJunction and Junction Panel are unrelated products. UseJunction at https://usejunction.dev is open-source AI coding observability for teams—usage, cost, plan and seat utilization, and device health across Cursor, Claude Code, Codex, Copilot, and more. Junction Panel at https://junctionpanel.dev is a browser/phone control surface for supervising local AI coding agents. usejunction.dev does not redirect to junctionpanel.dev.",
362363
compareOtherName: "Junction Panel",
@@ -368,7 +369,7 @@ export const compareJunctionPanel: ContentPage = {
368369
{ feature: "Tool overlap & idle seats", usejunction: "Yes", other: "No" },
369370
{ feature: "Live agent session control", usejunction: "No", other: "Yes — approvals, diffs, mobile supervision" },
370371
{ feature: "Self-hostable observability", usejunction: "Yes — Community License", other: "Local-first daemon + cloud control surface" },
371-
{ feature: "Pricing model", usejunction: "Self-host free (≤5 seats) or Managed $8/dev/mo", other: "Free / Core / Switchboard tiers" },
372+
{ feature: "Pricing model", usejunction: `Self-host free (≤5 seats) or Managed $${TEAM_PRICE_PER_DEV_USD}/dev/mo`, other: "Free / Core / Switchboard tiers" },
372373
],
373374
sections: [
374375
{
@@ -408,7 +409,7 @@ export const compareJunctionPanel: ContentPage = {
408409
{
409410
question: "What is UseJunction’s pricing?",
410411
answer:
411-
"Self-host under the UseJunction Community License for up to 5 seats free, or Managed at $8 per active developer per month. That is not Junction Panel’s Free / Core / Switchboard pricing.",
412+
`Self-host under the UseJunction Community License for up to 5 seats free, or Managed at $${TEAM_PRICE_PER_DEV_USD} per active developer per month. That is not Junction Panel’s Free / Core / Switchboard pricing.`,
412413
},
413414
],
414415
relatedPaths: [

apps/admin/e2e/public.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ test("homepage shows current pricing", async ({ page }) => {
8585
await page.goto("/");
8686
await expect(page.getByRole("heading", { name: /AI spend is data/i })).toBeVisible();
8787
await expect(page.getByText("Free", { exact: true })).toBeVisible();
88-
await expect(page.getByText("$8", { exact: true })).toBeVisible();
88+
await expect(page.getByText("$1", { exact: true })).toBeVisible();
8989
await expect(page.getByText("Custom", { exact: true })).toBeVisible();
9090
await expect(page.getByRole("heading", { name: "Community" })).toBeVisible();
9191
await expect(page.getByRole("heading", { name: "Managed", exact: true })).toBeVisible();

apps/admin/e2e/workspace.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,10 @@ test("Settings shows workspace, billing, Signals, and team visibility controls",
263263
const billing = page.getByRole("region", { name: "Billing" });
264264
await expect(billing).toBeVisible();
265265
await expect(billing.getByText("Team", { exact: true }).first()).toBeVisible();
266-
await expect(billing.getByText("2 active users billed at $8 per user per month.", { exact: true })).toBeVisible();
267-
await expect(billing.getByText("$16 / month", { exact: true })).toBeVisible();
266+
await expect(billing.getByText("2 active users billed at $1 per user per month.", { exact: true })).toBeVisible();
267+
await expect(billing.getByText("$2 / month", { exact: true })).toBeVisible();
268268
await expect(billing.getByRole("heading", { name: /Billed users/ })).toBeVisible();
269-
await expect(billing.getByText("$8 / month", { exact: true })).toHaveCount(2);
269+
await expect(billing.getByText("$1 / month", { exact: true })).toHaveCount(2);
270270
await expect(billing.getByText("E2E Owner", { exact: true })).toBeVisible();
271271
await expect(billing.getByText("owner@example.com", { exact: true })).toBeVisible();
272272
await expect(billing.getByText("E2E Developer", { exact: true })).toBeVisible();

apps/admin/lib/saas-billing/entitlements.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
export type SaasPlan = "community" | "team" | "enterprise";
66

77
export const USER_LIMIT_FREE = 5;
8-
export const TEAM_PRICE_PER_DEV_USD = 8;
8+
export const TEAM_PRICE_PER_DEV_USD = 1;
99

1010
export type OrgBillingFields = {
1111
plan: string;

apps/admin/tests/components/billing-settings-card.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ test("Team billing shows a simple plan summary, billed users, total, and seat sy
7575

7676
expect(screen.getByRole("region", { name: "Billing" })).toBeTruthy();
7777
expect(screen.getByText("Active subscription")).toBeTruthy();
78-
expect(screen.getByText("$16 / month")).toBeTruthy();
79-
expect(screen.getByText("2 active users billed at $8 per user per month.")).toBeTruthy();
78+
expect(screen.getByText("$2 / month")).toBeTruthy();
79+
expect(screen.getByText("2 active users billed at $1 per user per month.")).toBeTruthy();
8080
expect(screen.getByRole("heading", { name: /Billed users/ })).toBeTruthy();
81-
expect(screen.getAllByText("$8 / month")).toHaveLength(2);
81+
expect(screen.getAllByText("$1 / month")).toHaveLength(2);
8282
expect(screen.queryByText(/estimat/i)).toBeNull();
8383
expect(screen.getByText("Alice Admin")).toBeTruthy();
8484
expect(screen.getByText("alice@example.com")).toBeTruthy();
@@ -93,7 +93,7 @@ test.each([
9393
name: "Community",
9494
state: baseBilling,
9595
total: "$0 / month",
96-
detail: "Community is free. Team costs $8 per active user per month.",
96+
detail: "Community is free. Team costs $1 per active user per month.",
9797
status: "Free tier",
9898
},
9999
{

apps/admin/tests/saas-billing.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ test("blocks duplicate checkout only for active-like statuses", () => {
5252

5353
test("exports single-source developer pricing constants", () => {
5454
assert.equal(USER_LIMIT_FREE, 5);
55-
assert.equal(TEAM_PRICE_PER_DEV_USD, 8);
55+
assert.equal(TEAM_PRICE_PER_DEV_USD, 1);
5656
});
5757

5858
test("lemon webhook signature digests differ for wrong secrets", () => {

docs/saas-billing-lemon.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ migration.
2121
**Billed unit on Team:** each active developer (`Developer.removedAt IS NULL`).
2222
Invitations do not count until accepted. The minimum checkout quantity is one.
2323

24-
Marketing copy uses `TEAM_PRICE_PER_DEV_USD` ($8 / active developer / month) from
24+
Marketing copy uses `TEAM_PRICE_PER_DEV_USD` ($1 / active developer / month) from
2525
`apps/admin/lib/saas-billing/entitlements.ts`. The configured Lemon variant is the
2626
source of truth for the amount charged and must use **quantity-based**, not
2727
usage-based, billing.

0 commit comments

Comments
 (0)