Skip to content

Repository files navigation

🌊 EmotionWave

Co-created with AI

A living Nuxt-based website that reacts to the world's mood. Through real-time sentiment analysis of news and social media, the site's visual expression — colors, animations, and atmosphere — changes automatically.

🌐 Live Site: https://emotionwave.iamjarl.com (Vercel)

EmotionWave — live particle visualization of global sentiment

🎯 Project Purpose

Create a data-driven artwork where the website changes in real-time based on global sentiment. Users get a visual sense of "how the world feels" through an immersive experience combining visual and audio elements.

🛠️ Technologies

  • Framework: Nuxt 4.4.8 + Vite
  • UI: TailwindCSS 4.1.18
  • Visuals: Three.js 0.182.0 for particle effects (lazy loaded)
  • Audio: Tone.js 15.1.22 for generative ambient sound (lazy loaded)
  • Data: Multi-source sentiment analysis (GDELT API, NewsAPI, Reddit)
  • PWA: Service Worker for offline functionality
  • TypeScript: Full type safety throughout the application

🎨 Features

Visual Expression

  • Dynamic particle system that reacts to sentiment (1000-2000 particles based on device)
  • Color transitions based on mood with smooth animations
  • Emotion-aware palette: when emotion analysis is available, colors blend distinct hues for anger, fear, joy, sadness, surprise and disgust instead of a single negative-positive axis
  • Interactive mouse-based particle movement
  • Smooth 60fps animations and transitions
  • Responsive design with mobile optimization
  • GPU-accelerated rendering with WebGL
  • Live headline display: Rotating article headlines centered on screen, updating every 5 seconds

Audio Experience

  • Generative ambient music using Tone.js with high variation
  • Musical scale changes based on sentiment:
    • Negative (-1 to -0.5): C minor, low tones
    • Neutral-negative (-0.5 to 0): Eb major, ambient
    • Neutral-positive (0 to 0.5): F major, flowing
    • Positive (0.5 to 1): C major, uplifting
  • Multiple chord variations: 4-5 different chord progressions per sentiment range
  • Varied timing: Dynamic intervals (3-6 seconds) between musical phrases
  • Rich melodic content: Additional notes, arpeggios, and bass lines
  • Dynamic Timbre: Instrument character (oscillator/envelope) morphs between textures (Sharp/Soft) based on mood
  • Dynamic effects: Filter and reverb adjust based on sentiment with variation
  • Reverb and delay effects for atmospheric sound
  • Volume control with smooth transitions
  • Reactive music updates when sentiment changes during playback
  • User interaction required to start audio (browser policy)

Sentiment Analysis

  • Multi-source aggregation: Combines data from GDELT API, NewsAPI (optional), and Reddit
  • Emotion categories: headlines are also classified into seven emotions (Ekman 6 + neutral) and aggregated into a "world emotion" that drives the palette and musical scale
  • Advanced analysis: Optional HuggingFace Inference API integration for improved sentiment detection
    • Strategically used on top 10 articles for balance between accuracy and performance
    • Remaining articles use fast keyword-based analysis
  • Keyword-based fallback: Enhanced keyword analysis when APIs don't provide explicit sentiment scores
  • Reddit integration: Social media sentiment with full weight for valuable real-world mood signals
  • Real-time analysis of news articles from multiple sources
  • Intensity-weighted average sentiment across all sources (prioritizing strong emotional signals)
  • Filters out articles with zero sentiment (missing data) for improved accuracy
  • Retry logic with exponential backoff for reliable data fetching
  • 30-second cache to limit API calls
  • Sentiment score range: -1 (negative) to +1 (positive)
  • Smooth animated transitions between sentiment scores
  • Automatic fallback to dynamic time-based data if APIs fail
  • Graceful degradation: works even if some APIs are unavailable
  • Article headlines: API returns article titles for live display on the site

Progressive Web App (PWA)

  • Offline functionality with service worker
  • Installable on mobile devices
  • Fullscreen experience
  • Optimized for mobile performance

SEO & Social Sharing

  • Comprehensive meta tags (Open Graph, Twitter Cards)
  • Structured data (JSON-LD) for rich snippets
  • Dynamic sitemap.xml and robots.txt generation
  • Canonical URLs for proper indexing
  • Optimized favicon set for all platforms

📊 Sentiment Visualization Mapping

Score Visual Mood Audio Mood Background Color
-1 to -0.5 Dark, uneasy, flickering C minor, low tones Dark gray (#111827)
-0.5 to 0 Cold, rain-like particles Eb major, ambient Dark blue (#1e3a8a)
0 to 0.5 Neutral, light gradient F major, flowing Blue (#3b82f6)
0.5 to 1 Warm, bubbling, colorful C major, uplifting Yellow (#eab308)

🚀 Quick Start

Prerequisites

  • Node.js 20.x or higher
  • npm or yarn

Installation

  1. Clone the repository:
git clone https://github.com/JarlLyng/EmotionWave.git
cd EmotionWave
  1. Install dependencies:
npm install
  1. Create a .env file (optional):
NUXT_PUBLIC_SITE_URL=http://localhost:3000
NUXT_PUBLIC_BASE_URL=/
  1. Start the development server:
npm run dev

The application will be available at http://localhost:3000

Available Scripts

  • npm run dev - Start development server with hot-reload
  • npm run build - Build for production (SSR)
  • npm run generate - Generate static site for deployment
  • npm run preview - Preview production build locally

📚 Documentation

🐛 Known Issues & Limitations

  1. Static Hosting Limitations

    • Server-side API routes don't work on static hosting (GitHub Pages, etc.)
    • Application uses fallback data automatically on static hosting
    • For full functionality with HuggingFace sentiment analysis, deploy to Vercel
  2. Audio Autoplay

    • Browser policies require user interaction to start audio
    • User must click the sound button to enable audio
  3. GDELT API Rate Limits

    • May be rate-limited during high traffic
    • Fallback data ensures application always works

🔒 Security

  • No sensitive data exposed in client-side code
  • API keys stored as GitHub secrets
  • Service worker uses secure context
  • HTTPS required for PWA features

📈 Performance

Performance-focused by design:

  • Lazy loading: Three.js and Tone.js are loaded on demand, kept out of the initial bundle
  • GPU-accelerated rendering: WebGL with device-aware particle counts (1000 on mobile, 2000 on desktop)
  • Server-side caching: 30-second cache on the sentiment API to limit upstream calls
  • Bundle size: ~635KB gzipped production build

🤝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

📝 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • GDELT for news data
  • Tone.js for audio synthesis
  • Three.js for 3D graphics and particle effects
  • Nuxt team for the amazing framework

📞 Support

For issues, questions, or contributions, please open an issue on GitHub.


Built with ❤️ using Nuxt 4, Vue 3, Three.js, and Tone.js

About

A living website that visualizes the world's mood in real time — sentiment analysis of global news drives generative Three.js visuals and ambient Tone.js sound. Built with Nuxt 4.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages