For AI agents: Find a documentation index at https://talkjs.com/llms.txt (full content at https://talkjs.com/llms-full.txt). Get a markdown version of any page by appending .md to its URL path.
Skip to content

Angular chat

Angular chat for zoneless and server-rendered apps

A new Angular app is zoneless, can render on the server, and fails its build if the first bundle is over 1 MB. Your chat SDK has to fit all three. TalkJS fits with two changes: load it only in the browser, and put its CSS in global styles. We ran it on a fresh Angular 22.2.3 app, and TalkJS ran the backend, so there was no chat server to build.

This snippet is the browser-only import. The full component adds the users, the conversation, and an unread count.

// Runs only in the browser, never during SSR or prerendering.
afterNextRender(async () => {
  await import('@talkjs/web-components');

  const session = getTalkSession({ appId: this.appId, userId: this.userId });
  // ...
});
Nina
Hi Frank! Is the new project ready to review?
9:15 AM
You
Yes, I’ve just shared the latest version.
9:16 AM
Nina
Thanks! I’ll take a look this morning.
9:17 AM
thumbs-up
Write a reply…
You
Hey, I’m having trouble accessing my account. It says my password is incorrect.
5m ago
SupportBot
Hi there! No problem — let’s get that sorted. Have you tried resetting your password using the ‘Forgot password?’ link?
4m ago
thinking
thumbs-up
You
Yes, but I haven’t received the reset email yet.
3m ago
SupportBot
Thanks for confirming. I’ve just sent a new reset link to your email. Please check your inbox and spam folder.
2m ago
SupportBot
Is there anything else I can help you with?
just now
Got it — checking my inbox now!

How do I keep chat out of the server render and the first bundle?

Import the TalkJS web components inside afterNextRender, not at the top of the file. Angular’s SSR guide says these hooks “are only executed on the browser and skipped on the server.”

Here’s what that changed in a fresh Angular 22.2.3 app with server rendering and prerendering turned on (ng new --ssr):

CheckImport at the top of the fileImport inside afterNextRender
PrerenderingFailed with ReferenceError: customElements is not definedPrerendered the page, which then hydrated in the browser with no console errors
First bundle1.41 MBAbout 513 kB
ng buildError: over the CLI’s default 1 MB budgetBuilds, with the CLI’s 500 kB size warning
TalkJS codeIn the first bundleA lazy chunk of about 979 kB raw (235 kB transferred), loaded after the first render

Turning SSR off won’t get you under the budget. Without SSR, the top-level import still made a 1.37 MB first bundle, and ng build failed the same way.

The second change is the stylesheet. Add @import '@talkjs/web-components/default.css'; to src/styles.css. When we imported the CSS from TypeScript instead, Angular 22 stopped on a type error (TS2882). Once we got past that error, the CSS was missing from the ng build output and the chat showed up unstyled.

Does TalkJS work in a zoneless Angular app?

Yes. The TalkJS chatbox doesn’t need zone.js: in our zoneless test app, the other user’s messages showed up live without a reload.

For your own UI, read TalkJS data into a signal. An unread badge takes one subscribeConversations call. Filter on isUnread and set a signal to the number of conversations it returns. Ours went from 0 to 1 within 3 seconds of a new message in another conversation, and back to 0 when that conversation was marked read. No manual change detection.

The subscription starts with the 20 most recent conversations, so call loadMore if a user can have more unread ones than that. Each conversation in the result also has an unreadMessageCount, if you’d rather count messages. To stop listening when the component is destroyed, call unsubscribe() from DestroyRef.onDestroy, as the full component below does.

unreadCount = signal(0);

unreads = session.subscribeConversations(
  { filter: { isUnread: true } },
  (conversations) => this.unreadCount.set(conversations.length),
);

What does the whole Angular chat component look like?

It’s one standalone component, a template, and one line of CSS. Install the web components and the Data API:

npm install @talkjs/web-components @talkjs/core

Add the stylesheet to src/styles.css:

@import '@talkjs/web-components/default.css';

Then the component, in src/app/app.ts. CUSTOM_ELEMENTS_SCHEMA lets Angular accept the <t-chatbox> tag. Replace <APP_ID> with your app ID, from the Settings page of your TalkJS dashboard.

import {
  Component,
  CUSTOM_ELEMENTS_SCHEMA,
  DestroyRef,
  afterNextRender,
  inject,
  signal,
} from '@angular/core';
import { getTalkSession, type ConversationListSubscription } from '@talkjs/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.html',
  styleUrl: './app.css',
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class App {
  appId = '<APP_ID>';
  userId = 'frank';
  otherUserId = 'nina';
  conversationId = 'my_conversation';

  unreadCount = signal(0);

  constructor() {
    const destroyRef = inject(DestroyRef);
    let unreads: ConversationListSubscription | undefined;

    // Runs only in the browser, never during SSR or prerendering.
    afterNextRender(async () => {
      await import('@talkjs/web-components');

      const session = getTalkSession({ appId: this.appId, userId: this.userId });
      session.currentUser.createIfNotExists({ name: 'Frank' });
      session.user(this.otherUserId).createIfNotExists({ name: 'Nina' });
      const conversation = session.conversation(this.conversationId);
      conversation.createIfNotExists();
      conversation.participant(this.otherUserId).createIfNotExists();

      unreads = session.subscribeConversations(
        { filter: { isUnread: true } },
        (conversations) => this.unreadCount.set(conversations.length),
      );
    });

    destroyRef.onDestroy(() => unreads?.unsubscribe());
  }
}

