A web application built with Go, Templ, Tailwind CSS v4, DaisyUI, and HTMX to browse and control media streams via Discord webhooks. It fetches live streams from an Xtream API, displays them as clickable cards, and sends stream URLs to a Discord channel with a configurable command prefix. The application includes Authentik OIDC authentication for secure access.
- Responsive UI: Card-based layout with search and pagination, optimized for all screen sizes.
- Discord Integration: Click a card to send its stream URL to Discord with a custom prefix (e.g.,
! <url>
). - Authentication: Secure OIDC authentication using Authentik.
- Lightweight: Built with a minimal Alpine-based Docker image.
├── cmd/ # Main application entry point
├── handlers/ # HTTP handlers
├── internal/ # Private packages (cache, config, discord, xtream)
├── static/ # CSS, JS, and image assets
│ ├── css/
│ │ ├── input.css # Source CSS for Tailwind
│ │ └── styles.css # Generated CSS (ignored in Git)
│ └── js/ # HTMX and form-json scripts
├── templates/ # Templ files for server-side rendering
├── Dockerfile # Multi-stage build for production
├── Makefile # Build and watch commands
├── package.json # Node.js dependencies (Tailwind, DaisyUI)
└── .env # Environment variables
- Go (v1.23+)
- Node.js (v20+)
- Docker (optional, for containerized deployment)
- An Xtream API account (base URL, username, password)
- A Discord webhook URL
-
Clone the Repository:
git clone https://github.com/git-saj/go-media-control.git cd go-media-control
-
Install Dependencies:
- Go modules:
go mod download
- Node.js packages:
npm install
- Go modules:
-
Configure Environment:
- Copy
env.template
to.env
and fill in your credentials:Examplecp env.template .env
.env
:# Server configuration PORT=8080 # Xtream API configuration XTREAM_BASEURL=https://your-xtream-api.com XTREAM_USERNAME=your-username XTREAM_PASSWORD=your-password # Discord configuration DISCORD_WEBHOOK=https://discord.com/api/webhooks/your-webhook COMMAND_PREFIX=! # Authentik OIDC configuration AUTHENTIK_URL=https://your-authentik-instance.com AUTHENTIK_CLIENT_ID=your_client_id AUTHENTIK_CLIENT_SECRET=your_client_secret AUTHENTIK_REDIRECT_URL=http://localhost:8080/auth/callback SESSION_SECRET=your-very-secure-random-session-secret-key-here
- Copy
-
Set up Authentik (OIDC Provider):
In your Authentik admin interface:
a. Create OAuth2/OpenID Provider:
- Go to Applications → Providers → Create
- Choose OAuth2/OpenID Provider
- Set Name:
go-media-control
- Set Authorization flow:
default-authorization-flow
- Set Client type:
Confidential
- Set Redirect URIs:
http://localhost:8080/auth/callback
(adjust for your domain) - Leave other settings as default
- Save and note the Client ID and Client Secret
b. Create Application:
- Go to Applications → Applications → Create
- Set Name:
Go Media Control
- Set Slug:
go-media-control
- Set Provider: Select the provider you just created
- Set Launch URL:
http://localhost:8080/
(your app URL) - Save
c. Update your
.env
file with the Client ID and Client Secret from step 4a. -
Build and Run:
- Generate Templ files and CSS:
make generate-templ make build-css
- Run with live reloading:
make watch-templ & make watch-css & air
- Open
http://localhost:8080/
in your browser.
- Generate Templ files and CSS:
-
Build the Docker Image:
docker build -t go-media-control:latest .
-
Run the Container:
docker run -p 8080:8080 --env-file .env go-media-control:latest
- Open
http://localhost:8080/
.
- Open
The application uses Authentik for OIDC authentication. All routes except /auth/*
require authentication.
- Unauthenticated Access: Users accessing any protected route are redirected to
/auth/login
- Login: The login handler redirects to your Authentik instance for authentication
- Callback: After successful authentication, Authentik redirects back to
/auth/callback
- Session Creation: A secure session is created and the user is redirected to the home page
- Logout: Users can logout at
/auth/logout
(local) or/auth/logout?global=true
(Authentik + local)
GET /auth/login
- Initiate OIDC loginGET /auth/callback
- Handle OIDC callbackGET /auth/logout
- Logout (local session only)GET /auth/logout?global=true
- Logout from both app and AuthentikGET /auth/user
- Get current user info (JSON, for debugging)
The following environment variables are required for authentication:
AUTHENTIK_URL
- Your Authentik instance URL (without trailing slash)AUTHENTIK_CLIENT_ID
- OAuth2 Client ID from AuthentikAUTHENTIK_CLIENT_SECRET
- OAuth2 Client Secret from AuthentikAUTHENTIK_REDIRECT_URL
- Callback URL (must match Authentik configuration)SESSION_SECRET
- Secure random string for session encryption (32+ characters)
The application supports Redis for distributed caching, which is essential when running multiple replicas in production to share cached data.
To enable Redis caching, set the following environment variables in your .env
file:
USE_REDIS=true
REDIS_ADDR=redis:6379
REDIS_DB=0
USE_REDIS
: Set totrue
to enable Redis caching,false
for in-memory caching (default)REDIS_ADDR
: Redis server address (e.g.,localhost:6379
orredis:6379
in Docker)REDIS_PASSWORD
: Redis password (leave empty if no authentication)REDIS_DB
: Redis database number (default: 0)
For local development with Redis, use the provided docker-compose.yml
:
# Copy and configure your environment file
cp env.template .env
# Edit .env with your Xtream and Discord credentials
# Start the application with Redis
docker-compose up
This will start both the Go application and Redis in Docker containers. The app will connect to Redis at redis:6379
as configured.
The application caches the following data:
- Live Streams: 7 days
- Categories: 7 days
- EPG Data: 24 hours
- TMDB Movie Searches: 7 days
- TMDB Movie Details: 7 days
- Torrent Searches: 7 days
In production with multiple replicas:
- Deploy Redis separately (e.g., Redis Cloud, AWS ElastiCache, or self-hosted)
- Set
USE_REDIS=true
and configureREDIS_ADDR
to point to your Redis instance - All app replicas will share the same cache, improving performance and consistency
If Redis is unavailable, the application falls back to in-memory caching per instance.
- Authentication: Navigate to the application URL and you'll be redirected to Authentik for login
- Browse Channels: View up to 15 media stream cards (5 columns on large screens, fewer on smaller devices).
- Search: Type in the search bar to filter channels dynamically.
- Send to Discord: Click a card to send its stream URL to your Discord channel (e.g.,
! https://stream-url
). - Navigate: Use Previous/Next buttons for pagination.
- Logout: Access
/auth/logout
to logout locally, or/auth/logout?global=true
to logout from Authentik as well.