Add 14-day free trial + trial cap for siGit Code Cloud

GTM: let users try cloud before paying (card-required trial converts well), while bounding trial COGS. - StripeService: trial_period_days=14 on checkout subscriptions - Subscription: trialing users get TRIAL_ALLOWANCE (300) cloud requests, well below the paid caps (pro 2000 / team 6000) - Copy: 402 + web CTAs invite the free trial (Start 14-day free trial), billing page shows trial status + trial-end date Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Seto Elkahfi committed Jun 24, 2026 at 12:06 UTC 650bb5d6f7a6347de8a6254c7623f879c5159170
4 files changed +33 -11
app/controllers/api/v1/chat_completions_controller.rb
+2 -1
@@ -44,7 +44,8 @@ module Api
44 return if current_user&.entitled_to_cloud?
45
46 render json: error_body(
47 - "siGit Code Cloud requires a Pro subscription. Upgrade in your siGit account to use cloud models."
47 + "Start your free siGit Code Cloud trial to use cloud models — 14 days free, then $20/mo. " \
48 + "Begin it in your siGit account billing page."
49 ), status: :payment_required
50 end
51
app/models/subscription.rb
+8 -2
@@ -13,13 +13,19 @@ class Subscription < ApplicationRecord
13 # these are the included cloud requests before the cap kicks in.
14 CLOUD_ALLOWANCE = { "pro" => 2_000, "team" => 6_000 }.freeze
15
16 - # Entitled to siGit Code Cloud: on a paid plan in good standing.
16 + # During the free trial, cap cloud usage well below the paid allowance so a
17 + # trial can't run up an unbounded upstream bill. Enough to feel the product.
18 + TRIAL_ALLOWANCE = 300
19 +
20 + # Entitled to siGit Code Cloud: on a paid plan in good standing (incl. trial).
21 def entitled_to_cloud?
22 (pro? || team?) && (active? || trialing?)
23 end
24
21 - # Included cloud requests for this plan's billing period.
25 + # Included cloud requests for this period. The trial gets a tighter cap.
26 def cloud_allowance
27 + return TRIAL_ALLOWANCE if trialing?
28 +
29 CLOUD_ALLOWANCE.fetch(plan, 0)
30 end
31
app/services/stripe_service.rb
+8 -1
@@ -10,6 +10,10 @@ class StripeService
10 "team" => "sigit_code_team_monthly"
11 }.freeze
12
13 + # Free-trial length for new subscriptions. Card is collected at checkout and
14 + # Stripe auto-converts to paid when the trial ends. Tunable GTM knob.
15 + TRIAL_DAYS = 14
16 +
17 # A subscription's price lookup_key → our plan.
18 PLAN_BY_LOOKUP_KEY = {
19 "sigit_code_pro_monthly" => :pro,
@@ -50,7 +54,10 @@ class StripeService
54 success_url: success_url,
55 cancel_url: cancel_url,
56 metadata: { user_id: user.id.to_s },
53 - subscription_data: { metadata: { user_id: user.id.to_s } }
57 + subscription_data: {
58 + metadata: { user_id: user.id.to_s },
59 + trial_period_days: TRIAL_DAYS
60 + }
61 }.compact)
62
63 session.url
app/views/billing/show.html.erb
+15 -7
@@ -24,16 +24,24 @@
24 <div class="px-6 py-6">
25 <% if @entitled %>
26 <p class="text-sm text-gray-300">
27 - You're on <span class="text-gray-100 font-medium"><%= @plan.to_s.capitalize %></span> — siGit Code Cloud is unlocked.
28 - <% if @period_end %>
29 - <span class="text-gray-500">Renews <%= @period_end.strftime("%b %-d, %Y") %>.</span>
27 + <% if @status.to_s == "trialing" %>
28 + You're on a <span class="text-gray-100 font-medium">free trial</span> of
29 + <%= @plan.to_s.capitalize %> — siGit Code Cloud is unlocked.
30 + <% if @period_end %>
31 + <span class="text-gray-500">Trial ends <%= @period_end.strftime("%b %-d, %Y") %>, then $20/mo.</span>
32 + <% end %>
33 + <% else %>
34 + You're on <span class="text-gray-100 font-medium"><%= @plan.to_s.capitalize %></span> — siGit Code Cloud is unlocked.
35 + <% if @period_end %>
36 + <span class="text-gray-500">Renews <%= @period_end.strftime("%b %-d, %Y") %>.</span>
37 + <% end %>
38 <% end %>
39 </p>
40 <% else %>
41 <p class="text-sm text-gray-300">
42 You're on the free <span class="text-gray-100 font-medium">Garage</span> plan. AI runs
35 - <span class="text-gray-100">on your device</span> — private and free. Upgrade to use
36 - siGit Code Cloud (the Fast / Balanced / Large tiers) when you need more.
43 + <span class="text-gray-100">on your device</span> — private and free. Try siGit Code Cloud
44 + (the Fast / Balanced / Large tiers) free for 14 days when you need more.
45 </p>
46 <% end %>
47 </div>
@@ -63,8 +71,8 @@
71 <% if @entitled %>
72 <%= button_to "Manage billing", billing_portal_path, method: :post, data: { turbo: false }, class: "btn-primary cursor-pointer" %>
73 <% else %>
66 - <%= button_to "Upgrade to Pro", billing_checkout_path(plan: "pro"), method: :post, data: { turbo: false }, class: "btn-primary cursor-pointer" %>
67 - <%= button_to "Upgrade to Team", billing_checkout_path(plan: "team"), method: :post, data: { turbo: false }, class: "text-sm text-gray-400 hover:text-gray-200 transition-colors bg-transparent border-0 cursor-pointer" %>
74 + <%= button_to "Start 14-day free trial", billing_checkout_path(plan: "pro"), method: :post, data: { turbo: false }, class: "btn-primary cursor-pointer" %>
75 + <%= button_to "Try Team free", billing_checkout_path(plan: "team"), method: :post, data: { turbo: false }, class: "text-sm text-gray-400 hover:text-gray-200 transition-colors bg-transparent border-0 cursor-pointer" %>
76 <% end %>
77 </div>
78 </div>