Skip to content

chore: merge main into m18/cloud (#133, new prices and Pro) - #134

Merged
datlechin merged 2 commits into
m18/cloudfrom
chore/m18-sync-main-2
Nov 2, 2026
Merged

datlechin merged 2 commits into
m18/cloudfrom
chore/m18-sync-main-2

Conversation

@datlechin

Copy link
Copy Markdown
Member

Summary

Merges main into m18/cloud. m18/cloud was one commit behind: #133, live on tablepro.app since 2026-11-02. It brings:

  • New prices in pricing.json: Pro (the starter code) at $4.99 a month, $39 a year or $79 once; Team at $12 a seat a month or $120 a year, from 2 seats, with no one-time price.
  • Starter renamed Pro in every language's copy, catalogs and legal pages. Release posts keep their old wording.
  • Team's yearly price shown as a month's share, billed yearly. On One-time, the Team card is disabled and says Team is a subscription (tiers.team.subscriptionOnly).
  • The Enterprise contact card, the new-prices notice above the plans (content.priceChange), and the blog news kind with the new-prices-2026 post in English and Vietnamese, with its OG cards.
  • Copy fixes saying Team cannot be bought once, the compare model without a Team lifetime price, and the test updates.

Conflicts

  • resources/data/pricing.json: main's prices on m18's keys. Team has monthly and yearly prices only, and seats: {min: 2}. m18 keeps license.deviceLimit and has no activations, activationsPerSeat or seat max.
  • resources/js/lib/data/pricing.ts: m18's types with main's TeamCycle. Team prices are monthly and yearly only. tierPrice() returns undefined and sells() false for Team one-time. teamTotal() takes a TeamCycle and keeps m18's minimum-only clamp.
  • pricing-card.tsx, pricing-plans.tsx, plan-matrix.tsx, structured-data.ts: m18's signatures (maxSeats, no checkout prop) and short comments. On top of them: main's disabled Team one-time button, the subscription-only note, Team yearly shown per month, and the Enterprise card.
  • pages/Pricing.tsx: m18's page, with main's price-change notice above the plans.
  • i18n/messages/*/pricing.ts (12 locales): m18's Team activation line ("one person per seat, on up to N Macs"), plus main's "Everything in Pro", subscriptionOnly and the enterprise messages.
  • content/*/faq.json, features/sync-and-teams.json, pricing.json (36 files): m18's account-model copy, with Starter renamed Pro.
  • legal/*/privacy.md, refund-policy.md, terms.md (36 files): m18's text, with Starter renamed Pro and updatedAt set to 2026-11-02.
  • PricingDataTest, LegalPagesTest, PricingPageTest, compare-model.test.ts: m18's assertions at the new prices and dates, with the Pro name.

Main's decisions in copy that exists only on m18

  • Starter is Pro in the pricing page's "Using TablePro at work" ask and in the refund policy's self-refund paragraph, in 12 languages.
  • "A team without a subscription buys more one-time seats there" (FAQ, pricing, Sync & Teams) now says a team keeps its one-time seats and adds seats with a Team subscription, in 12 languages. Team Lifetime is no longer sold.

Tests changed on purpose

  • tests/Feature/Content/ReviewedFactsTest.php: the pricing page's reviewed fact pinned "buys more one-time seats there". It now pins "more seats come with a Team subscription" and rules out the old sentence.
  • tests/js/regional-pricing.test.ts: models GET /v2/pricing at the new prices, with Team from 2 seats and no lifetime plan. The seat-maximum case moves to Team yearly. It adds the new prices' rounding cases, such as $4.99 at 50% giving $2.49.

Merge

Merge with a merge commit, not a squash, so the next sync starts from this one.

Checks

  • php -d memory_limit=2G vendor/bin/pest --exclude-group=ssr: 1999 passed.
  • npm run typecheck: passes.
  • npm run test:js: 292 passed.
  • vendor/bin/pint --test: passed.
  • php artisan assets:generate --check: up to date.
  • composer audit --locked: no advisories.
  • npm run build, then REQUIRE_SSR=1 php -d memory_limit=2G vendor/bin/pest --group=ssr with the SSR service on the .env port: 259 passed and 1 skipped (the hero is supplied). The only failures are 9 in PageChunkTest, which fails locally on every branch because node_modules is a symlink.

… card and a news post (#133)

- pricing.json: Pro (the `starter` code) $4.99 a month, $39 a year or $79
  once, on 3 Macs; Team $12 a seat a month or $120 a seat a year, from 2
  seats, with no one-time price. The card shows Team's yearly price as a
  month's share, billed yearly, and says Team is a subscription when
  One-time is chosen.
- Starter is Pro in every language's copy, catalog and legal page. Release
  posts keep the name they shipped with.
- An Enterprise card: a contact route to hello@ with a fixed subject, so
  inquiries can be counted. No price, no checkout.
- A notice above the plans links the post that explains the change.
- The blog gets a third kind, news (`kind: news`), listed first on /blog
  and in llms.txt's Optional section, with its own test. The first one is
  new-prices-2026, in English and Vietnamese, with its OG cards.
- Copy that said Team can be bought once is corrected in 12 languages.
Brings #133: Pro (the `starter` code) at $4.99/$39/$79, Team at $12 a
seat monthly or $120 yearly from 2 seats with no one-time price, Starter
renamed Pro, the Enterprise contact card, the new-prices notice, the blog
news kind with the new-prices-2026 post, and its test changes.

Conflicts and how each was resolved:

- resources/data/pricing.json: main's prices on m18's keys. Team has
  monthly and yearly only and `seats: {min: 2}`; m18 keeps
  `license.deviceLimit` and no `activations`, `activationsPerSeat` or
  seat `max`.
- resources/js/lib/data/pricing.ts: m18's types with main's TeamCycle.
  Team prices are monthly and yearly only, tierPrice() returns undefined
  and sells() false for Team one-time, and teamTotal() takes a TeamCycle
  and keeps m18's minimum-only clamp.
- pricing-card.tsx, pricing-plans.tsx, plan-matrix.tsx,
  structured-data.ts: m18's signatures (`maxSeats`, no `checkout` prop)
  and short comments, with main's disabled Team one-time button, the
  subscription-only note, Team yearly shown per month, and the
  Enterprise card.
- pages/Pricing.tsx: m18's page with main's price-change notice above
  the plans.
- i18n/messages/*/pricing.ts (12): m18's Team activation ("one person
  per seat, on up to N Macs"); main's "Everything in Pro", the
  `subscriptionOnly` note and the Enterprise messages.
- content/*/faq.json, features/sync-and-teams.json, pricing.json (36):
  m18's account-model copy, with Starter renamed Pro.
- legal/*/privacy.md, refund-policy.md, terms.md (36): m18's text with
  Starter renamed Pro, updatedAt 2026-11-02.
- PricingDataTest, LegalPagesTest, PricingPageTest,
  compare-model.test.ts: m18's assertions at the new prices and dates,
  with the Pro name.

Changes for main's decisions in copy that exists only on m18:

- "Starter" is Pro in the pricing page's "Using TablePro at work" ask
  and the refund policy's self-refund paragraph, in 12 languages.
- "A team without a subscription buys more one-time seats there" now
  says a team keeps its one-time seats and adds seats with a Team
  subscription (FAQ, pricing, Sync & Teams; 12 languages). Team
  Lifetime is no longer sold.
- ReviewedFactsTest pinned that sentence; it now pins the new one and
  rules out the old.
- tests/js/regional-pricing.test.ts models GET /v2/pricing at the new
  prices: Team from 2 seats with no lifetime plan. It adds the new
  prices' rounding cases.
@datlechin
datlechin merged commit 5768844 into m18/cloud Nov 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant