Welcome to your temporary conversation. Send a message to try server-rendered chat and finite SSE updates.
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.
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