A web application that discovers the connections between actors and movies. Find movies that two actors have appeared in together, or find actors who have appeared in two movies. Built with Ruby/Sinatra backend, HTMX frontend, and deployed via Kamal to a DigitalOcean VPS.
- Actor Search: Search for actors with autocomplete suggestions and input validation
- Timeline Visualization: View filmographies organized by year in a vertical timeline
- Shared Movies Highlighting: Common movies between actors are highlighted in red
- Responsive Design: Works on desktop and mobile devices
- TMDB Integration: Uses The Movie Database API with circuit breaker resilience
- Redis Caching: High-performance caching with connection pooling
- Monitoring: Structured logging, error tracking (Sentry), and health checks
- Ruby 4.0+
- Bundler (
gem install bundler) - Docker (for Redis and production deployment)
- Doppler CLI (secrets management)
git clone <repository-url>
cd costar
make setup-devdoppler login
doppler setup --project costar --config devRequired secrets in the dev config:
TMDB_API_KEY— get one at TMDB APISESSION_SECRET— generate withopenssl rand -hex 32REDIS_URL—redis://localhost:6379for local Redis
Optional:
make redis-start # in a separate terminal
make dev # starts development server with Doppler secretsVisit http://localhost:4567
make # Interactive menu
make dev # Start development server (Doppler + Puma)
make test # Run all tests (RSpec + Cucumber)
make test-rspec # Run RSpec tests only
make test-cucumber # Run Cucumber tests only
make lint # Check code style (RuboCop)
make fix # Auto-fix code style issues
make security # Run security scans (Brakeman + bundler-audit)
make pre-commit # Run all checks before committing
make help # Show all available commands- TMDBService: API integration with caching and standardized error handling
- ResilientTMDBClient: Circuit breaker pattern for API resilience
- ActorComparisonService: Timeline generation and movie analysis
- TimelineBuilder: Performance-optimized timeline rendering
- SimpleRequestThrottler: Synchronous request rate limiting
- CacheCleaner: Background service for automatic TTL-based cache cleanup
- Rate Limiting: Rack::Attack with Redis backend
- Input Validation: Comprehensive sanitization for all user inputs
- Security Headers: CSP, HSTS, X-Frame-Options, and more
- CORS Protection: Environment-based origin allowlisting
- Caching: Redis with connection pooling (production) / Memory (development)
- Circuit Breaker: Automatic API failure handling
- Health Checks:
/health/simpleand/health/completeendpoints - Error Tracking: Sentry integration for production monitoring
GET /- Main application pageGET /health/simple- Basic health check (for load balancers)GET /health/complete- Comprehensive health check with dependencies
GET /api/actors/search?q=query&field=actor1- Search actors with validationGET /api/actors/:id/movies- Get actor filmographyGET /api/actors/compare?actor1_id=123&actor2_id=456&actor1_name=Name1&actor2_name=Name2- Timeline comparison
All API endpoints include rate limiting, input validation, CORS headers, and structured error responses.
CoStar is deployed to a DigitalOcean VPS via Kamal v2 with Traefik reverse proxy for HTTPS.
Live at: https://costar.internetblacksmith.dev
Production secrets are stored in Doppler and fetched at deploy time by Kamal's native Doppler adapter (configured in .kamal/secrets). No doppler run wrapper is needed — Kamal handles it directly.
make deploy # Deploy to production
make deploy-status # Show deployment status
make deploy-logs # Stream production logs
make deploy-rollback # Rollback to previous version
make deploy-setup # First-time Kamal setup on new servermake setup-deploy # Checks prerequisites, installs Kamal, generates .kamal/secretsDoppler must be configured with the costar/prd config containing all required secrets (see config/deploy.yml for the full list).
GitHub Actions runs tests and security scans on every push. Deployment to production can be triggered via make deploy or through the GitHub Actions deploy workflow.
- Host: DigitalOcean VPS with Traefik reverse proxy
- Registry: GitHub Container Registry (ghcr.io)
- Accessories: Redis 7.4 (managed by Kamal on the VPS)
- Domain:
costar.internetblacksmith.dev(Cloudflare DNS, grey cloud / DNS only)
- Ruby 4.0+ with Sinatra framework
- Redis for high-performance caching
- Puma web server
- HTMX for dynamic interactions
- ERB templating
- Modular CSS with ITCSS methodology
- TMDB API v3 for movie data
- Sentry for error tracking
- Doppler for secrets management
- PostHog for product analytics
- RSpec for unit/integration tests
- Cucumber for end-to-end BDD tests
- VCR + WebMock for API mocking
- RuboCop for code quality
- Brakeman for security scanning
This application uses TMDB and the TMDB APIs but is not endorsed, certified, or otherwise approved by TMDB.
Important: This is a non-commercial personal project. For commercial use, you must obtain a commercial agreement with TMDB. Review TMDB API Terms before deployment.
MIT License
Note: While this code is MIT licensed, the TMDB API has its own terms of use that must be followed when using the application.