And the template, src/app/app.html:

<p>Unread conversations: <strong data-testid="unread">{{ unreadCount() }}</strong></p>
<t-chatbox
  style="width: 100%; max-width: 400px; height: 600px;"
  [app-id]="appId"
  [user-id]="userId"
  [conversation-id]="conversationId"
/>

Adapted from the TalkJS Angular guide. We ran it in October 2026 on Angular 22.2.3 with @talkjs/web-components 0.3.12 and @talkjs/core 1.12.1, with SSR and prerendering on, and got a styled, live chat with no console errors. The template uses width: 100%; max-width: 400px because a fixed 400 px width overflowed a 390 px phone screen.

Nina

Angular chat example

Hi Nina, this is Frank from Angular 22 with SSR on
9:04 AM
Hi Frank, Nina replying via REST
9:04 AM
Thanks, Nina! Let’s try a few more messages.
9:05 AM
Sure, I’m here. What would you like to test next?
9:05 AM
Write a reply…
An illustrative preview of the test conversation. View the original Angular 22 test screenshot, October 2026.

The <t-chatbox> tag is in the template before the import finishes, so the browser doesn’t know it yet. The [app-id], [user-id] and [conversation-id] bindings still worked once the import finished. In the test projects we tried, the sample users didn’t exist, so the code creates two, Frank and Nina.

Before launch, have your server sign a token for each user, pass it to the session with setToken, and turn on authentication in your dashboard settings, as the TalkJS authentication docs describe.

Which Angular chat packages say they support Angular 22 and zoneless?

In October 2026, Stream’s README is the only source in this table that lists Angular 22 as supported, and it says zoneless mode isn’t supported yet. For TalkJS, the row shows what we ran.

PackageWhat it isAngular versions statedZonelessMessaging backendSource
TalkJS @talkjs/web-components 0.3.12 and @talkjs/core 1.12.1Chat UI as web components, plus a data APINone: no Angular peer dependency. We ran it on 22.2.3Yes in our test, with SSRIncludedOur test; npm
Stream stream-chat-angular 7.2.0Angular components for Stream Chat“Angular 17–22”. On 22, install ngx-float-ui@21 with --legacy-peer-deps“Zoneless mode isn’t yet supported”Included: Stream Chat, “a service for building chat applications”Its README, Oct 24, 2026
CometChat @cometchat/chat-uikit-angular 5.2.2UI kit on CometChat’s JavaScript SDKnpm peer range >=17.0.0 <22.0.0Not listedIncluded: CometChatnpm
Kendo UI for Angular ChatChat UI componentNot listedNot listedYou connect your own: “Integrate with AI services and other backend systems”Product page
DevExtreme Chat (DevExpress)Chat UI componentNot listedNot listedYou connect your own: “sending the message to the server for storage”Getting started guide
Syncfusion Angular Chat UIChat UI componentNot listedNot listedYou connect your own: “compatible with SignalR and other back ends”Product page
Ignite UI for Angular Chat (Infragistics)Chat UI componentNot listedNot listedYou connect your own: “plug the Chat into your own data source”Product page

A UI-only component still needs a server behind it that stores messages, delivers them to the other user, and sends push notifications. With TalkJS, our servers store and deliver the messages and send email, SMS, and push notifications to users who are offline.

If you build that server yourself, Angular adds one rule of its own. Server-rendered apps “cannot make use of browser-specific global objects like window, document, navigator, or location,” as the Angular SSR guide puts it, so your socket client has to open in afterNextRender too. The rest is the usual list: a real-time server, a way to catch users up on messages they missed, push sent from your own server, and moderation.

Retreat Guru logo
We were able to offload all messaging to TalkJS — hugely simplifying our development of an otherwise complex stack.
Deryk Wenaus
CTO, Retreat Guru

Ready-made chat UI you can customize

In Angular, each pre-built chat UI is one tag in a template: <t-chatbox> for a single conversation, <t-inbox> for a messaging page, and <t-conversation-list> for the list on its own. They’re the TalkJS web components, so you style them with properties, CSS, or a custom theme. For a chat popup, open a chatbox from a button of your own.

Inbox

The TalkJS Inbox shows the chat history on the left, selected conversation on the right. It’s designed to act as the messaging center of your app, usually living on its own page.

Chatbox

The TalkJS Chatbox is the right half of the Inbox UI mode. It takes up less space and is designed to be embedded in your app near an order confirmation, a booking, or user profile.

Conversation list

The user’s conversations in one list. Put a Chatbox next to it to open the one they pick, or use the Inbox, which combines the two.

FAQs

No. An Angular app uses the same two packages as a plain web page: @talkjs/web-components for the chat UI and @talkjs/core for the data. Their only peer dependency is @talkjs/core, and neither lists an @angular package. The same web components work in Ionic Angular and Vue, and React has its own components.

Nothing while you build: development mode is free on every plan and doesn’t expire. You start paying when you go live, per monthly active user. Basic is $279 a month, or $239 a month on yearly billing, and covers 10,000 monthly active users. The pricing page lists the other plans.