An infinite scroll storytelling web application that generates personalized, AI-powered narratives. Users can influence story direction through toggleable badges while experiencing endless, engaging content in a retro terminal theme.
- 🔄 Infinite Scroll Storytelling: Automatically generates new story segments as you scroll
- 🎛️ Interactive Story Influence: Toggle badges to control mood, genre, style, and character elements
- 🏷️ Dynamic Badge Creation: Add custom story influences through text input
- 📱 Responsive Design: Works seamlessly on desktop and mobile devices
- 🤖 AI-Powered Generation: Uses OpenRouter API for high-quality story creation
- 🖥️ Terminal Theme: Retro computing aesthetic with Terminal.css
- 💾 Session Management: Stories maintain continuity across segments
- ⚡ Performance Optimized: Configurable story summarization and session optimization
- Python 3.8+
- uv (recommended Python package manager)
-
Clone the repository:
git clone https://github.com/alx/doomscroll-stories.git cd doomscroll-stories -
Install dependencies using uv:
uv pip install -r requirements.txt
Alternative: If you don't have uv installed, you can use pip:
pip install -r requirements.txt
-
Configure environment variables:
cp .env.example .env # Edit .env with your actual values (see Environment Variables section) -
Run the application:
uv run python doom_scroll_storyteller.py
Alternative:
python doom_scroll_storyteller.py -
Open in browser: Visit
http://127.0.0.1:5000to start doom-scrolling!
Create a .env file in the project root with the following variables:
# OpenRouter API Key (required)
OPENROUTER_API_KEY=your-openrouter-api-key-here
# Flask Secret Key (change for production)
SECRET_KEY=your-secure-secret-key-change-this# OpenRouter Model (default: openai/gpt-4o-mini)
OPENROUTER_MODEL=openai/gpt-4o-mini
# Story optimization settings
SUMMARY_WINDOW_SIZE=5 # Summarize after N segments
RECENT_SEGMENTS_COUNT=2 # Keep N recent segments with summary
# Session optimization
OPTIMIZE_SESSIONS=true # Enable session cleanup
MAX_SESSION_SIZE_KB=500 # Maximum session data size- Visit OpenRouter.ai
- Sign up for an account
- Navigate to the API Keys section
- Create a new API key
- Copy the key to your
.envfile
-
Select Story Influences: Toggle badges in the sidebar to influence your story
- Mood: mysterious, romantic, funny, dark, heartwarming
- Genre: sci-fi, fantasy, horror, thriller, western
- Style: action-packed, slow-burn, explosive, intimate, epic
- Spicy: passionate, seductive, dangerous, forbidden
-
Add Character Elements: Choose character types, traits, and relationships
-
Create Custom Influences: Use the text input to add your own badge influences
-
Start Scrolling: Click "Generate Story" to begin your personalized narrative
-
Keep Scrolling: New story segments generate automatically as you reach the bottom
-
Change Direction: Toggle different badges to influence upcoming segments
-
Start Fresh: Click "New Story" to begin a completely new narrative
Backend (doom_scroll_storyteller.py):
StoryGeneratorclass: Handles OpenRouter API integration- Flask routes for API endpoints (
/api/start_story,/api/continue_story, etc.) - Session-based story state management with optimization
- Environment variable configuration via python-dotenv
- Comprehensive logging with
logging_config.py
Frontend (templates/index.html + static/style.css):
- Terminal.css + Bootstrap 5 for retro terminal design
- Vanilla JavaScript for infinite scroll and AJAX interactions
- Collapsible sidebar with toggleable story influence badges
- Dynamic content loading with smooth animations
- Mobile-responsive design with touch-friendly interfaces
- User selects story influence badges and character elements in sidebar
- Frontend sends AJAX request to
/api/start_storywith active influences StoryGeneratorcreates OpenRouter API call with influences as prompt context- Generated story segment stored in Flask session and returned to frontend
- As user scrolls,
/api/continue_storygenerates next segments with full story context - Story summarization automatically manages session size for long stories
- story_segments: List of generated story parts with automatic summarization
- badges: Available influence badges (default + user-added)
- session_optimization: Configurable cleanup and size management
- Stories maintain narrative continuity through intelligent context management
doomscroll_stories/
├── doom_scroll_storyteller.py # Main Flask application
├── logging_config.py # Logging configuration
├── requirements.txt # Python dependencies
├── templates/
│ └── index.html # Main web interface
├── static/
│ ├── style.css # Custom styles
│ └── terminal.css # Terminal theme styles
├── docs/
│ └── screenshot.png # Application screenshot
├── .env # Environment variables (create from .env.example)
└── CLAUDE.md # Development instructions
# Install dependencies
uv pip install -r requirements.txt
# Run the application
uv run python doom_scroll_storyteller.py
# For development with auto-reload
uv run python doom_scroll_storyteller.py --debugGET /- Main application interfacePOST /api/start_story- Generate initial story segmentPOST /api/continue_story- Generate next story segmentPOST /api/add_badge- Add custom story influence badgeGET /api/get_badges- Retrieve available badgesGET /api/get_characters- Retrieve character elementsPOST /api/reset_story- Reset story session
- Story Length: Modify segment length in OpenRouter prompts (currently 200-300 words)
- Default Badges: Edit initial badge categories in Flask application
- Styling: Customize appearance in
static/style.css - Models: Change OpenRouter model via
OPENROUTER_MODELenvironment variable - Session Behavior: Adjust optimization settings for performance vs. memory usage
- Infinite Scroll: Intersection Observer API for smooth scroll detection
- Terminal Theme: Custom CSS with Terminal.css integration for authentic retro look
- Session Optimization: Automatic story summarization prevents memory bloat
- Error Handling: Comprehensive error handling with user-friendly messages
- Mobile Support: Responsive design with collapsible sidebar
- Performance: Configurable API timeouts and request optimization
- Accessibility: Proper ARIA labels and keyboard navigation support
This project is open source and available under the MIT License.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
If you encounter any problems, please open an issue with:
- Your operating system
- Python version
- Error messages (if any)
- Steps to reproduce the issue
Enjoy your personalized doom-scrolling storytelling experience! 🎭✨
