<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: waiyan woody</title>
    <description>The latest articles on DEV Community by waiyan woody (@waiyan_woody_113f31a591fe).</description>
    <link>https://dev.to/waiyan_woody_113f31a591fe</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1836050%2F6ebaa328-53bf-4101-978d-8de53ef2c8d4.jpg</url>
      <title>DEV Community: waiyan woody</title>
      <link>https://dev.to/waiyan_woody_113f31a591fe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/waiyan_woody_113f31a591fe"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>waiyan woody</dc:creator>
      <pubDate>Sun, 23 Feb 2025 10:03:08 +0000</pubDate>
      <link>https://dev.to/waiyan_woody_113f31a591fe/-aoa</link>
      <guid>https://dev.to/waiyan_woody_113f31a591fe/-aoa</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/waiyan_woody_113f31a591fe" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1836050%2F6ebaa328-53bf-4101-978d-8de53ef2c8d4.jpg" alt="waiyan_woody_113f31a591fe"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/waiyan_woody_113f31a591fe/mastering-laravel-reverb-react-typescript-a-step-by-step-guide-to-real-time-broadcasting-3004" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Mastering Laravel Reverb &amp;amp; React TypeScript: A Step-by-Step Guide to Real-Time Broadcasting 🚀&lt;/h2&gt;
      &lt;h3&gt;waiyan woody ・ Feb 23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>laravel</category>
      <category>react</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Mastering Laravel Reverb &amp; React TypeScript: A Step-by-Step Guide to Real-Time Broadcasting 🚀</title>
      <dc:creator>waiyan woody</dc:creator>
      <pubDate>Sun, 23 Feb 2025 10:00:36 +0000</pubDate>
      <link>https://dev.to/waiyan_woody_113f31a591fe/mastering-laravel-reverb-react-typescript-a-step-by-step-guide-to-real-time-broadcasting-3004</link>
      <guid>https://dev.to/waiyan_woody_113f31a591fe/mastering-laravel-reverb-react-typescript-a-step-by-step-guide-to-real-time-broadcasting-3004</guid>
      <description>&lt;p&gt;Real-time broadcasting can be challenging, especially when setting up communication between a backend API and a frontend application — such as Laravel API with React.&lt;/p&gt;

&lt;p&gt;Laravel Reverb offers built-in support for monolithic applications, Inertia, and Livewire. However, when working with APIs, additional configuration steps are required. These steps can be complex for beginners, and finding solutions on platforms like YouTube or Stack Overflow isn’t always easy.&lt;/p&gt;

&lt;p&gt;In this guide, we walked through the installation, configuration, and setup process to ensure your backend and frontend communicate effectively using private channels.&lt;/p&gt;

&lt;p&gt;//Now let’s start&lt;/p&gt;

&lt;p&gt;First, we need to set up broadcasting in Laravel. Since we’re using Reverb,&lt;/p&gt;

&lt;p&gt;install it with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan install:broadcasting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted to install Reverb, select Yes&lt;br&gt;
⚠ Important: Since we are working with an API, &lt;br&gt;
we don't need to install the Node.js dependencies. &lt;br&gt;
When asked, choose No to skip the installation.&lt;br&gt;
and for client app (react) , we need to install laravel-echo and pusher-js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install laravel-echo pusher-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that you’ve installed all the required packages for both the frontend and backend, let’s proceed with the configuration.&lt;/p&gt;

&lt;p&gt;After installing Reverb, you’ll find the following credentials in your backend .env file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REVERB_APP_ID=000000
REVERB_APP_KEY=adfsadfadfsdfsdfsfsdf
REVERB_APP_SECRET=asdfasdfsdfsdf
REVERB_HOST="localhost"
REVERB_PORT=8080
REVERB_SCHEME=http
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;copy those credentials and write in your frontend .env like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_REVERB_APP_ID=000000
VITE_REVERB_APP_KEY=adfsadfadfsdfsdfsfsdf
VITE_REVERB_APP_SECRET=asdfasdfsdfsdf
VITE_REVERB_HOST="localhost"
VITE_REVERB_PORT=8080
VITE_REVERB_SCHEME=http
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since I’m using React with Vite, my .env configuration looks like this:&lt;/p&gt;

&lt;p&gt;If you’re using a different setup, your configuration may vary accordingly&lt;/p&gt;

&lt;p&gt;🔒Now, let’s move to the authorization step. If this isn’t configured properly, your application will encounter a 403 Forbidden error when accessing private channels.&lt;/p&gt;

