ChatBox Component
The ChatBox component is an intelligent chat interface that connects to an AI backend, supports markdown rendering, and can provide context-aware responses about blog posts.
Overview
Located in src/components/ChatBox.tsx, this component provides:
AI-powered chat using OpenAI GPT-4o-mini
Markdown rendering with syntax highlighting
Blog context integration for post summaries
Fullscreen mode for extended conversations
Auto-scrolling message history
Clear chat functionality
Loading states and error handling
Props
Controls the visibility of the chat interface. When false, the component returns null.
Callback function triggered when the close button is clicked.
Controls the chat interface color scheme. The component is optimized for dark mode.
Message to send automatically when opening the chat. Used with blogContext to request summaries.
Blog post data for context-aware responses. Includes title, excerpt, and content fields.
Type Definitions
The component uses these TypeScript interfaces:
interface Message {
role : 'user' | 'assistant' | 'system' ;
content : string ;
}
interface BlogContext {
title : string ;
excerpt : string ;
content : string ;
}
interface ChatBoxProps {
isOpen : boolean ;
onClose : () => void ;
isDarkMode ?: boolean ;
initialMessage ?: string ;
blogContext ?: BlogContext ;
}
Usage
Basic Chat
With Blog Context
import ChatBox from './components/ChatBox' ;
function App () {
const [ isChatOpen , setIsChatOpen ] = useState ( false );
return (
< ChatBox
isOpen = { isChatOpen }
onClose = { () => setIsChatOpen ( false ) }
isDarkMode = { true }
/>
);
}
Features
AI Backend Integration
The component connects to a Netlify serverless function:
// From ChatBox.tsx:9-11
const API_URL = process . env . NODE_ENV === 'development'
? '/.netlify/functions/chat'
: 'https://ethanclinick.netlify.app/.netlify/functions/chat' ;
Requests are sent with these parameters:
// From ChatBox.tsx:114-126
body : JSON . stringify ({
messages: [
{
role: 'system' ,
content: createSystemPromptWithBlogContext ( activeContext )
},
... messages ,
userMessage
],
temperature: 0.7 ,
top_p: 0.9 ,
max_tokens: 4000 ,
model: "gpt-4o-mini"
})
Markdown Rendering
Messages from the AI are rendered with full markdown support using react-markdown:
Supported Elements
Code Example
Headings : H1, H2, H3 with custom styling
Lists : Ordered and unordered with spacing
Code : Inline code and code blocks
Links : Auto-open in new tab with security
Blockquotes : With border styling
Strong/Bold : Enhanced visibility
// From ChatBox.tsx:181-233
< ReactMarkdown
components = { {
p : ({ children }) => (
< p className = "mb-4 last:mb-0 text-sm leading-relaxed text-gray-200" >
{ children }
</ p >
),
code : ({ inline , className , children }) => {
if ( inline ) {
return < code className = "bg-gray-800 text-orange-400 px-1.5 py-0.5 rounded text-sm font-mono" > { children } </ code > ;
}
return (
< div className = "my-4" >
< pre className = "bg-gray-900 border border-gray-800 p-4 rounded-lg overflow-x-auto" >
< code className = { ` ${ className } text-sm font-mono` } > { children } </ code >
</ pre >
</ div >
);
},
// ... more components
} }
>
{ formattedContent }
</ ReactMarkdown >
AI responses are automatically formatted for better readability:
// From ChatBox.tsx:14-31
const formatAIResponse = ( text : string ) : string => {
// Add double line breaks between sections
text = text . replace ( / \n (?= [ A-Z ] ) / g , ' \n\n ' );
// Add spacing after punctuation if missing
text = text . replace ( / ( [ .!? ] )( [ A-Z ] ) / g , '$1 \n\n $2' );
// Ensure proper spacing around lists
text = text . replace ( / ( [ .!? ] ) \n ( [ •\-* ] ) / g , '$1 \n\n $2' );
// Add spacing around code blocks
text = text . replace ( /```/ g , ' \n ``` \n ' );
return text . trim ();
};
Fullscreen Mode
Toggle between windowed and fullscreen layouts:
// From ChatBox.tsx:254-256
const toggleFullscreen = () => {
setIsFullscreen ( ! isFullscreen );
};
Fullscreen mode is only available on desktop (hidden on mobile via hidden md:block).
Blog Context System
When a blog context is provided, the system prompt is enhanced:
// From ChatBox.tsx:73-91
const createSystemPromptWithBlogContext = ( context ?: BlogContext ) => {
const basePrompt = createEnhancedSystemPrompt ();
if ( context ) {
return ` ${ basePrompt }
You are also helping the user understand a blog post. Here is the blog context:
Blog Title: ${ context . title }
Blog Excerpt: ${ context . excerpt }
Blog Content:
${ context . content }
When asked to summarize or discuss this blog, provide helpful insights...` ;
}
return basePrompt ;
};
State Management
Internal state tracked by the component:
// From ChatBox.tsx:34-40
const [ messages , setMessages ] = useState < Message []>([]);
const [ isLoading , setIsLoading ] = useState ( false );
const [ error , setError ] = useState < string | null >( null );
const [ isFullscreen , setIsFullscreen ] = useState ( false );
const [ currentBlogContext , setCurrentBlogContext ] = useState < BlogContext | undefined >( undefined );
const messagesEndRef = useRef < HTMLDivElement >( null );
const hasProcessedInitialMessage = useRef < string | null >( null );
API Configuration
The component expects a serverless function at /.netlify/functions/chat that accepts OpenAI-compatible request format. Ensure your backend is configured with the OpenAI API key.
Styling
The ChatBox uses a dark, modern aesthetic:
Container : Fixed positioning with responsive sizing
Background : Pure black (bg-black) with glass borders
Messages : User messages in gray bubbles, AI messages as full-width text
Input : Custom AIInput component (see src/components/ui/ai-input.tsx)
Customization Tips
Change AI model : Update the model parameter in ChatBox.tsx:125
Adjust response length : Modify max_tokens in ChatBox.tsx:124
Update greeting message : Edit the default message in ChatBox.tsx:54-56
Customize markdown styles : Modify the ReactMarkdown components in ChatBox.tsx:181-233
Dependencies
{
"react-markdown" : "^8.x" ,
"lucide-react" : "^0.x"
}