Project Info
Inspiration
We wanted to make neurofeedback fun and easy to understand. It is usually seen in medical or research settings, filled with charts and numbers. We thought, what if your brain had a mascot instead? A duck that shows up when your mind starts to wander felt like a lighthearted and effective way to help people stay focused. What It Does Memory Mallard is a Chrome extension that uses real-time EEG data from a Muse headband to tell when your focus drops while reading online. When that happens, a small animated duck walks across the screen and fades away. It acts as a gentle reminder to bring your attention back. After you finish reading, the extension gives you short questions based on the moments when you lost focus. These questions help you recall what you might have missed and understand the material better. How We Built It Memory Mallard is built as a full system that connects brain signals to what happens on your screen. The Muse EEG headset records brain activity. A Python backend analyzes the data using signal processing and basic machine learning on brainwave patterns like theta and beta ratios. A Tauri desktop app made with React and Rust shows the data and connects to the browser through WebSocket. The Chrome extension displays the animated duck on websites when focus is lost. The duck also talks using Fish Audio’s text-to-speech API in a Donald Duck-style voice. All parts work together in a loop: Muse → Python → Tauri → Extension → Browser. This lets the system read your attention in real time and give instant feedback. --- ## Challenges We Ran Into It was hard to connect the EEG stream to the browser in a stable way. The Muse headset sends data over OSC, which is not made for the web, so we built our own bridge server. The EEG data was also noisy and different for each user, which made it difficult to find good thresholds for focus detection. Chrome’s messaging system also added some complexity since background scripts and content scripts needed to talk to each other in real time. --- ## Accomplishments We’re Proud Of We managed to bring live brainwave data into a Chrome extension, something that is rarely done. We created a focus tool that is based on real science but still feels playful and friendly. We are proud of how we balanced hardware, software, and design under time pressure. Most of all, we built something that can make people smile while helping them focus. --- ## What We Learned We learned how to connect EEG sensors with web apps and process real-time data streams. We also learned more about how focus works from both a technical and human point of view. We realized that feedback does not have to be complex to be helpful. Sometimes a small, funny reminder like a duck can be enough to bring someone back to the task. Humor and good design can make serious technology feel approachable. --- ## What’s Next for Memory Mallard We want to expand Memory Mallard beyond reading and studying. The same idea can help drivers stay alert on long trips. By using EEG to track attention and giving small sound cues when focus drops, we could help prevent fatigue and improve safety. Our long-term goal is to explore how gentle feedback from brain data can make people more aware, focused, and safe in daily life.
🦆 Duck Controller - Complete Application
A desktop application that sends random duck messages from Python → Tauri → Browser Extension, displaying them on any webpage.
Architecture
┌─────────────────────────────────────────────────────────┐
│ Python Backend (Port 5000) │
│ - Random message generator │
│ - Sends messages every 5-10 seconds │
└─────────────────────┬───────────────────────────────────┘
│ HTTP POST
↓
┌─────────────────────────────────────────────────────────┐
│ Tauri Desktop App (Rust + React) │
│ - HTTP Server (Port 3030) - receives from Python │
│ - WebSocket Server (Port 3030/ws) - sends to extension │
│ - React Dashboard - displays activity │
└─────────────────────┬───────────────────────────────────┘
│ WebSocket
↓
┌─────────────────────────────────────────────────────────┐
│ Browser Extension (Chrome/Edge) │
│ - Background service worker │
│ - Content script injection │
│ - Displays duck messages on all web pages │
└─────────────────────────────────────────────────────────┘
🚀 Quick Start
Prerequisites
- Rust (latest stable) - Install
- Node.js 18+ - Install
- Python 3.8+ - Install
- Chrome/Edge Browser
- ffmpeg - Install (for video generation)
- Muse EEG Headset - muse-lsl for streaming
- API Keys:
- Anthropic Claude API key
- Fish Audio API key
📦 Installation
1. Setup Tauri Desktop App
cd calhackproj
# Install dependencies
npm install
# Run in development mode
npm run tauri dev
This will:
- Start the React frontend on
http://localhost:1420 - Start the Rust backend with HTTP server on
http://localhost:3030 - Start WebSocket server on
ws://localhost:3030/ws
2. Setup Python Backend
cd python-backend
# Create virtual environment (optional but recommended)
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Create .env file with API keys
echo "ANTHROPIC_API_KEY=your_key_here" > .env
echo "FISH_AUDIO_API_KEY=your_key_here" >> .env
# Run the backend
python main.py
The Python backend will:
- Start Flask server on port 5000
- Connect to Muse EEG headset for focus detection
- Take screenshots every 30 seconds
- Generate questions with Claude AI
- Create TTS audio with Fish Audio (Donald Duck voice)
- Generate lip-sync videos with animated duck
- Send video when user regains focus
3. Install Browser Extension
- Open Chrome/Edge
- Navigate to
chrome://extensions/(oredge://extensions/) - Enable Developer mode (toggle in top-right)
- Click Load unpacked
- Select the
browser-extensionfolder - The extension icon should appear in your toolbar
🎮 Usage
Running the Complete System
Terminal 1: Start Tauri App
cd calhackproj
npm run tauri dev
Terminal 2: Start Python Backend
cd python-backend
python main.py
Browser: Enable Extension
- Extension auto-connects to Tauri WebSocket
- Visit any website (e.g., google.com, youtube.com)
- Duck messages will appear as floating notifications!
📊 What Each Component Does
Python Backend (python-backend/main.py)
- Connects to Muse EEG headset for real-time brain monitoring
- Takes screenshots every 30 seconds
- Uses Claude AI to generate questions about screen content
- Generates TTS audio with Fish Audio (Donald Duck voice)
- Creates lip-sync videos with animated duck mouth movements
- Detects focus state changes and sends videos when focus is restored
- Endpoints:
GET /health- Health checkGET /api/metrics- Current EEG metricsGET /video/<filename>- Serve generated videosGET /screenshot/status- Screenshot generator statusGET /screenshot/latest- Latest generated video path
Tauri Backend (calhackproj/src-tauri/src/lib.rs)
- HTTP Server (Port 3030)
POST /api/message- Receives messages from PythonPOST /api/video- Receives video URLs from PythonGET /health- Health check
- WebSocket Server (Port 3030/ws)
- Broadcasts messages to all connected browser extensions
- Forwards video URLs to browser for display
- Tauri Commands
get_service_status- Returns status of all services
React Frontend (calhackproj/src/App.tsx)
- Beautiful dashboard showing:
- Service status (HTTP, WebSocket, Extension)
- Message count
- Real-time activity log
- Setup instructions
Browser Extension (AnnoyingDuckExtension/)
- Background Worker (
background.js)- Connects to Tauri WebSocket
- Auto-reconnects on disconnect
- Forwards messages to content scripts
- Content Script (
content.ts)- Spawns animated walking duck GIFs on distractions
- Displays lip-sync videos bottom-right with fade in/out
- Tracks attention metrics over 2-minute timeline
- Saves scroll positions when focus drops
- Popup (
popup.html)- Shows EEG connection status
- Displays attention timeline chart
- Manual quack button for testing
- Settings for duck visibility
🔧 Configuration
Python Backend
Edit python-backend/main.py:
TAURI_HTTP_URL = "http://localhost:3030/api/message"
MESSAGE_INTERVAL_MIN = 5 # seconds
MESSAGE_INTERVAL_MAX = 10 # seconds
Browser Extension
Edit browser-extension/background.js:
const WEBSOCKET_URL = 'ws://127.0.0.1:3030/ws';
const RECONNECT_INTERVAL = 3000; // 3 seconds
const MAX_RECONNECT_ATTEMPTS = 10;
🐛 Troubleshooting
Extension Not Connecting
- Check Tauri app is running:
http://localhost:3030/health - Check WebSocket server in terminal logs
- Open extension popup → Click "Reconnect"
- Check browser console (F12) for errors
Python Backend Can't Connect
- Ensure Tauri app is running first
- Check Tauri logs for HTTP server status
- Try manual send:
curl -X POST http://localhost:3030/api/message -H "Content-Type: application/json" -d '{"message":"Test","timestamp":"2024-01-01T00:00:00Z","type":"test"}'
No Messages Appearing
- Check Python backend logs - should show "Sent to Tauri"
- Check Tauri logs - should show "Received from Python"
- Check extension background worker console:
- Right-click extension icon → "Inspect service worker"
- Check webpage console (F12) - should show "Received duck message"
Port Already in Use
If port 3030 or 5000 is taken:
- Change ports in code (see Configuration section)
- Kill existing processes:
lsof -ti:3030 | xargs kill -9
📝 Development
Build for Production
Tauri App:
cd calhackproj
npm run tauri build
Python Backend (Executable):
cd python-backend
pip install pyinstaller
pyinstaller --onefile main.py
Browser Extension:
- Zip the
browser-extensionfolder - Upload to Chrome Web Store
🎨 Customization
Add More Duck Messages
Edit python-backend/main.py:
DUCK_MESSAGES = [
"🦆 Your custom message!",
"🦆 Another message!",
# Add more...
]
Change Message Display Style
Edit browser-extension/content.js - modify the createMessageBox() function CSS.
Adjust Message Frequency
Edit python-backend/main.py:
MESSAGE_INTERVAL_MIN = 2 # Faster
MESSAGE_INTERVAL_MAX = 5
📚 File Structure
annoying-duck-extension/
├── calhackproj/ # Tauri Desktop App
│ ├── src/ # React Frontend
│ │ ├── App.tsx # Main dashboard
│ │ └── App.css # Styling
│ ├── src-tauri/ # Rust Backend
│ │ ├── src/
│ │ │ └── lib.rs # HTTP + WebSocket server
│ │ └── Cargo.toml # Rust dependencies
│ └── package.json
├── python-backend/ # Python Backend
│ ├── main.py # Flask server + message generator
│ └── requirements.txt # Python dependencies
├── browser-extension/ # Chrome Extension
│ ├── manifest.json # Extension config
│ ├── background.js # Service worker
│ ├── content.js # Page injection
│ ├── popup.html # Popup UI
│ └── popup.js # Popup logic
└── README.md # This file
🚦 Testing the Flow
- Start Tauri: Should see "HTTP Server started" in terminal
- Start Python: Should see "Random message loop started!"
- Load Extension: Check popup shows "Connected"
- Open any website: Within 5-10 seconds, a duck message appears!
- Check Tauri Dashboard: Messages logged in real-time
🎯 Next Steps / Enhancements
- Add Python as Tauri sidecar (auto-start with app)
- Add native messaging for direct extension ↔ Tauri communication
- Persistent storage for message history
- Settings panel (message frequency, colors, sounds)
- Multiple duck themes/GIFs
- Desktop notifications
- System tray integration
📄 License
MIT License - Feel free to modify and use!
🦆 Enjoy Your Ducks!
Questions? Issues? Create a GitHub issue or check the troubleshooting section above.
Happy Ducking! 🦆
Analysis
View
Metric
- 11
- 9
- 6
- 4
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- AnthropicIn code
- CSSIn code
- FlaskIn code
- HTMLIn code
- PythonIn code
- ReactIn code
- RustIn code
- TypeScriptIn code
8 of 8 appear in the indexed code.
AI coding agents
- Claude CodeCommits
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
263 KB
Source files
30
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
ShawnL57/Cal_hacks
80 files · 1.7 MB · @ e0d0d8f
Structure
Interface
2 files · 3%Screens, components and styles rendered to the user.
Application logic
25 files · 31%Domain rules, services and shared utilities.
+1 more
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python36%
- TypeScript28%
- Markdown18%
- Rust8%
- HTML4%
- Shell3%
- Other (1)3%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
calhackproj/src-tauri/Cargo.toml
cargo · 13- axum
- chrono
- futures-util
- reqwest
- serde
- serde_json
- tauri
- tauri-plugin-opener
- tokio
- tokio-tungstenite
- tower
- tower-http
- +1 more
calhackproj/python-backend/requirements.txt
pypi · 11- anthropic
- fish-audio-sdk
- Flask
- Flask-CORS
- numpy
- pillow
- plotly
- pylsl
- python-dotenv
- requests
- scipy
calhackproj/package.json
npm · 10- @tauri-apps/api
- @tauri-apps/plugin-opener
- react
- react-dom
- +6 more
AnnoyingDuckExtension/package.json
npm · 22 development-only dependencies.
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.