quick-chat-react 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,294 @@
1
+ # quick-chat-react
2
+
3
+ Drop-in real-time chat for React apps built on **[Supabase](https://supabase.com)**.
4
+
5
+ > **Requires Supabase.** If your project uses Firebase, Auth0, or a custom backend, this library is not the right fit.
6
+
7
+ **Features:** real-time messaging · group conversations · voice messages · file & photo uploads · emoji reactions · read receipts · online status · contact management
8
+
9
+ ---
10
+
11
+ ## Use as your startup's base
12
+
13
+ `authMode="built-in"` gives you a complete user infrastructure in minutes — auth, profiles, real-time chat, file storage, and a navbar avatar component with sign out and theme switching. All production-ready on day one.
14
+
15
+ The **`profiles` table is yours.** The library only reads the columns it needs (`display_name`, `avatar_url`, `bio`, `is_online`, `last_seen`) — anything else you add is invisible to it and fully under your control. Extend it freely:
16
+
17
+ ```sql
18
+ ALTER TABLE public.profiles
19
+ ADD COLUMN IF NOT EXISTS plan TEXT DEFAULT 'free',
20
+ ADD COLUMN IF NOT EXISTS role TEXT DEFAULT 'member',
21
+ ADD COLUMN IF NOT EXISTS team_id UUID,
22
+ ADD COLUMN IF NOT EXISTS onboarded BOOLEAN DEFAULT false;
23
+ ```
24
+
25
+ Then read your custom fields with your own Supabase client alongside the library — no extra configuration needed. Gate library features by plan, drive onboarding flows from `onboarded`, restrict data by `team_id` via RLS — the library stays out of the way.
26
+
27
+ **→ Full guide: [Using quick-chat-react as a Startup Base](docs/startup-base.md)**
28
+
29
+ ---
30
+
31
+ ## Who it's for
32
+
33
+ - **Startups** — use built-in auth as your user system and extend the schema for your product
34
+ - **Lovable + Supabase projects** — add chat in 10 minutes, no backend changes needed
35
+ - Any **React + Supabase** app using email/password, Google, or GitHub auth
36
+ - Projects where chat users should be the same as your existing Supabase users
37
+
38
+ ## Compatibility
39
+
40
+ | Your setup | Supported |
41
+ |---|---|
42
+ | Fresh Supabase project | ✅ Yes |
43
+ | Supabase Auth (email/password) | ✅ Yes |
44
+ | Supabase OAuth (Google, GitHub) | ✅ Yes |
45
+ | Lovable + Supabase (no `profiles` table yet) | ✅ Yes |
46
+ | Lovable + Supabase (`profiles` table already exists) | ✅ Yes — [use the additive migration](docs/lovable-existing-schema.md) |
47
+ | Separate Supabase project for chat | ⚠️ Advanced — [see guide](docs/advanced-separate-project.md) |
48
+ | Firebase / Auth0 / custom auth backend | ❌ Not supported |
49
+
50
+ ---
51
+
52
+ ## Quick Start (10 minutes)
53
+
54
+ ```bash
55
+ npm install quick-chat-react
56
+ ```
57
+
58
+ ```ts
59
+ // main.tsx — import once
60
+ import "quick-chat-react/style.css";
61
+ ```
62
+
63
+ Run the migrations from [`/supabase/migrations/`](./supabase/migrations) in filename order via Supabase SQL Editor, then:
64
+
65
+ ```tsx
66
+ import { QuickChat } from "quick-chat-react";
67
+
68
+ export default function App() {
69
+ return (
70
+ <QuickChat
71
+ supabaseUrl={import.meta.env.VITE_SUPABASE_URL}
72
+ supabaseAnonKey={import.meta.env.VITE_SUPABASE_ANON_KEY}
73
+ />
74
+ );
75
+ }
76
+ ```
77
+
78
+ > **Already have a `profiles` table?** (Lovable-generated projects usually do.) Skip the standard migration files and run [`additive-for-existing-profiles.sql`](./supabase/migrations/additive-for-existing-profiles.sql) instead. See the [Lovable guide](docs/lovable-existing-schema.md).
79
+
80
+ Full step-by-step: [docs/quick-start.md](docs/quick-start.md)
81
+
82
+ ---
83
+
84
+ ## Auth Modes
85
+
86
+ ### Built-in auth (library handles login UI)
87
+
88
+ The library renders its own signup/login screens when the user is not signed in. Best for fresh projects with no existing auth.
89
+
90
+ ```tsx
91
+ <QuickChat
92
+ supabaseUrl={import.meta.env.VITE_SUPABASE_URL}
93
+ supabaseAnonKey={import.meta.env.VITE_SUPABASE_ANON_KEY}
94
+ // authMode="built-in" is the default — can be omitted
95
+ />
96
+ ```
97
+
98
+ ### External auth (pass your existing Supabase session)
99
+
100
+ Your app already has Supabase Auth. Pass the session tokens and the chat reuses the same logged-in user — no second login.
101
+
102
+ ```tsx
103
+ import { QuickChat } from "quick-chat-react";
104
+
105
+ // After your own supabase.auth.signIn...
106
+ const { data: { session } } = await supabase.auth.getSession();
107
+
108
+ <QuickChat
109
+ supabaseUrl={import.meta.env.VITE_SUPABASE_URL}
110
+ supabaseAnonKey={import.meta.env.VITE_SUPABASE_ANON_KEY}
111
+ authMode="external"
112
+ userData={{
113
+ id: session.user.id, // Supabase UUID — required
114
+ name: session.user.user_metadata.display_name ?? session.user.email,
115
+ avatar: session.user.user_metadata.avatar_url,
116
+ email: session.user.email,
117
+ accessToken: session.access_token, // required
118
+ refreshToken: session.refresh_token, // required for auto-refresh
119
+ }}
120
+ />
121
+ ```
122
+
123
+ Full guide with token refresh, OAuth setup, and profile sync: [docs/external-auth.md](docs/external-auth.md)
124
+
125
+ ---
126
+
127
+ ## Detailed Guides
128
+
129
+ | Guide | When to use |
130
+ |---|---|
131
+ | [Quick Start](docs/quick-start.md) | Fresh project, built-in auth, Lovable from scratch |
132
+ | [Startup Base](docs/startup-base.md) | Extending profiles, onboarding, plan gating, team isolation |
133
+ | [External Auth](docs/external-auth.md) | Already have Supabase Auth, want same-user chat |
134
+ | [Lovable Existing Schema](docs/lovable-existing-schema.md) | Lovable project with existing `profiles` table |
135
+ | [Separate Supabase Project](docs/advanced-separate-project.md) | Complete data isolation, separate billing |
136
+
137
+ ---
138
+
139
+ ## `ChatButton` component
140
+
141
+ A floating or inline button that shows the unread message count badge. Useful as an entry point to open a chat modal.
142
+
143
+ Pass `userData` with session tokens and the badge fetches and updates the unread count automatically via Supabase Realtime. `accessToken` and `refreshToken` are both required — Supabase Row Level Security rejects queries without a valid session.
144
+
145
+ ```tsx
146
+ import { ChatButton } from "quick-chat-react";
147
+
148
+ // Get the session from your own Supabase client after sign-in
149
+ const { data: { session } } = await supabase.auth.getSession();
150
+
151
+ <ChatButton
152
+ supabaseUrl={import.meta.env.VITE_SUPABASE_URL}
153
+ supabaseAnonKey={import.meta.env.VITE_SUPABASE_ANON_KEY}
154
+ userData={{
155
+ id: session.user.id,
156
+ name: session.user.user_metadata.display_name ?? session.user.email,
157
+ accessToken: session.access_token, // required — authenticates the Supabase query
158
+ refreshToken: session.refresh_token, // required — prevents session expiry after 1 h
159
+ }}
160
+ onClick={() => setIsChatOpen(true)}
161
+ />
162
+ ```
163
+
164
+ Full usage and customization guide: [docs/ChatButton.md](docs/ChatButton.md)
165
+
166
+ ---
167
+
168
+ ## `UserAvatar` component
169
+
170
+ A user avatar button for your navbar or header. When using `authMode="built-in"`, it detects the current session automatically — no extra wiring needed. On click it shows a dropdown with profile info, theme switcher (Light / Dark / System), and Sign out.
171
+
172
+ ```tsx
173
+ import { QuickChat, UserAvatar } from "quick-chat-react";
174
+
175
+ const url = import.meta.env.VITE_SUPABASE_URL;
176
+ const key = import.meta.env.VITE_SUPABASE_ANON_KEY;
177
+
178
+ export default function App() {
179
+ return (
180
+ <>
181
+ <nav className="flex items-center justify-between px-6 h-14 border-b">
182
+ <span className="font-semibold">My App</span>
183
+ <UserAvatar
184
+ supabaseUrl={url}
185
+ supabaseAnonKey={key}
186
+ authMode="built-in"
187
+ showName
188
+ />
189
+ </nav>
190
+ <QuickChat supabaseUrl={url} supabaseAnonKey={key} authMode="built-in" />
191
+ </>
192
+ );
193
+ }
194
+ ```
195
+
196
+ Full usage and customization guide: [docs/UserAvatar.md](docs/UserAvatar.md)
197
+
198
+ ---
199
+
200
+ ## Contact search
201
+
202
+ The chat sidebar includes a **Contacts** button (person+ icon) with two tabs:
203
+
204
+ - **My Contacts** — existing contacts with "Start chat" and "Remove" actions
205
+ - **Search** — type 2+ characters to find users by display name, then add them or start a chat directly
206
+
207
+ For a user to appear in search results they must have a `profiles` row in your Supabase database. This row is created automatically by a trigger whenever a Supabase auth user is created.
208
+
209
+ | Auth mode | What you need to do |
210
+ |-----------|---------------------|
211
+ | `built-in` | Nothing — profiles are created when users sign up through the built-in UI |
212
+ | `external` | Provision each user via the Admin API (`createUser`) as shown above — the trigger fires and creates the profile automatically |
213
+
214
+ ---
215
+
216
+ ## Props reference
217
+
218
+ ### `<QuickChat>`
219
+
220
+ | Prop | Type | Default | Description |
221
+ |---|---|---|---|
222
+ | `supabaseUrl` | `string` | — | **Required.** Your Supabase project URL. |
223
+ | `supabaseAnonKey` | `string` | — | **Required.** Your Supabase anon/public key. |
224
+ | `authMode` | `"built-in" \| "external"` | `"built-in"` | Auth flow to use. |
225
+ | `userData` | `UserData` | — | Required when `authMode="external"`. |
226
+ | `theme` | `"light" \| "dark" \| "system"` | `"system"` | UI color theme. |
227
+ | `showGroups` | `boolean` | `true` | Show group conversations in the sidebar. |
228
+ | `allowVoiceMessages` | `boolean` | `true` | Enable voice message recording. |
229
+ | `allowFileUpload` | `boolean` | `true` | Enable file and photo uploads. |
230
+ | `allowReactions` | `boolean` | `true` | Enable emoji reactions on messages. |
231
+ | `showOnlineStatus` | `boolean` | `true` | Show green online indicator dots. |
232
+ | `showReadReceipts` | `boolean` | `true` | Show read receipt checkmarks. |
233
+ | `height` | `string` | `"600px"` | Container height (any CSS value). |
234
+ | `width` | `string` | `"100%"` | Container width (any CSS value). |
235
+ | `onUnreadCountChange` | `(count: number) => void` | — | Fires when unread count changes. |
236
+ | `onConversationSelect` | `(id: string) => void` | — | Fires when a conversation is selected. |
237
+
238
+ ### `UserData`
239
+
240
+ | Field | Type | Required | Description |
241
+ |---|---|---|---|
242
+ | `id` | `string` | Yes | User's UUID. Must match `profiles.id` in Supabase. |
243
+ | `name` | `string` | Yes | Display name shown in chat. |
244
+ | `avatar` | `string` | No | Avatar image URL. |
245
+ | `email` | `string` | No | User's email address. |
246
+ | `description` | `string` | No | Short bio or role shown on profile. |
247
+ | `accessToken` | `string` | Yes (external mode) | Supabase JWT. Required for `authMode="external"`. |
248
+
249
+ ### `<ChatButton>`
250
+
251
+ | Prop | Type | Default | Description |
252
+ |---|---|---|---|
253
+ | `supabaseUrl` | `string` | — | **Required.** |
254
+ | `supabaseAnonKey` | `string` | — | **Required.** |
255
+ | `userData` | `UserData` | — | Needed to fetch unread count in external auth scenarios. |
256
+ | `onClick` | `() => void` | — | Click handler (e.g. open your chat modal). |
257
+ | `href` | `string` | — | Navigate to URL on click instead of `onClick`. |
258
+ | `position` | `"bottom-right" \| "bottom-left"` | `"bottom-right"` | Screen position (floating mode only). |
259
+ | `floating` | `boolean` | `true` | Fixed floating button. Set `false` for inline use. |
260
+ | `unreadCount` | `number` | — | Override unread count badge manually. |
261
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Button size. |
262
+ | `badgeColor` | `string` | — | Badge background color (CSS color value). |
263
+ | `buttonColor` | `string` | — | Button background color (CSS color value). |
264
+ | `iconColor` | `string` | — | Icon color (CSS color value). |
265
+ | `icon` | `ReactNode` | — | Custom icon element. |
266
+ | `label` | `string` | `"Open chat"` | Accessible aria-label for the button. |
267
+
268
+ ### `<UserAvatar>`
269
+
270
+ | Prop | Type | Default | Description |
271
+ |---|---|---|---|
272
+ | `supabaseUrl` | `string` | — | **Required.** |
273
+ | `supabaseAnonKey` | `string` | — | **Required.** |
274
+ | `authMode` | `"built-in" \| "external"` | `"built-in"` | Auth mode. `"built-in"` detects session automatically. |
275
+ | `userData` | `UserData` | — | Pass in external auth mode. |
276
+ | `showName` | `boolean` | `false` | Show display name next to the avatar. |
277
+ | `nameMaxLength` | `number` | `20` | Max characters before name is truncated with `…`. |
278
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Avatar size — `sm` 32 px, `md` 40 px, `lg` 48 px. |
279
+ | `floating` | `boolean` | `false` | Fixed floating element. Default is inline. |
280
+ | `position` | `"top-right" \| "top-left" \| "bottom-right" \| "bottom-left"` | `"top-right"` | Screen position (floating mode only). |
281
+ | `onThemeChange` | `(theme: string) => void` | — | Called when user picks a theme. |
282
+ | `onProfileClick` | `() => void` | — | Replace built-in profile dialog with custom handler. |
283
+ | `onLogout` | `() => void` | — | Called after sign-out completes (e.g. redirect to login). |
284
+ | `onLogin` | `() => void` | — | Called when "Sign in" is clicked (no active session). |
285
+ | `className` | `string` | — | Extra CSS classes on the trigger element. |
286
+ | `style` | `CSSProperties` | — | Inline styles on the trigger element. |
287
+
288
+ ---
289
+
290
+ ## Security notes
291
+
292
+ - The **anon key** is safe to expose on the frontend. All access is controlled by Supabase Row Level Security (RLS) policies — users can only read and write their own data.
293
+ - The **service role key** must never be exposed on the frontend. Use it only in your backend to generate access tokens.
294
+ - In external mode, `accessToken` grants the user access to Supabase. Treat it like a session token — send it over HTTPS, don't log it, and expire it appropriately.
Binary file