hazo_chat 1.1.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.
Files changed (135) hide show
  1. package/README.md +437 -0
  2. package/SETUP_CHECKLIST.md +858 -0
  3. package/dist/components/hazo_chat/hazo_chat.d.ts +16 -0
  4. package/dist/components/hazo_chat/hazo_chat.d.ts.map +1 -0
  5. package/dist/components/hazo_chat/hazo_chat.js +155 -0
  6. package/dist/components/hazo_chat/hazo_chat.js.map +1 -0
  7. package/dist/components/hazo_chat/hazo_chat_attachment_preview.d.ts +17 -0
  8. package/dist/components/hazo_chat/hazo_chat_attachment_preview.d.ts.map +1 -0
  9. package/dist/components/hazo_chat/hazo_chat_attachment_preview.js +60 -0
  10. package/dist/components/hazo_chat/hazo_chat_attachment_preview.js.map +1 -0
  11. package/dist/components/hazo_chat/hazo_chat_context.d.ts +36 -0
  12. package/dist/components/hazo_chat/hazo_chat_context.d.ts.map +1 -0
  13. package/dist/components/hazo_chat/hazo_chat_context.js +249 -0
  14. package/dist/components/hazo_chat/hazo_chat_context.js.map +1 -0
  15. package/dist/components/hazo_chat/hazo_chat_document_viewer.d.ts +15 -0
  16. package/dist/components/hazo_chat/hazo_chat_document_viewer.d.ts.map +1 -0
  17. package/dist/components/hazo_chat/hazo_chat_document_viewer.js +111 -0
  18. package/dist/components/hazo_chat/hazo_chat_document_viewer.js.map +1 -0
  19. package/dist/components/hazo_chat/hazo_chat_header.d.ts +16 -0
  20. package/dist/components/hazo_chat/hazo_chat_header.d.ts.map +1 -0
  21. package/dist/components/hazo_chat/hazo_chat_header.js +24 -0
  22. package/dist/components/hazo_chat/hazo_chat_header.js.map +1 -0
  23. package/dist/components/hazo_chat/hazo_chat_input.d.ts +18 -0
  24. package/dist/components/hazo_chat/hazo_chat_input.d.ts.map +1 -0
  25. package/dist/components/hazo_chat/hazo_chat_input.js +134 -0
  26. package/dist/components/hazo_chat/hazo_chat_input.js.map +1 -0
  27. package/dist/components/hazo_chat/hazo_chat_messages.d.ts +17 -0
  28. package/dist/components/hazo_chat/hazo_chat_messages.d.ts.map +1 -0
  29. package/dist/components/hazo_chat/hazo_chat_messages.js +109 -0
  30. package/dist/components/hazo_chat/hazo_chat_messages.js.map +1 -0
  31. package/dist/components/hazo_chat/hazo_chat_reference_list.d.ts +16 -0
  32. package/dist/components/hazo_chat/hazo_chat_reference_list.d.ts.map +1 -0
  33. package/dist/components/hazo_chat/hazo_chat_reference_list.js +59 -0
  34. package/dist/components/hazo_chat/hazo_chat_reference_list.js.map +1 -0
  35. package/dist/components/hazo_chat/hazo_chat_sidebar.d.ts +18 -0
  36. package/dist/components/hazo_chat/hazo_chat_sidebar.d.ts.map +1 -0
  37. package/dist/components/hazo_chat/hazo_chat_sidebar.js +72 -0
  38. package/dist/components/hazo_chat/hazo_chat_sidebar.js.map +1 -0
  39. package/dist/components/hazo_chat/index.d.ts +16 -0
  40. package/dist/components/hazo_chat/index.d.ts.map +1 -0
  41. package/dist/components/hazo_chat/index.js +19 -0
  42. package/dist/components/hazo_chat/index.js.map +1 -0
  43. package/dist/components/index.d.ts +9 -0
  44. package/dist/components/index.d.ts.map +1 -0
  45. package/dist/components/index.js +11 -0
  46. package/dist/components/index.js.map +1 -0
  47. package/dist/components/ui/avatar.d.ts +13 -0
  48. package/dist/components/ui/avatar.d.ts.map +1 -0
  49. package/dist/components/ui/avatar.js +28 -0
  50. package/dist/components/ui/avatar.js.map +1 -0
  51. package/dist/components/ui/badge.d.ts +16 -0
  52. package/dist/components/ui/badge.d.ts.map +1 -0
  53. package/dist/components/ui/badge.js +36 -0
  54. package/dist/components/ui/badge.js.map +1 -0
  55. package/dist/components/ui/button.d.ts +18 -0
  56. package/dist/components/ui/button.d.ts.map +1 -0
  57. package/dist/components/ui/button.js +47 -0
  58. package/dist/components/ui/button.js.map +1 -0
  59. package/dist/components/ui/chat_bubble.d.ts +19 -0
  60. package/dist/components/ui/chat_bubble.d.ts.map +1 -0
  61. package/dist/components/ui/chat_bubble.js +101 -0
  62. package/dist/components/ui/chat_bubble.js.map +1 -0
  63. package/dist/components/ui/index.d.ts +18 -0
  64. package/dist/components/ui/index.d.ts.map +1 -0
  65. package/dist/components/ui/index.js +20 -0
  66. package/dist/components/ui/index.js.map +1 -0
  67. package/dist/components/ui/input.d.ts +11 -0
  68. package/dist/components/ui/input.d.ts.map +1 -0
  69. package/dist/components/ui/input.js +18 -0
  70. package/dist/components/ui/input.js.map +1 -0
  71. package/dist/components/ui/loading_skeleton.d.ts +19 -0
  72. package/dist/components/ui/loading_skeleton.d.ts.map +1 -0
  73. package/dist/components/ui/loading_skeleton.js +30 -0
  74. package/dist/components/ui/loading_skeleton.js.map +1 -0
  75. package/dist/components/ui/scroll-area.d.ts +12 -0
  76. package/dist/components/ui/scroll-area.d.ts.map +1 -0
  77. package/dist/components/ui/scroll-area.js +25 -0
  78. package/dist/components/ui/scroll-area.js.map +1 -0
  79. package/dist/components/ui/separator.d.ts +11 -0
  80. package/dist/components/ui/separator.d.ts.map +1 -0
  81. package/dist/components/ui/separator.js +18 -0
  82. package/dist/components/ui/separator.js.map +1 -0
  83. package/dist/components/ui/skeleton.d.ts +9 -0
  84. package/dist/components/ui/skeleton.d.ts.map +1 -0
  85. package/dist/components/ui/skeleton.js +16 -0
  86. package/dist/components/ui/skeleton.js.map +1 -0
  87. package/dist/components/ui/textarea.d.ts +11 -0
  88. package/dist/components/ui/textarea.d.ts.map +1 -0
  89. package/dist/components/ui/textarea.js +18 -0
  90. package/dist/components/ui/textarea.js.map +1 -0
  91. package/dist/components/ui/tooltip.d.ts +14 -0
  92. package/dist/components/ui/tooltip.d.ts.map +1 -0
  93. package/dist/components/ui/tooltip.js +30 -0
  94. package/dist/components/ui/tooltip.js.map +1 -0
  95. package/dist/hooks/index.d.ts +10 -0
  96. package/dist/hooks/index.d.ts.map +1 -0
  97. package/dist/hooks/index.js +10 -0
  98. package/dist/hooks/index.js.map +1 -0
  99. package/dist/hooks/use_chat_messages.d.ts +25 -0
  100. package/dist/hooks/use_chat_messages.d.ts.map +1 -0
  101. package/dist/hooks/use_chat_messages.js +430 -0
  102. package/dist/hooks/use_chat_messages.js.map +1 -0
  103. package/dist/hooks/use_chat_references.d.ts +17 -0
  104. package/dist/hooks/use_chat_references.d.ts.map +1 -0
  105. package/dist/hooks/use_chat_references.js +133 -0
  106. package/dist/hooks/use_chat_references.js.map +1 -0
  107. package/dist/hooks/use_file_upload.d.ts +23 -0
  108. package/dist/hooks/use_file_upload.d.ts.map +1 -0
  109. package/dist/hooks/use_file_upload.js +212 -0
  110. package/dist/hooks/use_file_upload.js.map +1 -0
  111. package/dist/index.d.ts +13 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +17 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/lib/config.d.ts +41 -0
  116. package/dist/lib/config.d.ts.map +1 -0
  117. package/dist/lib/config.js +93 -0
  118. package/dist/lib/config.js.map +1 -0
  119. package/dist/lib/constants.d.ts +39 -0
  120. package/dist/lib/constants.d.ts.map +1 -0
  121. package/dist/lib/constants.js +70 -0
  122. package/dist/lib/constants.js.map +1 -0
  123. package/dist/lib/index.d.ts +9 -0
  124. package/dist/lib/index.d.ts.map +1 -0
  125. package/dist/lib/index.js +9 -0
  126. package/dist/lib/index.js.map +1 -0
  127. package/dist/lib/utils.d.ts +17 -0
  128. package/dist/lib/utils.d.ts.map +1 -0
  129. package/dist/lib/utils.js +20 -0
  130. package/dist/lib/utils.js.map +1 -0
  131. package/dist/types/index.d.ts +367 -0
  132. package/dist/types/index.d.ts.map +1 -0
  133. package/dist/types/index.js +8 -0
  134. package/dist/types/index.js.map +1 -0
  135. package/package.json +93 -0
