{"id":17613905,"url":"https://github.com/marktopper/spark-addons","last_synced_at":"2026-02-19T17:02:57.572Z","repository":{"id":86930063,"uuid":"252741708","full_name":"marktopper/spark-addons","owner":"marktopper","description":null,"archived":false,"fork":false,"pushed_at":"2020-03-14T16:42:38.000Z","size":36,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-01T16:00:02.840Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marktopper.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-03T13:33:03.000Z","updated_at":"2022-02-24T18:18:59.000Z","dependencies_parsed_at":"2023-05-29T20:45:09.993Z","dependency_job_id":null,"html_url":"https://github.com/marktopper/spark-addons","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/marktopper/spark-addons","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marktopper%2Fspark-addons","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marktopper%2Fspark-addons/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marktopper%2Fspark-addons/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marktopper%2Fspark-addons/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marktopper","download_url":"https://codeload.github.com/marktopper/spark-addons/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marktopper%2Fspark-addons/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29623546,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T13:04:20.082Z","status":"ssl_error","status_checked_at":"2026-02-19T13:03:33.775Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-22T18:14:59.165Z","updated_at":"2026-02-19T17:02:57.535Z","avatar_url":"https://github.com/marktopper.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spark Addons\n\nGrow your revenue by offering multiple add-on subscriptions in your Laravel Spark app.\n\n- Define \"add-on\" subscriptions\n- Supported metered (pay as you go) and licensed (monthly fee) usage types\n- Support multiple plans for each add-on\n- Allow users to subscribe and cancel their subscription to an add-on plan\n- Implemented in a similar style to existing Spark functionality\n\n## Forked\n\nThis respository was forked from `https://github.com/benmag/laravel-spark-addons#readme` which unforuntaely isn't available any longer.\n\n## Installation\n\n1. Include the package\n\n```composer\n  composer require centality-labs/spark-addons\n```\n\n2. Publish and run the migrations\n\n```php\n  php artisan vendor:publish --tag=spark-addons-migrations \u0026\u0026 php artisan migrate\n```\n\n3. Update change your Spark class in config/app.php\n\n```php\n  [\n      'aliases' =\u003e [\n          'Spark' =\u003e \\CentalityLabs\\SparkAddons\\Spark::class,\n      ]\n  ]\n```\n\n4. Switch the use `Laravel\\Spark\\Spark;` class in `SparkServiceProvider` to use `Centrality\\SparkAddons\\Spark;`\n\n5. Add the BillableAddonSubscriptions trait to your Team model\n\n```php\n  namespace App;\n\n  use Laravel\\Spark\\Team as SparkTeam;\n  use CentrailityLabs\\SparkAddons\\Traits\\BillableAddonSubscriptions;\n\n  class Team extends SparkTeam\n  {\n    use BillableAddonSubscriptions;\n    //...\n  }\n```\n\n6. Ensure the Vue components for spark-addons get built by adding the following to your `resources/assets/js/components/bootstrap.js` file.\n\n```js\nrequire(\"./../../../vendor/centrality-labs/spark-addons/resources/assets/js/bootstrap\");\n```\n\n7. Add your spark-addons config to your global Spark object in your layout file (resources/views/vendor/spark/layouts/app.blade.php)\n\n```javascript\n\u003c!-- Global Spark Object --\u003e\n\u003cscript\u003e\n    window.Spark = \u003c?php echo json_encode(array_merge(\n        Spark::scriptVariables(), [\n            'spark-addons' =\u003e config('spark-addons')\n        ]\n    )); ?\u003e\n\u003c/script\u003e\n```\n\n8. Show current add-on subscriptions in the subscriptions page by adding the following to the `views/vendor/spark/settings/subscription.blade.php` view\n\n```php\n   \u003caddon-subscriptions\n       :user=\"user\"\n       :team=\"team\"\n       :billable-type=\"billableType\"\u003e\n   \u003c/addon-subscriptions\u003e\n```\n\n## Usage\n\nYou can now define available add-on plans in a similar style to how you define your Spark plans inside your SparkServiceProvider.\n\n```php\n// SocketCluster\nSpark::addon(new \\CentalityLabs\\SparkAddons\\Addon([\n  'id' =\u003e 'socketcluster',\n  'name' =\u003e 'SocketCluster',\n  'description' =\u003e \"A scalable framework for real-time apps and services.\",\n]));\n\n// SocketCluster - Plan: Hobby\nSpark::addonPlan('socketcluster', 'Hobby', 'socketcluster:hobby')\n  -\u003eprice(19)\n  -\u003etrialDays(15)\n  -\u003efeatures([\n    \"Powered by 512mb RAM\",\n    \"No complicated setup\",\n    \"Email support\"\n  ])\n  -\u003eattributes([\n    'description' =\u003e \"Single 512mb SocketCluster instance, perfect for development\",\n]);\n\n// Servers\nSpark::addon(new \\CentalityLabs\\SparkAddons\\Addon([\n  'id' =\u003e 'servers',\n  'name' =\u003e 'Servers',\n  'description' =\u003e \"High performance cloud servers provisioned for you.\",\n]));\n\n// Servers: Standard 1X\nSpark::addonPlan('servers', 'Standard 1X', 'servers:standard-1x')\n  -\u003eusageType('metered')\n  -\u003eprice(0.10)\n  -\u003efeatures([\n    '512MB RAM',\n    '1 Core Processor',\n    '20GB SSD Disk',\n    '1TB Transfer'\n  ])\n  -\u003eattributes([\n    'description' =\u003e \"512MB RAM. Perfect server to power hobby and small apps.\",\n  ]);\n```\n\n## Configuration\n\n1. Publish config\n\n```php\n  php artisan vendor:publish --tag=spark-addons-config\n```\n\n2. Publish assets\n\n```php\n  php artisan vendor:publish --tag=spark-addons-assets\n```\n\n3. Publish views\n\n```php\nphp artisan vendor:publish --tag=spark-addons-views\n```\n\n## Metered Billing\n\nMetered billing or usage based billing allows you to charge your customer an amount based on what they have actually consumed by taking advantage of [Stripe's metered billing](https://stripe.com/docs/billing/subscriptions/metered-billing).\n\nFor example, at Codemason, our users can use Codemason Servers to run their apps. These servers are billed by the hour at the corresponding rate and can be cancelled at any time. At the end of the month, the customer is billed for the amount of hours they have accumulated.\n\nBy default metered add-on plans are measuring usage by the hour. However, it's easy to swap this implementation out for your own, just as you would for any other Spark interaction with the `*Spark::swap*` technique.\n\nThe behind the scenes of how this works is fairly simple: at the end of the billing cylce, Stripe fires a `invoice.created` webhook approximately an hour before the invoice is finalised and a charge is attempted. When your app receives that webhook, it calculates the number of hours the add-on has been active for and updates Stripe with the usage.\n\nTo make use of this functionality, you will make some additional configurations. Don't worry, it's still very easy and very straight forward.\n\n### _Override the default Stripe Webhook (required)_\n\nThe main thing we will need to do is make sure that the `SparkAddonsServiceProvider` is being manually registered after the `SparkServiceProvider`. This is to ensure that we're using our new controller that listens for the `invoice.created` webhook to perform usage calculations at the end of the month.\n\nDisable auto-discovery so we can override the existing `spark/webhoo`k that Laravel Spark provides\n\nDo this by adding the following to your `composer.json` file:\n\n```json\n\"extra\": {\n  \"laravel\": {\n    \"dont-discover\": [\n      \"laravel/dusk\",\n      \"centrality-labs/spark-addons\"\n    ]\n  }\n},\n```\n\nManually register the `SparkAddonsServiceProvider` after the `SparkServiceProvider` in the providers array in `config/app.php`\n\n```php\n'providers' =\u003e [\n  Laravel\\Spark\\Providers\\SparkServiceProvider::class,\n  App\\Providers\\SparkServiceProvider::class,\n  CentralityLabs\\SparkAddons\\SparkAddonsServiceProvider::class,\n  // ...\n]\n```\n\n## Interactions\n\nThese are the interactions, you are able to override them with your own custom implementations where required using `*Spark::swap*`\n\n| Interaction                 | Description                                                                                                                 |\n| --------------------------- | --------------------------------------------------------------------------------------------------------------------------- |\n| CalculateMeteredUsage       | Calculate the hour based usage for the add-on subscription.                                                                 |\n| RecordUsageUsingStripe      | Records the usage on Stripe                                                                                                 |\n| SubscribeAddon              | Adds a new add-on subscription to a owner                                                                                   |\n| SubscribeTeamAddon          | Adds a new add-on subscription to a owner                                                                                   |\n| CancelAddonSubscription     | Cancels an add-on subscription. If the add-on subscription is license based, it will reduce the subscription quantity       |\n| CancelTeamAddonSubscription | Cancels an add-on subscription. If the add-on subscription is license based, it will reduce the subscription quantity       |\n| ResumeAddonSubscription     | Resume a cancelled add-on subscription (only available if the add-on subscription is license based and in the grace period) |\n| ResumeTeamAddonSubscription | Resume a cancelled add-on subscription (only available if the add-on subscription is license based and in the grace period) |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarktopper%2Fspark-addons","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarktopper%2Fspark-addons","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarktopper%2Fspark-addons/lists"}