exelban's blog

One Day Project: Homelab Dashboard

January 28, 2025

Hi, With this article, I’m starting a series about my one-day projects. Some of these projects were done years ago, while others are more recent. I’ve decided to write about why and how I started these projects. Maybe I’ll inspire someone to start their own project with this series, or perhaps someone will find these projects interesting or helpful.

Problem

The first project I want to describe is a homelab dashboard. If you’re wondering what that is and why it’s useful, I’ll explain. It’s essentially a website with bookmarks, designed to keep all my homelab services accessible with a single click.

Why not just use browser bookmarks? First, it’s not fun. Second, I use different browsers and multiple devices, so I want a centralized place to manage them. Basically, it’s a webpage with bookmarks.

I also plan to evolve this page by adding time and weather information, but I haven’t found the free time to implement that yet.

Available Alternatives

Before starting a new project, I always explore existing solutions. The homelab community has a few popular options for solving the problem I described. The most popular ones are:

There are more, but these are the ones I’ve tried.
The biggest problem I have with these solutions is that they’re too complicated and try to solve too many problems. I prefer tools that solve one specific problem, not everything under the sun. That’s why I decided to create my own dashboard for the apps I host on my server, with the exact customization I need.

Technology Stack

Since I’m a Go developer, it didn’t take long to choose the backend. For the frontend, I chose VueJS because it’s my favorite framework. For scaffolding, I used Vite. Vite solves almost all problems associated with JavaScript projects: scaffolding, bundling, etc. It’s super easy to use and work with.

I also like to use Tailwind CSS in my frontend projects for quick designs that look great without requiring too much time.

Summary:

I use this stack in almost all my pet projects, occasionally making small changes or tweaks.

Idea

To start, I made a list of features I wanted in the app:

What is a preset?
A preset allows you to set an appropriate icon for a link. Initially, there were no presets. I tried detecting the link icon based on the URL and port, but this approach wasn’t reliable, so I moved to predefined presets.

With a clear list of features, I began development.

Development Process

One free weekend, after a cup of coffee and a game of LoL, I started a new project called JAD. Choosing a project name is always challenging for me, so I often default to “Just Another X,” where X is the project type. Hence, this project is called Just Another Dashboard.

I always start with the frontend, as it gives me a better idea of the API I need to develop. After a few hours playing with VueJS, I had a working version of the dashboard with mocked data. I even reused this mock data for a demo mode, ensuring the effort wasn’t wasted.

The initial version included a grid with a list of links and options to add, edit, and delete links. It was good enough for me at this stage, so I moved on to the backend.

For the backend, I kept things simple. It just needed to get, save, and delete objects from a JSON file. I didn’t bother with a database because:

  1. There wouldn’t be a large number of links.
  2. I didn’t want to spend time setting up even a lightweight DB like BoltDB.

Backend API:

Here’s how it works:
The frontend loads a list of links from the backend during initialization. When the user adds, edits, or deletes a link, it updates the list locally and sends the updated list to the backend, which saves it to the JSON file. This eliminates the need for separate endpoints for creating, editing, or deleting links.

The most time-consuming part of the backend was serving static files, but this was easily handled by embedding the dist folder into the Go application at compile time. The result was a small, standalone executable containing everything I needed.

I added a Dockerfile with three stages:

  1. Frontend build
  2. Backend build
  3. Final Alpine-based image for deployment

The final Docker image was only 10 MB.

After completing the MVP stage, I returned to the frontend to add drag-and-drop functionality for rearranging links. I also added a few presets and color customization for links. The presets are limited to the apps I use. If you don’t find a preset you need, feel free to make a PR, and I’ll add it.

Finally, I found an icon for the project, built everything, and deployed it to my homelab.

Result

JAD JAD

One-day projects aren’t always completed in a single day. More realistically, they take a weekend or at least a few days. If you could dedicate an entire day from morning to night, it might be possible, but life is usually more interesting than that.

Here’s a summary of the features in my homelab dashboard:

Here’s a docker-compose example for using the dashboard:

services:
  JAD:
    image: exelban/jad:latest
    restart: always
    ports:
      - "8080:8080"

For more details, check out the github repo.

Let me know if you need further modifications!