LarsaSub is launching soon. Purchases and account registration open shortly.

Documentation for larsasub v0.38.2. On an older version? Your release notes ship with the package (CHANGELOG.md).

Setup

Everything between composer require and a working billing installation: running the installer, making a model billable, connecting Mollie, declaring your license tier, and publishing the assets you want to customize. For a shorter walk-through to a first subscriber, see Quick start.

Requirements

Requirement Version
PHP ^8.3
Laravel ^12.11 | ^13.0, a full application (the package uses framework services beyond the split Illuminate components)
Payment provider A Mollie account and API key
Optional barryvdh/laravel-dompdf ^3.1, for the built-in invoice PDFs

A live installation also needs a public HTTPS URL for the webhooks, cron and a queue worker; the full list is in Before you install.

Installing the package

LarsaSub is not on Packagist. composer require only resolves once you have registered the private repository on larsasub.eu and authenticated with your license token — without that, composer reports "package not found". See the installation guide on larsasub.eu/docs for the composer config lines.

composer require peters-development/larsasub
php artisan larsasub:install

larsasub:install publishes the configuration, publishes the built dashboard assets, runs the migrations and seeds the payment methods (all inactive). It also prints the license tier you declared, and warns when Mollie Connect is enabled on a tier that does not cover it.

It is safe to run again. Re-running is the supported way to publish the assets that ship with a new package version and to apply its migrations. Every step is idempotent: payment methods are seeded with firstOrCreate, and a published config/larsasub.php is kept — the installer never overwrites your customizations. Pass --force-config when you deliberately want the package default back.

The dashboard assets (--tag=larsasub-assets) are force-published, because they are build artifacts that must match the installed version; a stale bundle against a newer payload shape is a broken UI, not a customization.

Option Effect
--seed Seed two example subscription plans (fresh install only)
--active Seed active subscriptions and charges for existing billables (test data, fresh install only)
--active-payment-methods Activate every seeded payment method (fresh install only)
--vue-components Publish the Vue SFC sources, with the modules, translations and stylesheet they use, for your own SPA build (never overwritten once published)
--force-config Overwrite an existing config/larsasub.php with the package default
--skip-migrations Do not run migrations; run php artisan migrate yourself

The three demo-data options are the exception to "safe to run again": they only act on a fresh install, one where the LarsaSub tables do not exist yet. On an existing installation --seed, --active and --active-payment-methods are skipped with an explanation, because they would duplicate purchasable plans, re-enable payment methods an operator switched off, and attach demo subscriptions to existing billables. Reseed through your own seeder instead.

When --skip-migrations leaves a fresh installation without its tables, the installer seeds nothing and tells you to finish with php artisan migrate && php artisan larsasub:install.

Migrations. larsasub:install calls php artisan migrate, which applies all pending migrations in your application — not only this package's. An interactive run asks before doing so; a non-interactive run (--no-interaction, deploy scripts) proceeds and says so. Use --skip-migrations to keep the two steps apart.

Making a model billable

Any Eloquent model can hold subscriptions and payments. Implement Contracts\BillableModel and add the IsBillableModel trait, plus IsMollieBillableModel, which the Mollie provider needs, and HasSubscriptions for the subscription shortcuts:

<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use PetersDevelopment\LarsaSub\Contracts\BillableModel;
use PetersDevelopment\LarsaSub\PaymentProviders\Mollie\Traits\IsMollieBillableModel;
use PetersDevelopment\LarsaSub\Traits\HasSubscriptions;
use PetersDevelopment\LarsaSub\Traits\IsBillableModel;

class User extends Authenticatable implements BillableModel
{
    use HasSubscriptions;
    use IsBillableModel;
    use IsMollieBillableModel;

    public function getBillableNameAttribute(): string
    {
        return $this->name;
    }

    public function getBillableEmailAttribute(): string
    {
        return $this->email;
    }

    public function getBillableIdentifierAttribute(): string
    {
        return (string) $this->id;
    }
}

billable.model defaults to App\Models\User. When another model pays, point the config at it:

// config/larsasub.php
'billable' => [
    'model' => \App\Models\Team::class,
    'relation' => 'team',   // how to get from the signed-in user to the payer
],

Things worth knowing before you go further:

Connecting Mollie

MOLLIE_KEY=test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

A test_ key puts every provider call in test mode; that detection is what the package keys its own test-mode handling on, including OAuth access tokens in Connect mode.

Payment methods are seeded inactive. Activate the ones your Mollie account actually supports before you sell anything; the Quick start shows how, and Payment methods and mandates explains each flag.

Webhooks must be reachable from the internet. For local development, point LarsaSub at an ngrok tunnel:

LARSASUB_NGROK_DOMAIN=https://your-subdomain.ngrok.io

Schemeless values get https:// prepended.

Declaring your license tier

LarsaSub is sold in three tiers, and you declare yours in the configuration:

LARSASUB_LICENSE_TIER=single   # single (default), unlimited or platform
Tier Covers
single One production application
unlimited Any number of applications, with payments settling to your own Mollie account
platform Collecting payments on behalf of others: required for Mollie Connect

The declaration is a local value: nothing is verified, signed or sent anywhere, and the package never contacts larsasub.eu. The one check it makes is against Connect: with connect.enabled on and a tier other than platform, the package refuses to boot. Only a short list of recovery commands still runs then (larsasub:doctor, larsasub:install, larsasub:license, config:clear, vendor:publish and a few others), so you can repair the configuration.

php artisan larsasub:license

shows the declared tier and whether the enabled features fit it.

Running the scheduler and a queue worker

Planning, collecting, renewing and ending subscriptions all happen in scheduled commands that the package registers itself, so cron must run schedule:run every minute; without it nothing is ever charged. Notifications and several listeners are queued, so run a queue worker too: the sync queue runs mail inside the webhook request, and larsasub:doctor warns about it outside local and testing. See Scheduled commands for frequencies and overlap protection.

Publishing assets

larsasub:install publishes what a standard installation needs. To publish individual groups:

# Configuration
php artisan vendor:publish --tag=larsasub-config

# Database migrations. Optional: the package loads its migrations itself,
# so `php artisan migrate` runs them without publishing
php artisan vendor:publish --tag=larsasub-migrations

# Blade views (published to resources/views/vendor/LarsaSub — the path the
# view finder reads LarsaSub:: overrides from; edits there win over the package)
#
# All-or-nothing: this copies the ENTIRE view tree, and every file you keep is
# then frozen at the version you published it. Prefer one of the two narrow
# tags below if that is what you actually want.
php artisan vendor:publish --tag=larsasub-views

# The mail layout alone (emails/layout.blade.php) — the mail chrome: colours,
# wordmark, footer, dark-mode block. Nearly every mail customization is this
# one file, and taking only it keeps the 49 notification views on the package.
php artisan vendor:publish --tag=larsasub-email-layout

# The invoice/credit-note PDF views alone
php artisan vendor:publish --tag=larsasub-invoice-views

# Translation files (published to lang/vendor/larsasub — or
# resources/lang/vendor/larsasub when your app keeps its language files there;
# the tag follows langPath(), which is the only path the loader reads)
php artisan vendor:publish --tag=larsasub-translations

# Vue components (SFC sources, for your own SPA build), with the utils,
# types, composables and frontend.json they import and the larsasub.css
# whose tokens their classes use, under resources/vendor/larsasub; see BUILD.md
php artisan vendor:publish --tag=larsasub-vue-components

# Built standalone dashboard assets. Republishing over an older copy needs
# --force; larsasub:install always forces them
php artisan vendor:publish --tag=larsasub-assets --force

Dashboard assets and theming

The standalone dashboard assets in public/vendor/larsasub/ are fully self-contained:

Theming by the host app is optional and works in two layers:

  1. Theme view — larsasub.standalone.theme_view (default null) names a Blade view that the dashboard views include after larsasub.css. Put your stylesheet markup there, whatever your asset pipeline is: @vite(['resources/css/app.css']), <link href="{{ mix('css/app.css') }}">, or a plain <link> tag. Because the dashboards read shadcn-style tokens (--background, --primary, --card, …), a host stylesheet that defines those tokens on :root/.dark re-themes the dashboards automatically.

    // resources/views/larsasub-theme.blade.php contains your @vite call
    'standalone' => [
        'theme_view' => 'larsasub-theme',
    ],
    
  2. Tailwind source scanning (optional) — only needed if your stylesheet should restyle package markup with its own utilities. Tailwind v4 hosts can add @source '../../public/vendor/larsasub/*.js'; to their CSS entry so package classes are included in the host build. With the bundled larsasub.css this is not required for correct rendering.

See Standalone dashboards for routing, middleware and the per-dashboard switches.

Customizing the PDF templates

The built-in invoice and credit-note PDFs (resources/views/vendor/LarsaSub/pdf/* once published) are rendered by dompdf, which is safe as long as the template only receives escaped data. When customizing them:

dompdf is a suggested dependency, not a required one: composer require barryvdh/laravel-dompdf to use the built-in PDFs. Consumers that render invoices through an external service can skip it entirely by binding their own Contracts\InvoiceRenderer; the built-in renderer then throws a LarsaSubException naming the missing package rather than a class-not-found mid-stream. See Invoicing and VAT.

Verifying the installation

php artisan larsasub:doctor

larsasub:doctor checks the configuration for combinations that render fine and only fail later (a guard nothing authenticates, a tenant-context hook that can never fire), and it verifies the columns of every shipped table — not just that the tables exist. Before 0.37.1 the migrations were edited in place, so a database created from an earlier release can have nothing pending while migrate reports success, and the next scheduled run dies on Unknown column. Since 0.37.1 every schema change is a new migration.

AI coding agents (Laravel Boost)

LarsaSub ships guidance for the AI coding agent you work with, in the format Laravel Boost loads from installed packages:

File What it is When the agent sees it
resources/boost/guidelines/core.blade.php The rules: billing state goes through the services, payment status comes from the webhook, provider calls stay outside your transactions, the relation-versus-property trap Up front, in every session
resources/boost/skills/larsasub-development/SKILL.md Task recipes: subscribing, access checks, plan changes, cost lines, one-time payments, credit, refunds, events, Connect, testing On demand, when the task touches billing

With Boost installed, run boost:install, and boost:update after upgrading LarsaSub. Boost includes the guideline automatically, and installs the skill when you enable skills during installation:

php artisan boost:install

Both files point the agent at the documentation shipped in vendor/peters-development/larsasub/docs/, so it reads the pages for the version you have installed. Without Boost, nothing loads them, and nothing else in the package depends on them.

Next: Quick start for a working end-to-end example, or Configuration for the full list of settings.