In this tutorial you'll add real-time one-to-one chat to a React + TypeScript app built with Vite, using QuickBlox. Two authenticated users exchange private messages that arrive in the browser the moment they are sent, with persistent message history across reloads. The SDK is installed as a regular npm dependency and imported the standard React way.
The full published tutorial walks through every step with explanations and screenshots: How to Build In-App Chat in a React Web Application. This folder is the finished project you can clone and run.
- React 19
- TypeScript 5.7
- Vite 6 (port
3007) - QuickBlox JavaScript SDK 2.23.0 — installed via
npm install quickblox
-
Open
src/config.ts— the only file you edit — and fill in your values:- App Credentials from the QuickBlox Dashboard (Overview tab → Application ID, Authorization Key, Authorization Secret, Account Key).
- Two test users in the
usersobject: for each ofAandB, paste thelogin,password, andopponentId— the other user's numeric ID from Dashboard → Users →IDcolumn.
-
Install dependencies and start the Vite dev server:
npm install npm start
-
Open two browser tabs to see real-time delivery in both directions:
- Tab 1:
http://localhost:3007/?user=A— signs in as User A, opponent is User B. - Tab 2:
http://localhost:3007/?user=B— signs in as User B, opponent is User A.
Each tab pre-fills the login form with the matching profile from
config.ts. Press Sign in in each tab and start sending messages. - Tab 1:
react-vite/
├── index.html The HTML shell — mounts React from src/main.tsx
├── package.json
├── tsconfig.json
├── vite.config.ts Aliases the SDK's platform shims to an empty module
└── src/
├── main.tsx React entry — createRoot(...).render(<App />)
├── App.tsx Shell: state.user ? <ChatScreen /> : <LoginScreen />
├── config.ts Your credentials — the only file you edit
├── empty-shim/ Empty module for the SDK's NativeScript/Node shims
├── types/quickblox.ts Narrow app-level types for SDK shapes
├── services/
│ ├── auth.ts QB.init / QB.createSession / QB.chat.connect
│ └── chat.ts QB.chat.dialog.create / message.list / send
├── context/ Context + useReducer-backed chat state
├── hooks/ useAuth / useDialog / useMessages / useChatListeners
├── components/ LoginScreen / ChatScreen / Conversation / MessageList / MessageInput
└── styles/App.css
The QuickBlox SDK declares two platform-specific shim packages — for NativeScript and for Node — that it only requires when running on those platforms. In a browser bundle those require calls sit on dead branches behind a runtime Utils.getEnv() check, so they never execute. But Vite still tries to resolve them at build time and fails with Failed to resolve import "nativescript-xmpp-client".
The fix is a one-line alias that points both packages at a local empty module:
// vite.config.ts
resolve: {
alias: {
'nativescript-xmpp-client': emptyShim,
'node-xmpp-client': emptyShim,
},
}The empty module lives at src/empty-shim/index.js and exports {}.
This project signs the user in directly from the browser to keep the example self-contained. In production, do not ship the Authorization Secret in browser code — anyone who reads it can authenticate as any user in your application. Move authentication to your backend and pass a short-lived session token to the client instead.
The same React source code is also available with Webpack as the build tool: React + Webpack.
- Published tutorial → How to Build In-App Chat in a React Web Application
- React tutorials hub → ../README.md
- JavaScript SDK reference → docs.quickblox.com/docs/js-quick-start