├── public ├── favicon.ico ├── robots.txt ├── index.php └── .htaccess ├── resources ├── css │ └── app.css ├── sass │ ├── _variables.scss │ └── app.scss ├── views │ ├── home.blade.php │ ├── auth │ │ ├── verify.blade.php │ │ ├── passwords │ │ │ ├── email.blade.php │ │ │ ├── confirm.blade.php │ │ │ └── reset.blade.php │ │ ├── login.blade.php │ │ └── register.blade.php │ ├── layouts │ │ └── app.blade.php │ └── welcome.blade.php └── js │ ├── echo.js │ ├── components │ ├── Main.jsx │ ├── Message.jsx │ ├── MessageInput.jsx │ └── ChatBox.jsx │ ├── app.js │ └── bootstrap.js ├── database ├── .gitignore ├── seeders │ └── DatabaseSeeder.php ├── migrations │ ├── 2024_03_25_000831_create_messages_table.php │ ├── 0001_01_01_000001_create_cache_table.php │ ├── 0001_01_01_000000_create_users_table.php │ └── 0001_01_01_000002_create_jobs_table.php └── factories │ └── UserFactory.php ├── bootstrap ├── cache │ └── .gitignore ├── providers.php └── app.php ├── storage ├── logs │ └── .gitignore ├── app │ ├── public │ │ └── .gitignore │ └── .gitignore └── framework │ ├── testing │ └── .gitignore │ ├── views │ └── .gitignore │ ├── cache │ ├── data │ │ └── .gitignore │ └── .gitignore │ ├── sessions │ └── .gitignore │ └── .gitignore ├── tests ├── TestCase.php ├── Unit │ └── ExampleTest.php └── Feature │ └── ExampleTest.php ├── .gitattributes ├── routes ├── console.php ├── channels.php └── web.php ├── .gitignore ├── .editorconfig ├── app ├── Http │ └── Controllers │ │ ├── Controller.php │ │ ├── Auth │ │ ├── ForgotPasswordController.php │ │ ├── ResetPasswordController.php │ │ ├── LoginController.php │ │ ├── ConfirmPasswordController.php │ │ ├── VerificationController.php │ │ └── RegisterController.php │ │ └── HomeController.php ├── Providers │ └── AppServiceProvider.php ├── Models │ ├── Message.php │ └── User.php ├── Jobs │ └── SendMessage.php └── Events │ └── GotMessage.php ├── artisan ├── vite.config.js ├── package.json ├── config ├── services.php ├── filesystems.php ├── broadcasting.php ├── mail.php ├── cache.php ├── queue.php ├── auth.php ├── app.php ├── logging.php ├── database.php └── session.php ├── phpunit.xml ├── .env.example ├── composer.json └── README.md /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/css/app.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite* 2 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /bootstrap/providers.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 8 | })->purpose('Display an inspiring quote')->hourly(); 9 | -------------------------------------------------------------------------------- /resources/views/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
11 |
12 |
13 |
14 | #### Installation:
15 |
16 | - **Pre-requisites**:
17 | - PHP >= 8.2
18 | - Composer
19 | - MySQL >= 5.7
20 | - Node.js >= 20
21 |
22 | - Clone the repository, or download the zip file and extract it.
23 | ```shell
24 | git clone git@github.com:boolfalse/laravel-reverb-react-chat.git && cd laravel-reverb-react-chat/
25 | ```
26 |
27 | - Copy the `.env.example` file to `.env`:
28 | ```shell
29 | cp .env.example .env
30 | ```
31 |
32 | - Install the dependencies.
33 | ```shell
34 | composer install
35 | ```
36 |
37 | - Generate the application key.
38 | ```shell
39 | php artisan key:generate
40 | ```
41 |
42 | - If you're planning to run the app on localhost using the default port, you can leave the `APP_URL` as is in the `.env` file:
43 | ```dotenv
44 | APP_URL=http://localhost
45 | ```
46 |
47 | - If you are planning to run the app on a different port or domain, set the `APP_URL` in the `.env` file:
48 | ```dotenv
49 | # a sample
50 | APP_URL=http://virtual-host.site
51 | ```
52 |
53 | - Create a MySQL database and set the database credentials in the `.env` file:
54 | ```dotenv
55 | DB_CONNECTION=mysql
56 | DB_HOST=127.0.0.1
57 | DB_PORT=3306
58 | DB_DATABASE="
128 |
129 | - If you are planning to use a custom domain (like `virtual-host.site`), make sure you have setup `APP_URL` in the `.env` file correctly as mentioned a few steps above.
130 |
131 | In the screenshot below is the case when two only commands are running: `php artisan queue:listen` and `php artisan reverb:start`.
132 |
138 |
139 | - Open the application in two different browser windows (or with normal and incognito mode), register two or more users, and start chatting with each other.
140 |
141 |
142 |
143 | #### Author:
144 |
145 | - [BoolFalse](https://boolfalse.com/)
146 |
--------------------------------------------------------------------------------
/config/database.php:
--------------------------------------------------------------------------------
1 | env('DB_CONNECTION', 'sqlite'),
20 |
21 | /*
22 | |--------------------------------------------------------------------------
23 | | Database Connections
24 | |--------------------------------------------------------------------------
25 | |
26 | | Below are all of the database connections defined for your application.
27 | | An example configuration is provided for each database system which
28 | | is supported by Laravel. You're free to add / remove connections.
29 | |
30 | */
31 |
32 | 'connections' => [
33 |
34 | 'sqlite' => [
35 | 'driver' => 'sqlite',
36 | 'url' => env('DB_URL'),
37 | 'database' => env('DB_DATABASE', database_path('database.sqlite')),
38 | 'prefix' => '',
39 | 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
40 | ],
41 |
42 | 'mysql' => [
43 | 'driver' => 'mysql',
44 | 'url' => env('DB_URL'),
45 | 'host' => env('DB_HOST', '127.0.0.1'),
46 | 'port' => env('DB_PORT', '3306'),
47 | 'database' => env('DB_DATABASE', 'laravel'),
48 | 'username' => env('DB_USERNAME', 'root'),
49 | 'password' => env('DB_PASSWORD', ''),
50 | 'unix_socket' => env('DB_SOCKET', ''),
51 | 'charset' => env('DB_CHARSET', 'utf8mb4'),
52 | 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
53 | 'prefix' => '',
54 | 'prefix_indexes' => true,
55 | 'strict' => true,
56 | 'engine' => null,
57 | 'options' => extension_loaded('pdo_mysql') ? array_filter([
58 | PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
59 | ]) : [],
60 | ],
61 |
62 | 'mariadb' => [
63 | 'driver' => 'mariadb',
64 | 'url' => env('DB_URL'),
65 | 'host' => env('DB_HOST', '127.0.0.1'),
66 | 'port' => env('DB_PORT', '3306'),
67 | 'database' => env('DB_DATABASE', 'laravel'),
68 | 'username' => env('DB_USERNAME', 'root'),
69 | 'password' => env('DB_PASSWORD', ''),
70 | 'unix_socket' => env('DB_SOCKET', ''),
71 | 'charset' => env('DB_CHARSET', 'utf8mb4'),
72 | 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
73 | 'prefix' => '',
74 | 'prefix_indexes' => true,
75 | 'strict' => true,
76 | 'engine' => null,
77 | 'options' => extension_loaded('pdo_mysql') ? array_filter([
78 | PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
79 | ]) : [],
80 | ],
81 |
82 | 'pgsql' => [
83 | 'driver' => 'pgsql',
84 | 'url' => env('DB_URL'),
85 | 'host' => env('DB_HOST', '127.0.0.1'),
86 | 'port' => env('DB_PORT', '5432'),
87 | 'database' => env('DB_DATABASE', 'laravel'),
88 | 'username' => env('DB_USERNAME', 'root'),
89 | 'password' => env('DB_PASSWORD', ''),
90 | 'charset' => env('DB_CHARSET', 'utf8'),
91 | 'prefix' => '',
92 | 'prefix_indexes' => true,
93 | 'search_path' => 'public',
94 | 'sslmode' => 'prefer',
95 | ],
96 |
97 | 'sqlsrv' => [
98 | 'driver' => 'sqlsrv',
99 | 'url' => env('DB_URL'),
100 | 'host' => env('DB_HOST', 'localhost'),
101 | 'port' => env('DB_PORT', '1433'),
102 | 'database' => env('DB_DATABASE', 'laravel'),
103 | 'username' => env('DB_USERNAME', 'root'),
104 | 'password' => env('DB_PASSWORD', ''),
105 | 'charset' => env('DB_CHARSET', 'utf8'),
106 | 'prefix' => '',
107 | 'prefix_indexes' => true,
108 | // 'encrypt' => env('DB_ENCRYPT', 'yes'),
109 | // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
110 | ],
111 |
112 | ],
113 |
114 | /*
115 | |--------------------------------------------------------------------------
116 | | Migration Repository Table
117 | |--------------------------------------------------------------------------
118 | |
119 | | This table keeps track of all the migrations that have already run for
120 | | your application. Using this information, we can determine which of
121 | | the migrations on disk haven't actually been run on the database.
122 | |
123 | */
124 |
125 | 'migrations' => [
126 | 'table' => 'migrations',
127 | 'update_date_on_publish' => true,
128 | ],
129 |
130 | /*
131 | |--------------------------------------------------------------------------
132 | | Redis Databases
133 | |--------------------------------------------------------------------------
134 | |
135 | | Redis is an open source, fast, and advanced key-value store that also
136 | | provides a richer body of commands than a typical key-value system
137 | | such as Memcached. You may define your connection settings here.
138 | |
139 | */
140 |
141 | 'redis' => [
142 |
143 | 'client' => env('REDIS_CLIENT', 'phpredis'),
144 |
145 | 'options' => [
146 | 'cluster' => env('REDIS_CLUSTER', 'redis'),
147 | 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
148 | ],
149 |
150 | 'default' => [
151 | 'url' => env('REDIS_URL'),
152 | 'host' => env('REDIS_HOST', '127.0.0.1'),
153 | 'username' => env('REDIS_USERNAME'),
154 | 'password' => env('REDIS_PASSWORD'),
155 | 'port' => env('REDIS_PORT', '6379'),
156 | 'database' => env('REDIS_DB', '0'),
157 | ],
158 |
159 | 'cache' => [
160 | 'url' => env('REDIS_URL'),
161 | 'host' => env('REDIS_HOST', '127.0.0.1'),
162 | 'username' => env('REDIS_USERNAME'),
163 | 'password' => env('REDIS_PASSWORD'),
164 | 'port' => env('REDIS_PORT', '6379'),
165 | 'database' => env('REDIS_CACHE_DB', '1'),
166 | ],
167 |
168 | ],
169 |
170 | ];
171 |
--------------------------------------------------------------------------------
/config/session.php:
--------------------------------------------------------------------------------
1 | env('SESSION_DRIVER', 'database'),
22 |
23 | /*
24 | |--------------------------------------------------------------------------
25 | | Session Lifetime
26 | |--------------------------------------------------------------------------
27 | |
28 | | Here you may specify the number of minutes that you wish the session
29 | | to be allowed to remain idle before it expires. If you want them
30 | | to expire immediately when the browser is closed then you may
31 | | indicate that via the expire_on_close configuration option.
32 | |
33 | */
34 |
35 | 'lifetime' => env('SESSION_LIFETIME', 120),
36 |
37 | 'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
38 |
39 | /*
40 | |--------------------------------------------------------------------------
41 | | Session Encryption
42 | |--------------------------------------------------------------------------
43 | |
44 | | This option allows you to easily specify that all of your session data
45 | | should be encrypted before it's stored. All encryption is performed
46 | | automatically by Laravel and you may use the session like normal.
47 | |
48 | */
49 |
50 | 'encrypt' => env('SESSION_ENCRYPT', false),
51 |
52 | /*
53 | |--------------------------------------------------------------------------
54 | | Session File Location
55 | |--------------------------------------------------------------------------
56 | |
57 | | When utilizing the "file" session driver, the session files are placed
58 | | on disk. The default storage location is defined here; however, you
59 | | are free to provide another location where they should be stored.
60 | |
61 | */
62 |
63 | 'files' => storage_path('framework/sessions'),
64 |
65 | /*
66 | |--------------------------------------------------------------------------
67 | | Session Database Connection
68 | |--------------------------------------------------------------------------
69 | |
70 | | When using the "database" or "redis" session drivers, you may specify a
71 | | connection that should be used to manage these sessions. This should
72 | | correspond to a connection in your database configuration options.
73 | |
74 | */
75 |
76 | 'connection' => env('SESSION_CONNECTION'),
77 |
78 | /*
79 | |--------------------------------------------------------------------------
80 | | Session Database Table
81 | |--------------------------------------------------------------------------
82 | |
83 | | When using the "database" session driver, you may specify the table to
84 | | be used to store sessions. Of course, a sensible default is defined
85 | | for you; however, you're welcome to change this to another table.
86 | |
87 | */
88 |
89 | 'table' => env('SESSION_TABLE', 'sessions'),
90 |
91 | /*
92 | |--------------------------------------------------------------------------
93 | | Session Cache Store
94 | |--------------------------------------------------------------------------
95 | |
96 | | When using one of the framework's cache driven session backends, you may
97 | | define the cache store which should be used to store the session data
98 | | between requests. This must match one of your defined cache stores.
99 | |
100 | | Affects: "apc", "dynamodb", "memcached", "redis"
101 | |
102 | */
103 |
104 | 'store' => env('SESSION_STORE'),
105 |
106 | /*
107 | |--------------------------------------------------------------------------
108 | | Session Sweeping Lottery
109 | |--------------------------------------------------------------------------
110 | |
111 | | Some session drivers must manually sweep their storage location to get
112 | | rid of old sessions from storage. Here are the chances that it will
113 | | happen on a given request. By default, the odds are 2 out of 100.
114 | |
115 | */
116 |
117 | 'lottery' => [2, 100],
118 |
119 | /*
120 | |--------------------------------------------------------------------------
121 | | Session Cookie Name
122 | |--------------------------------------------------------------------------
123 | |
124 | | Here you may change the name of the session cookie that is created by
125 | | the framework. Typically, you should not need to change this value
126 | | since doing so does not grant a meaningful security improvement.
127 | |
128 | |
129 | */
130 |
131 | 'cookie' => env(
132 | 'SESSION_COOKIE',
133 | Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
134 | ),
135 |
136 | /*
137 | |--------------------------------------------------------------------------
138 | | Session Cookie Path
139 | |--------------------------------------------------------------------------
140 | |
141 | | The session cookie path determines the path for which the cookie will
142 | | be regarded as available. Typically, this will be the root path of
143 | | your application, but you're free to change this when necessary.
144 | |
145 | */
146 |
147 | 'path' => env('SESSION_PATH', '/'),
148 |
149 | /*
150 | |--------------------------------------------------------------------------
151 | | Session Cookie Domain
152 | |--------------------------------------------------------------------------
153 | |
154 | | This value determines the domain and subdomains the session cookie is
155 | | available to. By default, the cookie will be available to the root
156 | | domain and all subdomains. Typically, this shouldn't be changed.
157 | |
158 | */
159 |
160 | 'domain' => env('SESSION_DOMAIN'),
161 |
162 | /*
163 | |--------------------------------------------------------------------------
164 | | HTTPS Only Cookies
165 | |--------------------------------------------------------------------------
166 | |
167 | | By setting this option to true, session cookies will only be sent back
168 | | to the server if the browser has a HTTPS connection. This will keep
169 | | the cookie from being sent to you when it can't be done securely.
170 | |
171 | */
172 |
173 | 'secure' => env('SESSION_SECURE_COOKIE'),
174 |
175 | /*
176 | |--------------------------------------------------------------------------
177 | | HTTP Access Only
178 | |--------------------------------------------------------------------------
179 | |
180 | | Setting this value to true will prevent JavaScript from accessing the
181 | | value of the cookie and the cookie will only be accessible through
182 | | the HTTP protocol. It's unlikely you should disable this option.
183 | |
184 | */
185 |
186 | 'http_only' => env('SESSION_HTTP_ONLY', true),
187 |
188 | /*
189 | |--------------------------------------------------------------------------
190 | | Same-Site Cookies
191 | |--------------------------------------------------------------------------
192 | |
193 | | This option determines how your cookies behave when cross-site requests
194 | | take place, and can be used to mitigate CSRF attacks. By default, we
195 | | will set this value to "lax" to permit secure cross-site requests.
196 | |
197 | | See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
198 | |
199 | | Supported: "lax", "strict", "none", null
200 | |
201 | */
202 |
203 | 'same_site' => env('SESSION_SAME_SITE', 'lax'),
204 |
205 | /*
206 | |--------------------------------------------------------------------------
207 | | Partitioned Cookies
208 | |--------------------------------------------------------------------------
209 | |
210 | | Setting this value to true will tie the cookie to the top-level site for
211 | | a cross-site context. Partitioned cookies are accepted by the browser
212 | | when flagged "secure" and the Same-Site attribute is set to "none".
213 | |
214 | */
215 |
216 | 'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
217 |
218 | ];
219 |
--------------------------------------------------------------------------------
/resources/views/welcome.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |