Skip to main content

Use content types

All messages in XMTP are encoded with a content type to ensure interoperability and consistency of experience across the XMTP network.

Two standard content types come bundled with the XMTP client SDK:

  1. xmtp.org/text:1.0, which defines a default TextCodec for plain text content

    To learn more about this text content type, see XIP-5.

  2. xmtp.org/composite:1.0, which defines an optional CompositeCodec for multiple content types in a single message

    To learn more about this composite content type, see XIP-9.

For these standard content types, xmtp.org is the authorityId value. xmtp.org is reserved for use as the authorityId for standard content types. Standard content types are those that have been adopted through the XMTP Improvement Proposal (XIP) process.

caution

Do not use xmtp.org as the authorityId for a custom content type that you create for your app. Instead, consider using a unique DNS domain or ENS name that can be widely recognized as belonging to your app. For example, frenz.xyz.

To learn more about authorityId and other parameters in a content type identifier, see Content Type Identifier and Parameters.

To learn more about the difference between standard and custom content types, see Content types with XMTP.

Send plain text messages using the TextCodec standard content type

An app built with XMTP uses the TextCodec (plain text) standard content type by default. This means that if your app is sending plain text messages only, you don’t need to perform any additional steps related to content types.

Send multiple content types in a message using the CompositeCodec standard content type

If you want your app to be able to send multiple content types; such as any combination of plain text, images, audio, and video; in a single message, you must set up your app to use the CompositeCodec standard content type.

info

While XMTP supports the CompositeCodec standard content type, the app reading the composite message must support the content types used in the composite message to be able to display them.

Import the CompositeCodec standard content type

Import the CompositeCodec content type from the xmtp-js client SDK to make it available in your app. For example:

import { CompositeCodec } from '@xmtp/xmtp-js'

Tag a message with the CompositeCodec standard content type

To enable a message API client to know to use the CompositeCodec content type to encode and decode a message, tag the message with the content type.

To do this, pass the CompositeCodec content type as an option to the Client.create() method. This configures the message API client instance to use CompositeCodec when encoding and decoding messages. For example:

const xmtp = Client.create(wallet, { codecs: [new CompositeCodec()] })

Build a custom content type

If you want to send a content type other than those supported by standard content types (plain text and composite messages), you must build a custom content type. This task uses a fictional AudioCodec custom content type to help illustrate the steps.

caution

Do not use xmtp.org as the authorityId for a custom content type that you create for your app. xmtp.org is reserved for use as the authorityId for standard content types only.

To learn more about authorityId and other parameters in a content type identifier, see Content Type Identifier and Parameters.

  1. Create an AudioCodec class that encodes and decodes the content type. For example, you can put this in the file that creates an XMTP client.

    import { Client, ContentTypeId } from '@xmtp/xmtp-js';

    const ContentTypeAudioKey = new ContentTypeId({
    authorityId: 'your.domain',
    typeId: 'audio-key',
    versionMajor: 1,
    versionMinor: 0,
    })

    class AudioCodec {
    get contentType() {
    return ContentTypeAudioKey;
    }

    encode(key: string | undefined) {
    return {
    type: ContentTypeAudioKey,
    parameters: {},
    content: new TextEncoder().encode(key)
    };
    }

    decode(content: { content: any }) {
    const uint8Array = content.content;
    const key = new TextDecoder().decode(uint8Array);
    return key;
    }
    }
  2. Pass the AudioCodec content type as an option to the Client.create() method.

    const xmtp = await Client.create(null, {
    env: 'dev',
    codecs: [new AudioCodec()]
    });
note

If you register a codec for a custom content type that is already in the default set, it will replace the original codec.

Send a custom content type

Once you’ve built your custom content type, you can immediately start using it to tag and send messages. This task uses a fictional AudioCodec custom content type to help illustrate the steps.

  1. Register your AudioCodec custom content type with the message API client. For example:

    import { Conversation, ContentTypeId } from '@xmtp/xmtp-js';

    const ContentTypeVoiceKey = new ContentTypeId({
    authorityId: 'your.domain',
    typeId: 'audio-key',
    versionMajor: 1,
    versionMinor: 0
    });
  2. Send a message using the send method with audioRecording as the content (in byteArrays).

    For example, you can build the AudioCodec to encode audioData as a binary representation of the audio file.

    In this code sample, the message is tagged and sent with two options: contentType and contentFallback. The contentType option is set to ContentTypeVoiceKey, which enables the message API client to know to use the AudioCodec to encode and decode the content. The contentFallback option is set to 'This is an audio recording' to enable an app to display descriptive text if it is unable to handle the custom content type.

    const audioRecording = 'xxxxxxx'; // audio recording in byteArrays
    conversation.send(audioRecording, {
    contentType: ContentTypeVoiceKey,
    contentFallback: 'This is an audio recording'
    })

    As a best practice, use the contentFallback option to provide an alt text-like plain text description that will display in place of the original content in the message if an app is unable to handle your custom (non-standard) content type.

info

Your custom content type WILL NOT automatically be supported by other apps and will display fallback text in them instead.

If another app wants to display your custom content type, they must implement your custom content type in their code exactly as it's defined in your code.

If developers take interest in your custom content type, consider proposing it as a standard through the XIP process.

Display messages with a specific content type

The contentTypeId will be available to help distinguish the content type the message contains.

For example, if the content is an audio type, then:

const contentTypeId = message.contentType.typeId
// contentTypeId is `audio-key`

Let's say your app receives a message tagged as audio-key in the contentTypeId and this content type uses the AudioCodec for encoding and decoding content. To display the audio message in your app, write a conditional in the view layer.

For example, in a messageList.tsx file that displays messages, you can do the following:

const TypeOfMessage = ({ message }: MessageTileProps): JSX.Element => {
const contentTypeId = message.contentType.typeId;
const isAudioMessage = contentTypeId === 'audio-key';

if (isAudioMessage) {
return (
<audio controls>
<source src={message.content} type="audio/mpeg" />
</audio>
);
} else if (message.error) {
return <div>{message.error.message}</div>;
} else {
return <Emoji text={message.content || ''} />;
}
};

If your app is unable to handle a custom content type, then the contentFallback option will automatically display.

To learn more from an example implementation, see this voice-note branch in the XMTP Inbox repo.

Was the information on this page helpful?