A => .envrc +1 -0
A => .gitignore +9 -0
@@ 1,9 @@
+# flake
+/.direnv/
+/result
+
+# zola build
+/public/
+
+# tailwindcss build
+/static/css/style.css
A => config.toml +36 -0
@@ 1,36 @@
+base_url = "https://dashboard.lab.liljamo.com"
+title = "Lab Dashboard"
+
+ignored_static = ["css/input.css"]
+
+generate_sitemap = false
+generate_robots_txt = false
+
+[[extra.sections]]
+title = "Proxmox"
+links = [
+ { href = "https://rustylily.loxe.lab.liljamo.com:8006", name = "rustylily" },
+ { href = "https://este.loxe.lab.liljamo.com:8006", name = "este" },
+ { href = "https://nessa.loxe.lab.liljamo.com:8006", name = "nessa" },
+ { subtitle = "Backup" },
+ { href = "https://pbs.loxe.lab.liljamo.com:8006", name = "PBS" },
+]
+
+[[extra.sections]]
+title = "Monitoring"
+links = [
+ { href = "https://metrics.lab.liljamo.com", name = "Grafana" },
+ { href = "https://prometheus.metrics.lab.liljamo.com", name = "Prometheus" },
+ { href = "https://alertmanager.metrics.lab.liljamo.com", name = "Alertmanager" },
+]
+
+[[extra.sections]]
+title = "Apps"
+links = [
+ { href = "https://vikunja.cloud.lab.liljamo.com", name = "Vikunja" },
+ { href = "https://outline.cloud.lab.liljamo.com", name = "Outline" },
+ { href = "https://miniflux.cloud.lab.liljamo.com", name = "Miniflux" },
+ { href = "https://umami.oci.lab.liljamo.com", name = "Umami", pub_href = "https://a.liljamo.dev" },
+ { href = "https://media.lab.liljamo.com", name = "Jellyfin" },
+ { href = "https://cloud.lab.liljamo.com", name = "Nextcloud", pub_href = "https://cloud.liljamo.com" },
+]
A => content/_index.md +3 -0
@@ 1,3 @@
++++
+template = "index.html"
++++
A => flake.lock +27 -0
@@ 1,27 @@
+{
+ "nodes": {
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1764384123,
+ "narHash": "sha256-UoliURDJFaOolycBZYrjzd9Cc66zULEyHqGFH3QHEq0=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "59b6c96beacc898566c9be1052ae806f3835f87d",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nixpkgs": "nixpkgs"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
A => flake.nix +35 -0
@@ 1,35 @@
+{
+ inputs.nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
+
+ outputs = { nixpkgs, ... }:
+ let
+ pkgs = nixpkgs.legacyPackages.x86_64-linux.pkgs;
+
+ buildInputs = with pkgs; [
+ just
+
+ zola
+ tailwindcss_4
+ ];
+ in
+ {
+ packages.x86_64-linux.default = pkgs.stdenv.mkDerivation {
+ name = "dashboard-zola";
+ src = ./.;
+ inherit buildInputs;
+ buildPhase = ''
+ just build
+ '';
+ installPhase = ''
+ mkdir -p $out
+ cp -R public $out
+ '';
+ };
+
+ devShells.x86_64-linux.default = pkgs.mkShell {
+ buildInputs = with pkgs; [
+ tailwindcss-language-server
+ ] ++ buildInputs;
+ };
+ };
+}
A => justfile +15 -0
@@ 1,15 @@
+tailwindInput := "./static/css/input.css"
+tailwindOutput := "./static/css/style.css"
+
+_default:
+ just --list
+
+build:
+ tailwindcss -i {{tailwindInput}} -o {{tailwindOutput}} --minify
+ zola build
+
+css:
+ tailwindcss -i {{tailwindInput}} -o {{tailwindOutput}} --watch
+
+serve:
+ zola serve
A => static/css/input.css +1 -0
@@ 1,1 @@
+@import 'tailwindcss';
A => templates/index.html +25 -0
@@ 1,25 @@
+{% extends "layouts/base.html" %}
+
+{% block content %}
+<div class="flex flex-col p-2">
+ {% for section in config.extra.sections %}
+ <p class="font-bold text-lg">{{ section.title }}</p>
+ <div class="flex flex-col p-2 border">
+ {% for link in section.links %}
+ {% if link.subtitle %}
+ <div class="pt-2 font-medium text-md">
+ <p>{{ link.subtitle }}</p>
+ </div>
+ {% else %}
+ <div>
+ <a href={{ link.href }} target="_blank" class="hover:underline text-sky-500">{{ link.name }}</a>
+ {% if link.pub_href %}
+ <span>(<a href={{ link.pub_href }} target="_blank" class="hover:underline text-sky-700">pub</a>)</span>
+ {% endif %}
+ </div>
+ {% endif %}
+ {% endfor %}
+ </div>
+ {% endfor %}
+</div>
+{% endblock content %}
A => templates/layouts/base.html +18 -0
@@ 1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+ <title>{{ config.title }}</title>
+
+ <link rel="stylesheet" href="/css/style.css"/>
+ </head>
+ <body>
+ <main class="flex flex-col items-center h-full min-h-screen">
+ <div class="max-w-5xl min-w-xs p-2">
+ {% block content %} {% endblock %}
+ </div>
+ </main>
+ </body>
+</html>