A simplified and scalable way to connect NightBot and custom widgets.
As a drummer who occasionally streams on Twitch, I wanted a way to allow users in chat to request songs for me to play. This led me to discover NightBot, a great integration platform that integrates with your Twitch channel to allow users to request songs in chat and add them to a queue.
The challenge then was to find a way to display this queue, along with other NightBot data, in a way that was both simplistic and modular/scalable. I decided to write an application that integrates with NightBot's API and shows things like a streamer's queue and current song in a widget, which could then be rendered on a streaming tool such as OBS.
- Build an application that balances ease of use with modularity and customization.
- Provide as many integrations as possible with NightBot, enabling the creation of widgets to present the data of these integrations via a web view(s).
- Make the application portable, with the ability to use it in a Docker container, on a local machine, on a hosted web server, or a Raspberry Pi. Any device that can run web technologies can serve up the application.
An example of how you may use this application would be:
- Clone and build the project
- Add a custom widget to pull your NightBot queue data and render it in a React component.
- Start the app and connect it to your NightBot account.
- Add a Browser source to OBS and point it to the endpoint that exposes your custom widget.
- Now you have a rendered view of your NightBot data in your stream!
The following tools/dependencies are required in order to use this app:
This app assumes that you have correctly configured both of these tools to run from the terminal on your machine.
$ git clone https://github.com/danielfullerton/nightbot-go.git
This will install all of the JavaScript/TypeScript dependencies for the UI, as well as the Go packages for the server.
$ npm install && go get all
After installing all dependencies, run the following command:
$ npm start
This command, which is defined in package.json, will build the UI application and start the server. This command
is only intended to be used on your local machine. It will assume you are running the application at the domain
name "localhost", and will start the application on port 5775.
You can now navigate to the application on in your browser to begin setup, which is explained
in the Configuring Credentials section.
If you want to run the app on a different port or host the app on an external server, you can change the BASE_URL and PORT properties via environment variables. For example:
# Build and run the project
$ npm run build:all
$ BASE_URL=http://myexampleserver.com PORT=8081 ./main
# OR alternatively, run without building Go binary
$ BASE_URL=http://myexampleserver.com PORT=8081 go run cmd/main.go
If you are creating new widgets, you may want to run the React app with hot reload abilities. This uses webpack-dev-server, and will setup a dedicated server solely for hosting the UI and NOT the Go API endpoints. However, the included webpack.config.js configuration will proxy all calls to /api to http://localhost:5775. This means that you can run the Go server and the webpack development server at the same time like so:
# In one shell, run:
$ webpack-dev-server
# In another shell, run:
$ npm start
This will start the Go server on http://localhost:5775 and the UI application on http://localhost:4200. You can now edit your React widgets and watch them change in the browser in real time, and API calls will be proxied to the server in case you want to fetch real data.
First, start the application. This section will assume you ran the following command:
$ npm start
For an app to integrate with NightBot, it must use a pair of keys known as a "client id" and "client secret". You can obtain
these by going to the NightBot applications page and adding a new app.
Then, click the pencil icon next to that app name and click New Secret. Write down the Client ID and Client Secret values
somewhere secure. Finally, you will need to add this app's Redirect URI in the Redirect URIs box. Enter your base URL and port
for NightBot Go, followed by the path /api/config/token. An sample configuration looks like this:
NightBotExample
Navigate to the home page of the app. Follow the instructions on this page to set up the
app to integrate with your NightBot account. Once you have entered your credentials, click the blue Submit button.
NOTE: Everytime you restart the application, you will also need to perform this step. It is recommended that you run
the app as a background process or on a separate server so that you can start it once and leave it alone.
This app also supports setting your NightBot client id and client secret credentials via environment variables, like so:
$ CLIENT_ID=******* CLIENT_SECRET=******* npm start
This is convenient if you are starting the app from another build or container process, such as Docker. If you
use this method of setting your credentials, you will simply need to navigate to the app's home page and click the
green Use Environment Variables button.
Alternatively, you can simply navigate to the authorize URL and it will auto-redirect you to
the NightBot authorization page.
This application is written so that you can write your own widgets using React. These can either be static widgets,
such as an image or some simple markup, or they can be data-driven, such as a queue widget that pulls NightBot queue
data and populates a widget with each song title.
In theory, you could this application without ever integrating with NightBot just for the purpose of hosting a server
with many static widgets, or widgets that pull data from external APIs. However, that is not the intended scope of this
project.
There are two potential ways to use widgets.
This is the recommended usage. Using this pattern, there is a single React component; let's call it overlay.ts. Because this
app fetches all data and exposes it globally within the UI, you can use a single React component to consume and render all of it.
This widget will be added to a route within the React app, and will serve as the entire overlay. Your streaming app, for example
OBS, can point to this URL and render the overlay over the entire stream window.
For example, we may have a widget called Overlay.tsx, which we place on a route called /overlay. You could then
create a Browser source in OBS that points to http://localhost:5775/overlay, and this overlay widget would be rendered in
your stream window.
Using this pattern, all widgets would belong to the direction /app/components/, and each is a .tsx file representing a React component.
The standard practice is for each of these components to map to a different route, defined in /app/app.component.tsx. Then,
your streaming tool (for example, OBS) will point to each of these widget URLs separately to
render them.
For example, we may have a widget called HelloWorld.tsx, which we place on a route called /hello-world. You could then
create a Browser source in OBS that points to http://localhost:5775/hello-world, and this widget would be rendered in
your stream window.
In order to create a custom widget, you will need some basic experience with the JavaScript framework React. First, create a new React component in the /app/components folder, and add this component to the routes list in /app/app.component.tsx (See the existing placeholder widgets NowPlaying and Queue for examples of how to do this). From there, you can define any custom functionality within your widget class using JavaScript or TypeScript. This includes making http calls using the package Axios, which you can use to call external APIs or any of the endpoints provided by this application.
This section provides the API endpoints that the application exposes, which you can then use from your widgets to interact with NightBot. This list should keep growing as time goes on and more development work is done.
Used to fetch your current queue data from NightBot.
GET /api/queue
{
"_total": 1,
"_currentSong": {
"_id": "string",
"createdAt": "string",
"updatedAt": "string",
"track": {
"providerId": "string",
"provider": "string",
"duration": 100,
"title": "string",
"artist": "string",
"url": "string"
},
"user": {
"name": "string",
"displayName": "string",
"providerId": "string",
"provider": "string"
},
"_position": 0
},
"_requestsEnabled": true,
"_providers": ["strings"],
"_searchProvider": "string",
"status": 0,
"queue": [{
"_id": "string",
"createdAt": "string",
"updatedAt": "string",
"track": {
"providerId": "string",
"provider": "string",
"duration": 100,
"title": "string",
"artist": "string",
"url": "string"
},
"user": {
"name": "string",
"displayName": "string",
"providerId": "string",
"provider": "string"
},
"_position": 0
}]
}
More capabilities are in development and coming soon!
This project is developed completely without funding and is free to use. Please consider donating to support further development efforts and the ongoing maintenance of this project.
Venmo: @Daniel-Fullerton-368
This project is licensed under the Apache License 2.0 license. Please read here for more information.