---
description: Add a custom header to your RealtimeKit meeting UI with individual components.
title: Add Custom Header
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/realtime/llms.txt  
> Use this file to discover all available pages before exploring further.

# Add Custom Header

Last updated Aug 24, 2026|Copy as Markdown|[View as Markdown](https://e8aee267.previews.developers.cloudflare.com/realtime/realtimekit/ui-kit/custom-header/index.md)|[Agent setup](https://e8aee267.previews.developers.cloudflare.com/agent-setup/)

Prerequisite

This guide builds on top of the [Build Your Own UI](https://e8aee267.previews.developers.cloudflare.com/realtime/realtimekit/ui-kit/build-your-own-ui/). It is recommended to read that guide first. Portions of the code will not be repeated here for brevity.

For a complete list of available UI Kit components, refer to the [Component Library](https://e8aee267.previews.developers.cloudflare.com/realtime/realtimekit/ui-kit/component-library/).

In this guide, we will learn how to add a custom header for your RealtimeKit meeting experience.

WebMobile

ReactWeb ComponentsAngular

RealtimeKit UI provides the [RtkHeader](https://e8aee267.previews.developers.cloudflare.com/realtime/realtimekit/ui-kit/component-library/#rtk-header) component for a default header.

If you need additional controls, replace `RtkHeader` with individual UI Kit components and custom elements.

Import the required components:

```jsx
import {
	RtkLogo,
	RtkRecordingIndicator,
	RtkLivestreamIndicator,
	RtkMeetingTitle,
	RtkGridPagination,
	RtkParticipantCount,
	RtkViewerCount,
	RtkClock,
} from "@cloudflare/realtimekit-ui";
```

In your `RtkUIProvider` from [Build Your Own UI](https://e8aee267.previews.developers.cloudflare.com/realtime/realtimekit/ui-kit/build-your-own-ui/), replace:

```jsx
<RtkHeader />
```

with:

```jsx
<div
	style={{
		display: "flex",
		justifyContent: "space-between",
		backgroundColor: "black",
		color: "white",
	}}
>
	<div
		id="header-left"
		style={{ display: "flex", alignItems: "center", height: "48px" }}
	>
		<RtkLogo />
		<RtkRecordingIndicator />
		<RtkLivestreamIndicator />
	</div>
	<div
		id="header-center"
		style={{ display: "flex", alignItems: "center", height: "48px" }}
	>
		<RtkMeetingTitle />
	</div>
	<div
		id="header-right"
		style={{ display: "flex", alignItems: "center", height: "48px" }}
	>
		<RtkGridPagination />
		<RtkParticipantCount />
		<RtkViewerCount />
		<RtkClock />
		<button onClick={handleReportBugClick}>Report Bug</button>
	</div>
</div>
```

Define the click handler:

```jsx
const handleReportBugClick = () => {
	console.log("Report Bug Clicked");
};
```

For a complete example, refer to the [custom UI example ↗](https://github.com/cloudflare/realtimekit-web-examples/tree/main/react-examples/examples/create-your-own-ui) and the [custom header component ↗](https://github.com/cloudflare/realtimekit-web-examples/blob/main/react-examples/examples/create-your-own-ui/src/components/meeting-header.tsx).

RealtimeKit UI provides the [rtk-header](https://e8aee267.previews.developers.cloudflare.com/realtime/realtimekit/ui-kit/component-library/#rtk-header) component for a default header.

If you need additional controls, replace `rtk-header` with individual UI Kit components and custom elements. In the `renderJoinedScreen` function from [Build Your Own UI](https://e8aee267.previews.developers.cloudflare.com/realtime/realtimekit/ui-kit/build-your-own-ui/), replace:

```html
<rtk-header style="display: flex; justify-content: space-between;"></rtk-header>
```

with:

```html
<div
	style="display: flex; justify-content: space-between; align-items: center; height: 48px; padding: 0 12px; background-color: black; color: white;"
>
	<div style="display: flex; align-items: center; gap: 8px;">
		<rtk-logo></rtk-logo>
		<rtk-recording-indicator></rtk-recording-indicator>
		<rtk-livestream-indicator></rtk-livestream-indicator>
	</div>

	<div style="display: flex; align-items: center;">
		<rtk-meeting-title></rtk-meeting-title>
	</div>

	<div style="display: flex; align-items: center; gap: 8px;">
		<rtk-grid-pagination></rtk-grid-pagination>
		<rtk-participant-count></rtk-participant-count>
		<rtk-viewer-count></rtk-viewer-count>
		<rtk-clock></rtk-clock>
		<button id="report-bug-button" type="button">Report Bug</button>
	</div>
</div>
```

Register the click handler after rendering:

```javascript
document.querySelector("#report-bug-button").addEventListener("click", () => {
	console.log("Report Bug Clicked");
});
```

For a complete example, refer to the [custom UI example ↗](https://github.com/cloudflare/realtimekit-web-examples/tree/main/html-examples/examples/create-your-own-ui) and the [custom header component ↗](https://github.com/cloudflare/realtimekit-web-examples/blob/main/html-examples/examples/create-your-own-ui/components/meeting-header.js).

RealtimeKit UI provides the [rtk-header](https://e8aee267.previews.developers.cloudflare.com/realtime/realtimekit/ui-kit/component-library/#rtk-header) component for a default header.

If you need additional controls, replace `rtk-header` with individual UI Kit components and custom elements. Create a custom header component that uses the RealtimeKit angular components directly.

#### Create Custom Header Component

```typescript
import { Component, AfterViewInit } from "@angular/core";

@Component({
	selector: "app-custom-header",
	template: `
		<div class="custom-header">
			<div class="header-left">
				<rtk-logo></rtk-logo>
				<rtk-recording-indicator></rtk-recording-indicator>
				<rtk-livestream-indicator></rtk-livestream-indicator>
			</div>

			<div class="header-center">
				<rtk-meeting-title></rtk-meeting-title>
			</div>

			<div class="header-right">
				<rtk-grid-pagination></rtk-grid-pagination>
				<rtk-participant-count></rtk-participant-count>
				<rtk-viewer-count></rtk-viewer-count>
				<rtk-clock></rtk-clock>
				<button
					type="button"
					class="report-bug-button"
					(click)="onReportBugClick()"
				>
					Report Bug
				</button>
			</div>
		</div>
	`,
	styles: [
		`
			.custom-header {
				display: flex;
				justify-content: space-between;
				align-items: center;
				height: 48px;
				padding: 0 12px;
				background-color: black;
				color: white;
			}

			.header-left,
			.header-right {
				display: flex;
				align-items: center;
				gap: 8px;
			}

			.header-center {
				display: flex;
				align-items: center;
			}

			.report-bug-button {
				background: none;
				border: 1px solid white;
				color: white;
				padding: 4px 8px;
				border-radius: 4px;
				cursor: pointer;
				font-size: 12px;
			}

			.report-bug-button:hover {
				background-color: rgba(255, 255, 255, 0.1);
			}
		`,
	],
})
export class CustomHeaderComponent implements AfterViewInit {
	ngAfterViewInit() {
		console.log("Custom header initialized");
	}

	onReportBugClick() {
		console.log("Report Bug Clicked");
		// Add your custom logic here
		// For example: open a modal, navigate to a form, etc.
	}
}
```

#### Use in Your Meeting Component

In your main meeting component template, replace:

```html
<rtk-header style="display: flex; justify-content: space-between;"></rtk-header>
```

with:

```html
<app-custom-header></app-custom-header>
```

#### Complete Meeting Component Example

```typescript
import {
	Component,
	ElementRef,
	OnInit,
	OnDestroy,
	ViewChild,
} from "@angular/core";

@Component({
	selector: "app-meeting",
	template: `
		<rtk-meeting #meetingComponent id="meeting-component">
			<!-- Custom header replaces rtk-header -->
			<app-custom-header></app-custom-header>

			<!-- Other meeting UI components -->
			<rtk-grid></rtk-grid>
			<rtk-sidebar></rtk-sidebar>
		</rtk-meeting>
	`,
})
export class MeetingComponent implements OnInit, OnDestroy {
	@ViewChild("meetingComponent", { static: true }) meetingElement!: ElementRef;

	meeting: any;
	private authToken = "<participant_auth_token>";

	async ngOnInit() {
		const RealtimeKitClient =
			await import("https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit@latest/dist/index.es.js");

		this.meeting = await RealtimeKitClient.default.init({
			authToken: this.authToken,
		});

		const meetingComponent = this.meetingElement.nativeElement;
		meetingComponent.showSetupScreen = true;
		meetingComponent.meeting = this.meeting;
	}

	ngOnDestroy() {
		// Cleanup logic
	}
}
```

#### Module Configuration

Don't forget to declare your custom header component in your Angular module:

```typescript
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";

import { AppComponent } from "./app.component";
import { MeetingComponent } from "./meeting.component";
import { CustomHeaderComponent } from "./custom-header.component";

@NgModule({
	declarations: [AppComponent, MeetingComponent, CustomHeaderComponent],
	imports: [BrowserModule],
	providers: [],
	bootstrap: [AppComponent],
	schemas: [CUSTOM_ELEMENTS_SCHEMA], // Required for RTK web components
})
export class AppModule {}
```

This approach gives you full control over the header layout while maintaining Angular's component architecture and event handling patterns.

RealtimeKit UI provides the `RtkMeetingHeaderView` component for a default header.

If you need additional controls, replace `RtkMeetingHeaderView` with individual UI Kit components and custom elements.

Import the required components:

```swift
import RealtimeKitUI
```

#### Create custom header view

Create a custom header view that uses the RealtimeKit iOS components directly:

```swift
import UIKit
import RealtimeKit
import RealtimeKitUI

class CustomHeaderView: UIView {
    private let meeting: RealtimeKitClient

    private lazy var titleLabel: RtkMeetingTitleLabel = {
        return RtkMeetingTitleLabel(meeting: meeting)
    }()

    private lazy var participantCountView: RtkParticipantCountView = {
        return RtkParticipantCountView(meeting: meeting)
    }()

    private lazy var clockView: RtkClockView = {
        return RtkClockView(meeting: meeting)
    }()

    private lazy var recordingView: RtkRecordingView = {
        return RtkRecordingView(meeting: meeting)
    }()

    private let reportBugButton = UIButton(type: .system)

    init(meeting: RealtimeKitClient) {
        self.meeting = meeting
        super.init(frame: .zero)
        setupUI()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupUI() {
        backgroundColor = .black

        // Configure report bug button
        reportBugButton.setTitle("Report Bug", for: .normal)
        reportBugButton.setTitleColor(.white, for: .normal)
        reportBugButton.layer.borderColor = UIColor.white.cgColor
        reportBugButton.layer.borderWidth = 1
        reportBugButton.layer.cornerRadius = 4
        reportBugButton.contentEdgeInsets = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 8)
        reportBugButton.addTarget(self, action: #selector(handleReportBugTap), for: .touchUpInside)

        // Create stack views for layout
        let leftStack = UIStackView(arrangedSubviews: [recordingView])
        leftStack.axis = .horizontal
        leftStack.spacing = 8
        leftStack.alignment = .center

        let centerStack = UIStackView(arrangedSubviews: [titleLabel])
        centerStack.axis = .horizontal
        centerStack.alignment = .center

        let rightStack = UIStackView(arrangedSubviews: [
            participantCountView,
            clockView,
            reportBugButton
        ])
        rightStack.axis = .horizontal
        rightStack.spacing = 8
        rightStack.alignment = .center

        let mainStack = UIStackView(arrangedSubviews: [leftStack, centerStack, rightStack])
        mainStack.axis = .horizontal
        mainStack.distribution = .equalSpacing
        mainStack.alignment = .center
        mainStack.translatesAutoresizingMaskIntoConstraints = false

        addSubview(mainStack)

        NSLayoutConstraint.activate([
            mainStack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12),
            mainStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12),
            mainStack.topAnchor.constraint(equalTo: topAnchor),
            mainStack.bottomAnchor.constraint(equalTo: bottomAnchor),
            heightAnchor.constraint(equalToConstant: 48)
        ])
    }

    @objc private func handleReportBugTap() {
        print("Report Bug Tapped")
        // Add your custom logic here
    }
}
```

#### Use in your meeting view controller

In your `MeetingViewController`, replace the default header with your custom header:

```swift
import UIKit
import RealtimeKit
import RealtimeKitUI

class MeetingViewController: UIViewController {
    private var meeting: RealtimeKitClient?
    private var customHeader: CustomHeaderView?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupMeeting()
    }

    private func setupMeeting() {
        Task {
            do {
                let client = try await RealtimeKitClient.init(authToken: "<PARTICIPANT_AUTH_TOKEN>")
                self.meeting = client
                await MainActor.run {
                    setupCustomHeader(meeting: client)
                }
            } catch {
                print("Failed to initialize meeting: \(error)")
            }
        }
    }

    private func setupCustomHeader(meeting: RealtimeKitClient) {
        let header = CustomHeaderView(meeting: meeting)
        self.customHeader = header

        view.addSubview(header)
        header.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            header.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            header.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            header.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
    }
}
```

RealtimeKit UI provides the `RtkMeetingHeaderView` component for a default header.

If you need additional controls, replace `RtkMeetingHeaderView` with individual UI Kit components and custom elements.

Import the required components:

```kotlin
import com.cloudflare.realtimekit.ui.view.headers.RtkMeetingHeaderView
import com.cloudflare.realtimekit.ui.view.RtkMeetingTitleView
import com.cloudflare.realtimekit.ui.view.RtkParticipantCountView
import com.cloudflare.realtimekit.ui.view.RtkClockView
import com.cloudflare.realtimekit.ui.view.RtkRecordingIndicator
import com.cloudflare.realtimekit.ui.view.RtkLivestreamIndicator
import com.cloudflare.realtimekit.ui.view.RtkGridPaginatorView
```

#### Create custom header layout

Create an XML layout file for your custom header:

```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:orientation="horizontal"
    android:gravity="center_vertical"
    android:paddingHorizontal="12dp"
    android:background="@android:color/black">

    <!-- Left section -->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:gravity="start|center_vertical">

        <com.cloudflare.realtimekit.ui.view.RtkRecordingIndicator
            android:id="@+id/recordingIndicator"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <com.cloudflare.realtimekit.ui.view.RtkLivestreamIndicator
            android:id="@+id/livestreamIndicator"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp" />
    </LinearLayout>

    <!-- Center section -->
    <com.cloudflare.realtimekit.ui.view.RtkMeetingTitleView
        android:id="@+id/meetingTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white" />

    <!-- Right section -->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:gravity="end|center_vertical">

        <com.cloudflare.realtimekit.ui.view.RtkGridPaginatorView
            android:id="@+id/gridPaginator"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <com.cloudflare.realtimekit.ui.view.RtkParticipantCountView
            android:id="@+id/participantCount"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp" />

        <com.cloudflare.realtimekit.ui.view.RtkClockView
            android:id="@+id/clock"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp" />

        <Button
            android:id="@+id/reportBugButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:text="Report Bug"
            android:textColor="@android:color/white"
            android:background="@android:color/transparent"
            style="?android:attr/borderlessButtonStyle" />
    </LinearLayout>
</LinearLayout>
```

#### Create custom header view class

```kotlin
package com.example.meeting

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.widget.Button
import android.widget.LinearLayout
import com.cloudflare.realtimekit.ui.view.RtkClockView
import com.cloudflare.realtimekit.ui.view.RtkMeetingTitleView
import com.cloudflare.realtimekit.ui.view.RtkParticipantCountView
import com.cloudflare.realtimekit.ui.view.RtkRecordingIndicator

class CustomHeaderView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    init {
        LayoutInflater.from(context).inflate(R.layout.custom_header, this, true)
        setupReportBugButton()
    }

    private fun setupReportBugButton() {
        findViewById<Button>(R.id.reportBugButton).setOnClickListener {
            Log.d("CustomHeader", "Report Bug Clicked")
            // Add your custom logic here
        }
    }
}
```

#### Use in your meeting activity

In your `MeetingActivity`, replace the default header with your custom header:

```kotlin
package com.example.meeting

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.cloudflare.realtimekit.RealtimeKitClient

class MeetingActivity : AppCompatActivity() {
    private lateinit var meeting: RealtimeKitClient
    private lateinit var customHeader: CustomHeaderView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_meeting)

        customHeader = findViewById(R.id.customHeader)
        initializeMeeting()
    }

    private fun initializeMeeting() {
        RealtimeKitClient.init(
            authToken = "<PARTICIPANT_AUTH_TOKEN>",
            onSuccess = { client ->
                meeting = client
                // Configure meeting UI
            },
            onError = { error ->
                Log.e("Meeting", "Failed to initialize: $error")
            }
        )
    }
}
```

RealtimeKit UI provides the `RtkHeader` component for a default header.

If you need additional controls, replace `RtkHeader` with individual UI Kit components and custom elements.

Import the required components:

```tsx
import {
	RtkLogo,
	RtkRecordingIndicator,
	RtkLiveStreamIndicator,
	RtkMeetingTitle,
	RtkGridPagination,
	RtkParticipantCount,
	RtkClock,
} from "@cloudflare/realtimekit-react-native-ui";
import {
	useRealtimeKitMeeting,
	useRealtimeKitSelector,
} from "@cloudflare/realtimekit-react-native";
```

#### Create custom header component

Create a custom header component that uses the RealtimeKit React Native components directly. Each component requires the `meeting` instance as a prop, which you obtain via the `useRealtimeKitMeeting` hook. The component waits for `roomJoined` before rendering to ensure the meeting state is ready:

```tsx
import React from "react";
import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
import {
	RtkLogo,
	RtkRecordingIndicator,
	RtkLiveStreamIndicator,
	RtkMeetingTitle,
	RtkGridPagination,
	RtkParticipantCount,
	RtkClock,
} from "@cloudflare/realtimekit-react-native-ui";
import {
	useRealtimeKitMeeting,
	useRealtimeKitSelector,
} from "@cloudflare/realtimekit-react-native";

interface CustomHeaderProps {
	onReportBugPress?: () => void;
}

export function CustomHeader({ onReportBugPress }: CustomHeaderProps) {
	const { meeting } = useRealtimeKitMeeting();
	const { roomJoined } = useRealtimeKitSelector((state) => state.self);

	const handleReportBugPress = () => {
		console.log("Report Bug Pressed");
		onReportBugPress?.();
	};

	if (!roomJoined) {
		return null;
	}

	return (
		<View style={styles.container}>
			{/* Left section */}
			<View style={styles.leftSection}>
				<RtkLogo />
				<RtkRecordingIndicator meeting={meeting} />
				<RtkLiveStreamIndicator meeting={meeting} />
			</View>

			{/* Center section */}
			<View style={styles.centerSection}>
				<RtkMeetingTitle meeting={meeting} />
			</View>

			{/* Right section */}
			<View style={styles.rightSection}>
				<RtkGridPagination meeting={meeting} />
				<RtkParticipantCount meeting={meeting} />
				<RtkClock meeting={meeting} />
				<TouchableOpacity
					style={styles.reportBugButton}
					onPress={handleReportBugPress}
				>
					<Text style={styles.reportBugText}>Report Bug</Text>
				</TouchableOpacity>
			</View>
		</View>
	);
}

const styles = StyleSheet.create({
	container: {
		flexDirection: "row",
		justifyContent: "space-between",
		alignItems: "center",
		height: 48,
		paddingHorizontal: 12,
		backgroundColor: "black",
	},
	leftSection: {
		flexDirection: "row",
		alignItems: "center",
		gap: 8,
	},
	centerSection: {
		flexDirection: "row",
		alignItems: "center",
	},
	rightSection: {
		flexDirection: "row",
		alignItems: "center",
		gap: 8,
	},
	reportBugButton: {
		borderWidth: 1,
		borderColor: "white",
		borderRadius: 4,
		paddingHorizontal: 8,
		paddingVertical: 4,
	},
	reportBugText: {
		color: "white",
		fontSize: 12,
	},
});
```

Note

`useRealtimeKitMeeting` and `useRealtimeKitSelector` must be called inside a component rendered within a `RealtimeKitProvider`. The `roomJoined` guard ensures the header only renders once the participant has successfully joined the meeting. `meeting.join()` is called from the parent `MeetingScreen` so that the join lifecycle is managed in one place.

#### Use in your meeting screen

In your meeting screen, replace the default `RtkHeader` with your custom header:

```tsx
import React, { useEffect } from "react";
import { View, StyleSheet } from "react-native";
import {
	RealtimeKitProvider,
	useRealtimeKitClient,
} from "@cloudflare/realtimekit-react-native";
import {
	RtkGrid,
	RtkControlbar,
	RtkDialogManager,
} from "@cloudflare/realtimekit-react-native-ui";
import { CustomHeader } from "./CustomHeader";

function MeetingContainer() {
	const [meeting, initMeeting] = useRealtimeKitClient();

	useEffect(() => {
		initMeeting({
			authToken: "<PARTICIPANT_AUTH_TOKEN>",
		});
	}, [initMeeting]);

	useEffect(() => {
		if (!meeting) return;
		meeting.join();
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [meeting]);

	if (!meeting) {
		return null;
	}

	return (
		<RealtimeKitProvider value={meeting}>
			<View style={styles.container}>
				{/* Custom header replaces RtkHeader */}
				<CustomHeader
					onReportBugPress={() => console.log("Report bug pressed")}
				/>

				{/* Meeting grid */}
				<View style={styles.gridContainer}>
					<RtkGrid meeting={meeting} />
				</View>

				{/* Control bar */}
				<RtkControlbar meeting={meeting} />
			</View>

			{/* Required components */}
			<RtkDialogManager meeting={meeting} />
		</RealtimeKitProvider>
	);
}

export function MeetingScreen() {
	return <MeetingContainer />;
}

const styles = StyleSheet.create({
	container: {
		flex: 1,
		backgroundColor: "black",
	},
	gridContainer: {
		flex: 1,
	},
});
```

Note

You must include `RtkDialogManager`. If you leave it out, features like settings toggles will not work.

Was this helpful?

YesNo

## On this page

[![](https://e8aee267.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://e8aee267.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/realtime/realtimekit/ui-kit/custom-header/#page","headline":"Add Custom Header · Cloudflare Realtime docs","description":"Add a custom header to your RealtimeKit meeting UI with individual components.","url":"https://developers.cloudflare.com/realtime/realtimekit/ui-kit/custom-header/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-08-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
