{"id":50297544,"url":"https://github.com/patrickfiedler/infoboard","last_synced_at":"2026-05-28T10:01:04.215Z","repository":{"id":332231181,"uuid":"1130215527","full_name":"patrickfiedler/infoboard","owner":"patrickfiedler","description":"Self-hosted digital signage: display PDFs, images, videos and YouTube on multiple screens — with playlist, admin panel and browser-based setup","archived":false,"fork":false,"pushed_at":"2026-04-13T07:29:56.000Z","size":1587,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-13T09:59:06.149Z","etag":null,"topics":["digital-signage","flask","kiosk","media-player","pdf-viewer","playlist","python","raspberry-pi","self-hosted","slideshow"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/patrickfiedler.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":"2026-01-08T07:35:26.000Z","updated_at":"2026-04-13T07:29:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/patrickfiedler/infoboard","commit_stats":null,"previous_names":["patrickfiedler/kundenstopper","patrickfiedler/infoboard"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/patrickfiedler/infoboard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfiedler%2Finfoboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfiedler%2Finfoboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfiedler%2Finfoboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfiedler%2Finfoboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patrickfiedler","download_url":"https://codeload.github.com/patrickfiedler/infoboard/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfiedler%2Finfoboard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33603475,"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-28T02:00:06.440Z","response_time":99,"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":["digital-signage","flask","kiosk","media-player","pdf-viewer","playlist","python","raspberry-pi","self-hosted","slideshow"],"created_at":"2026-05-28T10:01:03.424Z","updated_at":"2026-05-28T10:01:04.209Z","avatar_url":"https://github.com/patrickfiedler.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Infoboard\n\nSelf-hosted digital signage that runs in any modern browser. No dedicated player software needed — point a browser at a URL and it displays your content. Manage multiple screens and zones from a single web-based admin panel.\n\n## Features\n\n- **Multiple displays** — each screen gets its own URL (`/display/\u003cslug\u003e`)\n- **Multi-zone layouts** — split a display into up to 4 zones (7 presets), each with its own playlist\n- **Playlist per display/zone** — drag-and-drop ordering, per-item duration\n- **Media types**: PDF (multi-page), image, image gallery, local video, YouTube embed, website (via proxy)\n- **Server-side PDF rendering** — PDFs pre-rendered to images via poppler-utils, no client-side PDF engine needed; parallel rendering across CPU cores\n- **PDF spread view** — side-by-side page pairs (book/magazine layout), configurable per playlist item\n- **Image galleries** — batch upload, sortable, shown as slideshow\n- **Website proxy** — embeds external pages by stripping X-Frame-Options/CSP headers\n- **Admin panel** — upload, rename, delete media; manage playlists; configure per-display settings\n- **Authentication** — single admin user with bcrypt-hashed password\n- **Auto-updating display** — polls for changes every 10 seconds, no manual refresh needed\n\n## Technology Stack\n\n- **Backend**: Flask 3 (Python)\n- **WSGI Server**: Waitress (production-ready)\n- **Authentication**: Flask-Login + bcrypt\n- **Database**: SQLite\n- **PDF Rendering**: poppler-utils (`pdftoppm`)\n- **Frontend**: Vanilla JS + [SortableJS](https://sortablejs.github.io/Sortable/) for drag-and-drop\n\n## Quick Start\n\n### Automated Installation (Recommended)\n\n```bash\ngit clone https://github.com/patrickfiedler/infoboard.git\ncd infoboard\n./deploy.sh\n```\n\nThe deployment script will guide you through setup interactively.\n\n### Manual Installation\n\n1. **Clone and install dependencies**\n   ```bash\n   git clone https://github.com/patrickfiedler/infoboard.git\n   cd infoboard\n   pip install -r requirements.txt\n   ```\n\n2. **Configure**\n   ```bash\n   python3 generate_password_hash.py   # generate bcrypt hash for your password\n   cp config.json.example config.json\n   # edit config.json with your settings\n   ```\n\n3. **Run**\n   ```bash\n   python3 app.py\n   ```\n\nSee [DEPLOYMENT.md](DEPLOYMENT.md) for systemd service setup and update procedures.\n\n## Requirements\n\n- Python 3.8+\n- `poppler-utils` for PDF rendering: `apt install poppler-utils`\n\n## Configuration\n\n`config.json` (created from `config.json.example`):\n\n| Key | Default | Description |\n|-----|---------|-------------|\n| `admin_username` | `admin` | Admin login username |\n| `admin_password_hash` | — | Bcrypt hash (generate with `generate_password_hash.py`) |\n| `secret_key` | — | Flask session secret — **change this!** |\n| `port` | `8080` | Server port |\n| `host` | `0.0.0.0` | Bind address |\n| `upload_folder` | `uploads` | Media storage directory |\n| `render_workers` | `null` | Max parallel PDF render workers (null = all CPU cores) |\n\n## Usage\n\nAfter starting the server:\n\n- **Display**: `http://localhost:8080/display/\u003cslug\u003e` — open fullscreen in a browser\n- **Admin**: `http://localhost:8080/admin` — manage content and displays\n\nThe display polls for updates every 10 seconds. No refresh needed when you change content in the admin panel.\n\n### Kiosk mode (Firefox)\n\n```bash\n./firefox-kiosk.sh http://localhost:8080/display/\u003cslug\u003e\n```\n\n## File Structure\n\n```\ninfoboard/\n├── app.py                      # All routes and business logic\n├── models.py                   # Database operations\n├── migrate.py                  # Migration runner\n├── config.py                   # Configuration loader\n├── migrations/                 # Numbered migration scripts\n├── templates/\n│   ├── display.html            # Fullscreen display view\n│   ├── admin.html              # Admin panel\n│   └── login.html              # Login page\n├── static/js/\n│   └── sortable.min.js         # Drag-and-drop (SortableJS)\n├── deploy.sh                   # Automated deployment\n├── update.sh                   # Automated update\n├── firefox-kiosk.sh            # Launch Firefox in kiosk mode\n├── cookie_hide.conf            # CSS selectors to hide on proxied pages\n├── config.json.example         # Config template\n├── generate_password_hash.py   # Generate bcrypt password hash\n└── infoboard.service       # Systemd service template\n```\n\n## Security Notes\n\n- Admin password stored as bcrypt hash (cost factor 12)\n- File uploads restricted to allowed extensions\n- Uploaded files stored with UUID filenames (prevents path traversal)\n- Session management via Flask-Login\n\n## Updating\n\n```bash\ncd /path/to/infoboard\n./update.sh\n```\n\nThe update script creates a backup tag, pulls the latest code, updates dependencies and restarts the service. See [DEPLOYMENT.md](DEPLOYMENT.md) for rollback instructions.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickfiedler%2Finfoboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatrickfiedler%2Finfoboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickfiedler%2Finfoboard/lists"}