Source: Roblox Creator Hub · CC BY 4.0 · View source · Code samples: MIT Imported 2026-10-03. Formatting adapted for this site.
Custom text chat UI
This example shows how to use the TextChatService class to design your own frontend. It reuses the default text channels from CreateDefaultTextChannels and is very simple compared to the default UI.
Disable the default UI that comes with the
TextChatServiceby setting theChatWindowConfiguration.EnabledandChatInputBarConfiguration.Enabledproperties tofalsein Studio's Properties window.Create a replacement for the chat input bar. This is the text box that emits messages when the user presses Enter.
Create a
ScreenGuiand parent it toStarterGui.Create a
TextBoxand parent it to the newScreenGui, then reposition and resize it as desired.Create a
LocalScriptand parent it to the newTextBox.Add the following code to the
LocalScript:```lua title="Client" local TextChatService = game:GetService("TextChatService") -- RBXGeneral is the default public channel local RBXGeneral = TextChatService:FindFirstChild("TextChannels"):WaitForChild("RBXGeneral") local textBox = script.Parent textBox.FocusLost:Connect(function(enterPressed) local text = textBox.Text if enterPressed and #text > 0 then local success, response = pcall(function() return RBXGeneral:SendAsync(textBox.Text) end) if not success then RBXGeneral:DisplaySystemMessage("Failed to send message") end -- Users expect the input box to be cleared after sending a message textBox.Text = "" end end) ```
Create a replacement for the chat window. This is the
ScrollingFramethat displays messages as they are received fromTextChatService.MessageReceived. This step also creates aUIListLayoutto automatically layout the messages.Create another new
ScreenGuiand parent it toStarterGui.Create a
ScrollingFrameand parent it to theScreenGui, then reposition and resize it as desired.Create a
UIListLayoutand parent it to theScrollingFrame.Create a
LocalScriptand parent it to theScrollingFrame.Add the following code to the
LocalScript:local TextChatService = game:GetService("TextChatService") -- Function to create a new text label for each message received local function addMessageGui(textChatMessage: TextChatMessage) local isOutgoingMessage = textChatMessage.Status == Enum.TextChatMessageStatus.Sending local parent = script.Parent local originalLabel = parent:FindFirstChild(textChatMessage.MessageId) if originalLabel then originalLabel.Text = textChatMessage.Text originalLabel.BackgroundTransparency = if isOutgoingMessage then 0.5 else 0 else local textLabel = Instance.new("TextLabel") textLabel.BorderSizePixel = 0 textLabel.Font = Enum.Font.BuilderSans textLabel.TextSize = 18 textLabel.TextXAlignment = Enum.TextXAlignment.Left textLabel.BackgroundTransparency = if isOutgoingMessage then 0.5 else 0 textLabel.BackgroundColor3 = Color3.fromRGB(0, 0, 0) textLabel.TextColor3 = Color3.fromRGB(255, 255, 255) textLabel.Name = textChatMessage.MessageId textLabel.AutomaticSize = Enum.AutomaticSize.XY textLabel.Text = textChatMessage.Text textLabel.Parent = parent end end -- Start listening for incoming messages TextChatService.MessageReceived:Connect(addMessageGui)
Note
When using the [`TextChatService.MessageReceived`](/docs/textchatservice#textchatservice-messagereceived) event, it's important to check if the message already exists in the chat window. This event is called once when sending and once when the message is received from the server.