Chat Demo

Notes

  • Temporary browser-session sandbox, not published. Session ownership is not authentication.
  • Same-origin and CSRF checks are enforced. No rate-protection or production-readiness guarantee.
  • History retains the welcome plus the latest 25 complete exchanges (51 entries).
  • Messages allow at most 4096 UTF-16 units before trimming; this is not a raw HTTP limit.
  • Chat expires after 30 idle minutes. Streams end after 5 minutes; Resume is explicit.
  • At most 32 chats, two streams per session and 64 streams in this process. Expired resources are reclaimed; valid chats are never evicted for admission.
Connecting to a finite private stream.

ChatModule

A real transcript and composer with application-owned session history and finite SSE.

Temporary, non-published chat. Session ownership is not authentication. Same-origin and CSRF checks are enforced. Only the welcome and latest 25 complete exchanges are retained.
Demo Agent08:08:30

Welcome to your temporary conversation. Send a message to try server-rendered chat and finite SSE updates.

Java composition & chat API
ChatDemoPage module composition
public static Component chatSpecimen(String conversationId, List<ChatMessageView> history) {
    ChatTranscriptRenderer<ChatMessageView, Void> renderer =
        ChatTranscriptRenderer.<ChatMessageView, Void>builder()
            .withEmptyStateText("No messages yet. Start by sending one below.")
            .withBodyTextResolver((message, context) -> message.body()).build();
    Component transcript = new HtmlTag("div").withId("chat-history")
        .withAttribute("data-chat-conversation-id", conversationId)
        .withChild(Alert.warning("Temporary, non-published chat. Session ownership is not authentication. Same-origin and CSRF checks are enforced. Only the welcome and latest 25 complete exchanges are retained."))
        .withChild(renderer.render(history, null));
    TextInput input = TextInput.create("message").withPlaceholder("Type a message").required();
    input.withAttribute("maxlength", "4096");
    input.withAttribute("autocomplete", "off");
    input.withAttribute("autocorrect", "off");
    input.withAttribute("autocapitalize", "off");
    input.withAttribute("spellcheck", "false");
    Form composer = Form.create().withId("chat-composer").withHxPost("/chat/messages")
        .withHxTarget("#chat-history").withHxSwap("outerHTML").addField("Message", input);
    composer.withAttribute("autocomplete", "off");
    composer.withChild(new HtmlTag("input", true).withAttribute("type", "hidden")
        .withAttribute("name", "conversationId").withAttribute("value", conversationId));
    composer.withChild(Button.submit("Send"));
    return ChatModule.create().withModuleId("chat-module").withTitle("ChatModule")
        .withDescription("A real transcript and composer with application-owned session history and finite SSE.")
        .withTranscript(transcript).withComposer(composer)
        .withUiConfig(new ChatUiConfig(conversationId, ChatTransportMode.SSE,
            "/chat/history", "/chat/stream", "#chat-history", "outerHTML", null));
}
// Equivalent to ChatDemoPage's module plus its complete transcript/composer helpers.
// The application owns transport coordination, identity, limits and CSRF.

ChatMessageData supplies message values; DefaultChatMessageComponent renders each message through the transcript renderer. ChatTransportMode and ChatUiConfig describe routing metadata, not an implemented WebSocket server. This site demonstrates SSE only.

Chat helper referenceChatModule API