&lt;p&gt;You need to configure bootstrap/app.php in your Laravel backend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-&amp;gt;withRouting(
    web: __DIR__ . '/../routes/web.php', 
    // you need to comment channel declaration here
    api: __DIR__ . '/../routes/api.php',

) 
// and add this to authorize your private channels
-&amp;gt;withBroadcasting(
    __DIR__ . '/../routes/channels.php',
    ['prefix' =&amp;gt; 'api', 'middleware' =&amp;gt; ['api', 'auth:sanctum']],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be sure to check your config/cors.php file. In the ‘allowed_origins’ setting, make sure to add the URL of your frontend application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'allowed_origins' =&amp;gt; [env('FRONTEND_URL', 'http://localhost:5173')],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the frontend, create a file named echo.js (or echo.ts if you're using TypeScript) and configure it as follows:&lt;/p&gt;

&lt;p&gt;This is the TypeScript example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import axios from "axios";
import Echo from "laravel-echo";
import Pusher from "pusher-js";

// Ensure TypeScript recognizes Pusher globally
declare global {
  interface Window {
    Pusher: typeof Pusher;
    Echo: Echo;
  }
}
window.Pusher = Pusher;
window.Echo = new Echo({
  broadcaster: "reverb",
  key: import.meta.env.VITE_REVERB_APP_KEY as string, // Explicitly cast environment variable
  authorizer: (channel, options) =&amp;gt; {
    return {
      authorize: (socketId: string, callback: (error: boolean, data: any) =&amp;gt; void) =&amp;gt; {
        axios
          .post("&amp;lt;http://127.0.0.1:8000/api/broadcasting/auth&amp;gt;", {
            socket_id: socketId,
            channel_name: channel.name,
          },{
                headers: {
                Authorization: `Bearer ${localStorage.getItem('token')}`,
                },
            })
          .then((response) =&amp;gt; {
            callback(false, response.data);
          })
          .catch((error) =&amp;gt; {
            callback(true, error);
          });
      },
    };
  },
  wsHost: import.meta.env.VITE_REVERB_HOST as string,
  wsPort: (import.meta.env.VITE_REVERB_PORT as unknown as number) ?? 80,
  wssPort: (import.meta.env.VITE_REVERB_PORT as unknown as number) ?? 443,
  forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? "https") === "https",
  enabledTransports: ["ws", "wss"],
});
export default window.Echo;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and For JavaScript you can configure like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import axios from "@/utils/axios";
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
authorizer: (channel, options) =&amp;gt; {
return {
authorize: (socketId, callback) =&amp;gt; {
axios.post('/api/broadcasting/auth', {
socket_id: socketId,
channel_name: [channel.name](&amp;lt;http://channel.name/&amp;gt;)
})
.then(response =&amp;gt; {
callback(false, response.data);
})
.catch(error =&amp;gt; {
callback(true, error);
});
}
};
},
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;//That’s all you need to do for the configuration! Now, let’s start both the backend and frontend:&lt;/p&gt;

&lt;p&gt;Start the Laravel backend&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start Laravel Reverb with debugging enabled&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan reverb:start --debug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the queue listener&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan queue:listen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the frontend&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s test this with a private channel ,&lt;/p&gt;

&lt;p&gt;First declare your private channel at routes/channels.php like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Private Channel (Only authenticated users can listen)
Broadcast::channel('private-chat.{userId}', function ($user, $userId) {
return (int) $user-&amp;gt;id === (int) $userId;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Private Channel → Only allows a specific user to listen (e.g., messages for userId).&lt;/p&gt;

&lt;p&gt;And Run this command to create an event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:event PrivateMessageEvent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, modify app/Events/PrivateMessageEvent.php:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class PrivateMessageEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels; 
    public string $message;
    public int $userId;

    public function __construct(string $message, int $userId)
     {
         $this-&amp;gt;message = $message;
         $this-&amp;gt;userId = $userId;
     }

     public function broadcastOn(): array
     {
         return [new PrivateChannel("private-chat.{$this-&amp;gt;userId}")];
     }

     public function broadcastAs(): string
     {
         return 'PrivateMessageEvent';
     } 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify routes/api.php to trigger test events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Send a private message
Route::get('/broadcast-private/{userId}', function ($userId) {
    event(new PrivateMessageEvent("Hello User {$userId}, this is a private message! 🚀", $userId));
    return response()-&amp;gt;json(['status' =&amp;gt; 'Private event sent']);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An example of how to use a private channel on the client side. Test in your react component like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//import your echo.js or echo 
import echo from "@/utils/echo";

useEffect(() =&amp;gt; {
    // Private Channel Listener
    const privateChannel = echo.private(`private-chat.${userId}`);
    privateChannel.listen(".PrivateMessageEvent", (data: { message: string }) =&amp;gt; {
      console.log("🔒 Private event received:", data);
      setPrivateMessage(data.message);
    });

    return () =&amp;gt; {
      privateChannel.stopListening(".PrivateMessageEvent");
    };
  }, [userId]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope this article helped you understand the setup process better! If you have any questions or run into issues, feel free to drop a comment or check out the reference video (&lt;a href="https://youtu.be/xEV7ruVUEvs" rel="noopener noreferrer"&gt;https://youtu.be/xEV7ruVUEvs&lt;/a&gt;) for more insights.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
