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

Escalated Laravel Laravel Package

escalated-dev/escalated-laravel

A full-featured, embeddable support ticket system for Laravel with SLA tracking, escalation rules, agent workflows, and a customer portal. Self-host or sync to cloud with one config change.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Build vs. buy for customer support: it replaces a paid helpdesk SaaS (Zendesk, Intercom, Freshdesk) with a self-hosted, MIT-licensed system inside an app you already operate — eliminating per-seat and per-ticket pricing from the support line item.
  • Roadmap acceleration: SLA policies, escalation rules, department routing, agent queues, canned responses, audit timelines, inbound email, a knowledge base, and an embeddable widget are all shipped features. That is typically one to two engineers for a quarter — decide whether support tooling is core to your differentiation or a commodity to import.
  • Support as a product surface, now beyond your own app: v1.9.4 makes the widget embeddable on any site — marketing pages, docs, a separate storefront, a partner portal — via a standalone embed.js script tag plus an allowlist of origins. This turns the decision from "do we add a support page" into "where do we want support to appear across our whole web estate," including properties that are not Laravel.
  • Retention and conversion bets: the embeddable /support/widget plus public KB search turn support into a product surface (deflection, self-service, guest tickets via magic links) rather than a cost center. Useful input for pricing/packaging decisions — e.g., gating SLA and branded email behind a paid tier.
  • Context capture on the widget: widget tickets and live chats now persist host-supplied metadata (order number, plan, page URL) as a sanitised flat map, alongside a server-recorded embedded_on origin. That is the difference between "a stranger typed something" and a support conversation with the customer's plan, order, and journey attached — a decision input for deflection quality, routing rules, and any support-to-revenue analytics you plan to build.
  • Data residency and compliance posture: self-hosted mode keeps all ticket PII in your own database with no external calls. That is a decision input for regulated or EU customers, and for security reviews that reject third-party subprocessors. Note the new cross-origin path is a deliberate, scoped relaxation (see below) rather than a new outbound dependency.
  • Commercial model strategy: the three hosting modes (self-hosted → synced → cloud) give a clean upgrade path from free OSS to paid multi-app unified inbox. If you are building a support-adjacent product line, this is a reference architecture worth studying even if you don't adopt.
  • Stack commitment: the frontend is Inertia.js + Vue 3, distributed as a separate npm package. Adopting this is a frontend architecture decision, not just a dependency — weigh it alongside any Blade/Livewire/React plans. The new embed.js route slightly softens this: the widget can now live on a non-Inertia site without that site adopting the frontend stack.
  • Extensibility decisions: ticket "subjects" (attach a Project, Customer, or asset to a ticket) and the Ticketable/TicketSubject contracts let you model support against your own domain objects. This shapes how deeply support is woven into the product versus bolted on.

When to Consider This Package

Adopt when:

  • You are on Laravel 11–13 / PHP 8.2+ and already use (or are willing to adopt) Inertia + Vue.
  • You need real ticketing semantics — SLAs, escalation, assignment, internal notes — not a contact form.
  • You want support reachable from multiple web properties — including static marketing sites, docs, or non-Laravel apps — without giving each one an integration; the origin allowlist plus embed.js covers this.
  • Support volume is modest and predictable; a single database is sufficient.
  • Seat-based SaaS costs are material relative to your revenue, or customer data cannot leave your infrastructure.
  • You want UUID/ULID host-model support without migration surgery (handled out of the box, with a user_key_type override).

Look elsewhere when:

  • Your stack is not Laravel, or your frontend is not Inertia/Vue — the UI layer is not portable. (The embedded widget is the one exception; the agent and admin surfaces are not.)
  • You need a mature integration ecosystem (Jira, Salesforce, Slack marketplace apps), vendor SLAs, or audited certifications (SOC 2, HIPAA BAAs). An OSS package with 28 stars and 0 dependents carries real single-vendor and bus-factor risk; treat escalated.dev as a dependency you cannot easily replace.
  • You expect very high ticket volume or strict scaling guarantees — there is no public evidence of production scale here.
  • Your requirements are genuinely thin (basic ticket CRUD, email-to-ticket only). The install surface — migrations, config, Tailwind sources, page resolver, gates, npm package — may cost more than a small in-house build.
  • You cannot tolerate a schema commitment: user-key column types are fixed at migration time, and switching key strategy later requires a manual migration.

Specific to v1.9.4:

  • The origin allowlist is empty by default, so upgrading changes nothing until a site is listed — low-risk to take the version.
  • When you do list an origin, requests from it skip the CSRF check and always run as a guest, with CORS headers returned (including on 422 and 429). Get security sign-off on that rule explicitly: it is correct for an anonymous embed, but it means an allowlisted origin can create guest tickets and live chats without a session. Keep the list tight, prefer exact origins over subdomain wildcards where practical, and use escalated.widget.serve_script to disable the script route if you don't embed externally.
  • Widget configuration was previously not persisted from the admin settings page — the controller dropped the fields, so the widget could not be switched on via the UI. If you trialled this earlier and concluded the widget was broken, re-evaluate; the fix is the difference between a shipped feature and a dead one.

Mitigations if adopting: pilot on one product surface, pin the version, keep the migrations under your own review, and confirm an exit path — the data lives in your database, so extraction is feasible even if the package is abandoned.

How to Pitch It (Stakeholders)

To executives: This is an MIT-licensed helpdesk we install into our Laravel app instead of renting one. It covers the capabilities customers actually evaluate — SLA tracking, escalation rules, an agent queue, a customer portal, a knowledge base, and an embedded support widget — and it ships in days rather than a quarter of engineering time. The latest release makes that widget embeddable on any of our sites with a single script tag, so support can appear on the marketing site, docs, and other properties without per-site integration work, and each conversation can carry context like plan or order number. Because it runs self-hosted by default, customer ticket data stays in our database, which simplifies security reviews and data-residency questions, and we remove per-agent SaaS fees from the support budget. The tradeoff is community size: the project has limited public adoption, so we should run it as a scoped pilot, monitor it, and retain a documented exit path. There is also a paid cloud tier available if we later want a unified inbox across multiple apps — a possible upsell path rather than a requirement.

To engineering: Laravel-native, Composer-installed, artisan escalated:install plus migrations, with a Vue 3 component library pulled from npm and wired through a page resolver. Authorization is via two Gates (escalated-admin, escalated-agent); host models opt in through Ticketable/HasTickets and optional TicketSubject implementations. User key types (integer, UUID, ULID, string) are auto-detected at migration time. Broadcasting is opt-in (Pusher/Reverb/Soketi) with polling fallback, email threading headers are handled, and code style is enforced with Pint in CI.

v1.9.4 adds a cross-origin embedding path: list origins in escalated.widget.allowed_origins (ESCALATED_WIDGET_ALLOWED_ORIGINS) or the admin widget_allowed_origins setting, with https://*.example.com wildcard support; listed origins get CORS headers (including on 422 and 429), bypass CSRF, and are forced to guest. GET {prefix}/widget/embed.js serves a standalone bundle from @escalated-dev/escalated, disableable via escalated.widget.serve_script. Widget tickets and chats now persist host metadata, sanitised to a flat map of short scalars, plus a server-set embedded_on origin; /config advertises accepts_metadata: true. Also fixed: admin settings now actually save widget_enabled, colour, position, greeting, and departments, and live-chat metadata is bounded like ticket metadata. The binding constraints remain the Inertia/Vue agent UI and the migration-time schema decisions — review both before we commit, and route the CSRF-exempt guest path through a security review.

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.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc