flowglad-subscriptions
Utility for handling subscription management workflows including upgrades, cancellations, and status checks.
Install
mkdir -p .claude/skills/flowglad-subscriptions && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/4641" && unzip -o skill.zip -d .claude/skills/flowglad-subscriptions && rm skill.zipInstalls to .claude/skills/flowglad-subscriptions
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Manage subscription lifecycle including cancellation, plan changes, reactivation, and status display. Use this skill when users need to upgrade, downgrade, cancel, or reactivate subscriptions.Key capabilities
- →Synchronizes client-side state after billing mutations
- →Implements server-side reload patterns
- →Configures cancellation timing logic (immediate vs end-of-period)
- →Handles trial status expiration checks
- →Maps internal subscription status to display labels
How it works
It provides logic hooks and utility functions that force a data refresh and state validation after a subscription change is initiated.
Inputs & outputs
When to use flowglad-subscriptions
- →Handle a user subscription cancellation
- →Implement a plan upgrade/downgrade
- →Check user trial status
About this skill
Subscriptions Management
Abstract
This skill covers subscription lifecycle management including cancellation, plan changes, reactivation, trial handling, and status display. Proper subscription management ensures users can upgrade, downgrade, cancel, and reactivate subscriptions with correct billing behavior.
Table of Contents
- Reload After Mutations — CRITICAL
- Cancel Timing Options — HIGH
- Upgrade vs Downgrade Behavior — HIGH
- Reactivation with uncancelSubscription — MEDIUM
- Trial Status Detection — MEDIUM
- Subscription Status Display — MEDIUM
1. Reload After Mutations
Impact: CRITICAL
After any subscription mutation (cancel, upgrade, downgrade, reactivate), the local billing state is stale. Failing to reload causes UI to show outdated subscription information.
1.1 Client-Side State Sync
Impact: CRITICAL (users see incorrect subscription status)
When using useBilling() on the client, mutations update the server but the local state remains stale until explicitly reloaded.
Incorrect: assumes state updates automatically
function CancelButton() {
const { cancelSubscription, currentSubscription } = useBilling()
const handleCancel = async () => {
await cancelSubscription({
id: currentSubscription.id,
cancellation: { timing: 'at_end_of_current_billing_period' },
})
// BUG: currentSubscription still shows old status!
// UI will not reflect cancellation until page refresh
}
return (
<div>
<button onClick={handleCancel}>Cancel Subscription</button>
{/* Shows incorrect status because we didn't reload */}
<p>Status: {currentSubscription?.status}</p>
</div>
)
}
The UI continues showing the old subscription status because the local useBilling() state wasn't refreshed.
Correct: reload after mutation
function CancelButton() {
const { cancelSubscription, currentSubscription, reload } = useBilling()
const [isLoading, setIsLoading] = useState(false)
const handleCancel = async () => {
setIsLoading(true)
try {
await cancelSubscription({
id: currentSubscription.id,
cancellation: { timing: 'at_end_of_current_billing_period' },
})
// Refresh local state to reflect the cancellation
await reload()
} finally {
setIsLoading(false)
}
}
return (
<div>
<button onClick={handleCancel} disabled={isLoading}>
{isLoading ? 'Canceling...' : 'Cancel Subscription'}
</button>
{/* Now shows correct status after reload */}
<p>Status: {currentSubscription?.status}</p>
</div>
)
}
1.2 Server-Side Reload Pattern
Impact: CRITICAL (server actions may return stale data)
When performing mutations server-side and returning billing data to the client, you must fetch fresh data after the mutation.
Incorrect: returns stale billing data
// Server action
export async function upgradeSubscription(priceSlug: string) {
const session = await auth()
const billing = await flowglad(session.user.id).getBilling()
await billing.adjustSubscription({ priceSlug })
// BUG: billing object still has old data!
return {
success: true,
subscription: billing.currentSubscription, // Stale!
}
}
Correct: fetch fresh billing after mutation
// Server action
export async function upgradeSubscription(priceSlug: string) {
const session = await auth()
const billing = await flowglad(session.user.id).getBilling()
await billing.adjustSubscription({ priceSlug })
// Fetch fresh billing state after mutation
const freshBilling = await flowglad(session.user.id).getBilling()
return {
success: true,
subscription: freshBilling.currentSubscription, // Fresh!
}
}
2. Cancel Timing Options
Impact: HIGH
Flowglad supports two cancellation timing modes. Using the wrong mode leads to billing disputes and poor user experience.
2.1 End of Period vs Immediate
Impact: HIGH (billing and access implications)
Most SaaS applications should cancel at the end of the billing period to let users keep access for time they've paid for.
Incorrect: immediately cancels without understanding impact
async function handleCancel() {
await billing.cancelSubscription({
id: billing.currentSubscription.id,
// This immediately ends access!
// User loses features they already paid for
cancellation: { timing: 'immediately' },
})
}
Immediate cancellation removes access right away, even if the user paid for the full month. This often leads to support tickets and refund requests.
Correct: cancel at end of period (default for most cases)
async function handleCancel() {
await billing.cancelSubscription({
id: billing.currentSubscription.id,
// User keeps access until their paid period ends
cancellation: { timing: 'at_end_of_current_billing_period' },
})
await billing.reload()
}
Use immediately only for specific cases like fraud prevention, user request for immediate refund, or account deletion.
2.2 User Communication
Impact: HIGH (user confusion)
When showing cancellation options, clearly communicate what each timing option means.
Incorrect: vague cancellation UI
function CancelModal() {
return (
<div>
<h2>Cancel Subscription</h2>
<button onClick={() => handleCancel('immediately')}>
Cancel Now
</button>
<button onClick={() => handleCancel('at_end_of_current_billing_period')}>
Cancel Later
</button>
</div>
)
}
"Cancel Now" and "Cancel Later" don't explain the billing implications.
Correct: clear communication of timing
function CancelModal() {
const { currentSubscription } = useBilling()
const endDate = currentSubscription?.currentPeriodEnd
return (
<div>
<h2>Cancel Subscription</h2>
<div>
<button onClick={() => handleCancel('at_end_of_current_billing_period')}>
Cancel at End of Billing Period
</button>
<p>
You'll keep access until {formatDate(endDate)}.
No further charges will occur.
</p>
</div>
<div>
<button onClick={() => handleCancel('immediately')}>
Cancel Immediately
</button>
<p>
Access ends now. You may be eligible for a prorated refund.
</p>
</div>
</div>
)
}
3. Upgrade vs Downgrade Behavior
Impact: HIGH
Upgrades and downgrades have different default behaviors. Not understanding this leads to incorrect UI and user confusion.
3.1 Immediate Upgrades
Impact: HIGH (billing timing)
By default, upgrades apply immediately with prorated billing. Users get instant access to the new plan.
Incorrect: suggests upgrade happens later
function UpgradeButton({ targetPriceSlug }: { targetPriceSlug: string }) {
const { adjustSubscription, reload } = useBilling()
return (
<button onClick={async () => {
await adjustSubscription({ priceSlug: targetPriceSlug })
await reload()
}}>
{/* Misleading: upgrade happens immediately, not next month */}
Upgrade Starting Next Month
</button>
)
}
Correct: communicate immediate effect
function UpgradeButton({ targetPriceSlug }: { targetPriceSlug: string }) {
const { adjustSubscription, reload, getPrice } = useBilling()
const price = getPrice(targetPriceSlug)
return (
<div>
<button onClick={async () => {
await adjustSubscription({ priceSlug: targetPriceSlug })
await reload()
}}>
Upgrade Now to {price?.product.name}
</button>
<p>
Your new plan starts immediately.
You'll be charged a prorated amount for the remainder of this billing period.
</p>
</div>
)
}
3.2 Deferred Downgrades
Impact: HIGH (user expectation mismatch)
Downgrades typically apply at the end of the current billing period. Users keep their current plan until then.
Incorrect: implies immediate downgrade
function DowngradeButton({ targetPriceSlug }: { targetPriceSlug: string }) {
const { adjustSubscription, reload } = useBilling()
return (
<button onClick={async () => {
await adjustSubscription({ priceSlug: targetPriceSlug })
await reload()
}}>
{/* Misleading: downgrade doesn't happen immediately */}
Switch to Basic Now
</button>
)
}
Correct: communicate deferred effect
function DowngradeButton({ targetPriceSlug }: { targetPriceSlug: string }) {
const { adjustSubscription, currentSubscription, reload, getPrice } = useBilling()
const price = getPrice(targetPriceSlug)
const endDate = currentSubscription?.currentPeriodEnd
return (
<div>
<button onC
---
*Content truncated.*
When not to use it
- →When building a custom billing engine from scratch
- →When subscription state does not require client-server synchronization
Prerequisites
Limitations
- →Depends on network-synced state updates
- →Limited by the API's subscription lifecycle rules
How it compares
It enforces synchronization standards, whereas manual implementations often forget to update UI state after server-side mutations.
Compared to similar skills
flowglad-subscriptions side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| flowglad-subscriptions (this skill) | 1 | 6mo | No flags | Intermediate |
| zendesk | 15 | 3mo | Review | Intermediate |
| zapier-workflows | 11 | 8mo | Review | Beginner |
| controlling-spotify | 7 | 3mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by flowglad
View all by flowglad →You might also like
zendesk
vm0-ai
Zendesk Support REST API for managing tickets, users, organizations, and support operations. Use this skill to create tickets, manage users, search, and automate customer support workflows.
zapier-workflows
davila7
Manage and trigger pre-built Zapier workflows and MCP tool orchestration. Use when user mentions workflows, Zaps, automations, daily digest, research, search, lead tracking, expenses, or asks to "run" any process. Also handles Perplexity-based research and Google Sheets data tracking.
controlling-spotify
oaustegard
Control Spotify playback and manage playlists via MCP server. Use when user requests playing music, controlling Spotify, creating playlists, searching songs, or managing their Spotify library.
smithery-ai-cli
smithery-ai
Find, connect, and use MCP tools and skills via the Smithery CLI. Use when the user searches for new tools or skills, wants to discover integrations, connect to an MCP, install a skill, or wants to interact with an external service (email, Slack, Discord, GitHub, Jira, Notion, databases, cloud APIs, monitoring, etc.).
connect-apps
ComposioHQ
Connect Claude to external apps like Gmail, Slack, GitHub. Use this skill when the user wants to send emails, create issues, post messages, or take actions in external services.
freshdesk-automation
sickn33
Automate Freshdesk helpdesk operations including tickets, contacts, companies, notes, and replies via Rube MCP (Composio). Always search tools first for current schemas.