# System message

> **Info:** This is release candidate documentation for **Stream Chat React SDK v15**. For the latest stable version, see the [latest version (v14)](https://getstream.io/chat/docs/sdk/react/).

A system message is a message of type `system`. It reports an event in the channel rather than something a user wrote, for example a member joining or a moderation command. `MessageList` and `VirtualizedMessageList` render it with the `MessageSystem` override instead of the message UI. This recipe replaces it.

## Best practices

- Keep system messages visually distinct from user messages, but quieter.
- Show the message's text: it says what happened.
- Show who triggered the event only where your app's privacy rules allow it. The sender is `message.user`.
- Replace `MessageSystem` for a different layout. For a different look only, style `str-chat__message--system`.
- Test with every event your app turns into a system message, such as members being added and removed, and moderation commands.

### Default system message component

The default is `EventComponent`. It renders the message's `text` in a centered line, or its `html` when `MessageList`'s `unsafeHTML` prop is set:

![The default system message](https://getstream.io/docs-assets/images/14a9365a8fb9.png)

A system message comes from the server. Your backend sends one with `type: "system"`, as [System messages](https://getstream.io/chat/docs/javascript/silent-messages/#system-messages) shows, and adding or removing members can create one, as [Channel members](https://getstream.io/chat/docs/javascript/channel-members/) shows.

### Custom system message component

This component shows the text, the time and the user who triggered the event:

>
> **Note:** To see it, mute a user with the `/mute` command followed by an `@mention`. The command has to be enabled for the channel type in the [Dashboard](https://getstream.io/signin/?product=chat).
>

```tsx label="React" title="src/CustomSystemMessage.tsx"
import type { PropsWithChildren } from "react";
import { convertTimestampToDate } from "stream-chat";
import type { EventComponentProps } from "stream-chat-react";
import { Avatar, WithComponents } from "stream-chat-react";
import "./CustomSystemMessage.css";

const CustomSystemMessage = ({ message }: EventComponentProps) => {
  const { created_at, text, user } = message;
  const date = convertTimestampToDate(created_at);

  return (
    <div className="custom-system-message">
      <div>
        Event: <strong>{text?.trim()}</strong> at {date?.toString()}
      </div>
      {user && (
        <div className="custom-system-message__actor">
          Actor:
          <Avatar
            imageUrl={user.image}
            size="sm"
            userName={user.name || user.id}
          />
          {user.name}
        </div>
      )}
    </div>
  );
};

// Declared once, so WithComponents gets the same object on every render.
const overrides = { MessageSystem: CustomSystemMessage };

export const WithCustomSystemMessages = ({ children }: PropsWithChildren) => (
  <WithComponents overrides={overrides}>{children}</WithComponents>
);
```

```css label="CSS" title="src/CustomSystemMessage.css"
.custom-system-message {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 1rem;
  border-radius: var(--str-chat__radius-md);
  background: linear-gradient(
    to right,
    orange,
    yellow,
    green,
    cyan,
    blue,
    violet
  );
}

.custom-system-message__actor {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
```

Wrap the channel in it, so every message list inside renders system messages with `CustomSystemMessage`:

```tsx title="src/ChannelWithSystemMessages.tsx"
import type { Channel as StreamChannel } from "stream-chat";
import { Channel, MessageComposer, MessageList } from "stream-chat-react";
import { WithCustomSystemMessages } from "./CustomSystemMessage";

export const ChannelWithSystemMessages = ({
  channel,
}: {
  channel: StreamChannel;
}) => (
  <WithCustomSystemMessages>
    <Channel channel={channel}>
      <MessageList />
      <MessageComposer />
    </Channel>
  </WithCustomSystemMessages>
);
```

![A custom system message with the event, its time and the actor](https://getstream.io/docs-assets/images/3cd3b7cd6cf3.png)

How it works:

1. The list renders `MessageSystem` for every message of type `system`, and passes the message as `message`. Unlike a message UI, it renders outside `MessageContext`, so the message comes from its props.
2. `created_at` is a nanosecond number, so `convertTimestampToDate` turns it into a date; [Data conventions](https://getstream.io/chat/docs/sdk/react/v15/state/state-and-entities/data-conventions/#timestamps) explains why.
3. `message.user` is the user the server sent the message as. A system message your backend sends without a user has none, so the actor line is left out.

`MessageList` also passes `unsafeHTML`. To render a system message's `html` the way the default does, read that prop as well.

The props are on [ComponentContext](https://getstream.io/chat/docs/sdk/react/v15/component-reference/channel/componentcontext/), under `MessageSystem`. The other parts of the message list, such as the date separators, are in [Message list UI](https://getstream.io/chat/docs/sdk/react/v15/ui/components/message-list-ui/#replacing-parts).

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v15/recipes/message/system-message/](https://getstream.io/chat/docs/sdk/react/v15/recipes/message/system-message/).