Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Stripe Laravel Package

tightenco/nova-stripe

Stripe metrics for Laravel Nova. Adds dashboard cards that pull monthly recurring revenue, new customers, churn, and subscription activity straight from the Stripe API, so you can monitor key billing stats inside Nova without leaving your admin panel.

View on GitHub
Deep Wiki
Context7

Getting Started

tightenco/nova-stripe v3 is effectively a new package. It is no longer a pair of dashboard cards that call Stripe on render. It now syncs Stripe records into your database — Products, Customers, Charges, Subscriptions — and exposes them as Nova resources with search, filters, and pagination. If you used v2, read this section as a migration, not an upgrade.

Minimal install:

composer require tightenco/nova-stripe

php artisan vendor:publish --provider="Tighten\NovaStripe\NovaStripeServiceProvider"
php artisan migrate

Publish both the config and the migrations (publish without --tag on first install, then prune). Set keys via env — never hard-code:

STRIPE_KEY=pk_test_xxx
STRIPE_SECRET=sk_test_xxx

Register the resources in app/Nova/NovaServiceProvider::resources() — this is the shift from v2, where you registered cards in cards():

public function resources()
{
    return [
        new \Tighten\NovaStripe\Resources\Charge,
        new \Tighten\NovaStripe\Resources\Customer,
        new \Tighten\NovaStripe\Resources\Product,
        new \Tighten\NovaStripe\Resources\Subscription,
    ];
}

Then populate the tables by running the package's sync command (check the service provider / src/Console for the exact signature in your installed tag) and, more importantly, put it on the scheduler.

Where to look first: src/ and the published database/migrations/. The README describes intent; the actual resource classes, table names, and config keys are what you'll be reading and overriding. Confirm the sync command name from the provider's commands() before assuming it.

First useful use case: a support-facing set of Nova resources for Customers and Subscriptions, synced hourly, so support can find a customer by email and see their subscription status and recent charges without touching the Stripe dashboard. That is the core value now — it just happens to require a scheduler and a database table to get there.

Implementation Patterns

Treat the sync as ETL, not as a cache. The package gives you the fetch-and-store layer; the cadence is your decision. A pragmatic setup:

// app/Console/Kernel.php (or routes/console.php on Laravel 11)
$schedule->command('nova-stripe:sync')->hourly();

Hourly is fine for support browsing. If finance watches failed charges live, run it every five minutes and accept the API cost — but understand that "live" now means "as fresh as your last run", which is a genuinely different guarantee than v2.

Gate the resources, not just the fields. Authorization is still yours. Use Nova policies or canSee/canRun on the resource and its actions:

public static function authorizedToViewAny($request)
{
    return $request->user()->hasRole('finance');
}

Customers and Subscriptions contain PII and revenue data; Charges contain amounts. Decide per-resource who sees what. A user who can reach the resource can browse every synced record.

Extend the resources rather than fork them. Subclass the package resource and add fields, metrics, or links:

namespace App\Nova;

use Tighten\NovaStripe\Resources\Customer as BaseCustomer;

class Customer extends BaseCustomer
{
    public function fields(NovaRequest $request)
    {
        return array_merge(parent::fields($request), [
            // your fields: account owner, internal org, MRR, etc.
        ]);
    }
}

This is also the mechanism for scoping: override indexQuery to restrict to a region/brand/tenant. Prefer this over editing vendor files.

Join synced Stripe data to your own models. This is the biggest new capability and the reason to adopt v3. Store stripe_id on your users/teams table, then relate:

public function stripeCustomer()
{
    return $this->belongsTo(\Tighten\NovaStripe\Models\Customer::class, 'stripe_id', 'stripe_id');
}

Now a Customer resource can show your internal account owner, and your own Nova resources can show subscription status. v2 could never do this because nothing was persisted.

Build the metrics v2 couldn't. With charges and subscriptions in SQL, "MRR this month", "failed charges last 7 days", and "refunds by product" become ordinary queries and ordinary Nova cards/metrics. Keep the package's resources for browsing and write your own trend cards against the synced tables — you now have history, so trends are possible.

Currency filtering is first-class. v3 adds currency filtering. If you settle in multiple currencies, lean on it rather than summing mixed-currency amounts. Do not let anyone add a total across currencies in a custom metric.

Staging vs production is now a data problem, not just a key problem. In v2, test keys produced fake cards that vanished with the env. In v3, test data is written into your database. Keep test and live syncs in separate databases, or at minimum separate tables via config, and never point a production database at test keys to "try it out" — you'll mix fake customers into real records.

Multi-account. The config is still a single key pair. For per-brand or per-region Stripe accounts, run a separate sync job per account (your own command wrapping StripeClient), tag rows with an account identifier, and scope resources with indexQuery. Hot-swapping the package config at runtime is not a viable pattern.

Gotchas and Tips

  • This is a breaking rewrite. The card classes (Balance, Charges), the card registration flow, and the config shape from v2 are gone or substantially changed. Any cards() entry referencing Tighten\NovaStripe\Cards\* will fail after upgrading. Plan the migration: publish new config/migrations, register resources, remove old cards, and delete the v2 config keys you no longer use.
  • The live balance card is gone. The release notes list Products, Customers, Charges, Subscriptions — no balance/account card. If your finance dashboard depended on it, that's a regression you must replace with your own card or a Stripe API call in a custom metric.
  • Freshness is now bounded by your cron. "No webhooks" was a v2 caveat and is still true: the sync is pull-based. A charge created one minute ago may not appear. State the sync interval to stakeholders so nobody treats the Nova table as a live ledger. If you need realtime, that's webhooks into your own tables — still not this package.
  • Deletions and drift. Pull-based syncs typically upsert; verify how the package handles records deleted or archived in Stripe. If they linger in your tables, your "active subscriptions" count will slowly rot. Check the sync implementation for a prune/truncate step, and schedule a full refresh periodically.
  • Rate limits on first sync. The initial run paginates your entire Stripe account. On a large account that's slow and can brush Stripe's rate limits. Run the first sync manually in a maintenance window, watch the output, and check row counts against the Stripe dashboard before trusting the data.
  • Verify idempotency. The sync should upsert on stripe_id. Confirm there's a unique index on it in the published migration; without one, repeated runs duplicate rows and your counts silently inflate. This is the first thing to check when numbers look wrong.
  • Indexes for Nova search/pagination. Search and filters run against your DB now. If the published migrations ship minimal indexes, add your own on stripe_id, customer/email, created_at, and currency — otherwise pagination degrades badly on large charge tables, which the package can't fix for you.
  • Secrets and config caching. Keep env() reads inside config/nova-stripe.php only. env() in a resource or card returns null once config:cache runs, and the failure looks like an auth error.
  • Timezone drift is still there. Stripe timestamps are UTC. Synced created_at values may be stored as-is or cast by the resource — check the field formatting in the resource before telling anyone the times are wrong.
  • Test keys leaking into production is now worse. In v2 it showed fake numbers. In v3 it writes fake records into your production tables. Add a deploy check on the sk_test_/sk_live_ prefix, and consider a visible "TEST MODE" banner in the resource header.
  • Debugging a blank or empty resource. Work outward: php artisan tinker and hit Stripe directly (\Stripe\Stripe::setApiKey(config('nova-stripe.secret')); \Stripe\Customer::all(['limit' => 1]);) to isolate keys/API access from Nova. Then verify the resource is registered in NovaServiceProvider::resources(). Then check the tables actually have rows — an empty resource is usually a sync that never ran or a scheduled command that failed silently. Run the sync manually with verbose output.
  • Silent scheduler failures. A cron that errors looks identical to "no new data". Add a failing-command notification (->onFailure(...) or Laravel's scheduler failure events) so a broken sync surfaces before finance does.
  • Version pairing. v3 is a rewrite with Laravel 11 support and a 2025 release; verify composer.json constraints against your Nova major (4/5) and PHP version before upgrading, and re-read src/ in the installed tag rather than relying on v2 docs, blog posts, or the current README.
  • Extension points. Subclass the resources, override fields/indexQuery, publish and edit views if needed, and build your own cards against the synced tables. With a narrow scope and a fresh rewrite, upstream PRs are slower than a local subclass — don't fork.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle