syriable/laravel-converse

Marketplace-grade 1:1 messaging for Laravel: one thread per relationship, per-participant state, governed multi-type messages, and an event for everything.

Maintainers

Package info

github.com/syriable/laravel-converse

pkg:composer/syriable/laravel-converse

Transparency log

Fund package maintenance!

syriable

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.2.1 2026-07-18 18:58 UTC

This package is auto-updated.

Last update: 2026-07-18 19:05:27 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Marketplace-grade private messaging between two users — the messaging model behind platforms like Fiverr, generalized into a headless Laravel package: one trusted thread per relationship, private per-side state, governed multi-type messages, presence-aware notifications, and an event for everything.

$buyer->messageTo($seller)->text('Hi! Is this service available?')->send();

No routes, no views, no JavaScript, no broadcasting transport — Converse is a domain layer you build your own UI, API, and real-time transport on top of.

Key features

  • One conversation per pair — a unique normalized pair key, safe under concurrent creation, replaceable via the ConversationResolver contract.
  • Per-participant state — read horizon, unread counter, folders, star, hide, mute, notes, labels: every one-sided action is invisible to the other side.
  • Governed messages — a send-policy chain, an edit/delete window with an immutable revision log, soft delete only, and a pluggable moderation pipeline with human review.
  • Configurable message pipeline — whitespace normalization, exact-duplicate blocking, and opt-in PII masking, all reorderable and extensible with your own stages.
  • Structured message types — plain text and system messages built in; register your own validated types (offers, invoices, appointments).
  • Blocking & reporting — directional blocks that also stop new conversations from forming, plus message reporting delegated to Laravel Casework (cases, decisions, enforcement, appeals).
  • Attachments — Spatie Media Library on messages; MIME allowlist; participant-gated temporary URLs; per-file and per-sender size limits; optional prune retention.
  • Presence-aware notifications — online/offline from syriable/laravel-user-context; an offline recipient gets an email; an online one gets an immediate in-app notification; a recipient already viewing a thread gets no redundant notification. Per-channel preferences, debounced to avoid an email storm.
  • Event-driven — every domain change fires an event; build response-rate metrics, real-time broadcasts, CRM sync, or anything else as plain listeners.
  • TestableConverse::fake() plus purpose-built assertions, and every documented notification/presence interaction is testable with Notification::fake() alone.

Requirements

PHP 8.3+, Laravel 12 or 13. Requires syriable/laravel-user-context (presence, locale, timezone, location) and syriable/laravel-casework (reporting, cases, enforcement) — both are first-party companions installed automatically and are not optional.

Installation

composer require syriable/laravel-converse
php artisan converse:install

# Attachments (Spatie Media Library)
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="medialibrary-migrations"

# Reporting (Laravel Casework)
php artisan vendor:publish --provider="Syriable\Casework\CaseworkServiceProvider" --tag="casework-migrations"

php artisan migrate

# Seed the default report reasons Converse offers
php artisan db:seed --class="Syriable\Converse\Database\Seeders\ConverseReasonSeeder"

Add the trait to any model that should be able to converse:

use Syriable\Converse\Concerns\HasConversations;

class User extends Authenticatable
{
    use HasConversations;
}

Full walkthrough, including presence setup: docs/installation.md.

Quick start

// Send a message — resolves or creates the pair's conversation automatically.
$message = $buyer->messageTo($seller)->text('Can you design a minimal logo?')->send();

// Reply, attach a file, or send a structured type.
$buyer->messageTo($seller)->replyTo($message)->text('Sounds good!')->send();
$buyer->messageTo($seller)->text('Reference image attached')->attach($uploadedFile)->send();
$seller->messageTo($buyer)->custom('offer', ['price' => 120, 'days' => 4])->send();

// Read the inbox.
$buyer->conversations()->inbox()->cursorPaginate(20);
$message->conversation->messagesFor($buyer)->cursorPaginate(50);
$message->conversation->markReadBy($buyer);

// Organize.
$message->conversation->archiveFor($buyer);
$message->conversation->starFor($buyer);

// Block, report, moderate.
$buyer->block($seller, 'spam');
$message->reportBy($buyer, reason: 'inappropriate');

// Presence-aware notifications — nothing extra to call. An offline
// recipient gets emailed; an online one gets a real-time in-app
// notification instead, and never both.
$buyer->messageTo($seller)->text('Hello!')->send();     // routed automatically

Documentation

Everything beyond this landing page lives in docs/:

Page Covers
Installation Setup, requirements, verification
Configuration Every config key, explained
Architecture The mental model — start here for anything deep
Conversations Identity, resolution, listing, membership
Messages Sending, replies, editing, deleting, reading
Message Pipeline Text transformation, duplicate blocking, PII masking
Message Types Structured, validated message types
Moderation Automated moderation, verdicts, human review
Blocking Directional blocks and send refusal
Reporting User-filed reports via Laravel Casework
Attachments Media Library, MIME allowlist, retention, signed links
Organizing Conversations Folders, star, mute, hide, notes, labels
Presence & Real-Time Online/offline detection, active-conversation tracking
Notifications Channel routing, preferences, debounce, mail content
Events The complete domain event catalogue
Models Every Eloquent model, at a glance
Database Every table, column, and index
Lifecycle Message, conversation, attachment, and notification state machines
Commands converse:install, converse:doctor, converse:retention, converse:recount
Extension Points Every contract, in one place
Testing Converse::fake(), factories, testing patterns
Security The full security posture
Performance What's fast, what to watch, and why
Upgrading Version support and first-release adoption notes
Troubleshooting Symptom-first problem index
FAQ Common conceptual questions
Contributing Development setup, house style, PR conventions

Testing

composer test

Contributing

See docs/contributing.md for development setup, code style, and pull request conventions.

Security

If you discover a security vulnerability, please email the maintainer listed in composer.json directly rather than opening a public issue. See docs/security.md for the package's full security posture.

Credits

License

The MIT License (MIT). See LICENSE.md for more information.