"Listen... to the whispers in the dark..."
A horror story reader with an immersive retro CRT monitor aesthetic. Experience creepypasta and horror stories with atmospheric audio, spooky visual effects, and an automatic narrator that whispers tales in a haunting voice.
- Authentic scanline effects across the entire viewport
- Subtle screen jitter animation mimicking CRT instability
- Monochromatic green phosphor glow
- Per-paragraph blur - Each paragraph blurs individually when idle, hover to reveal for suspenseful reading
- Fixed-width terminal fonts
Random atmospheric effects that appear during your reading session:
- Crawling Spiders - Watch spiders crawl across your screen
- Floating Ghosts - Ethereal apparitions drift through the page
- Screen Glitches - Reality-bending visual distortions
- Jump Scares - Sudden frightening images with sound
- Shadow Figures - Dark entities lurking at the edges
- Randomized Background Music - Each story plays a unique atmospheric track from 11 longer audio files
- Contextual Sound Effects - Keyword-based audio that matches story content
- Jump Scare Sounds - 6 short, impactful sound effects for maximum fright
- Narrator Voice - Optional text-to-speech with creepy voice settings (lower pitch, slower rate)
- Smart Audio Management - Respects browser autoplay policies, pauses narrator during effects
- Enabled by default - Automatically starts reading stories when you open them
- Reads full article content with atmospheric voice (pitch: 0.7, rate: 0.8)
- Toggle on/off with the NARRATE button or in settings
- Continues narrating even during jump scares and spooky effects
- Uses Web Speech API with event-based state tracking for accurate playback
- Full keyboard navigation support
- Screen reader compatible with ARIA labels
- Reduce motion option for sensitive users
- Disable blur effects toggle
- WCAG AA color contrast compliance
- Respects
prefers-reduced-motionsystem setting
- Node.js 18+
- npm or yarn
# Clone the repository
git clone <repository-url>
cd whisperer
# Install dependencies
npm install
# Start development server
npm run devThe app will open at http://localhost:5173 (or the next available port).
On first launch, the app automatically seeds with 11 horror stories including:
- The Haunted Server Room
- The Last Commit
- The Cursed Algorithm
- The Midnight Debugger
- The Infinite Loop
- And more creepy tales...
Important:
- Click anywhere on the page after loading to enable audio (browser autoplay policy requirement)
- The narrator is enabled by default and will start reading automatically
- All articles are horror-themed with atmospheric background music
- Browse the feed of horror stories
- Click any story to read the full content
- Background music and narrator start automatically (after user interaction)
- Hover over each paragraph to reveal the text - creates suspenseful reading experience
- Random spooky effects appear every 30-90 seconds
- Click the NARRATE button to pause/resume narration
- Use the back button to return to the feed
- Auto-Start: Narrator is enabled by default and begins reading automatically
- Toggle: Click the "NARRATE" button (๐) in any article to stop/start narration
- Disable: Go to settings (โ๏ธ) and toggle "Narrator" to OFF to disable completely
- Note: Narrator continues during jump scares and visual effects for uninterrupted storytelling
- Reduce Motion - Disables screen jitter and reduces animations
- Disable Blur - Shows all text clearly without hover requirement
- Narrator - Enables text-to-speech functionality
- React 19 with TypeScript (strict mode)
- Vite - Lightning-fast build tool and dev server
- CSS Modules with PostCSS for scoped styling
- Vitest - Unit testing framework with jsdom
- fast-check - Property-based testing library
- Web Speech API - Text-to-speech narrator
- LocalStorage - Article persistence and preferences
src/
โโโ components/ # React components (visual effects, UI elements)
โ โโโ JumpScare.tsx
โ โโโ FloatingGhost.tsx
โ โโโ CrawlingSpider.tsx
โ โโโ GlitchEffect.tsx
โ โโโ ShadowFigure.tsx
โ โโโ Scanlines.tsx
โ โโโ ScreenJitter.tsx
โ โโโ ...
โโโ contexts/ # React Context providers
โ โโโ ThemeContext.tsx
โ โโโ AccessibilityContext.tsx
โ โโโ ArticleContext.tsx
โ โโโ NarratorContext.tsx
โโโ hooks/ # Custom React hooks
โ โโโ useArticleAudio.ts
โ โโโ useRandomSpookyEffect.ts
โ โโโ useDebounce.ts
โโโ utils/ # Utility functions
โ โโโ AudioManager.ts # Audio playback management
โ โโโ Narrator.ts # Text-to-speech system
โ โโโ soundMapping.ts # Keyword-based audio selection
โ โโโ ArticleRepository.ts # Article CRUD operations
โ โโโ seedData.ts # Demo horror stories
โโโ views/ # Top-level view components
โ โโโ FeedView.tsx
โ โโโ ArticleView.tsx
โ โโโ CuratorView.tsx
โโโ types/ # TypeScript type definitions
โโโ test/ # Test setup and integration tests
# Run all tests once
npm run test
# Run tests in watch mode
npm run test:watch
# Run tests with UI
npm run test:ui
# Run accessibility tests only
npm run test:a11y
# Lint code
npm run lint- Unit Tests - Specific component behaviors
- Property-Based Tests - Universal properties with fast-check (100+ iterations)
- Integration Tests - Complete user flows
- Accessibility Tests - WCAG compliance with react-axe
Use the Curator view (accessible via settings) to add new horror stories:
- Enter title, content, and source
- Stories are automatically saved to LocalStorage
- Preview text is generated (first 150 characters)
Audio files are organized by purpose:
Background Music (public/media/sounds/)
- Files >1.8MB for sustained atmosphere
- 11 tracks including Abyss.mp3, CrEEP.mp3, trappist.wav
Jump Scare Sounds
- Files <500KB for quick impact
- 6 sounds including ghost sounds, roars, screams
Edit component files in src/components/ to customize:
- Scanline density and opacity
- Screen jitter intensity
- Blur amount and transition speed
- Spooky effect timing and behavior
npm run dev # Start Vite dev server
npm run build # TypeScript compilation + Vite build
npm run preview # Preview production build locally
npm run test # Run all tests once
npm run test:watch # Run tests in watch mode
npm run test:ui # Run tests with Vitest UI
npm run test:a11y # Run accessibility tests only
npm run lint # Run ESLint# Build and start the container
docker-compose up -d
# View logs
docker-compose logs -f
# Stop the container
docker-compose downThe app will be available at http://localhost:3000
# Build the image
docker build -t whisperer .
# Run the container
docker run -d -p 3000:80 --name whisperer whisperer
# View logs
docker logs -f whisperer
# Stop and remove
docker stop whisperer
docker rm whispererThe Docker image uses:
- Multi-stage build for optimized image size
- Nginx as the web server
- Gzip compression for faster loading
- Security headers for protection
- Health checks for monitoring
- Asset caching for performance
Deploy to any platform that supports Docker:
- AWS ECS/Fargate
- Google Cloud Run
- Azure Container Instances
- DigitalOcean App Platform
- Heroku Container Registry
- Self-hosted with Docker
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Opera 76+
Note: Web Speech API support varies by browser. Narrator functionality requires a browser with speech synthesis support.
This project is open source and available under the MIT License.
Horror stories sourced from:
- Creepypasta Archive
- r/NoSleep
- r/LetsNotMeet
- Various horror fiction communities
Audio assets are royalty-free or used under appropriate licenses.
- Audio may not play until user interacts with the page (browser autoplay policy)
- Some browsers may not support all Web Speech API voices
- Performance may vary on older devices with many visual effects active
- Narrator is enabled by default - disable in settings if you prefer silent reading
Contributions are welcome! Feel free to:
- Add new horror stories
- Improve visual effects
- Enhance audio system
- Fix bugs
- Improve accessibility
"The darkness calls to you... Will you answer?" ๐ป