@cometchat/skills-cli 2.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.
Files changed (95) hide show
  1. package/README.md +70 -0
  2. package/bin/cometchat.mjs +7 -0
  3. package/dist/index.js +4395 -0
  4. package/dist/registry/schemas/template.schema.json +142 -0
  5. package/dist/registry/v6/experiences/1-conversation-list/astro.template.json +89 -0
  6. package/dist/registry/v6/experiences/1-conversation-list/nextjs-pages.template.json +83 -0
  7. package/dist/registry/v6/experiences/1-conversation-list/nextjs.template.json +83 -0
  8. package/dist/registry/v6/experiences/1-conversation-list/react-router.template.json +102 -0
  9. package/dist/registry/v6/experiences/1-conversation-list/reactjs.template.json +86 -0
  10. package/dist/registry/v6/experiences/1-conversation-list/templates/astro/ChatApp.css.tpl +39 -0
  11. package/dist/registry/v6/experiences/1-conversation-list/templates/astro/ChatApp.tsx.tpl +86 -0
  12. package/dist/registry/v6/experiences/1-conversation-list/templates/astro/CometChatSelector.tsx.tpl +40 -0
  13. package/dist/registry/v6/experiences/1-conversation-list/templates/astro/chat.astro.tpl +17 -0
  14. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs/CometChatNoSSR.css.tpl +39 -0
  15. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs/CometChatNoSSR.tsx.tpl +86 -0
  16. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs/CometChatSelector.tsx.tpl +41 -0
  17. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs/chat-page.tsx.tpl +11 -0
  18. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs-pages/CometChatNoSSR.css.tpl +39 -0
  19. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs-pages/CometChatNoSSR.tsx.tpl +88 -0
  20. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs-pages/CometChatSelector.tsx.tpl +41 -0
  21. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs-pages/chat-page.tsx.tpl +15 -0
  22. package/dist/registry/v6/experiences/1-conversation-list/templates/react-router/CometChat-route.tsx.tpl +22 -0
  23. package/dist/registry/v6/experiences/1-conversation-list/templates/react-router/CometChatNoSSR.css.tpl +39 -0
  24. package/dist/registry/v6/experiences/1-conversation-list/templates/react-router/CometChatNoSSR.tsx.tpl +87 -0
  25. package/dist/registry/v6/experiences/1-conversation-list/templates/react-router/CometChatSelector.tsx.tpl +40 -0
  26. package/dist/registry/v6/experiences/1-conversation-list/templates/reactjs/App.css.tpl +32 -0
  27. package/dist/registry/v6/experiences/1-conversation-list/templates/reactjs/App.tsx.tpl +55 -0
  28. package/dist/registry/v6/experiences/1-conversation-list/templates/reactjs/CometChatSelector.tsx.tpl +40 -0
  29. package/dist/registry/v6/experiences/1-conversation-list/templates/reactjs/main.tsx.tpl +46 -0
  30. package/dist/registry/v6/experiences/2-one-to-one/astro.template.json +81 -0
  31. package/dist/registry/v6/experiences/2-one-to-one/nextjs.template.json +77 -0
  32. package/dist/registry/v6/experiences/2-one-to-one/react-router.template.json +93 -0
  33. package/dist/registry/v6/experiences/2-one-to-one/reactjs.template.json +77 -0
  34. package/dist/registry/v6/experiences/2-one-to-one/templates/astro/ChatApp.css.tpl +21 -0
  35. package/dist/registry/v6/experiences/2-one-to-one/templates/astro/ChatApp.tsx.tpl +66 -0
  36. package/dist/registry/v6/experiences/2-one-to-one/templates/astro/chat.astro.tpl +17 -0
  37. package/dist/registry/v6/experiences/2-one-to-one/templates/nextjs/CometChatNoSSR.css.tpl +21 -0
  38. package/dist/registry/v6/experiences/2-one-to-one/templates/nextjs/CometChatNoSSR.tsx.tpl +66 -0
  39. package/dist/registry/v6/experiences/2-one-to-one/templates/nextjs/chat-page.tsx.tpl +11 -0
  40. package/dist/registry/v6/experiences/2-one-to-one/templates/react-router/CometChat-route.tsx.tpl +21 -0
  41. package/dist/registry/v6/experiences/2-one-to-one/templates/react-router/CometChatNoSSR.css.tpl +21 -0
  42. package/dist/registry/v6/experiences/2-one-to-one/templates/react-router/CometChatNoSSR.tsx.tpl +67 -0
  43. package/dist/registry/v6/experiences/2-one-to-one/templates/reactjs/App.css.tpl +4 -0
  44. package/dist/registry/v6/experiences/2-one-to-one/templates/reactjs/App.tsx.tpl +44 -0
  45. package/dist/registry/v6/experiences/2-one-to-one/templates/reactjs/main.tsx.tpl +46 -0
  46. package/dist/registry/v6/experiences/3-tab-based/astro.template.json +93 -0
  47. package/dist/registry/v6/experiences/3-tab-based/nextjs.template.json +90 -0
  48. package/dist/registry/v6/experiences/3-tab-based/react-router.template.json +105 -0
  49. package/dist/registry/v6/experiences/3-tab-based/reactjs.template.json +90 -0
  50. package/dist/registry/v6/experiences/3-tab-based/templates/astro/ChatApp.css.tpl +39 -0
  51. package/dist/registry/v6/experiences/3-tab-based/templates/astro/ChatApp.tsx.tpl +93 -0
  52. package/dist/registry/v6/experiences/3-tab-based/templates/astro/CometChatTabs.css.tpl +43 -0
  53. package/dist/registry/v6/experiences/3-tab-based/templates/astro/CometChatTabs.tsx.tpl +72 -0
  54. package/dist/registry/v6/experiences/3-tab-based/templates/astro/chat.astro.tpl +17 -0
  55. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/CometChatNoSSR.css.tpl +39 -0
  56. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/CometChatNoSSR.tsx.tpl +93 -0
  57. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/CometChatTabs.css.tpl +43 -0
  58. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/CometChatTabs.tsx.tpl +73 -0
  59. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/chat-page.tsx.tpl +11 -0
  60. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChat-route.tsx.tpl +21 -0
  61. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChatNoSSR.css.tpl +39 -0
  62. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChatNoSSR.tsx.tpl +94 -0
  63. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChatTabs.css.tpl +43 -0
  64. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChatTabs.tsx.tpl +72 -0
  65. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/App.css.tpl +7 -0
  66. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/App.tsx.tpl +62 -0
  67. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/CometChatTabs.css.tpl +43 -0
  68. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/CometChatTabs.tsx.tpl +72 -0
  69. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/main.tsx.tpl +46 -0
  70. package/dist/registry/v6/features/catalog.json +344 -0
  71. package/dist/registry/v6/production/astro/cometchat-token.ts.tpl +86 -0
  72. package/dist/registry/v6/production/astro.template.json +51 -0
  73. package/dist/registry/v6/production/nextjs/route.ts.tpl +79 -0
  74. package/dist/registry/v6/production/nextjs.template.json +50 -0
  75. package/dist/registry/v6/production/react-router/api.cometchat-token.ts.tpl +73 -0
  76. package/dist/registry/v6/production/react-router.template.json +58 -0
  77. package/dist/registry/v6/user-mgmt/astro/cometchat-user.ts.tpl +164 -0
  78. package/dist/registry/v6/user-mgmt/astro.template.json +33 -0
  79. package/dist/registry/v6/user-mgmt/nextjs/route.ts.tpl +212 -0
  80. package/dist/registry/v6/user-mgmt/nextjs.template.json +57 -0
  81. package/dist/registry/v6/user-mgmt/react-router/api.cometchat-user.ts.tpl +176 -0
  82. package/dist/registry/v6/user-mgmt/react-router.template.json +40 -0
  83. package/dist/registry/v6/widget/astro/CometChatWidget.css.tpl +105 -0
  84. package/dist/registry/v6/widget/astro/CometChatWidget.tsx.tpl +88 -0
  85. package/dist/registry/v6/widget/astro.template.json +38 -0
  86. package/dist/registry/v6/widget/nextjs/CometChatWidget.css.tpl +105 -0
  87. package/dist/registry/v6/widget/nextjs/CometChatWidget.tsx.tpl +88 -0
  88. package/dist/registry/v6/widget/nextjs.template.json +40 -0
  89. package/dist/registry/v6/widget/react-router/CometChatWidget.css.tpl +105 -0
  90. package/dist/registry/v6/widget/react-router/CometChatWidget.tsx.tpl +98 -0
  91. package/dist/registry/v6/widget/react-router.template.json +36 -0
  92. package/dist/registry/v6/widget/reactjs/CometChatWidget.css.tpl +105 -0
  93. package/dist/registry/v6/widget/reactjs/CometChatWidget.tsx.tpl +89 -0
  94. package/dist/registry/v6/widget/reactjs.template.json +36 -0
  95. package/package.json +53 -0
