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

Staci Laravel Package

splash/staci

Staci is a Laravel package from Splash for turning your app into fast static HTML. It works with existing routes and Blade views to generate or cache pages, reducing server load and simplifying deployment to static hosting.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm what you're actually installing first. splash/staci is a Splash connector bundle, so it is an adapter, not a standalone address library. Before writing code, open the repo and check three files:

  1. composer.json — the require block tells you the supported Laravel/PHP range and, critically, which Splash core package (splash/connectors or similar) it depends on. That core package defines the interfaces your application code should actually depend on.
  2. config/staci.php (or whatever the published config is named) — this is where the embedded dataset path/connection and any credentials live.
  3. src/ — look for a ServiceProvider, a Connector class, and a Console/ directory. The console commands are usually the fastest way to understand the intended lifecycle (import → query).

Typical install:

composer require splash/staci
php artisan vendor:publish --tag=staci-config

Then read the config before running anything. "Embedded" almost always means the dataset lives locally (a SQLite file, a MySQL dump, or a bundled binary) rather than being called over HTTP, so there is usually a one-off import/install step:

php artisan staci:install    # or staci:import / staci:sync — check `php artisan list | grep staci`

Run that on a scratch database first. It is usually the slowest and most failure-prone part of the whole integration.

First use case — address lookup/validation. Start with the narrowest thing that proves the wiring works:

use Splash\Staci\Facades\Staci; // verify the real facade/alias in src/

$result = Staci::search('10 rue de la Paix, 75002');

If there is no facade, resolve the connector from the container (app(StaciConnector::class)) or inject it — the service provider is auto-discovered, so it should already be bound.

Once a single lookup returns data, you have validated config, dataset, and autoloading in one shot. Only then build the HTTP layer.

Implementation Patterns

Depend on the interface, not the connector. The whole point of a Splash connector bundle is swappability — embedded STACI for dev/CI and a remote or newer dataset in production. Type-hint against whatever interface from the Splash core the connector implements, and bind the concrete class in a service provider:

// AppServiceProvider::register()
$this->app->bind(AddressLookup::class, fn () => app(StaciConnector::class));

Now a test double is a one-line swap, and you can migrate connectors later without touching controllers.

Wrap it in a repository with a cache layer. Embedded lookups are fast but not free, and address data is extremely cacheable:

class AddressRepository
{
    public function __construct(private AddressLookup $staci) {}

    public function findByPostalCode(string $zip): Collection
    {
        return Cache::remember("staci:zip:{$zip}", now()->addDay(), fn () =>
            $this->staci->search(['postal_code' => $zip])
        );
    }
}

Invalidate by tag or by a version key that you bump after each dataset import (staci:v3:zip:75002). Tag-based flushing is cleaner if your cache driver supports it — check, because file and database drivers silently do not.

Autocomplete endpoint. The embedded connector is usually a synchronous, low-latency call, which makes it a good fit for a debounced typeahead. Keep the controller thin, throttle the route, and always cap the result count:

Route::get('/addresses', fn (Request $request) => AddressResource::collection(
    $repo->search($request->string('q'), limit: 8)
))->middleware('throttle:60,1');

Validation rule. A custom rule that confirms a postal-code/city pair exists is a high-value, low-risk first integration:

Validator::extend('staci_address', fn ($attr, $value) => $repo->exists($value));

Fail open here (log and pass) if the connector throws — you do not want an address dataset hiccup to block checkout.

Deployment pattern. Separate "import the dataset" from "deploy the code." The import is long-running and should run as a release step or a queued job, not inside a migration or a service provider boot(). Idempotent command + a data_version marker in the config or DB is the pattern to aim for.

Gotchas and Tips

  • Config caching bites on first deploy. php artisan config:cache after publishing but before setting env vars will freeze defaults. Publish, set env, then cache.
  • Dataset size vs. PHP memory. Embedded datasets are often hundreds of MB. If the connector loads rows into PHP collections, a broad search('') will exhaust memory_limit. Always filter and paginate at the query level; never ->all() on a full table.
  • Import timeouts. The install/import command will likely exceed default CLI limits on large dumps. Run it with an explicit higher limit and in chunks if the command supports --chunk. Wrap it in try/finally in your deploy script so a partial import fails the deploy loudly rather than leaving a half-populated table served to users.
  • Accents, case, and abbreviations. French address data is full of é/e, Saint-/St-, and leading zeros in department codes. Normalize input (lowercase, strip diacritics) on both write and read paths, and test "1 rue de l'Église" vs "1 rue de l'Eglise" explicitly. If the connector's search() is a simple LIKE, this is on you, not the package.
  • Database connection collisions. Embedded connectors often ship their own connection name or reuse the default. If the package defines a separate connection, migrations and transactions will not behave the way you expect — check whether DB::transaction() spans it. Never assume the connector participates in your app's transaction.
  • Don't import in tests. CI should use a small fixture SQLite file, or a faked implementation of the interface. The full dataset will make the suite unusable and the package's own test helpers (if any) are the intended path.
  • Logging. Wrap calls in a decorator that logs query, duration, and result count at debug. When results look wrong, the question is always "bad input, bad dataset version, or connector bug" — the log answers it in one look.
  • Extension points. Look for a StaciManager/factory-style class before you subclass anything. Splash bundles typically let you register drivers or override the container binding; that is the sanctioned way to add caching or retries, and it survives composer update far better than patching src/.
  • Low signal on the repo itself. Zero stars and zero dependents means no community debugging to lean on. Pin the version in composer.json, read the connector's tests as the de facto documentation, and be prepared to vendor-patch. Verify the dataset's licensing/update cadence before you build a production feature on it — embedded address data goes stale.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect