{"id":50400791,"url":"https://github.com/muddyblack/terminal-slide-show","last_synced_at":"2026-05-30T23:03:59.150Z","repository":{"id":209236857,"uuid":"723544489","full_name":"Muddyblack/Terminal-Slide-Show","owner":"Muddyblack","description":"Script to auto manage files from google drive and directly show them on a Raspberry-Pi or any browser capable device in a slide-show. Allowing video and images at the same time.","archived":false,"fork":false,"pushed_at":"2026-01-27T12:53:28.000Z","size":9115,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-27T22:49:05.702Z","etag":null,"topics":["bash","google-drive-api-v3","javascript","raspberry-pi","react","slideshow","terminal-based"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Muddyblack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-11-26T02:02:24.000Z","updated_at":"2026-01-27T12:53:31.000Z","dependencies_parsed_at":"2024-11-12T21:30:24.382Z","dependency_job_id":"e2ae68d1-f05e-4958-9b80-8a837716cf0c","html_url":"https://github.com/Muddyblack/Terminal-Slide-Show","commit_stats":null,"previous_names":["muddyblack/slideshow","asta-dhbw/terminal-slide-show","muddyblack/terminal-slide-show"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/Muddyblack/Terminal-Slide-Show","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Muddyblack%2FTerminal-Slide-Show","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Muddyblack%2FTerminal-Slide-Show/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Muddyblack%2FTerminal-Slide-Show/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Muddyblack%2FTerminal-Slide-Show/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Muddyblack","download_url":"https://codeload.github.com/Muddyblack/Terminal-Slide-Show/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Muddyblack%2FTerminal-Slide-Show/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33712582,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","google-drive-api-v3","javascript","raspberry-pi","react","slideshow","terminal-based"],"created_at":"2026-05-30T23:03:59.011Z","updated_at":"2026-05-30T23:03:59.143Z","avatar_url":"https://github.com/Muddyblack.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Terminal Slide Show\n\nA modern, full-featured digital signage solution built with React and Node.js that automatically synchronizes and displays media content from Google Drive. Perfect for information displays, digital signage, and automated presentations.\n\n## Features\n\n- 🖼️ Seamless display of images and videos from Google Drive\n- ⚡ Real-time updates via WebSocket connections\n- 📦 Intelligent caching system for optimal performance\n- 🔄 Automatic content synchronization with change detection\n- 📅 Advanced scheduling with vacation periods and daily time windows\n- ⌚ Configurable display times and operating days\n- 🎯 Date-based content targeting through filename parsing\n- 📱 Touch and swipe support for navigation\n- 🖥️ Full kiosk mode support\n- 🎨 Smooth transitions and animations\n- 🌅 Dynamic day/night mode transitions\n- 🌡️ Live weather updates and animations\n- 🚀 NASA Astronomy Picture of the Day integration\n- 📊 Health monitoring and automatic recovery\n- 🔒 Secure operation with minimal dependencies\n\n## Real-Time Updates\n\nThe application uses WebSocket connections to provide real-time updates:\n- Instant content updates when files change in Google Drive\n- Live schedule status synchronization\n- Immediate system health notifications\n- Automatic reconnection handling\n- Reduced server load compared to polling\n\n## Caching System\n\nMulti-level caching strategy for optimal performance:\n- **Browser Cache**: \n  - Media files cached with appropriate headers\n  - Conditional requests using ETags\n  - Cache invalidation on content updates\n\n- **Server-Side Cache**:\n  - Efficient media file storage\n  - Metadata caching for quick access\n  - Automatic cache cleanup\n\n## Prerequisites\n\n- Node.js (v18.0.0 or higher)\n- npm (v8.0.0 or higher)\n- A Google Cloud Platform account\n- For kiosk mode: Debian-based Linux system (e.g., Raspberry Pi OS)\n- WebSocket-capable browser\n\n## Project Structure\n\n```\nterminal-slide-show/\n├── client/                 # Frontend React application\n│   ├── public/            # Static assets\n│   ├── src/\n│   │   ├── components/    # React components\n│   │   │   ├── slideshow/      # Slideshow components\n│   │   │   └── dynamic_daily_view/  # Dynamic view components\n│   │   ├── hooks/        # Custom React hooks\n│   │   │   └── useWebSocket.js # WebSocket connection hook\n│   │   ├── utils/        # Utility functions\n│   │   └── styles/       # CSS stylesheets\n├── server/                # Backend application\n│   ├── config/               # Configuration files\n│   │   ├── config.js        # Main configuration\n│   │   └── frontend.config.js # Frontend-specific config\n│   ├── src/\n│   │   ├── services/     # Core services\n│   │   │   ├── websocket/     # WebSocket server\n│   │   │   └── cache/         # Caching service\n│   │   └── utils/        # Utility functions\n│   └── data/             # Local data (quotes, facts)\n├── scripts/             # Shell scripts\n└── downloads/           # Local media storage\n```\n\n## Setup Instructions\n\n### 1. Installation\n\n```bash\n# Clone the repository\ngit clone URL\ncd terminal-slide-show\n\n# Install dependencies\nnpm install\n\n# Create necessary directories\nmkdir -p downloads logs cache\n\n# Create configuration files\ncp server/config/config.example.js server/config/config.js\ncp server/config/.env.example server/config/.env\n```\n\n### 2. Google Drive Authentication\nYou have two options for authenticating with Google Drive:\n#### Option A: Using API Key (Simpler, for personal use)\n1. Create a new project in [Google Cloud Console](https://console.cloud.google.com/)\n2. Enable the Google Drive API\n3. Create API credentials:\n   - Go to \"APIs \u0026 Services\" \u003e \"Credentials\"\n   - Click \"Create Credentials\" \u003e \"API Key\"\n   - Copy the API key\n4. Add the API key to `config.js`:\n   ```javascript\n   google: {\n     useServiceAccount: false,\n     apiKey: 'YOUR_API_KEY',\n     folderId: 'YOUR_FOLDER_ID'\n   }\n   ```\n5. Make your Google Drive folder publicly accessible (with link)\n#### Option B: Using Service Account (More secure, recommended for production)\n1. Create a new project in [Google Cloud Console](https://console.cloud.google.com/)\n2. Enable the Google Drive API\n3. Create a Service Account:\n   - Navigate to \"IAM \u0026 Admin\" \u003e \"Service Accounts\"\n   - Click \"Create Service Account\"\n   - Grant the role \"Drive File Viewer\" or necessary permissions\n   - Create and download JSON key\n4. Place the downloaded JSON key in `server/config/service-account.json`\n5. Share your Google Drive folder with the service account email\n6. Configure `config.js`:\n   ```javascript\n   google: {\n     useServiceAccount: true,\n     serviceAccountPath: './config/service-account.json',\n     folderId: 'YOUR_FOLDER_ID'\n   }\n   ```\n\n### 3. Cache Configuration\n\nConfigure caching behavior in `config.js`:\n\n```javascript\ncache: {\n  // Browser cache settings\n  browser: {\n    maxAge: 86400,        // Cache lifetime in seconds\n    revalidate: true,     // Enable revalidation\n    etags: true           // Enable ETag support\n  },\n  // Server cache settings\n  server: {\n    mediaCache: {\n      maxSize: '1GB',     // Maximum cache size\n      cleanupInterval: '1h' // Cache cleanup interval\n    },\n    metadataCache: {\n      ttl: 300,           // Time-to-live in seconds\n      checkPeriod: 600    // Cleanup check interval\n    }\n  }\n}\n```\n\n### 4. WebSocket Configuration\n\nConfigure WebSocket behavior in `config.js`:\n\n```javascript\nwebsocket: {\n  // WebSocket server settings\n  server: {\n    port: 3001,\n    heartbeat: 30000,     // Heartbeat interval\n    reconnectTimeout: 5000 // Client reconnection timeout\n  },\n  // Client settings\n  client: {\n    reconnectAttempts: 5,\n    reconnectInterval: 1000,\n    messageTimeout: 5000\n  }\n}\n```\n\n## File Naming Convention\nFiles in Google Drive should follow this naming pattern to enable scheduling:\n- Single date: `filename_DD-MM-YYYY.ext`\n- Date range: `filename_DD-MM-YYYY@DD-MM-YYYY.ext`\n- Short format: `filename_DD-MM@DD-MM.ext`\n- Custom duration: `filename_Xs.ext` (where X is duration in seconds)\n\nIt is possible to also use just `YY` and use any of these separators: `-._`\nYou can combine both date and duration patterns:\nExamples:\n```\nbanner_01-01-2024@31-01-2024.jpg  # Show in January 2024\nnotice_15-03.jpg                  # Show on March 15th (any year)\nevent_01-06@15-06.jpg            # Show June 1-15 (any year)\n\nimage_5s_25-12-2024.jpg    ✅ (works)\nimage_10s_.jpg             ✅ (works)\nimage5s_25-12-2024.jpg     ❌ (won't work - missing leading _)\nimage_5s25-12-2024.jpg     ❌ (won't work - missing trailing _)\n```\n\n## Scheduling\n\nConfigure display times in `config.js`:\n\n```javascript\nschedule: {\n  enabled: true,\n  onTime: '06:30',      // Display start time\n  offTime: '20:00',     // Display end time\n  days: [1, 2, 3, 4, 5], // Monday to Friday\n  vacationPeriods: [    // Optional vacation periods\n    { start: '24.06.2024', end: '24.07.2024' }\n  ]\n\n}\n```\n\n## WebSocket Events\n\nThe application supports the following WebSocket events:\n\n```javascript\n// Client-side subscription\nws.subscribe('media-update', (data) =\u003e {\n  // Handle media updates\n});\n\nws.subscribe('schedule-update', (data) =\u003e {\n  // Handle schedule changes\n});\n\nws.subscribe('system-health', (data) =\u003e {\n  // Handle system health updates\n});\n```\n\n## Cache Headers\n\nThe application sets appropriate cache headers for different types of content:\n\n```javascript\n// Example cache headers for media files\n{\n  'Cache-Control': 'public, max-age=86400',\n  'ETag': true,\n  'Last-Modified': timestamp\n}\n\n// Example cache headers for dynamic content\n{\n  'Cache-Control': 'no-cache, must-revalidate',\n  'ETag': true\n}\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\nThis project is licensed under the GPL-3.0 License - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmuddyblack%2Fterminal-slide-show","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmuddyblack%2Fterminal-slide-show","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmuddyblack%2Fterminal-slide-show/lists"}