xiaohongshu
xiaohongshu
chatbot-widget-creator
Creates a battle-tested ChatGPT-style chatbot widget that solves real-world production issues. Features infinite re-render protection, text selection "Ask AI", RAG backend integration, streaming SSE, and comprehensive performance monitoring.
Full skill instructions
Creates a production-ready ChatGPT-style chatbot widget with advanced features:
var(--ifm-color-primary) to match host site brandingMessageBubbleBackend Requirements:
POST /api/chat returning Server-Sent Events{ "question": string, "stream": boolean }{ "type": "chunk", "content": string }Frontend Dependencies:
npm install react framer-motion react-markdown react-syntax-highlighter remark-gfm lucide-react clsx tailwind-merge
# Note: No ChatKit dependency - this is a custom implementation
# Create main directory structure
mkdir -p src/components/ChatWidget/{components,hooks,contexts,utils,styles}
# Copy all template files
cp -r .claude/skills/chatbot-widget-creator/templates/* src/components/ChatWidget/
Your backend must implement:
@app.post("/api/chat")
async def chat_endpoint(request: ChatRequest):
"""Chat endpoint with Server-Sent Events streaming."""
# Request format
{
"question": "What is physical AI?",
"stream": true,
"context": { # Optional
"selectedText": "...",
"source": "User selection"
}
}
# Response format (SSE)
data: {"type": "start", "session_id": "..."}
data: {"type": "chunk", "content": "Physical AI refers to..."}
data: {"type": "chunk", "content": "embodied AI systems..."}
data: {"type": "done", "session_id": "..."}
Add to your site root (e.g., src/theme/Root.tsx):
import React from 'react';
import AnimatedChatWidget from '../components/ChatWidget/components/AnimatedChatWidget';
export default function Root({ children }) {
const getChatEndpoint = () => {
const hostname = window.location.hostname;
if (hostname === 'localhost') {
return 'http://localhost:7860/api/chat';
}
return 'https://your-domain.com/api/chat';
};
return (
<>
{children}
<AnimatedChatWidget
apiUrl={getChatEndpoint()}
maxTextSelectionLength={2000}
fallbackTextLength={5000}
/>
</>
);
}
// Consolidated state to prevent fragmentation
interface ChatState {
messages: ChatMessage[];
isOpen: boolean;
isThinking: boolean;
currentStreamingId?: string;
error: Error | null;
renderCount: number;
}
// Split context pattern
const ChatStateContext = createContext<{ state: ChatState }>();
const ChatActionsContext = createContext<{ actions: ChatActions }>();
// Components only subscribe to what they need
const messages = useChatSelector(s => s.messages); // Re-renders on messages change
const actions = useChatActions(); // Never re-renders
❌ Multiple useState hooks:
// Bad - causes context fragmentation
const [messages, setMessages] = useState([]);
const [isOpen, setIsOpen] = useState(false);
✅ Consolidated useReducer:
// Good - single state source
const [state, dispatch] = useReducer(chatReducer, initialState);
❌ Circular dependencies:
// Bad - callback depends on state that changes
const handleChunk = useCallback((chunk) => {
if (session.currentStreamingId) { // Dependency on state
updateMessage(session.currentStreamingId, chunk);
}
}, [session.currentStreamingId]); // Infinite re-render!
✅ Stable references:
// Good - no circular dependencies
const streamingIdRef = useRef<string>();
const handleChunk = useCallback((chunk) => {
if (streamingIdRef.current) {
dispatch(updateStreamingAction(streamingIdRef.current, chunk));
}
}, [dispatch]); // Stable dependency array
// Proper SSE parsing
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data !== '[DONE]') {
const parsed = JSON.parse(data);
if (parsed.type === 'chunk' && parsed.content) {
handleChunk(parsed.content);
} else if (parsed.type === 'done') {
handleComplete();
}
}
}
}
Edit src/components/ChatWidget/styles/ChatWidget.module.css:
/* Primary colors */
.widget {
background: #171717; /* Dark mode background */
width: 380px;
height: 700px;
}
/* Message bubbles */
.userMessageBubble {
background: var(--ifm-color-primary); /* Theme integration */
color: white;
}
.aiMessageBubble {
background: #21262d;
border: 1px solid #30363d;
}
Infinite Re-renders
Memory Leaks
window.performance.memorySSE Not Working
text/event-streamdata: {} formatCache-Control: no-cache is setstream: true in the bodyhandleChunk(JSON.parse(data).content) not the raw stringText Selection Issues
useTextSelection is enableduser-select: none conflictsMarkdown Rendering & Layout Issues
list-style-position: inside on ul/olp margins in lists: li > p { margin: 0; display: inline; }.messageRenderer, headings, and lists in light mode media queries or classes.aiMessageBubble background is transparent or correctly coloredp, ul, ol (e.g., 0.25rem).messageRenderer > *:first-child { margin-top: 0; }!important if global site styles (like Docusaurus) override your chat styles.aiMessage { display: grid; align-items: end; }A production-ready chat widget that:
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience