The central pattern: features are defined once, values are set per-plan. This is what lets a single users feature be 5 on Basic, 50 on Pro, and 999999 on Enterprise -- one definition, three limits.
The five-step flow
1. Create features in the Features resource
For each capability or quota that varies by plan:
- Name and slug (e.g. "Users" /
users) - Reset cycle if applicable
Don't worry about values yet -- features have no value of their own.
2. Open a plan
Navigate to the Plans resource and edit the plan you want to attach features to.
3. Switch to the Features tab
This is the relation manager for the plan_features pivot.
4. Attach a feature
Click Attach. The form prompts for:
- Feature -- pick from the existing features
- Value -- the per-plan limit (e.g.
5,50,999999for quota;true/falsefor boolean features) - Sort order -- where this feature appears on the plan's pricing card
5. Repeat for each plan
The same feature appears on multiple plans; the value can differ for each.
Worked example
Imagine you're modeling Basic / Pro / Enterprise tiers.
Features (created once):
| Slug | Name | Reset cycle |
|---|---|---|
users |
Users | Never (running count) |
api-requests |
API Requests | Monthly |
ssl |
SSL | Never (boolean flag) |
Per-plan attachments:
| Plan | users |
api-requests |
ssl |
|---|---|---|---|
| Basic | 5 | 100 | false |
| Pro | 50 | 10000 | true |
| Enterprise | 999999 | 999999 | true |
In the admin: open Basic plan -> Features tab -> Attach (Users, value=5) -> Attach (API Requests, value=100) -> Attach (SSL, value=false). Repeat for Pro and Enterprise with their values.
In code, your app then checks:
$sub->canUseFeature('users'); // bool
$sub->getFeatureValue('users'); // string -- the per-plan limit
$sub->recordFeatureUsage('users'); // increment current count
Translatable fields
Plan and feature names / descriptions are stored as JSON via spatie/laravel-translatable. The admin forms write to the current application locale.
If you need a locale switcher in the admin, look at filament-spatie-translatable -- it stacks cleanly on top of these resources.
"Unlimited" features
There's no built-in "unlimited" sentinel. Pick a convention and stick with it:
999999if you want code that does$used < $valueto keep working naively-1if you want explicit "unlimited" handling in your app- A separate
is_unlimitedcolumn on a custom Plan / Feature subclass if you want it modeled explicitly
The package is intentionally agnostic here.
Contributing
Thanks for your interest in contributing to crumbls/subscriptions-filament.
Local setup
git clone https://github.com/Crumbls/subscriptions-filament.git
cd subscriptions-filament
composer install
To hack on this package alongside the underlying crumbls/subscriptions package, add a path repository to your test app's composer.json:
{
"repositories": [
{ "type": "path", "url": "../subscriptions" },
{ "type": "path", "url": "../subscriptions-filament" }
]
}
Pull requests
- Open the PR against
main. - Breaking changes belong behind a version bump — note them in
CHANGELOG.md. - If the change affects what admins see, include a screenshot or screen recording.
Reporting issues
Open a GitHub issue with:
- Affected version (
composer show crumbls/subscriptions-filament). crumbls/subscriptionsversion.- PHP, Laravel, and Filament versions.
- Steps to reproduce.
- Expected vs. actual behavior.
Security issues
Please do not open public issues for security vulnerabilities. See SECURITY.md for reporting channels.
Contributors
Thank you to everyone who has contributed to this package. Every pull request, bug report, and idea makes a difference.