@@ -0,0 +1,86 @@
1
+ import { useEffect, useState } from "react";
2
+ import {
3
+ CometChatMessageComposer,
4
+ CometChatMessageHeader,
5
+ CometChatMessageList,
6
+ CometChatUIKit,
7
+ UIKitSettingsBuilder,
8
+ } from "@cometchat/chat-uikit-react";
9
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
10
+ import { CometChatSelector } from "./CometChatSelector";
11
+ // IMPORTANT: css-variables.css MUST be imported here (inside the React island)
12
+ // — global stylesheets imported in .astro files do not apply to client:only islands.
13
+ import "@cometchat/chat-uikit-react/css-variables.css";
14
+ import "./ChatApp.css";
15
+
16
+ const COMETCHAT_CONSTANTS = {
17
+ APP_ID: import.meta.env.{{ENV_PREFIX}}COMETCHAT_APP_ID as string,
18
+ REGION: import.meta.env.{{ENV_PREFIX}}COMETCHAT_REGION as string,
19
+ AUTH_KEY: import.meta.env.{{ENV_PREFIX}}COMETCHAT_AUTH_KEY as string,
20
+ };
21
+ const UID = "{{LOGIN_UID}}";
22
+
23
+ export default function ChatApp() {
24
+ const [user, setUser] = useState<CometChat.User | undefined>();
25
+ const [error, setError] = useState<string | null>(null);
26
+ const [selectedUser, setSelectedUser] = useState<CometChat.User | undefined>();
27
+ const [selectedGroup, setSelectedGroup] = useState<CometChat.Group | undefined>();
28
+
29
+ useEffect(() => {
30
+ const settings = new UIKitSettingsBuilder()
31
+ .setAppId(COMETCHAT_CONSTANTS.APP_ID)
32
+ .setRegion(COMETCHAT_CONSTANTS.REGION)
33
+ .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY)
34
+ .subscribePresenceForAllUsers()
35
+ .build();
36
+
37
+ CometChatUIKit.init(settings)?.then(() => {
38
+ CometChatUIKit.getLoggedinUser().then((u) => {
39
+ if (!u) {
40
+ CometChatUIKit.login(UID)
41
+ .then(setUser)
42
+ .catch((e: unknown) => setError(String(e)));
43
+ } else {
44
+ setUser(u);
45
+ }
46
+ });
47
+ }).catch((e: unknown) => setError(String(e)));
48
+ }, []);
49
+
50
+ if (error) return <div style={{ color: "red", padding: 16, fontFamily: "monospace" }}>{error}</div>;
51
+ if (!user) return null;
52
+
53
+ return (
54
+ <div className="conversations-with-messages">
55
+ <div className="conversations-wrapper">
56
+ <CometChatSelector
57
+ onSelectorItemClicked={(activeItem) => {
58
+ const item =
59
+ activeItem instanceof CometChat.Conversation
60
+ ? activeItem.getConversationWith()
61
+ : activeItem;
62
+ if (item instanceof CometChat.User) {
63
+ setSelectedUser(item);
64
+ setSelectedGroup(undefined);
65
+ } else if (item instanceof CometChat.Group) {
66
+ setSelectedUser(undefined);
67
+ setSelectedGroup(item);
68
+ }
69
+ }}
70
+ />
71
+ </div>
72
+ {selectedUser || selectedGroup ? (
73
+ <div className="messages-wrapper">
74
+ {selectedUser && <CometChatMessageHeader user={selectedUser} />}
75
+ {selectedGroup && <CometChatMessageHeader group={selectedGroup} />}
76
+ {selectedUser && <CometChatMessageList user={selectedUser} />}
77
+ {selectedGroup && <CometChatMessageList group={selectedGroup} />}
78
+ {selectedUser && <CometChatMessageComposer user={selectedUser} />}
79
+ {selectedGroup && <CometChatMessageComposer group={selectedGroup} />}
80
+ </div>
81
+ ) : (
82
+ <div className="empty-conversation">Select a conversation to start chatting</div>
83
+ )}
84
+ </div>
85
+ );
86
+ }
@@ -0,0 +1,40 @@
1
+ import { useEffect, useState } from "react";
2
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
3
+ import {
4
+ CometChatConversations,
5
+ CometChatUIKitLoginListener,
6
+ } from "@cometchat/chat-uikit-react";
7
+
8
+ interface SelectorProps {
9
+ onSelectorItemClicked?: (
10
+ input: CometChat.Conversation | CometChat.User | CometChat.Group,
11
+ type: string
12
+ ) => void;
13
+ }
14
+
15
+ export const CometChatSelector = ({
16
+ onSelectorItemClicked = () => {},
17
+ }: SelectorProps) => {
18
+ const [loggedInUser, setLoggedInUser] = useState<CometChat.User | null>(null);
19
+ const [activeConversation, setActiveConversation] = useState<
20
+ CometChat.Conversation | undefined
21
+ >();
22
+
23
+ useEffect(() => {
24
+ setLoggedInUser(CometChatUIKitLoginListener.getLoggedInUser());
25
+ }, []);
26
+
27
+ return (
28
+ <>
29
+ {loggedInUser && (
30
+ <CometChatConversations
31
+ activeConversation={activeConversation}
32
+ onItemClick={(e) => {
33
+ setActiveConversation(e);
34
+ onSelectorItemClicked(e, "updateSelectedItem");
35
+ }}
36
+ />
37
+ )}
38
+ </>
39
+ );
40
+ };
@@ -0,0 +1,17 @@
1
+ ---
2
+ import ChatApp from "../cometchat/ChatApp.tsx";
3
+ ---
4
+
5
+ <html lang="en">
6
+ <head>
7
+ <meta charset="utf-8" />
8
+ <meta name="viewport" content="width=device-width" />
9
+ <title>Chat</title>
10
+ <style>
11
+ html, body { margin: 0; padding: 0; height: 100%; }
12
+ </style>
13
+ </head>
14
+ <body>
15
+ <ChatApp client:only="react" />
16
+ </body>
17
+ </html>
@@ -0,0 +1,39 @@
1
+ .conversations-with-messages {
2
+ display: flex;
3
+ height: 100vh;
4
+ width: 100%;
5
+ }
6
+
7
+ .conversations-wrapper {
8
+ height: 100%;
9
+ width: 480px;
10
+ overflow: hidden;
11
+ display: flex;
12
+ flex-direction: column;
13
+ }
14
+
15
+ .conversations-wrapper > .cometchat {
16
+ overflow: hidden;
17
+ }
18
+
19
+ .messages-wrapper {
20
+ width: calc(100% - 480px);
21
+ height: 100%;
22
+ display: flex;
23
+ flex-direction: column;
24
+ }
25
+
26
+ .empty-conversation {
27
+ height: 100%;
28
+ width: 100%;
29
+ display: flex;
30
+ justify-content: center;
31
+ align-items: center;
32
+ background: white;
33
+ color: var(--cometchat-text-color-secondary, #727272);
34
+ font: var(--cometchat-font-body-regular, 400 14px Roboto);
35
+ }
36
+
37
+ .cometchat .cometchat-message-composer {
38
+ border-radius: 0;
39
+ }
@@ -0,0 +1,86 @@
1
+ "use client";
2
+ import React, { useEffect, useState } from "react";
3
+ import {
4
+ CometChatMessageComposer,
5
+ CometChatMessageHeader,
6
+ CometChatMessageList,
7
+ CometChatUIKit,
8
+ UIKitSettingsBuilder,
9
+ } from "@cometchat/chat-uikit-react";
10
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
11
+ import { CometChatSelector } from "./CometChatSelector";
12
+ // css-variables.css is imported in app/globals.css — do NOT import it here
13
+ import "./CometChatNoSSR.css";
14
+
15
+ const COMETCHAT_CONSTANTS = {
16
+ APP_ID: process.env.{{ENV_PREFIX}}COMETCHAT_APP_ID!,
17
+ REGION: process.env.{{ENV_PREFIX}}COMETCHAT_REGION!,
18
+ AUTH_KEY: process.env.{{ENV_PREFIX}}COMETCHAT_AUTH_KEY!,
19
+ };
20
+ const UID = "{{LOGIN_UID}}";
21
+
22
+ const CometChatNoSSR: React.FC = () => {
23
+ const [user, setUser] = useState<CometChat.User | undefined>();
24
+ const [error, setError] = useState<string | null>(null);
25
+ const [selectedUser, setSelectedUser] = useState<CometChat.User | undefined>();
26
+ const [selectedGroup, setSelectedGroup] = useState<CometChat.Group | undefined>();
27
+
28
+ useEffect(() => {
29
+ const settings = new UIKitSettingsBuilder()
30
+ .setAppId(COMETCHAT_CONSTANTS.APP_ID)
31
+ .setRegion(COMETCHAT_CONSTANTS.REGION)
32
+ .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY)
33
+ .subscribePresenceForAllUsers()
34
+ .build();
35
+
36
+ CometChatUIKit.init(settings)?.then(() => {
37
+ CometChatUIKit.getLoggedinUser().then((u) => {
38
+ if (!u) {
39
+ CometChatUIKit.login(UID)
40
+ .then(setUser)
41
+ .catch((e: unknown) => setError(String(e)));
42
+ } else {
43
+ setUser(u);
44
+ }
45
+ });
46
+ }).catch((e: unknown) => setError(String(e)));
47
+ }, []);
48
+
49
+ if (error) return <div style={{ color: "red", padding: 16, fontFamily: "monospace" }}>{error}</div>;
50
+ if (!user) return null;
51
+
52
+ return (
53
+ <div className="conversations-with-messages">
54
+ <div className="conversations-wrapper">
55
+ <CometChatSelector
56
+ onSelectorItemClicked={(activeItem) => {
57
+ const item =
58
+ activeItem instanceof CometChat.Conversation
59
+ ? activeItem.getConversationWith()
60
+ : activeItem;
61
+ if (item instanceof CometChat.User) {
62
+ setSelectedUser(item);
63
+ setSelectedGroup(undefined);
64
+ } else if (item instanceof CometChat.Group) {
65
+ setSelectedUser(undefined);
66
+ setSelectedGroup(item);
67
+ }
68
+ }}
69
+ />
70
+ </div>
71
+ {selectedUser || selectedGroup ? (
72
+ <div className="messages-wrapper">
73
+ {selectedUser && <CometChatMessageHeader user={selectedUser} />}
74
+ {selectedGroup && <CometChatMessageHeader group={selectedGroup} />}
75
+ {selectedUser && <CometChatMessageList user={selectedUser} />}
76
+ {selectedGroup && <CometChatMessageList group={selectedGroup} />}
77
+ {selectedUser && <CometChatMessageComposer user={selectedUser} />}
78
+ {selectedGroup && <CometChatMessageComposer group={selectedGroup} />}
79
+ </div>
80
+ ) : (
81
+ <div className="empty-conversation">Select a conversation to start chatting</div>
82
+ )}
83
+ </div>
84
+ );
85
+ };
86
+ export default CometChatNoSSR;
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ import { useEffect, useState } from "react";
3
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
4
+ import {
5
+ CometChatConversations,
6
+ CometChatUIKitLoginListener,
7
+ } from "@cometchat/chat-uikit-react";
8
+
9
+ interface SelectorProps {
10
+ onSelectorItemClicked?: (
11
+ input: CometChat.Conversation | CometChat.User | CometChat.Group,
12
+ type: string
13
+ ) => void;
14
+ }
15
+
16
+ export const CometChatSelector = ({
17
+ onSelectorItemClicked = () => {},
18
+ }: SelectorProps) => {
19
+ const [loggedInUser, setLoggedInUser] = useState<CometChat.User | null>(null);
20
+ const [activeConversation, setActiveConversation] = useState<
21
+ CometChat.Conversation | undefined
22
+ >();
23
+
24
+ useEffect(() => {
25
+ setLoggedInUser(CometChatUIKitLoginListener.getLoggedInUser());
26
+ }, []);
27
+
28
+ return (
29
+ <>
30
+ {loggedInUser && (
31
+ <CometChatConversations
32
+ activeConversation={activeConversation}
33
+ onItemClick={(e) => {
34
+ setActiveConversation(e);
35
+ onSelectorItemClicked(e, "updateSelectedItem");
36
+ }}
37
+ />
38
+ )}
39
+ </>
40
+ );
41
+ };
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ import dynamic from "next/dynamic";
3
+
4
+ const CometChatComponent = dynamic(
5
+ () => import("../cometchat/CometChatNoSSR"),
6
+ { ssr: false }
7
+ );
8
+
9
+ export default function ChatPage() {
10
+ return <CometChatComponent />;
11
+ }
@@ -0,0 +1,39 @@
1
+ .conversations-with-messages {
2
+ display: flex;
3
+ height: 100vh;
4
+ width: 100%;
5
+ }
6
+
7
+ .conversations-wrapper {
8
+ height: 100%;
9
+ width: 480px;
10
+ overflow: hidden;
11
+ display: flex;
12
+ flex-direction: column;
13
+ }
14
+
15
+ .conversations-wrapper > .cometchat {
16
+ overflow: hidden;
17
+ }
18
+
19
+ .messages-wrapper {
20
+ width: calc(100% - 480px);
21
+ height: 100%;
22
+ display: flex;
23
+ flex-direction: column;
24
+ }
25
+
26
+ .empty-conversation {
27
+ height: 100%;
28
+ width: 100%;
29
+ display: flex;
30
+ justify-content: center;
31
+ align-items: center;
32
+ background: white;
33
+ color: var(--cometchat-text-color-secondary, #727272);
34
+ font: var(--cometchat-font-body-regular, 400 14px Roboto);
35
+ }
36
+
37
+ .cometchat .cometchat-message-composer {
38
+ border-radius: 0;
39
+ }
@@ -0,0 +1,88 @@
1
+ // Pages Router has no RSC boundary — no `"use client"` directive needed.
2
+ // This file is rendered ONLY on the client because src/pages/chat.tsx
3
+ // imports it via next/dynamic with { ssr: false }.
4
+ import React, { useEffect, useState } from "react";
5
+ import {
6
+ CometChatMessageComposer,
7
+ CometChatMessageHeader,
8
+ CometChatMessageList,
9
+ CometChatUIKit,
10
+ UIKitSettingsBuilder,
11
+ } from "@cometchat/chat-uikit-react";
12
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
13
+ import { CometChatSelector } from "./CometChatSelector";
14
+ // css-variables.css is imported in src/styles/globals.css — do NOT import it here
15
+ import "./CometChatNoSSR.css";
16
+
17
+ const COMETCHAT_CONSTANTS = {
18
+ APP_ID: process.env.{{ENV_PREFIX}}COMETCHAT_APP_ID!,
19
+ REGION: process.env.{{ENV_PREFIX}}COMETCHAT_REGION!,
20
+ AUTH_KEY: process.env.{{ENV_PREFIX}}COMETCHAT_AUTH_KEY!,
21
+ };
22
+ const UID = "{{LOGIN_UID}}";
23
+
24
+ const CometChatNoSSR: React.FC = () => {
25
+ const [user, setUser] = useState<CometChat.User | undefined>();
26
+ const [error, setError] = useState<string | null>(null);
27
+ const [selectedUser, setSelectedUser] = useState<CometChat.User | undefined>();
28
+ const [selectedGroup, setSelectedGroup] = useState<CometChat.Group | undefined>();
29
+
30
+ useEffect(() => {
31
+ const settings = new UIKitSettingsBuilder()
32
+ .setAppId(COMETCHAT_CONSTANTS.APP_ID)
33
+ .setRegion(COMETCHAT_CONSTANTS.REGION)
34
+ .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY)
35
+ .subscribePresenceForAllUsers()
36
+ .build();
37
+
38
+ CometChatUIKit.init(settings)?.then(() => {
39
+ CometChatUIKit.getLoggedinUser().then((u) => {
40
+ if (!u) {
41
+ CometChatUIKit.login(UID)
42
+ .then(setUser)
43
+ .catch((e: unknown) => setError(String(e)));
44
+ } else {
45
+ setUser(u);
46
+ }
47
+ });
48
+ }).catch((e: unknown) => setError(String(e)));
49
+ }, []);
50
+
51
+ if (error) return <div style={{ color: "red", padding: 16, fontFamily: "monospace" }}>{error}</div>;
52
+ if (!user) return null;
53
+
54
+ return (
55
+ <div className="conversations-with-messages">
56
+ <div className="conversations-wrapper">
57
+ <CometChatSelector
58
+ onSelectorItemClicked={(activeItem) => {
59
+ const item =
60
+ activeItem instanceof CometChat.Conversation
61
+ ? activeItem.getConversationWith()
62
+ : activeItem;
63
+ if (item instanceof CometChat.User) {
64
+ setSelectedUser(item);
65
+ setSelectedGroup(undefined);
66
+ } else if (item instanceof CometChat.Group) {
67
+ setSelectedUser(undefined);
68
+ setSelectedGroup(item);
69
+ }
70
+ }}
71
+ />
72
+ </div>
73
+ {selectedUser || selectedGroup ? (
74
+ <div className="messages-wrapper">
75
+ {selectedUser && <CometChatMessageHeader user={selectedUser} />}
76
+ {selectedGroup && <CometChatMessageHeader group={selectedGroup} />}
77
+ {selectedUser && <CometChatMessageList user={selectedUser} />}
78
+ {selectedGroup && <CometChatMessageList group={selectedGroup} />}
79
+ {selectedUser && <CometChatMessageComposer user={selectedUser} />}
80
+ {selectedGroup && <CometChatMessageComposer group={selectedGroup} />}
81
+ </div>
82
+ ) : (
83
+ <div className="empty-conversation">Select a conversation to start chatting</div>
84
+ )}
85
+ </div>
86
+ );
87
+ };
88
+ export default CometChatNoSSR;
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ import { useEffect, useState } from "react";
3
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
4
+ import {
5
+ CometChatConversations,
6
+ CometChatUIKitLoginListener,
7
+ } from "@cometchat/chat-uikit-react";
8
+
9
+ interface SelectorProps {
10
+ onSelectorItemClicked?: (
11
+ input: CometChat.Conversation | CometChat.User | CometChat.Group,
12
+ type: string
13
+ ) => void;
14
+ }
15
+
16
+ export const CometChatSelector = ({
17
+ onSelectorItemClicked = () => {},
18
+ }: SelectorProps) => {
19
+ const [loggedInUser, setLoggedInUser] = useState<CometChat.User | null>(null);
20
+ const [activeConversation, setActiveConversation] = useState<
21
+ CometChat.Conversation | undefined
22
+ >();
23
+
24
+ useEffect(() => {
25
+ setLoggedInUser(CometChatUIKitLoginListener.getLoggedInUser());
26
+ }, []);
27
+
28
+ return (
29
+ <>
30
+ {loggedInUser && (
31
+ <CometChatConversations
32
+ activeConversation={activeConversation}
33
+ onItemClick={(e) => {
34
+ setActiveConversation(e);
35
+ onSelectorItemClicked(e, "updateSelectedItem");
36
+ }}
37
+ />
38
+ )}
39
+ </>
40
+ );
41
+ };
@@ -0,0 +1,15 @@
1
+ // Pages Router auto-routes this file to /chat. The CometChat SDK uses
2
+ // browser-only globals (WebSocket, IndexedDB, etc.) so we MUST disable
3
+ // SSR for the chat component via next/dynamic with { ssr: false }.
4
+ // This mirrors the App Router pattern where CometChatNoSSR has a
5
+ // `"use client"` directive — Pages Router achieves the same isolation
6
+ // at the import site instead of with a directive.
7
+ import dynamic from "next/dynamic";
8
+
9
+ const CometChatNoSSR = dynamic(() => import("../cometchat/CometChatNoSSR"), {
10
+ ssr: false,
11
+ });
12
+
13
+ export default function ChatPage() {
14
+ return <CometChatNoSSR />;
15
+ }
@@ -0,0 +1,22 @@
1
+ import React, { lazy, Suspense, useEffect, useState } from "react";
2
+
3
+ // Lazy-load the CometChat component so it never executes during SSR
4
+ const CometChatNoSSR = lazy(() => import("../cometchat/CometChatNoSSR"));
5
+
6
+ export default function CometChatRoute() {
7
+ const [mounted, setMounted] = useState(false);
8
+
9
+ useEffect(() => {
10
+ setMounted(true);
11
+ }, []);
12
+
13
+ if (!mounted) {
14
+ return <div style={{ padding: 16 }}>Loading…</div>;
15
+ }
16
+
17
+ return (
18
+ <Suspense fallback={<div style={{ padding: 16 }}>Loading…</div>}>
19
+ <CometChatNoSSR />
20
+ </Suspense>
21
+ );
22
+ }
@@ -0,0 +1,39 @@
1
+ .conversations-with-messages {
2
+ display: flex;
3
+ height: 100vh;
4
+ width: 100%;
5
+ }
6
+
7
+ .conversations-wrapper {
8
+ height: 100%;
9
+ width: 480px;
10
+ overflow: hidden;
11
+ display: flex;
12
+ flex-direction: column;
13
+ }
14
+
15
+ .conversations-wrapper > .cometchat {
16
+ overflow: hidden;
17
+ }
18
+
19
+ .messages-wrapper {
20
+ width: calc(100% - 480px);
21
+ height: 100%;
22
+ display: flex;
23
+ flex-direction: column;
24
+ }
25
+
26
+ .empty-conversation {
27
+ height: 100%;
28
+ width: 100%;
29
+ display: flex;
30
+ justify-content: center;
31
+ align-items: center;
32
+ background: white;
33
+ color: var(--cometchat-text-color-secondary, #727272);
34
+ font: var(--cometchat-font-body-regular, 400 14px Roboto);
35
+ }
36
+
37
+ .cometchat .cometchat-message-composer {
38
+ border-radius: 0;
39
+ }
@@ -0,0 +1,87 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import {
3
+ CometChatMessageComposer,
4
+ CometChatMessageHeader,
5
+ CometChatMessageList,
6
+ CometChatUIKit,
7
+ UIKitSettingsBuilder,
8
+ } from "@cometchat/chat-uikit-react";
9
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
10
+ import { CometChatSelector } from "./CometChatSelector";
11
+ // css-variables.css is imported in app/app.css — do NOT import it here
12
+ import "./CometChatNoSSR.css";
13
+
14
+ const COMETCHAT_CONSTANTS = {
15
+ APP_ID: import.meta.env.{{ENV_PREFIX}}COMETCHAT_APP_ID as string,
16
+ REGION: import.meta.env.{{ENV_PREFIX}}COMETCHAT_REGION as string,
17
+ AUTH_KEY: import.meta.env.{{ENV_PREFIX}}COMETCHAT_AUTH_KEY as string,
18
+ };
19
+ const UID = "{{LOGIN_UID}}";
20
+
21
+ const CometChatNoSSR: React.FC = () => {
22
+ const [user, setUser] = useState<CometChat.User | undefined>();
23
+ const [error, setError] = useState<string | null>(null);
24
+ const [selectedUser, setSelectedUser] = useState<CometChat.User | undefined>();
25
+ const [selectedGroup, setSelectedGroup] = useState<CometChat.Group | undefined>();
26
+
27
+ useEffect(() => {
28
+ if (typeof window === "undefined") return;
29
+
30
+ const settings = new UIKitSettingsBuilder()
31
+ .setAppId(COMETCHAT_CONSTANTS.APP_ID)
32
+ .setRegion(COMETCHAT_CONSTANTS.REGION)
33
+ .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY)
34
+ .subscribePresenceForAllUsers()
35
+ .build();
36
+
37
+ CometChatUIKit.init(settings)?.then(() => {
38
+ CometChatUIKit.getLoggedinUser().then((u) => {
39
+ if (!u) {
40
+ CometChatUIKit.login(UID)
41
+ .then(setUser)
42
+ .catch((e: unknown) => setError(String(e)));
43
+ } else {
44
+ setUser(u);
45
+ }
46
+ });
47
+ }).catch((e: unknown) => setError(String(e)));
48
+ }, []);
49
+
50
+ if (error) return <div style={{ color: "red", padding: 16, fontFamily: "monospace" }}>{error}</div>;
51
+ if (!user) return null;
52
+
53
+ return (
54
+ <div className="conversations-with-messages">
55
+ <div className="conversations-wrapper">
56
+ <CometChatSelector
57
+ onSelectorItemClicked={(activeItem) => {
58
+ const item =
59
+ activeItem instanceof CometChat.Conversation
60
+ ? activeItem.getConversationWith()
61
+ : activeItem;
62
+ if (item instanceof CometChat.User) {
63
+ setSelectedUser(item);
64
+ setSelectedGroup(undefined);
65
+ } else if (item instanceof CometChat.Group) {
66
+ setSelectedUser(undefined);
67
+ setSelectedGroup(item);
68
+ }
69
+ }}
70
+ />
71
+ </div>
72
+ {selectedUser || selectedGroup ? (
73
+ <div className="messages-wrapper">
74
+ {selectedUser && <CometChatMessageHeader user={selectedUser} />}
75
+ {selectedGroup && <CometChatMessageHeader group={selectedGroup} />}
76
+ {selectedUser && <CometChatMessageList user={selectedUser} />}
77
+ {selectedGroup && <CometChatMessageList group={selectedGroup} />}
78
+ {selectedUser && <CometChatMessageComposer user={selectedUser} />}
79
+ {selectedGroup && <CometChatMessageComposer group={selectedGroup} />}
80
+ </div>
81
+ ) : (
82
+ <div className="empty-conversation">Select a conversation to start chatting</div>
83
+ )}
84
+ </div>
85
+ );
86
+ };
87
+ export default CometChatNoSSR;