diff --git a/CHAT_SETUP.md b/CHAT_SETUP.md
new file mode 100644
index 0000000..c202bfa
--- /dev/null
+++ b/CHAT_SETUP.md
@@ -0,0 +1,225 @@
+# Live Chat Widget Setup Guide
+
+This guide will help you set up the Live Chat widget to display Twitch and YouTube live chat in OBS.
+
+## Quick Start
+
+1. **Start the server**
+ ```bash
+ uv run streamer-widgets --tray
+ ```
+
+2. **Configure Chat**
+ - Open http://127.0.0.1:8765/config in your browser
+ - Configure your Twitch channel and/or YouTube video ID
+ - (Optional) Set up OAuth for authenticated connections
+
+3. **Add to OBS**
+ - Create a new Browser Source
+ - URL: `http://127.0.0.1:8765/widgets/livechat/`
+ - Width: 400px (or your preference)
+ - Height: 600px (or your preference)
+ - Check "Shutdown source when not visible" for performance
+
+## Features
+
+### Supported Platforms
+- **Twitch**: IRC WebSocket connection (anonymous or authenticated)
+- **YouTube**: Live Chat API (requires OAuth)
+
+### Emote Support
+- Twitch native emotes
+- FrankerFaceZ (FFZ)
+- BetterTTV (BTTV)
+- 7TV
+- YouTube emoji (native)
+
+### Display Options
+- **Unified View**: Mix messages from both platforms chronologically
+- **Separate Columns**: (Coming soon) Side-by-side platform displays
+- Customizable message limit
+- Timestamps
+- User badges
+- Platform indicators
+
+## Authentication Setup
+
+### Configuration File
+
+OAuth credentials are stored in a JSON configuration file. On first run, the application creates an example config at:
+
+**Windows:** `%LOCALAPPDATA%\StreamerWidgets\config.json`
+
+You can also find the exact path in the web UI at http://127.0.0.1:8765/config
+
+### Twitch OAuth (Optional)
+
+For anonymous chat reading, you don't need OAuth. For authenticated connections:
+
+1. **Create a Twitch Application**
+ - Go to https://dev.twitch.tv/console/apps
+ - Click "Register Your Application"
+ - Name: `My Chat Widget` (or any name)
+ - OAuth Redirect URLs: `http://localhost:8765/auth/twitch/callback`
+ - Category: Chat Bot
+ - Client Type: **Confidential**
+ - Click "Create"
+
+2. **Configure Credentials**
+ - Open `config.json` in a text editor (see path above)
+ - Under `twitch_oauth`, set:
+ - `client_id`: Your Twitch Client ID
+ - `client_secret`: Your Twitch Client Secret
+ - `redirect_uri`: Keep as `http://localhost:8765/auth/twitch/callback`
+ - Save the file
+ - **Restart the application**
+
+ Example:
+ ```json
+ {
+ "twitch_oauth": {
+ "client_id": "abc123xyz456",
+ "client_secret": "def789ghi012",
+ "redirect_uri": "http://localhost:8765/auth/twitch/callback"
+ }
+ }
+ ```
+
+3. **Authenticate**
+ - Go to http://127.0.0.1:8765/config
+ - Click "Login with Twitch"
+ - Authorize the application in the browser popup
+
+### YouTube OAuth (Required for YouTube)
+
+YouTube Live Chat requires OAuth authentication:
+
+1. **Create a Google Cloud Project**
+ - Go to https://console.cloud.google.com/
+ - Create a new project
+ - Enable "YouTube Data API v3"
+
+2. **Create OAuth Credentials**
+ - Go to "Credentials" in your project
+ - Click "Create Credentials" → "OAuth client ID"
+ - Application type: Web application
+ - Authorized redirect URIs: `http://localhost:8765/auth/youtube/callback`
+ - Click "Create"
+
+3. **Configure Credentials**
+ - Open `config.json` in a text editor
+ - Under `youtube_oauth`, set:
+ - `client_id`: Your YouTube Client ID (ends with `.apps.googleusercontent.com`)
+ - `client_secret`: Your YouTube Client Secret
+ - `redirect_uri`: Keep as `http://localhost:8765/auth/youtube/callback`
+ - Save the file
+ - **Restart the application**
+
+ Example:
+ ```json
+ {
+ "youtube_oauth": {
+ "client_id": "123456789-abc.apps.googleusercontent.com",
+ "client_secret": "GOCSPX-xyz123abc456",
+ "redirect_uri": "http://localhost:8765/auth/youtube/callback"
+ }
+ }
+ ```
+
+4. **Authenticate**
+ - Go to http://127.0.0.1:8765/config
+ - Click "Login with YouTube"
+ - Sign in with your Google account
+ - Authorize the application
+
+## Configuration Options
+
+### Channel/Video Settings
+- **Twitch Channel**: The channel name to monitor (without #)
+- **YouTube Video ID**: The ID from the YouTube video/stream URL
+ - Example: For `https://youtube.com/watch?v=dQw4w9WgXcQ`, use `dQw4w9WgXcQ`
+
+### Emote Providers
+- Enable/disable FFZ, BTTV, and 7TV emotes
+- Emotes are loaded when connecting to a channel
+
+### Display Settings
+- **Max Messages**: Number of messages to keep (10-200)
+- **Show Timestamps**: Display message times
+- **Show Badges**: Display user badges (mod, subscriber, etc.)
+- **Unified View**: Mix both platforms or show separately
+
+### Filtering (Advanced)
+Not yet implemented in UI, but available via API:
+- Filter by user roles
+- Block messages with specific keywords
+- Set minimum message length
+
+## Customization
+
+### Widget Styling
+
+Edit `app/assets/web/widgets/livechat/style.css` to customize:
+- Colors and themes
+- Font sizes
+- Message spacing
+- Platform indicators
+- Badge styles
+
+### Widget Size
+
+Adjust in OBS Browser Source properties:
+- **Vertical chat**: 400x600px or 400x800px
+- **Horizontal chat**: 800x400px or 1000x400px
+
+## Troubleshooting
+
+### Twitch Chat Not Connecting
+- Check that the channel name is correct (lowercase, no #)
+- For authenticated connections, verify OAuth tokens are valid
+- Check console output for error messages
+
+### YouTube Chat Not Showing
+- Ensure the video/stream has live chat enabled
+- Verify OAuth authentication is complete
+- Check that the video ID is correct
+- YouTube requires authenticated access
+
+### Emotes Not Loading
+- Check internet connection
+- Third-party emote services may be rate-limited
+- Try disabling/re-enabling emote providers in config
+
+### Messages Not Appearing in OBS
+- Verify the widget URL is correct
+- Check that the browser source is visible
+- Refresh the browser source
+- Check browser console for WebSocket errors
+
+## API Endpoints
+
+For advanced integration:
+
+- `GET /api/chat/messages?limit=50` - Get recent messages
+- `GET /api/chat/config` - Get current configuration
+- `POST /api/chat/config` - Update configuration
+- `GET /ws` - WebSocket for real-time updates
+
+## Notes
+
+- Tokens are stored locally in `%LOCALAPPDATA%/StreamerWidgets/tokens.json`
+- Chat history is kept in memory (not persisted)
+- Anonymous Twitch connections have no rate limits for reading
+- YouTube API has daily quotas (should be sufficient for chat reading)
+
+## Future Enhancements
+
+- [ ] Chat commands/interactions
+- [ ] Message filtering UI
+- [ ] Custom badge images
+- [ ] Sound notifications
+- [ ] Chat replay/history
+- [ ] Multi-column layout
+- [ ] Custom CSS themes
+- [ ] Raid/host notifications
+- [ ] Viewer count display
diff --git a/CONFIG_README.md b/CONFIG_README.md
new file mode 100644
index 0000000..f670a56
--- /dev/null
+++ b/CONFIG_README.md
@@ -0,0 +1,57 @@
+# Configuration Guide
+
+## OAuth Credentials Configuration
+
+OAuth credentials for Twitch and YouTube are **no longer hardcoded** in the source code. Instead, they are loaded from a JSON configuration file.
+
+### Configuration File Location
+
+The config file is automatically created on first run at:
+
+- **Windows**: `%LOCALAPPDATA%\StreamerWidgets\config.json`
+- **Typical path**: `C:\Users\YourName\AppData\Local\StreamerWidgets\config.json`
+
+You can also see the exact path in the web UI at: http://127.0.0.1:8765/config
+
+### Example Configuration
+
+See `config.example.json` in the project root for a template.
+
+```json
+{
+ "twitch_oauth": {
+ "client_id": "YOUR_TWITCH_CLIENT_ID",
+ "client_secret": "YOUR_TWITCH_CLIENT_SECRET",
+ "redirect_uri": "http://localhost:8765/auth/twitch/callback"
+ },
+ "youtube_oauth": {
+ "client_id": "YOUR_YOUTUBE_CLIENT_ID.apps.googleusercontent.com",
+ "client_secret": "YOUR_YOUTUBE_CLIENT_SECRET",
+ "redirect_uri": "http://localhost:8765/auth/youtube/callback"
+ },
+ "server_host": "127.0.0.1",
+ "server_port": 8765
+}
+```
+
+### Setup Steps
+
+1. **Run the application once** to generate the config file
+2. **Edit the config file** with your OAuth credentials from Twitch/YouTube developer consoles
+3. **Restart the application** to load the new credentials
+4. **Visit the config UI** at http://127.0.0.1:8765/config to authenticate
+
+### No Credentials Needed for Twitch Anonymous
+
+Twitch chat can be read **anonymously without OAuth**. You only need Twitch OAuth if you want authenticated access (for rate limit benefits).
+
+YouTube **requires OAuth** to access live chat data.
+
+### Security Notes
+
+- The config file is stored locally on your machine
+- Never commit `config.json` to version control
+- Keep your Client Secrets private
+- The example file `config.example.json` contains placeholder values only
+
+For detailed setup instructions, see [CHAT_SETUP.md](CHAT_SETUP.md)
diff --git a/DISTRIBUTION.md b/DISTRIBUTION.md
new file mode 100644
index 0000000..0edd507
--- /dev/null
+++ b/DISTRIBUTION.md
@@ -0,0 +1,197 @@
+# Distribution Guide
+
+## How the Config System Works with PyInstaller
+
+### Architecture Overview
+
+The application uses a **two-location** file system:
+
+1. **Bundled Files (Read-Only)** - Inside the .exe
+ - Python source code
+ - Web assets (`app/assets/web/`)
+ - Everything compiled into the executable
+
+2. **User Data Directory (Read-Write)** - User's local machine
+ - Configuration: `%LOCALAPPDATA%\StreamerWidgets\config.json`
+ - OAuth Tokens: `%LOCALAPPDATA%\StreamerWidgets\tokens.json`
+ - Album Art: `%LOCALAPPDATA%\StreamerWidgets\art\`
+
+### Why This Works Well
+
+**Benefits:**
+- ✅ **No hardcoded credentials** in the .exe
+- ✅ **Survives updates** - User config persists when you release new versions
+- ✅ **User-specific** - Each user has their own OAuth credentials
+- ✅ **Secure** - Credentials never in source control or distributed executable
+- ✅ **Easy to find** - Standard Windows application data location
+
+**User Experience:**
+1. User downloads and runs `streamer-widgets.exe`
+2. App creates `config.json` automatically on first run
+3. User visits http://127.0.0.1:8765/config
+4. Clicks "Open Config Directory" button
+5. Edits `config.json` with their OAuth credentials
+6. Restarts the app
+7. OAuth authentication works!
+
+## Building the Executable
+
+### Build Command
+
+```bash
+uv sync --group build
+pyinstaller --noconsole --onefile --name streamer-widgets ^
+ --add-data "app/assets/web;app/assets/web" ^
+ run_tray.py
+```
+
+### What Gets Bundled
+
+- All Python code
+- `app/assets/web/` directory (HTML, CSS, JS for widgets)
+- Python dependencies
+
+### What Does NOT Get Bundled
+
+- `config.json` - Created at runtime in user directory
+- `tokens.json` - Created when user authenticates
+- `config.example.json` - Template file (not needed in .exe)
+
+## Distribution Checklist
+
+When distributing the application:
+
+- [ ] Build the executable with PyInstaller
+- [ ] Test the .exe on a clean machine (no Python installed)
+- [ ] Verify config directory creation works
+- [ ] Test "Open Config Directory" button in web UI
+- [ ] Include `CHAT_SETUP.md` or link to documentation
+- [ ] Provide example OAuth setup instructions
+
+## User Setup Instructions (for README/docs)
+
+### For End Users
+
+**First Run:**
+
+1. Run `streamer-widgets.exe`
+2. The app creates a configuration file automatically
+3. Open http://127.0.0.1:8765/config in your browser
+
+**Setting Up Chat Authentication:**
+
+1. In the config UI, you'll see a warning if OAuth is not configured
+2. Click the **"📁 Open Config Directory"** button
+3. This opens: `C:\Users\YourName\AppData\Local\StreamerWidgets\`
+4. Edit `config.json` with your OAuth credentials:
+ - Get Twitch credentials from https://dev.twitch.tv/console/apps
+ - Get YouTube credentials from https://console.cloud.google.com/
+5. Save the file
+6. **Restart the application**
+7. Return to http://127.0.0.1:8765/config and click "Login with Twitch/YouTube"
+
+**Example config.json:**
+
+```json
+{
+ "twitch_oauth": {
+ "client_id": "your_twitch_client_id_here",
+ "client_secret": "your_twitch_client_secret_here",
+ "redirect_uri": "http://localhost:8765/auth/twitch/callback"
+ },
+ "youtube_oauth": {
+ "client_id": "your_youtube_client_id.apps.googleusercontent.com",
+ "client_secret": "your_youtube_client_secret_here",
+ "redirect_uri": "http://localhost:8765/auth/youtube/callback"
+ },
+ "server_host": "127.0.0.1",
+ "server_port": 8765
+}
+```
+
+## Troubleshooting for Users
+
+### "I can't find the config file"
+
+1. Visit http://127.0.0.1:8765/config
+2. The warning box shows the exact path
+3. Or click "Open Config Directory" to open it directly
+
+### "OAuth isn't working"
+
+1. Check that `client_id` and `client_secret` are filled in (not placeholders)
+2. Make sure you **restarted the app** after editing config.json
+3. Verify the redirect URIs match in both:
+ - Your Twitch/YouTube developer console
+ - The `config.json` file
+
+### "Config directory won't open"
+
+The path is always: `%LOCALAPPDATA%\StreamerWidgets\`
+
+In Windows:
+1. Press `Win + R`
+2. Type: `%LOCALAPPDATA%\StreamerWidgets`
+3. Press Enter
+
+## Updates and Versioning
+
+When you release a new version:
+
+1. Users download the new `.exe`
+2. **Config persists** - No need to reconfigure OAuth
+3. **Tokens persist** - Users stay authenticated
+4. Just replace the old .exe with the new one
+
+The config directory is **separate from the executable**, so updates are seamless.
+
+## Security Considerations
+
+**What's Safe:**
+- Distribute `streamer-widgets.exe` publicly
+- Share the source code on GitHub
+- Include `config.example.json` as a template
+
+**What to NEVER Distribute:**
+- Actual `config.json` with real credentials
+- `tokens.json` files
+- Real OAuth Client IDs/Secrets
+
+**User Responsibility:**
+- Users must obtain their own OAuth credentials
+- Credentials are stored locally on their machine only
+- Never share `config.json` or `tokens.json` files
+
+## Advantages Over Alternatives
+
+### Why Not Environment Variables?
+❌ Hard for non-technical users
+❌ Doesn't work well with PyInstaller .exe
+❌ Difficult to edit and manage
+
+### Why Not Hardcoded Credentials?
+❌ Security risk
+❌ Every user would use the same credentials
+❌ Would hit OAuth rate limits
+❌ Can't distribute publicly
+
+### Why Config File in User Directory?
+✅ Standard practice for desktop apps
+✅ Survives application updates
+✅ User-specific credentials
+✅ Easy to locate and edit
+✅ Secure (local machine only)
+✅ Works perfectly with PyInstaller
+
+## Summary
+
+The config system is **production-ready for distribution**:
+
+1. **No code changes needed** by end users
+2. **Auto-creates config** on first run
+3. **Easy to find** via UI button
+4. **Persists across updates**
+5. **Secure** - no credentials in .exe
+6. **User-friendly** - clear instructions in UI
+
+Just build the .exe and distribute it. Users will be guided through the setup process by the web UI.
diff --git a/IMPLEMENTATION_SUMMARY.md b/IMPLEMENTATION_SUMMARY.md
new file mode 100644
index 0000000..75e1ff8
--- /dev/null
+++ b/IMPLEMENTATION_SUMMARY.md
@@ -0,0 +1,285 @@
+# Live Chat Widget - Implementation Summary
+
+## Overview
+
+A comprehensive live chat widget system has been implemented that supports both Twitch and YouTube live chat with extensive emote support (FrankerFaceZ, BetterTTV, 7TV) and real-time WebSocket streaming to OBS.
+
+## Architecture
+
+### Frontend Components
+
+1. **Chat Widget** (`app/assets/web/widgets/livechat/`)
+ - `index.html` - Minimal HTML structure
+ - `style.css` - Styled chat interface with platform indicators, badges, animations
+ - `app.js` - WebSocket client, message rendering, emote parsing, auto-scroll
+
+2. **Configuration UI** (`app/assets/web/config.html`)
+ - Platform authentication controls
+ - Channel/video configuration
+ - Emote provider toggles
+ - Display settings
+ - Real-time status indicators
+
+### Backend Components
+
+1. **Data Models** (`app/chat_models.py`)
+ - `Platform` - Enum for Twitch/YouTube
+ - `UserRole` - Broadcaster, Mod, VIP, Subscriber, Viewer
+ - `Emote` - Code, URL, provider, animation flag
+ - `ChatBadge` - Badge name and icon
+ - `ChatUser` - User ID, name, color, roles, badges
+ - `ChatMessage` - Complete message with user, text, emotes, timestamp
+ - `AuthTokens` - OAuth token storage with expiry
+ - `ChatConfig` - All widget configuration options
+
+2. **State Management** (`app/state.py`)
+ - Extended `AppState` with:
+ - `chat_messages` - Deque of recent messages (max 100)
+ - `chat_config` - Current configuration
+ - `twitch_tokens` / `youtube_tokens` - OAuth credentials
+ - Methods for adding messages and broadcasting to WebSocket clients
+
+3. **Twitch Integration** (`app/providers/twitch_chat.py`)
+ - IRC WebSocket client (`wss://irc-ws.chat.twitch.tv:443`)
+ - Supports anonymous and authenticated connections
+ - IRC message parsing (PRIVMSG, tags, badges, emotes)
+ - Emote loading from:
+ - Twitch native (from IRC tags)
+ - FrankerFaceZ API (global + channel)
+ - BetterTTV API (global + channel)
+ - 7TV API (global + channel)
+ - Auto-reconnect on disconnect
+
+4. **YouTube Integration** (`app/providers/youtube_chat.py`)
+ - YouTube Live Chat API polling client
+ - OAuth required (YouTube Data API v3)
+ - Fetches live chat ID from video
+ - Polls for new messages with adaptive interval
+ - Parses user roles (owner, moderator, sponsor)
+
+5. **Authentication System** (`app/auth.py`)
+ - OAuth flow handlers for Twitch and YouTube
+ - Token storage in `%LOCALAPPDATA%/StreamerWidgets/tokens.json`
+ - Automatic token loading on startup
+ - Browser-based authentication with popup windows
+ - Callback URL handling at `/auth/{platform}/callback`
+
+6. **Chat Manager** (`app/chat_manager.py`)
+ - Coordinates Twitch and YouTube clients
+ - Starts/stops based on configuration
+ - Manages asyncio tasks for each platform
+ - Graceful shutdown and restart
+
+7. **WebServer Updates** (`app/webserver.py`)
+ - Added livechat widget to WIDGETS list
+ - `/api/chat/messages` - Get recent messages
+ - `/api/chat/config` - GET/POST configuration
+ - `/config` - Configuration UI page
+ - OAuth routes registered via `register_auth_routes()`
+ - Enhanced WebSocket to send chat history on connect
+
+8. **Main Integration** (`app/main.py`)
+ - Load saved OAuth tokens on startup
+ - Initialize and start ChatManager
+ - Graceful shutdown of chat connections
+
+## Features Implemented
+
+### Core Functionality
+- ✅ Real-time chat from Twitch and YouTube
+- ✅ WebSocket streaming to OBS browser source
+- ✅ Unified message stream (both platforms mixed)
+- ✅ Platform-specific visual indicators (color borders, icons)
+- ✅ User badges (broadcaster, mod, VIP, subscriber)
+- ✅ Username colors (Twitch native colors)
+- ✅ Timestamps
+- ✅ Message animations (slide-in effect)
+- ✅ Auto-scroll with manual scroll detection
+
+### Emote Support
+- ✅ Twitch native emotes
+- ✅ FrankerFaceZ (FFZ) global and channel emotes
+- ✅ BetterTTV (BTTV) global and channel emotes
+- ✅ 7TV global and channel emotes
+- ✅ Animated emote support
+- ✅ Emote caching
+- ✅ Configurable emote provider toggles
+
+### Authentication
+- ✅ Twitch OAuth (optional, anonymous reading supported)
+- ✅ YouTube OAuth (required for YouTube API)
+- ✅ Secure token storage
+- ✅ Token persistence across restarts
+- ✅ Browser-based auth flow
+
+### Configuration
+- ✅ Web-based configuration UI
+- ✅ Platform enable/disable
+- ✅ Channel/video ID settings
+- ✅ Emote provider toggles
+- ✅ Display options (timestamps, badges, max messages)
+- ✅ Live status indicators
+
+### OBS Integration
+- ✅ Transparent background
+- ✅ Customizable CSS styling
+- ✅ Responsive design
+- ✅ Low resource usage
+- ✅ Auto-reconnecting WebSocket
+
+## API Endpoints
+
+### Widget Access
+- `GET /widgets/livechat/` - Chat widget HTML
+- `GET /config` - Configuration page
+
+### REST API
+- `GET /api/chat/messages?limit=50` - Fetch recent messages
+- `GET /api/chat/config` - Get current configuration
+- `POST /api/chat/config` - Update configuration
+
+### WebSocket
+- `GET /ws` - Real-time message stream
+ - Sends `chat_history` on connect
+ - Sends `chat_message` for each new message
+
+### OAuth
+- `GET /auth/twitch/login` - Initiate Twitch OAuth
+- `GET /auth/twitch/callback` - Twitch OAuth callback
+- `GET /auth/youtube/login` - Initiate YouTube OAuth
+- `GET /auth/youtube/callback` - YouTube OAuth callback
+
+## File Structure
+
+```
+app/
+├── chat_models.py # Data models for chat system
+├── chat_manager.py # Chat client coordinator
+├── auth.py # OAuth handlers
+├── state.py # Extended with chat state
+├── webserver.py # Added chat endpoints
+├── main.py # Integrated chat manager
+├── providers/
+│ ├── twitch_chat.py # Twitch IRC client
+│ └── youtube_chat.py # YouTube API client
+└── assets/web/
+ ├── config.html # Configuration UI
+ └── widgets/
+ └── livechat/
+ ├── index.html # Widget HTML
+ ├── style.css # Widget styles
+ └── app.js # WebSocket client
+
+CHAT_SETUP.md # User setup guide
+IMPLEMENTATION_SUMMARY.md # This file
+```
+
+## Configuration Requirements
+
+### For Twitch (Optional OAuth)
+Users who want authenticated Twitch access need to:
+1. Create app at https://dev.twitch.tv/console/apps
+2. Set redirect URI to `http://localhost:8765/auth/twitch/callback`
+3. Edit `app/auth.py` with Client ID and Secret
+
+Anonymous reading works without OAuth.
+
+### For YouTube (Required OAuth)
+Users need to:
+1. Create Google Cloud project
+2. Enable YouTube Data API v3
+3. Create OAuth credentials (Web application)
+4. Set redirect URI to `http://localhost:8765/auth/youtube/callback`
+5. Edit `app/auth.py` with Client ID and Secret
+
+## Usage Flow
+
+1. **Start Server**: `uv run streamer-widgets --tray`
+2. **Configure** (if using OAuth):
+ - Visit http://127.0.0.1:8765/config
+ - Click "Login with Twitch" or "Login with YouTube"
+ - Authorize in browser popup
+3. **Set Channel/Video**:
+ - Enter Twitch channel name
+ - Enter YouTube video ID
+ - Save configuration
+4. **Add to OBS**:
+ - Create Browser Source
+ - URL: `http://127.0.0.1:8765/widgets/livechat/`
+ - Size: 400x600 (or custom)
+5. **Chat appears in OBS** with live updates
+
+## Technical Highlights
+
+### Twitch IRC
+- Efficient IRC WebSocket connection
+- Minimal overhead (no polling)
+- Supports IRC tags for rich metadata
+- Handles PING/PONG keepalive
+- Graceful reconnection
+
+### YouTube API
+- Polling-based with adaptive intervals
+- Respects API rate limits
+- Extracts live chat ID automatically
+- Handles OAuth token refresh
+
+### Emote Systems
+- Parallel API calls for fast loading
+- Caching to avoid repeated requests
+- Fallback for missing emotes
+- Support for both static and animated
+
+### WebSocket Broadcasting
+- Efficient message distribution
+- Dead client cleanup
+- Initial history on connect
+- Type-safe message format
+
+### Performance
+- Message limit (deque with maxlen)
+- Auto-scroll optimization
+- Lazy emote replacement
+- Minimal DOM updates
+
+## Future Enhancements
+
+Potential additions (not implemented):
+- Separate column view (Twitch | YouTube)
+- Message filtering by keywords/roles
+- Custom badge images
+- Sound notifications
+- Chat replay
+- Custom themes
+- Viewer count display
+- Raid/host notifications
+- Chat commands
+- Donation/sub alerts
+
+## Testing Checklist
+
+- [ ] Twitch anonymous connection
+- [ ] Twitch authenticated connection
+- [ ] YouTube authenticated connection
+- [ ] FFZ emotes display
+- [ ] BTTV emotes display
+- [ ] 7TV emotes display
+- [ ] User badges display
+- [ ] Platform indicators
+- [ ] WebSocket reconnection
+- [ ] Configuration persistence
+- [ ] OAuth token storage
+- [ ] Multiple browser sources
+- [ ] OBS transparency
+- [ ] Auto-scroll behavior
+- [ ] Manual scroll detection
+
+## Notes
+
+- All dependencies already present (aiohttp)
+- No additional packages required for basic functionality
+- OAuth credentials must be user-provided
+- Tokens stored locally (not cloud)
+- Chat history is in-memory only (not persisted to disk)
+- Anonymous Twitch reading has no rate limits
+- YouTube API has daily quota (sufficient for chat reading)
diff --git a/README.md b/README.md
index 26a417e..9e177da 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,11 @@
## Streamer Widgets (OBS Browser Sources)
-This app runs a **single local web server** that hosts multiple streamer widgets (starting with **Now Playing**) on **one port**, and pushes updates via **WebSockets**.
+This app runs a **single local web server** that hosts multiple streamer widgets on **one port**, and pushes updates via **WebSockets**.
+
+### Available Widgets
+
+- **Now Playing**: Display currently playing music from Windows Media
+- **Live Chat**: Display Twitch and YouTube live chat with emote support (FFZ, BTTV, 7TV)
### Run (dev)
@@ -9,9 +14,19 @@ uv sync
uv run streamer-widgets --tray
```
-Then add this as an OBS Browser Source:
+Then add as OBS Browser Sources:
- **Now Playing**: `http://127.0.0.1:8765/widgets/nowplaying/`
+- **Live Chat**: `http://127.0.0.1:8765/widgets/livechat/`
+- **Configuration**: `http://127.0.0.1:8765/config`
+
+### Live Chat Setup
+
+See [CHAT_SETUP.md](CHAT_SETUP.md) for detailed instructions on:
+- Connecting to Twitch and YouTube
+- Setting up OAuth authentication
+- Configuring emote providers (FFZ, BTTV, 7TV)
+- Customizing the chat widget
### Build a standalone `.exe` (PyInstaller)
@@ -24,4 +39,6 @@ pyinstaller --noconsole --onefile --name streamer-widgets ^
The executable will be in `dist/streamer-widgets.exe`.
+**For end users:** Configuration files are stored in `%LOCALAPPDATA%\StreamerWidgets\`. The app auto-creates a config template on first run. Use the config UI at http://127.0.0.1:8765/config to open the config directory and set up OAuth credentials.
+
diff --git a/app/assets/web/config.html b/app/assets/web/config.html
new file mode 100644
index 0000000..c0b1f8b
--- /dev/null
+++ b/app/assets/web/config.html
@@ -0,0 +1,470 @@
+
+
+
+
+
+ Chat Configuration - Streamer Widgets
+
+
+
+
+
+ Live Chat Configuration
+
+
+
+
+
+ Twitch
+ Not Connected
+
+
+
Login with Twitch
+
(Optional - for extra features)
+
+
+
+
+
+ YouTube
+ Not Logged In
+
+
+
+
Login with YouTube
+
+
+
+
+
Emote Providers
+
+
+ Enable FrankerFaceZ emotes
+
+
+
+ Enable BetterTTV emotes
+
+
+
+ Enable 7TV emotes
+
+
+
+
+
+
+
+
+
Save Configuration
+
Back to Widgets
+
+
+
+
+
+
+
+ 🔧 Advanced Settings
+
+
+
+ Configuration files are stored at:
+
+
+
📁 Open Config Directory
+
+
+
Setting Up OAuth Credentials
+
+ To enable login functionality, you need to create OAuth apps and add your credentials to config.json:
+
+
+
+ Set redirect URI to: http://localhost:8765/auth/twitch/callback (or youtube)
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/assets/web/index.html b/app/assets/web/index.html
index cf5374d..d82f6cf 100644
--- a/app/assets/web/index.html
+++ b/app/assets/web/index.html
@@ -80,6 +80,7 @@
.widget-url-row {
display: flex;
align-items: center;
+ gap: 8px;
background: #ffffff;
border: 1px solid #cbd5e1;
border-radius: 6px;
@@ -87,7 +88,56 @@
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 13px;
color: #475569;
- overflow-x: auto;
+ }
+ .widget-url-row input {
+ flex: 1;
+ border: none;
+ background: transparent;
+ font-family: inherit;
+ font-size: inherit;
+ color: inherit;
+ outline: none;
+ min-width: 0;
+ }
+ .copy-btn {
+ background: #0f172a;
+ color: white;
+ border: none;
+ padding: 4px 10px;
+ border-radius: 4px;
+ font-size: 12px;
+ cursor: pointer;
+ flex-shrink: 0;
+ }
+ .copy-btn:hover {
+ background: #1e293b;
+ }
+ .widget-options {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+ margin-top: 8px;
+ padding-top: 12px;
+ border-top: 1px solid #e2e8f0;
+ }
+ .option-group {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ }
+ .option-group label {
+ font-size: 12px;
+ font-weight: 600;
+ color: #64748b;
+ text-transform: uppercase;
+ }
+ .option-group select {
+ padding: 6px 10px;
+ border: 1px solid #cbd5e1;
+ border-radius: 4px;
+ font-size: 13px;
+ background: white;
+ cursor: pointer;
}
.footer {
border-top: 1px solid #e2e8f0;
@@ -97,6 +147,13 @@
color: #64748b;
text-align: center;
}
+ .footer a {
+ color: #0f172a;
+ text-decoration: none;
+ }
+ .footer a:hover {
+ text-decoration: underline;
+ }
code {
font-family: inherit;
background: rgba(0,0,0,0.05);
@@ -118,8 +175,50 @@
+
+