salla/laravel-starter-kit
A Laravel starter kit from Salla that scaffolds a modern PHP application with sensible defaults for authentication, authorization, settings, and admin-ready structure, helping teams skip boilerplate and launch maintainable Laravel apps faster.
Still a template repo, not a package — you don't composer require it into an existing app. Start from 3.0.0:
composer create-project salla/laravel-starter-kit my-salla-app
cd my-salla-app && cp .env.example .env && php artisan key:generate
3.0.0 is mostly a big dependency consolidation (dozens of Dependabot bumps merged in one go) plus a reorganized webhooks section in the README. That README pass is the first thing to read — it's the only place the event list and payload shapes are documented in-tree.
First places to look, in order:
routes/ — install flow, OAuth callback, and webhook endpoints..env.example / config/salla.php — SALLA_CLIENT_ID, SALLA_CLIENT_SECRET, SALLA_REDIRECT_URI, SALLA_WEBHOOK_SECRET.composer.json — confirm what you actually got. This release lands on laravel/framework 8.83.x and salla/ouath2-merchant 1.4.0 (note the typo in the package name — it's upstream, not you).app/Actions/ — the starter now pulls lorisleiva/laravel-actions 2.4.x; business logic is expected to live in action classes, not controllers or raw jobs.First use case: install the app on a dev store.
https://<ngrok-id>.ngrok.io/salla/callback.app.store.authorize and order.created.php artisan serve behind the tunnel, install on a test store, verify: token row written, callback 200, webhook payload in storage/logs/laravel.log.OAuth / Easy Mode flow. The starter handles the auth-code exchange via salla/ouath2-merchant. 3.0.0 bumps it 1.0.0 → 1.4.0, so treat the package as the source of truth for the exchange and token shape — don't hand-roll HTTP calls against the token endpoint, and re-read that package's changelog if you're upgrading an existing install. Add onboarding after the token save, never inside the callback controller; that controller must stay fast and idempotent.
Actions as the unit of work. With laravel-actions in the stack, the natural shape is:
verify signature → resolve store → MyEventAction::dispatch($storeId, $payloadId) → return 200
The same action class is callable three ways — from the webhook controller, from the queue, from php artisan — which kills the "test it by reinstalling" loop. Keep one action per event and an event→action map in config so adding a webhook is a one-line change and reviewers can see coverage in a single file.
Token-per-store model. Every Salla API call is scoped to a store, not a user. Pass the store_id explicitly into actions and requests. Salla apps are largely server-to-server; don't build features that assume a Laravel session.
Wrap the API client. Nothing outside the client touches raw tokens. Centralize SallaClient::for($store) — token lookup, proactive refresh, retry/backoff, error normalization. Everything else asks for a store-scoped client.
Agency / multi-app extension. Running several Salla apps off one codebase? Add an apps table and key tokens by (app_id, store_id). Branch config before requests reach controllers.
Local dev loop as a standing pattern. Tunnel + Partners dashboard + webhook replay is your inner loop. Keep a php artisan salla:replay <event> command that constructs the payload and calls the action directly — a few lines now that actions are first-class.
laravel/framework 8.83.x, not 9/10/11. If your org requires a supported major, budget a service-provider + Breeze + Inertia upgrade pass before you commit to the starter — $bindings/$singletons closure style and the Breeze scaffolding are the usual friction.daisyui 1.x → 3.x across this release range changes component class names and Tailwind config shape. If you kept the stock Breeze/Inertia UI, your screens will look wrong until you re-check the Tailwind + daisyUI config. axios, postcss, qs, json5, decode-uri-component bumps are security fixes — run npm install clean rather than restoring an old lockfile.larave… mid-list). Don't infer the full diff from them — run composer outdated / read composer.lock after install.http://localhost. Always tunnel.$request->getContent() bytes, not the parsed array. Re-encoding JSON breaks signatures — this is the #1 "webhook always fails" cause.SALLA_*, run php artisan config:clear, and clear config:cache on your queue workers too.Cache::lock("salla:refresh:$storeId"). Refresh-on-401 gives spiky latency and thundering-herd refreshes from parallel jobs.ShouldBeUnique — with laravel-actions the uniqueness middleware goes on the action/job, not the controller. Duplicate order.created double-charging customers is a real, common failure.SerializesModels but raw arrays don't compress. Pass the store id + the webhook event row id, and re-fetch inside handle() — otherwise large order payloads bloat the queue table.RateLimiter::for('salla', ...). Failed-webhook retries stack up and burn quota fast.dir="rtl" and lang/ar scaffolding before building screens you'd retrofit.composer update — you own the integration surface.How can I help you explore Laravel packages today?