In a previous blog post I talked about how I manage multiple development projects using a tool I created called Spinup. Spinup is a command line tool that allows me to quickly launch, create and manage groups of commands required to run development environments for different projects. It’s a working fine, but I still have to open a terminal and type a command to launch a project. I wanted to make it even easier by creating a UI for it.
Why a UI?
I use the terminal a lot and prefer to do so over using a UI if possible, but opening multiple terminals to run different projects can get a bit tedious. So I decided to create a UI for Spinup to make it easier to launch projects. It would be helpful to have a list of all the project configurations I have and be able to launch them with a click of a button.
Wails
After a bit of searching online I found a framework called Wails that allows you to create desktop applications using Go. The frontend can be written in JavaScript using a framework like Vue.js, React, Svelte, etc. Since I already know React, I decided to use that for the frontend. Wails also allows you to call Go functions from JavaScript and vice versa, which is perfect for what I needed.
Creating the UI
I started with creating a page that would list all the projects I had configured in Spinup. This was nice since it ga a good overview of all the projects I had configured. Next I needed a way to launch a project, so I added a “play” button to each project that would start the project when clicked. If a project was running the button would change to a “stop” button to indicate that it was running and could be stopped.
Next was an overview of all command templates I had configured. The overview was much quicker to implement since I already had the project overview that I could copy from. Since commands are quite simple in their configuration I decided I would be easiest to add a form to add or update commands first. I added a button at the top of the page to add a new command and a button to each command to edit it. The form would be pre-filled with the command configuration if the edit button was clicked. I also added a delete button to each command to remove it.
After implementing the command form I did the same for projects. They required some additional fields like a select input to choose what commands should be configured for that project.
The final result looks something like this:

Separation of Concerns
At first I made the Wails app in a separate repo that required the core Spinup module in its go.mod file. This was not really a good solution since if I wanted to make changes to the core of Spinup for things I wanted to add in the Wails app I would have to update and tag two separate repos. I still wanted the CLI to keep working as it was, so after merging the two repos I added an if statement to the main.go file that would invoke the CLI handling if one or more arguments were passed to the spinup
command:
func main() {
if len(os.Args) > 1 {
c := cli.New()
c.Handle()
return
}
app := app.NewApp()
...
}
This way the CLI could still be used along side the Wails app.
Packaging
Since I run Ubuntu on my personal laptop and work laptop I thought it would be a good idea to have a .deb
package for easy installation. Spinup relies on a couple of config files that need to be in a specific location, so I added a post install script that would link the config files to the correct location. After a bit of fenagling with the deb
package I got it to work and could install Spinup with a simple dpkg -i
command.
I also tried to create a .rpm
installer for RHEL based systems. I think it should work but I haven’t tested it yet.
Since basically all my colleagues are running macOS on their work laptops and I wanted them to try Spinup out, I tried to make an installer for macOS as well. My first though was basically to just copy the file structure I used for the Linux installers and include a post install script in a zip file. Apparently macOS doesn’t allow you to just store some files the way Linux does. Code signing is required to store files in certain locations. Instead of using /usr/share/spinup
I can use /usr/local/share/spinup
as the location for the spinup binary and config files for dnsmasq, etc. I haven’t let one of my colleagues try this new version yet, but I found out about this when trying to install Spinup the same way I would on Linux.
Conclusion
Wails is a cool way of making desktop apps with Go and JavaScript. It was quite easy to work with once everything was configured. There are still some things I would like to improve within the UI, but for now it’s working fine.