@@ -0,0 +1,858 @@
1
+ # hazo_chat Setup Checklist
2
+
3
+ A comprehensive, step-by-step guide for setting up hazo_chat in a Next.js project. This checklist is designed for both AI assistants and human developers.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ 1. [Prerequisites](#1-prerequisites)
10
+ 2. [Package Installation](#2-package-installation)
11
+ 3. [Configuration Files](#3-configuration-files)
12
+ 4. [Database Setup](#4-database-setup)
13
+ 5. [Environment Variables](#5-environment-variables)
14
+ 6. [Next.js Configuration](#6-nextjs-configuration)
15
+ 7. [API Routes](#7-api-routes)
16
+ 8. [Page Routes (Optional)](#8-page-routes-optional)
17
+ 9. [Component Integration](#9-component-integration)
18
+ 10. [Verification Checklist](#10-verification-checklist)
19
+ 11. [Troubleshooting](#11-troubleshooting)
20
+
21
+ ---
22
+
23
+ ## 1. Prerequisites
24
+
25
+ ### Required Software
26
+ - [ ] Node.js >= 18.0.0
27
+ - [ ] npm >= 9.0.0 or yarn >= 1.22.0
28
+ - [ ] Next.js >= 14.0.0 (App Router)
29
+
30
+ ### Required Knowledge
31
+ - React and Next.js fundamentals
32
+ - Basic understanding of REST APIs
33
+ - TypeScript basics
34
+
35
+ ---
36
+
37
+ ## 2. Package Installation
38
+
39
+ ### Step 2.1: Install Core Packages
40
+
41
+ ```bash
42
+ npm install hazo_chat hazo_connect hazo_auth hazo_config
43
+ ```
44
+
45
+ ### Step 2.2: Install Peer Dependencies (if not already installed)
46
+
47
+ ```bash
48
+ npm install react react-dom
49
+ ```
50
+
51
+ ### Step 2.3: Install Additional Dependencies
52
+
53
+ ```bash
54
+ # For UUID generation (optional, if not using hazo_auth's ID generation)
55
+ npm install uuid
56
+ npm install -D @types/uuid
57
+ ```
58
+
59
+ ### Verification
60
+ - [ ] `package.json` contains `hazo_chat`, `hazo_connect`, `hazo_auth`
61
+ - [ ] No npm installation errors
62
+ - [ ] `node_modules/hazo_chat` exists
63
+
64
+ ---
65
+
66
+ ## 3. Configuration Files
67
+
68
+ ### Step 3.1: Create hazo_connect_config.ini
69
+
70
+ Create in project root: `hazo_connect_config.ini`
71
+
72
+ ```ini
73
+ [database]
74
+ ; Database type: sqlite, postgrest, supabase
75
+ type = sqlite
76
+
77
+ ; For SQLite - path relative to project root
78
+ sqlite_path = ./data/app.db
79
+
80
+ ; For PostgreSQL/Supabase (uncomment if using)
81
+ ; postgrest_url = http://localhost:3000
82
+ ; supabase_url = https://your-project.supabase.co
83
+ ; supabase_anon_key = your-anon-key
84
+ ```
85
+
86
+ ### Step 3.2: Create hazo_auth_config.ini
87
+
88
+ Create in project root: `hazo_auth_config.ini`
89
+
90
+ ```ini
91
+ [auth]
92
+ ; JWT secret for token signing
93
+ jwt_secret = your-secure-secret-key-here
94
+ jwt_expiry = 7d
95
+
96
+ ; Cookie settings
97
+ cookie_name = hazo_auth_token
98
+ cookie_secure = false
99
+ cookie_http_only = true
100
+ cookie_same_site = lax
101
+
102
+ [login]
103
+ enable_remember_me = true
104
+ max_login_attempts = 5
105
+ lockout_duration = 300
106
+
107
+ [registration]
108
+ enable_registration = true
109
+ require_email_verification = false
110
+ default_role = user
111
+
112
+ [ui]
113
+ ; Visual panel image for auth pages
114
+ visual_panel_image = /globe.svg
115
+ ```
116
+
117
+ ### Step 3.3: Create hazo_chat_config.ini (Optional)
118
+
119
+ Create in project root: `hazo_chat_config.ini`
120
+
121
+ ```ini
122
+ [chat]
123
+ ; Polling interval in milliseconds (default: 5000)
124
+ polling_interval = 5000
125
+
126
+ ; Messages to load per page (default: 20)
127
+ messages_per_page = 20
128
+
129
+ [uploads]
130
+ ; Maximum file size in MB (default: 10)
131
+ max_file_size_mb = 10
132
+
133
+ ; Allowed file extensions
134
+ allowed_types = pdf,png,jpg,jpeg,gif,txt,doc,docx
135
+ ```
136
+
137
+ ### Verification
138
+ - [ ] `hazo_connect_config.ini` exists in project root
139
+ - [ ] `hazo_auth_config.ini` exists in project root
140
+ - [ ] Database path directory exists (create `./data/` if using SQLite)
141
+
142
+ ---
143
+
144
+ ## 4. Database Setup
145
+
146
+ ### Step 4.1: Create hazo_chat Table
147
+
148
+ Run this SQL to create the chat messages table:
149
+
150
+ ```sql
151
+ -- hazo_chat table for storing chat messages
152
+ CREATE TABLE IF NOT EXISTS hazo_chat (
153
+ id TEXT PRIMARY KEY,
154
+ reference_id TEXT NOT NULL,
155
+ reference_type TEXT DEFAULT 'chat',
156
+ sender_user_id TEXT NOT NULL,
157
+ receiver_user_id TEXT NOT NULL,
158
+ message_text TEXT,
159
+ reference_list TEXT,
160
+ read_at TEXT,
161
+ deleted_at TEXT,
162
+ created_at TEXT NOT NULL,
163
+ changed_at TEXT NOT NULL
164
+ );
165
+
166
+ -- Performance indexes
167
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_reference_id ON hazo_chat(reference_id);
168
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_sender ON hazo_chat(sender_user_id);
169
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_receiver ON hazo_chat(receiver_user_id);
170
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_created ON hazo_chat(created_at DESC);
171
+ ```
172
+
173
+ ### Step 4.2: Ensure hazo_users Table Exists
174
+
175
+ hazo_auth should have created this, but verify:
176
+
177
+ ```sql
178
+ -- hazo_users table (created by hazo_auth)
179
+ CREATE TABLE IF NOT EXISTS hazo_users (
180
+ id TEXT PRIMARY KEY,
181
+ email_address TEXT UNIQUE NOT NULL,
182
+ password_hash TEXT NOT NULL,
183
+ name TEXT,
184
+ profile_picture_url TEXT,
185
+ profile_source TEXT DEFAULT 'default',
186
+ is_active INTEGER DEFAULT 1,
187
+ email_verified INTEGER DEFAULT 0,
188
+ created_at TEXT NOT NULL,
189
+ changed_at TEXT NOT NULL
190
+ );
191
+ ```
192
+
193
+ ### Verification
194
+ - [ ] `hazo_chat` table exists in database
195
+ - [ ] `hazo_users` table exists with at least one user
196
+ - [ ] Can query: `SELECT * FROM hazo_chat LIMIT 1`
197
+
198
+ ---
199
+
200
+ ## 5. Environment Variables
201
+
202
+ ### Step 5.1: Create .env.local
203
+
204
+ ```env
205
+ # Database (if not using config.ini)
206
+ HAZO_CONNECT_TYPE=sqlite
207
+ HAZO_CONNECT_SQLITE_PATH=./data/app.db
208
+
209
+ # Auth secrets
210
+ HAZO_AUTH_JWT_SECRET=your-secure-secret-key-min-32-chars
211
+
212
+ # Optional: Supabase/PostgreSQL
213
+ # HAZO_CONNECT_POSTGREST_URL=http://localhost:3000
214
+ # SUPABASE_URL=https://your-project.supabase.co
215
+ # SUPABASE_ANON_KEY=your-anon-key
216
+ ```
217
+
218
+ ### Step 5.2: Add to .gitignore
219
+
220
+ ```gitignore
221
+ # Environment files
222
+ .env
223
+ .env.local
224
+ .env.*.local
225
+
226
+ # Database files (if using SQLite)
227
+ *.db
228
+ *.sqlite
229
+ data/
230
+ ```
231
+
232
+ ### Verification
233
+ - [ ] `.env.local` exists
234
+ - [ ] `.env.local` is in `.gitignore`
235
+ - [ ] Secrets are not committed to git
236
+
237
+ ---
238
+
239
+ ## 6. Next.js Configuration
240
+
241
+ ### Step 6.1: Update next.config.js
242
+
243
+ ```javascript
244
+ /**
245
+ * Next.js Configuration with hazo_chat support
246
+ */
247
+
248
+ const path = require('path');
249
+
250
+ /** @type {import('next').NextConfig} */
251
+ const nextConfig = {
252
+ // Transpile the hazo packages for ES module support
253
+ transpilePackages: ['hazo_chat', 'hazo_connect', 'hazo_auth'],
254
+
255
+ // Webpack configuration
256
+ webpack: (config, { isServer }) => {
257
+ // Configure module resolution
258
+ config.resolve.extensionAlias = {
259
+ '.js': ['.js', '.ts', '.tsx'],
260
+ '.jsx': ['.jsx', '.tsx'],
261
+ };
262
+
263
+ // Enable package exports resolution
264
+ config.resolve.conditionNames = ['import', 'require', 'default'];
265
+
266
+ // Server-side externals
267
+ if (isServer) {
268
+ config.externals = config.externals || [];
269
+ if (Array.isArray(config.externals)) {
270
+ config.externals.push("sql.js");
271
+ config.externals.push("hazo_notify");
272
+ }
273
+ }
274
+
275
+ // WebAssembly support for sql.js
276
+ config.experiments = {
277
+ ...(config.experiments ?? {}),
278
+ asyncWebAssembly: true,
279
+ };
280
+
281
+ return config;
282
+ },
283
+
284
+ // Experimental features
285
+ experimental: {
286
+ serverComponentsExternalPackages: [
287
+ "sql.js",
288
+ "better-sqlite3",
289
+ "hazo_notify",
290
+ ],
291
+ },
292
+ };
293
+
294
+ module.exports = nextConfig;
295
+ ```
296
+
297
+ ### Verification
298
+ - [ ] `next.config.js` includes transpilePackages
299
+ - [ ] Server externals configured for sql.js
300
+ - [ ] No build errors with `npm run build`
301
+
302
+ ---
303
+
304
+ ## 7. API Routes
305
+
306
+ Create the following API routes in `src/app/api/`:
307
+
308
+ ### Step 7.1: Chat Messages API
309
+
310
+ **File: `src/app/api/hazo_chat/messages/route.ts`**
311
+
312
+ ```typescript
313
+ /**
314
+ * API route for chat message operations
315
+ */
316
+
317
+ export const dynamic = "force-dynamic";
318
+
319
+ import { NextRequest, NextResponse } from "next/server";
320
+ import { cookies } from "next/headers";
321
+ import { createCrudService } from "hazo_connect/server";
322
+ import { getHazoConnectSingleton } from "hazo_connect/nextjs/setup";
323
+ import { v4 as uuid_v4 } from "uuid";
324
+
325
+ interface ChatMessageDB {
326
+ id: string;
327
+ reference_id: string;
328
+ reference_type: string;
329
+ sender_user_id: string;
330
+ receiver_user_id: string;
331
+ message_text: string | null;
332
+ reference_list: string | null;
333
+ read_at: string | null;
334
+ deleted_at: string | null;
335
+ created_at: string;
336
+ changed_at: string;
337
+ [key: string]: unknown;
338
+ }
339
+
340
+ // GET - Fetch messages
341
+ export async function GET(request: NextRequest) {
342
+ try {
343
+ const cookieStore = cookies();
344
+ const current_user_id = cookieStore.get("hazo_auth_user_id")?.value;
345
+
346
+ if (!current_user_id) {
347
+ return NextResponse.json(
348
+ { success: false, error: "Not authenticated" },
349
+ { status: 401 }
350
+ );
351
+ }
352
+
353
+ const { searchParams } = new URL(request.url);
354
+ const receiver_user_id = searchParams.get("receiver_user_id");
355
+ const reference_id = searchParams.get("reference_id");
356
+ const reference_type = searchParams.get("reference_type");
357
+
358
+ if (!receiver_user_id) {
359
+ return NextResponse.json(
360
+ { success: false, error: "receiver_user_id is required" },
361
+ { status: 400 }
362
+ );
363
+ }
364
+
365
+ const hazoConnect = getHazoConnectSingleton();
366
+ const chatService = createCrudService<ChatMessageDB>(hazoConnect, "hazo_chat");
367
+
368
+ const messages = await chatService.list((query) => {
369
+ let filteredQuery = query.whereOr([
370
+ { field: "sender_user_id", operator: "eq", value: current_user_id },
371
+ { field: "receiver_user_id", operator: "eq", value: current_user_id },
372
+ ]);
373
+
374
+ if (reference_id) {
375
+ filteredQuery = filteredQuery.where("reference_id", "eq", reference_id);
376
+ }
377
+ if (reference_type) {
378
+ filteredQuery = filteredQuery.where("reference_type", "eq", reference_type);
379
+ }
380
+
381
+ return filteredQuery.order("created_at", "asc");
382
+ });
383
+
384
+ return NextResponse.json({
385
+ success: true,
386
+ messages: messages || [],
387
+ current_user_id,
388
+ });
389
+ } catch (error) {
390
+ console.error("[hazo_chat/messages GET] Error:", error);
391
+ return NextResponse.json(
392
+ { success: false, error: "Failed to fetch messages" },
393
+ { status: 500 }
394
+ );
395
+ }
396
+ }
397
+
398
+ // POST - Create message
399
+ export async function POST(request: NextRequest) {
400
+ try {
401
+ const cookieStore = cookies();
402
+ const sender_user_id = cookieStore.get("hazo_auth_user_id")?.value;
403
+
404
+ if (!sender_user_id) {
405
+ return NextResponse.json(
406
+ { success: false, error: "Not authenticated" },
407
+ { status: 401 }
408
+ );
409
+ }
410
+
411
+ const body = await request.json();
412
+ const { receiver_user_id, message_text, reference_id, reference_type, reference_list } = body;
413
+
414
+ if (!receiver_user_id || !message_text?.trim()) {
415
+ return NextResponse.json(
416
+ { success: false, error: "receiver_user_id and message_text are required" },
417
+ { status: 400 }
418
+ );
419
+ }
420
+
421
+ const hazoConnect = getHazoConnectSingleton();
422
+ const chatService = createCrudService<ChatMessageDB>(hazoConnect, "hazo_chat");
423
+
424
+ const message_id = uuid_v4();
425
+ const now = new Date().toISOString();
426
+
427
+ const message_record: ChatMessageDB = {
428
+ id: message_id,
429
+ reference_id: reference_id || message_id,
430
+ reference_type: reference_type || "chat",
431
+ sender_user_id,
432
+ receiver_user_id,
433
+ message_text: message_text.trim(),
434
+ reference_list: reference_list ? JSON.stringify(reference_list) : null,
435
+ read_at: null,
436
+ deleted_at: null,
437
+ created_at: now,
438
+ changed_at: now,
439
+ };
440
+
441
+ await chatService.insert(message_record);
442
+
443
+ return NextResponse.json({
444
+ success: true,
445
+ message: message_record,
446
+ });
447
+ } catch (error) {
448
+ console.error("[hazo_chat/messages POST] Error:", error);
449
+ return NextResponse.json(
450
+ { success: false, error: "Failed to send message" },
451
+ { status: 500 }
452
+ );
453
+ }
454
+ }
455
+ ```
456
+
457
+ ### Step 7.2: Auth Me API
458
+
459
+ **File: `src/app/api/hazo_auth/me/route.ts`**
460
+
461
+ ```typescript
462
+ /**
463
+ * API route to get current authenticated user
464
+ */
465
+
466
+ export const dynamic = "force-dynamic";
467
+
468
+ import { NextRequest, NextResponse } from "next/server";
469
+ import { hazo_get_auth } from "hazo_auth/lib/auth/hazo_get_auth.server";
470
+
471
+ export async function GET(request: NextRequest) {
472
+ try {
473
+ const auth_result = await hazo_get_auth(request);
474
+
475
+ if (!auth_result.is_authenticated || !auth_result.user) {
476
+ return NextResponse.json({
477
+ is_authenticated: false,
478
+ user_id: null,
479
+ email: null,
480
+ });
481
+ }
482
+
483
+ return NextResponse.json({
484
+ is_authenticated: true,
485
+ user_id: auth_result.user.id,
486
+ email: auth_result.user.email_address,
487
+ name: auth_result.user.name,
488
+ profile_picture_url: auth_result.user.profile_picture_url,
489
+ });
490
+ } catch (error) {
491
+ console.error("[hazo_auth/me] Error:", error);
492
+ return NextResponse.json({
493
+ is_authenticated: false,
494
+ user_id: null,
495
+ email: null,
496
+ });
497
+ }
498
+ }
499
+ ```
500
+
501
+ ### Step 7.3: User Profiles API
502
+
503
+ **File: `src/app/api/hazo_auth/profiles/route.ts`**
504
+
505
+ ```typescript
506
+ /**
507
+ * API route to fetch user profiles by IDs
508
+ */
509
+
510
+ export const dynamic = "force-dynamic";
511
+
512
+ import { NextRequest, NextResponse } from "next/server";
513
+ import { createCrudService } from "hazo_connect/server";
514
+ import { getHazoConnectSingleton } from "hazo_connect/nextjs/setup";
515
+
516
+ interface UserProfile {
517
+ id: string;
518
+ name: string;
519
+ email: string;
520
+ avatar_url?: string;
521
+ }
522
+
523
+ export async function POST(request: NextRequest) {
524
+ try {
525
+ const body = await request.json();
526
+ const { user_ids } = body;
527
+
528
+ if (!Array.isArray(user_ids) || user_ids.length === 0) {
529
+ return NextResponse.json(
530
+ { success: false, error: "user_ids array is required" },
531
+ { status: 400 }
532
+ );
533
+ }
534
+
535
+ const hazoConnect = getHazoConnectSingleton();
536
+ const usersService = createCrudService(hazoConnect, "hazo_users");
537
+
538
+ const users = await usersService.list((query) =>
539
+ query.whereIn("id", user_ids)
540
+ );
541
+
542
+ const profiles: UserProfile[] = users.map((user) => ({
543
+ id: user.id as string,
544
+ name: (user.name as string) || (user.email_address as string).split("@")[0],
545
+ email: user.email_address as string,
546
+ avatar_url: user.profile_picture_url as string | undefined,
547
+ }));
548
+
549
+ return NextResponse.json({ success: true, profiles });
550
+ } catch (error) {
551
+ console.error("[hazo_auth/profiles] Error:", error);
552
+ return NextResponse.json(
553
+ { success: false, error: "Failed to fetch profiles" },
554
+ { status: 500 }
555
+ );
556
+ }
557
+ }
558
+ ```
559
+
560
+ ### Step 7.4: Additional Auth API Routes (Required for full hazo_auth)
561
+
562
+ Create these additional routes if using hazo_auth authentication pages:
563
+
564
+ | Route | File Path | Purpose |
565
+ |-------|-----------|---------|
566
+ | Login | `api/hazo_auth/login/route.ts` | User login |
567
+ | Logout | `api/hazo_auth/logout/route.ts` | User logout |
568
+ | Register | `api/hazo_auth/register/route.ts` | User registration |
569
+ | Users List | `api/hazo_auth/users/route.ts` | List all users |
570
+
571
+ See the test-app in this repository for complete implementations.
572
+
573
+ ### Verification Checklist
574
+ - [ ] `api/hazo_chat/messages/route.ts` exists
575
+ - [ ] `api/hazo_auth/me/route.ts` exists
576
+ - [ ] `api/hazo_auth/profiles/route.ts` exists
577
+ - [ ] API routes return 200 when tested with curl
578
+
579
+ ---
580
+
581
+ ## 8. Page Routes (Optional)
582
+
583
+ If using hazo_auth authentication pages, create these routes:
584
+
585
+ ### Authentication Pages
586
+
587
+ | Page | File Path | Purpose |
588
+ |------|-----------|---------|
589
+ | Login | `app/hazo_auth/login/page.tsx` | Login page |
590
+ | Register | `app/hazo_auth/register/page.tsx` | Registration page |
591
+ | Forgot Password | `app/hazo_auth/forgot_password/page.tsx` | Password reset request |
592
+ | Reset Password | `app/hazo_auth/reset_password/page.tsx` | Password reset form |
593
+ | Verify Email | `app/hazo_auth/verify_email/page.tsx` | Email verification |
594
+ | My Settings | `app/hazo_auth/my_settings/page.tsx` | User settings |
595
+
596
+ See the test-app for complete page implementations.
597
+
598
+ ---
599
+
600
+ ## 9. Component Integration
601
+
602
+ ### Step 9.1: Create hazo_auth Service Wrapper
603
+
604
+ **File: `src/lib/hazo_auth_client.ts`**
605
+
606
+ ```typescript
607
+ /**
608
+ * Client-side hazo_auth service wrapper
609
+ */
610
+
611
+ import type { HazoAuthInstance, HazoUserProfile } from 'hazo_chat';
612
+
613
+ export const hazo_auth_client: HazoAuthInstance = {
614
+ hazo_get_auth: async () => {
615
+ try {
616
+ const response = await fetch('/api/hazo_auth/me');
617
+ const data = await response.json();
618
+
619
+ if (data.is_authenticated) {
620
+ return {
621
+ id: data.user_id,
622
+ email: data.email,
623
+ };
624
+ }
625
+ return null;
626
+ } catch (error) {
627
+ console.error('Failed to get auth:', error);
628
+ return null;
629
+ }
630
+ },
631
+
632
+ hazo_get_user_profiles: async (user_ids: string[]): Promise<HazoUserProfile[]> => {
633
+ try {
634
+ const response = await fetch('/api/hazo_auth/profiles', {
635
+ method: 'POST',
636
+ headers: { 'Content-Type': 'application/json' },
637
+ body: JSON.stringify({ user_ids }),
638
+ });
639
+ const data = await response.json();
640
+
641
+ if (data.success) {
642
+ return data.profiles;
643
+ }
644
+ return [];
645
+ } catch (error) {
646
+ console.error('Failed to get profiles:', error);
647
+ return [];
648
+ }
649
+ },
650
+ };
651
+ ```
652
+
653
+ ### Step 9.2: Integrate HazoChat Component
654
+
655
+ **File: `src/app/chat/page.tsx`**
656
+
657
+ ```typescript
658
+ 'use client';
659
+
660
+ import { useState, useEffect } from 'react';
661
+ import { useRouter } from 'next/navigation';
662
+ import { HazoChat } from 'hazo_chat';
663
+ import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
664
+ import { hazo_auth_client } from '@/lib/hazo_auth_client';
665
+
666
+ export default function ChatPage() {
667
+ const router = useRouter();
668
+ const [is_authenticated, set_is_authenticated] = useState(false);
669
+ const [is_loading, set_is_loading] = useState(true);
670
+ const [recipient_id, set_recipient_id] = useState<string>('');
671
+
672
+ // Check authentication on mount
673
+ useEffect(() => {
674
+ async function check_auth() {
675
+ const user = await hazo_auth_client.hazo_get_auth();
676
+ if (!user) {
677
+ router.push('/hazo_auth/login');
678
+ return;
679
+ }
680
+ set_is_authenticated(true);
681
+ set_is_loading(false);
682
+ }
683
+ check_auth();
684
+ }, [router]);
685
+
686
+ if (is_loading) {
687
+ return <div>Loading...</div>;
688
+ }
689
+
690
+ if (!is_authenticated || !recipient_id) {
691
+ return <div>Select a user to chat with</div>;
692
+ }
693
+
694
+ const hazo_connect = getHazoConnectSingleton();
695
+
696
+ return (
697
+ <div className="h-screen">
698
+ <HazoChat
699
+ hazo_connect={hazo_connect}
700
+ hazo_auth={hazo_auth_client}
701
+ receiver_user_id={recipient_id}
702
+ document_save_location="/uploads/chat"
703
+ reference_id={`chat-${recipient_id}`}
704
+ reference_type="direct_message"
705
+ title="Chat"
706
+ on_close={() => router.back()}
707
+ />
708
+ </div>
709
+ );
710
+ }
711
+ ```
712
+
713
+ ---
714
+
715
+ ## 10. Verification Checklist
716
+
717
+ ### Installation Verification
718
+ - [ ] All packages installed without errors
719
+ - [ ] `npm run build` completes successfully
720
+ - [ ] No TypeScript errors
721
+
722
+ ### Configuration Verification
723
+ - [ ] `hazo_connect_config.ini` exists and is readable
724
+ - [ ] Database file/connection is accessible
725
+ - [ ] Environment variables are set
726
+
727
+ ### Database Verification
728
+ - [ ] `hazo_chat` table exists
729
+ - [ ] `hazo_users` table exists with test users
730
+ - [ ] Can insert and query messages
731
+
732
+ ### API Verification
733
+
734
+ Test with curl or browser:
735
+
736
+ ```bash
737
+ # Test auth endpoint
738
+ curl http://localhost:3000/api/hazo_auth/me
739
+
740
+ # Test profiles endpoint (with cookie/auth)
741
+ curl -X POST http://localhost:3000/api/hazo_auth/profiles \
742
+ -H "Content-Type: application/json" \
743
+ -d '{"user_ids": ["user-id-here"]}'
744
+
745
+ # Test messages endpoint (with cookie/auth)
746
+ curl "http://localhost:3000/api/hazo_chat/messages?receiver_user_id=user-id"
747
+ ```
748
+
749
+ Expected responses:
750
+ - [ ] `/api/hazo_auth/me` returns user data or `is_authenticated: false`
751
+ - [ ] `/api/hazo_auth/profiles` returns user profiles array
752
+ - [ ] `/api/hazo_chat/messages` returns messages array
753
+
754
+ ### UI Verification
755
+ - [ ] Chat component renders without errors
756
+ - [ ] Messages load and display correctly
757
+ - [ ] Can send new messages
758
+ - [ ] Messages appear in real-time (within polling interval)
759
+ - [ ] File upload works (if configured)
760
+
761
+ ---
762
+
763
+ ## 11. Troubleshooting
764
+
765
+ ### Error: "hazo_connect.from is not a function"
766
+
767
+ **Cause:** Using wrong adapter type or import.
768
+
769
+ **Solution:**
770
+ ```typescript
771
+ // Wrong
772
+ import hazo_connect from 'hazo_connect';
773
+
774
+ // Correct
775
+ import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
776
+ const hazo_connect = getHazoConnectSingleton();
777
+ ```
778
+
779
+ ### Error: "Module not found"
780
+
781
+ **Cause:** Package not transpiled by Next.js.
782
+
783
+ **Solution:** Add to `next.config.js`:
784
+ ```javascript
785
+ transpilePackages: ['hazo_chat', 'hazo_connect', 'hazo_auth'],
786
+ ```
787
+
788
+ ### Error: "Hydration failed"
789
+
790
+ **Cause:** Server/client rendering mismatch.
791
+
792
+ **Solution:**
793
+ ```typescript
794
+ const [mounted, set_mounted] = useState(false);
795
+ useEffect(() => set_mounted(true), []);
796
+ if (!mounted) return null;
797
+ ```
798
+
799
+ ### Error: "Database not found"
800
+
801
+ **Cause:** SQLite path incorrect or directory doesn't exist.
802
+
803
+ **Solution:**
804
+ 1. Create data directory: `mkdir -p ./data`
805
+ 2. Check path in `hazo_connect_config.ini`
806
+ 3. Ensure path is relative to project root
807
+
808
+ ### Messages Not Loading
809
+
810
+ **Checklist:**
811
+ 1. Is user authenticated? Check `/api/hazo_auth/me`
812
+ 2. Is `reference_id` provided to HazoChat?
813
+ 3. Is database accessible?
814
+ 4. Check browser console for errors
815
+ 5. Check server logs for API errors
816
+
817
+ ### Polling Not Working
818
+
819
+ **Checklist:**
820
+ 1. Check network tab for `/api/hazo_chat/messages` requests
821
+ 2. Verify `polling_interval` in config (default: 5000ms)
822
+ 3. Check for JavaScript errors in console
823
+
824
+ ---
825
+
826
+ ## Quick Setup Summary
827
+
828
+ ```bash
829
+ # 1. Install packages
830
+ npm install hazo_chat hazo_connect hazo_auth hazo_config uuid
831
+
832
+ # 2. Create config files
833
+ touch hazo_connect_config.ini hazo_auth_config.ini
834
+
835
+ # 3. Create database directory
836
+ mkdir -p ./data
837
+
838
+ # 4. Create API routes
839
+ mkdir -p src/app/api/hazo_chat/messages
840
+ mkdir -p src/app/api/hazo_auth/me
841
+ mkdir -p src/app/api/hazo_auth/profiles
842
+
843
+ # 5. Update next.config.js with transpilePackages
844
+
845
+ # 6. Run database migrations (create hazo_chat table)
846
+
847
+ # 7. Start development server
848
+ npm run dev
849
+
850
+ # 8. Test API endpoints
851
+
852
+ # 9. Integrate HazoChat component
853
+ ```
854
+
855
+ ---
856
+
857
+ For more information, see the [README.md](./README.md) and [test-app](./test-app) for complete working examples.
858
+