sergeybruhin/nova-supportrays
Laravel Nova package by Sergey Bruhin that adds support-focused elements to your Nova admin panel, offering a lightweight way to surface help resources. Early-stage project with zero stars and limited documentation, so evaluate carefully before production use.
This is a Nova 4 tool that puts a SupportRays helpdesk inbox inside your admin panel, with every action performed under the logged-in Nova user's own SupportRays identity rather than a shared staff token. That single design decision drives most of the setup work: the person clicking "reply" must exist as a SupportRays manager with the same email address as their Nova account.
Minimum path to a working screen:
composer require sergeybruhin/nova-supportrays then php artisan migrate (the package stores each user's encrypted manager key locally).SUPPORTRAYS_BASE_URL and SUPPORTRAYS_PROJECT_UUID are non-optional; SUPPORTRAYS_PORTAL_URL, SUPPORTRAYS_INTEGRATION_NAME and SUPPORTRAYS_TIMEOUT are tuning knobs.NovaServiceProvider::tools():use SergeyBruhin\NovaSupportRays\NovaSupportRays;
public function tools()
{
return [
new NovaSupportRays,
];
}
viewNovaSupportRays gate. Do this before announcing the feature — the default gate behaviour is the first thing to verify in a staging deploy./nova/supportrays, and complete the one-time connection: a code is emailed to the address on your Nova user, and the resulting key is stored encrypted against that user.First real use case: open the «Без исполнителя» (unassigned) tab, search for a customer, assign the ticket to yourself, reply, and watch it move out of «Ждут ответа» (awaiting reply). That exercises connection, inbox filters, ticket page, assignment and the reply path in one pass. Do it with two different Nova users to confirm each gets their own identity rather than silently sharing one.
Treat connection state as user state, not app state. Because there's no shared staff token, onboarding is per-person and per-browser-session-agnostic. Build your rollout around that: a short internal doc ("check your inbox for the SupportRays code, connect once") beats a support ticket per person. There is no admin-level "connect for everyone" switch, so plan for new hires as a normal onboarding step.
Gate first, tool second. The viewNovaSupportRays gate is your only authorisation lever. A common pattern is to tie it to a Nova role/permission rather than true:
Gate::define('viewNovaSupportRays', fn ($user) => $user->hasRole('support'));
Keep it aligned with who actually exists as a SupportRays manager, otherwise people will see the menu item and hit a connect wall they can't complete.
Use TicketContextProvider for host-app context. This is the main extension point and the one that makes the tool feel native. Implement the contract to render your own sidebar cards — customer record, recent orders, subscription status, LTV — so an agent never has to open a second tab:
class CustomerContext implements TicketContextProvider
{
public function cards(Ticket $ticket): array
{
$customer = Customer::where('email', $ticket->requester_email)->first();
return [
// your Nova card / link definitions here
];
}
}
Resolve customer identity from the ticket's requester, and guard for null — tickets can come from people who never registered. Keep the queries cheap; this renders on every 20 s refresh of the ticket page.
Lean on the filters rather than building your own inbox. The four tabs with counts, plus search and status/priority/overdue filters, cover most triage. Teach the team the «Просрочено» (overdue) filter as the morning sweep — it maps directly onto SLA timers shown on the ticket page.
Use internal notes for the audit trail. Replies are customer-visible; notes are not. The idempotent write path means a double-click or a flaky network won't duplicate a message, so you can be relaxed about retries in your own tooling. Standardise on "note before you escalate" so change history reads sensibly.
Respect the polling budget. The inbox refreshes every 60 s and the ticket page every 20 s. Don't pin the ticket page on wall-mounted dashboards for a whole team and don't open dozens of tabs — each is live traffic against SupportRays through the proxy. Encourage "one ticket tab at a time".
Route any programmatic work through the proxy semantics. If you build sidecar tooling, mirror the package's behaviour: 401/403 from SupportRays becomes a 409 not_connected (never a Nova logout), and an outage returns 503. Your UI should render those as "reconnect your account" and "SupportRays is down, try later" respectively — not as generic errors.
Watchers and tags are your routing layer. Setting assignee, category, tags and watchers on the ticket page is cheap and makes the tabs meaningful. Convention example: a vip tag plus adding the account manager as watcher on anything from a top-tier customer.
+support suffixes, changed surnames) will connect and then see nothing useful, or fail to connect at all. Normalise before go-live.APP_KEY rotation carefully: rotating it without re-encrypting will break every stored key and force everyone to reconnect. Plan rotation as a comms event, not a silent deploy.not_connected (409) is not an auth failure. Don't wire generic 401 handling into this tool; a 409 means "this Nova user hasn't connected (or their key was revoked)". Catch it and render a connect prompt.SUPPORTRAYS_TIMEOUT with care — too low and slow-but-healthy API calls fail; too high and you erode that protection.SUPPORTRAYS_PORTAL_URL, or email) so they don't discover this mid-incident.new NovaSupportRays against an unmigrated database gives you a broken menu item; migrate first in every environment, including ephemeral review apps.SUPPORTRAYS_PROJECT_UUID pointing at the right project? That sequence resolves nearly every report.TicketContextProvider against your own database rather than trying to widen the proxy.How can I help you explore Laravel packages today?