Open-source, self-hosted digital signage for the places people gather.
Restaurants, churches, schools, event venues, and community spaces.
DisplayGrid gives you full control over your screens without a cloud subscription, recurring fees, or vendor lock-in.
Native installers are published automatically on each release via GitHub Actions.
| Platform | Download |
|---|---|
| Windows | DisplayGrid-Server-Setup.exe |
| macOS | DisplayGrid-Server.dmg |
| Linux x64 | DisplayGrid-Server.AppImage |
| Linux ARM64 (Raspberry Pi 4B/5) | DisplayGrid-Server-arm64.AppImage |
| Platform | Download |
|---|---|
| Windows | DisplayGrid-Kiosk-Setup.exe |
| macOS | DisplayGrid-Kiosk.dmg |
| Linux x64 | DisplayGrid-Kiosk.AppImage |
| Linux ARM64 (Raspberry Pi 4B/5) | DisplayGrid-Kiosk-arm64.AppImage |
No release published yet? Run from source — it only takes a few minutes.
| Screens dashboard | Playlist manager |
![]() |
![]() |
| Asset library | Multi-zone layout editor |
![]() |
![]() |
| Display client (kiosk view) | |
![]() |
|
- Multi-screen management: configure resolution, refresh rate, rotation, colour profile, and panel grid per screen
- Zone-based organisation: group screens into named zones (lobby, corridor, reception)
- Playlist builder: drag-and-drop slides with per-slide durations, transitions, and day/time scheduling
- Asset library: upload images, videos, and PDFs with automatic WebP optimisation via Sharp
- Real-time delivery: WebSocket server pushes playlist updates to displays instantly
- Screen health monitoring: live online/offline status, last-seen timestamps, and client IP
- Emergency override: broadcast a full-screen alert to every display simultaneously
- Kiosk lock: PIN-protected overlay with configurable key combo; no browser chrome visible
- Offline resilience: display clients cache their last playlist and keep playing through network outages
- Role-based access: Super Admin, Admin, Operator, Viewer
- LED wall support: define panel grids (e.g. 3×2) for tiled display configurations
- Multi-zone layouts: split a screen into independently controlled regions, each with its own playlist
- Time-based scheduling: restrict slides to specific days and time windows; server re-evaluates every minute
- Standalone apps: native installers for Windows, macOS, and Linux — a tray-based server app manages the dashboard and WebSocket server; a dedicated kiosk app runs displays fullscreen with no browser configuration required; ARM64 AppImage for Raspberry Pi 4B/5
- NDI source support: stream live video from NDI devices on the network directly to any display
| Layer | Technology |
|---|---|
| Dashboard | Next.js 14 (App Router), Tailwind CSS |
| Database | SQLite · Drizzle ORM · better-sqlite3 |
| Auth | NextAuth v5 (JWT, edge-safe) |
| Real-time | Node.js ws WebSocket server |
| Display client | Vite + React |
| Monorepo | Turborepo + pnpm workspaces |
| Image processing | Sharp (WebP, JPEG, PNG, AVIF) |
- Node.js 18 or 20 LTS
- pnpm 9+
- Chromium or Google Chrome on display client machines
- A machine to act as the server (Raspberry Pi 4/5, mini PC, or any always-on device)
git clone https://github.com/JoeMighty/DisplayGrid.git
cd DisplayGrid
pnpm installConfigure the dashboard:
cp apps/dashboard/.env.example apps/dashboard/.env.localEdit apps/dashboard/.env.local:
NEXTAUTH_SECRET=<node -e "console.log(require('crypto').randomBytes(32).toString('hex'))">
NEXTAUTH_URL=http://localhost:3000
DB_PATH=/absolute/path/to/DisplayGrid/data/displaygrid.dbCreate the database:
mkdir -p data
pnpm db:migrateStart:
# Terminal 1: dashboard (port 3000) + display client (port 5173)
pnpm dev
# Terminal 2: WebSocket server (port 3001)
node apps/dashboard/ws-server.jsOpen http://localhost:3000 and follow the first-run setup wizard.
For a cleaner dev URL (http://displaygrid.test instead of http://localhost:3000):
# Windows: run PowerShell as Administrator
.\scripts\add-hosts.ps1# macOS / Linux
sudo ./scripts/add-hosts.shThen optionally run Caddy for clean URLs without a port number:
caddy run --config CaddyfileSee docs/SETUP.md for the complete setup guide.
DisplayGrid/
├── apps/
│ ├── dashboard/ # Next.js dashboard (port 3000)
│ │ ├── src/app/ # App Router pages and API routes
│ │ └── ws-server.js # WebSocket server (port 3001)
│ └── display-client/ # Vite/React kiosk client (port 5173)
├── packages/
│ ├── db/ # Drizzle schema + SQLite client
│ └── shared/ # Constants shared across apps
├── data/ # SQLite database + uploaded assets (gitignored)
├── docs/ # GitHub Pages site + setup guides
├── scripts/ # Hosts file setup (add-hosts.ps1 / .sh)
└── Caddyfile # Optional reverse proxy for clean URLs
| Minimum | Recommended | |
|---|---|---|
| Device | Raspberry Pi 4 (2 GB) | Raspberry Pi 5 (4 GB+) or mini PC |
| OS | Any Linux, macOS, Windows | Same |
| Storage | 8 GB+ SD / SSD | 32 GB+ SSD |
Any device running Chromium in kiosk mode:
| Device | Suitable for |
|---|---|
| Raspberry Pi 5 | 4K content, smooth video |
| Raspberry Pi 4 | 1080p images and web slides |
| Mini PC / NUC | Any resolution |
| Old laptop or Mac mini | Any resolution |
chromium-browser --kiosk --noerrdialogs --disable-infobars \
http://<server>:5173Add to /etc/xdg/lxsession/LXDE-pi/autostart for boot autostart.
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--kiosk --noerrdialogs --disable-infobars \
http://<server>:5173Add as a Login Item in System Settings → General → Login Items.
Create a shortcut with target:
"C:\Program Files\Google\Chrome\Application\chrome.exe" --kiosk --noerrdialogs --disable-infobars http://<server>:5173
Copy to shell:startup to run on login.
Unlock kiosk: Hold Ctrl+Alt+K for 3 seconds to open the admin panel.
For kiosks on separate machines, point the display client at the server's IP:
# apps/display-client/.env.local
VITE_API_BASE=http://192.168.1.10:3000
VITE_WS_BASE=ws://192.168.1.10:3001
# Pre-configure token to skip the token entry screen
VITE_SCREEN_TOKEN=your-screen-token-hereSee docs/SETUP.md for cross-VLAN and firewall configuration.
| Role | Can do |
|---|---|
| Super Admin | Everything, including deleting users and assigning any role |
| Admin | Manage all content and users (cannot delete users) |
| Operator | Manage screens, playlists, assets (no user management) |
| Viewer | Read-only access to all content pages |
Issues and pull requests are welcome. Please open an issue before starting significant work so we can discuss the approach.
DisplayGrid is designed for community gathering places: restaurants, churches, schools, and event venues. It is not intended for surveillance, military use, law enforcement monitoring, or facial recognition systems.
MIT. See LICENSE
By JoeMighty




