# Glance Dashboard for Kisfenyo # Namespace: glance-system # Domain: kisfenyo.dooplex.hu # Version: v0.8.4 # # Features: # - Custom background image # - Custom logo # - Weather widget (Budapest) # - YouTube subscriptions # - RSS feeds # - To-do list # - iFrames for Cal.com, Google Calendar, Outline # - Bookmarks/Links to all apps # - Calendar widget # # Authentik Integration: # 1. Create Application: "Glance Home" # 2. Create Provider: Proxy Provider with external host https://kisfenyo.dooplex.hu # 3. Create Outpost: glance-outpost # 4. Update auth-url annotation with actual outpost service name --- apiVersion: v1 kind: ConfigMap metadata: name: glance-config-kisfenyo namespace: glance-system labels: app.kubernetes.io/name: glance-kisfenyo app.kubernetes.io/instance: glance-kisfenyo data: glance.yml: | # Glance Configuration # Documentation: https://github.com/glanceapp/glance/blob/main/docs/configuration.md server: host: 0.0.0.0 port: 8080 assets-path: /app/assets document: head: | branding: logo-url: https://web.dooplex.hu/static/DooPlex_logo_3.png favicon-url: https://web.dooplex.hu/static/DooPlex_favicon_3.png app-name: "Kisfenyo's Home" app-icon-url: https://web.dooplex.hu/static/DooPlex_favicon_3.png app-background-color: "#132b66" hide-footer: true theme: disable-picker: true background-color: 210 35 12 # Was: 280 30 15 (purple → blue) primary-color: 200 70 60 # Was: 280 60 70 (purple → cyan-blue) positive-color: 150 55 50 # Was: 120 50 50 (green → teal-green, matches better) negative-color: 0 70 60 # Unchanged (red) contrast-multiplier: 1.2 # Unchanged text-saturation-multiplier: 0.8 # Unchanged custom-css-file: /assets/custom.css pages: # ==================== HOME PAGE ==================== - name: Home slug: home width: wide columns: # ---------- LEFT COLUMN ---------- - size: small widgets: # Glance Custom API Widget - System Stats from Prometheus # Add this widget to your glance.yml configuration under a column's widgets section # # Prometheus URL: http://prometheus.mon-system.svc.cluster.local:9090 # # This widget displays: # - Hostname & Uptime # - CPU usage % and Temperature # - Memory usage % # - Disk usage for all mount points with progress bars # - Fan speeds # # Note: Make sure your Glance version is v0.8.0+ for all template functions - type: custom-api title: DooPlex Server cache: 30s url: ${PROMETHEUS_URL}/api/v1/query parameters: query: node_uname_info subrequests: uptime_days: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: floor((time() - node_boot_time_seconds) / 86400) uptime_hours: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: floor((time() - node_boot_time_seconds) % 86400 / 3600) cpu: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) memory: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 cpu_temp: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: node_hwmon_temp_celsius{instance="dooplex",chip="platform_coretemp_0",sensor="temp1"} fans: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: fan_speed_rpm{instance="dooplex"} disk_root: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) disk_root_used: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) / 1073741824 disk_root_total: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: node_filesystem_size_bytes{mountpoint="/"} / 1073741824 disk_ssd2: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/ssd_2"} / node_filesystem_size_bytes{mountpoint="/mnt/ssd_2"}) disk_ssd2_used: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: (node_filesystem_size_bytes{mountpoint="/mnt/ssd_2"} - node_filesystem_avail_bytes{mountpoint="/mnt/ssd_2"}) / 1073741824 disk_ssd2_total: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: node_filesystem_size_bytes{mountpoint="/mnt/ssd_2"} / 1073741824 disk_hdd1: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/1_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/1_hdd"}) disk_hdd1_used: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: (node_filesystem_size_bytes{mountpoint="/mnt/1_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/1_hdd"}) / 1099511627776 disk_hdd1_total: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: node_filesystem_size_bytes{mountpoint="/mnt/1_hdd"} / 1099511627776 disk_hdd2: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/2_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/2_hdd"}) disk_hdd2_used: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: (node_filesystem_size_bytes{mountpoint="/mnt/2_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/2_hdd"}) / 1099511627776 disk_hdd2_total: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: node_filesystem_size_bytes{mountpoint="/mnt/2_hdd"} / 1099511627776 disk_hdd3: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/3_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/3_hdd"}) disk_hdd3_used: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: (node_filesystem_size_bytes{mountpoint="/mnt/3_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/3_hdd"}) / 1099511627776 disk_hdd3_total: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: node_filesystem_size_bytes{mountpoint="/mnt/3_hdd"} / 1099511627776 disk_hdd4: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/4_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/4_hdd"}) disk_hdd4_used: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: (node_filesystem_size_bytes{mountpoint="/mnt/4_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/4_hdd"}) / 1099511627776 disk_hdd4_total: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: node_filesystem_size_bytes{mountpoint="/mnt/4_hdd"} / 1099511627776 disk_hdd5: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: 100 * (1 - node_filesystem_avail_bytes{mountpoint="/mnt/5_hdd"} / node_filesystem_size_bytes{mountpoint="/mnt/5_hdd"}) disk_hdd5_used: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: (node_filesystem_size_bytes{mountpoint="/mnt/5_hdd"} - node_filesystem_avail_bytes{mountpoint="/mnt/5_hdd"}) / 1099511627776 disk_hdd5_total: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: node_filesystem_size_bytes{mountpoint="/mnt/5_hdd"} / 1099511627776 template: | {{ $hostname := .JSON.String "data.result.0.metric.nodename" }} {{ $uptimeDays := (.Subrequest "uptime_days").JSON.Float "data.result.0.value.1" }} {{ $uptimeHours := (.Subrequest "uptime_hours").JSON.Float "data.result.0.value.1" }} {{ $cpu := (.Subrequest "cpu").JSON.Float "data.result.0.value.1" }} {{ $mem := (.Subrequest "memory").JSON.Float "data.result.0.value.1" }} {{ $temp := (.Subrequest "cpu_temp").JSON.Float "data.result.0.value.1" }} {{ $fans := (.Subrequest "fans").JSON.Array "data.result" }}
Host
{{ $hostname }}
CPU
{{ printf "%.1f" $cpu }}%
Uptime
{{ printf "%.0f" $uptimeDays }}d {{ printf "%.0f" $uptimeHours }}h
Memory
{{ printf "%.1f" $mem }}%
Temp
{{ printf "%.0f" $temp }}°C
Fans (RPM)
{{ range $i, $fan := $fans }}{{ if $i }}/{{ end }}{{ $fan.Int "value.1" }}{{ end }}
Storage
{{ $rootPct := (.Subrequest "disk_root").JSON.Float "data.result.0.value.1" }} {{ $rootUsed := (.Subrequest "disk_root_used").JSON.Float "data.result.0.value.1" }} {{ $rootTotal := (.Subrequest "disk_root_total").JSON.Float "data.result.0.value.1" }}
Root
{{ printf "%.0f" $rootUsed }} / {{ printf "%.0f" $rootTotal }} GB ({{ printf "%.0f" $rootPct }}%)
{{ $ssd2Pct := (.Subrequest "disk_ssd2").JSON.Float "data.result.0.value.1" }} {{ $ssd2Used := (.Subrequest "disk_ssd2_used").JSON.Float "data.result.0.value.1" }} {{ $ssd2Total := (.Subrequest "disk_ssd2_total").JSON.Float "data.result.0.value.1" }}
SSD2
{{ printf "%.0f" $ssd2Used }} / {{ printf "%.0f" $ssd2Total }} GB ({{ printf "%.0f" $ssd2Pct }}%)
{{ $hdd1Pct := (.Subrequest "disk_hdd1").JSON.Float "data.result.0.value.1" }} {{ $hdd1Used := (.Subrequest "disk_hdd1_used").JSON.Float "data.result.0.value.1" }} {{ $hdd1Total := (.Subrequest "disk_hdd1_total").JSON.Float "data.result.0.value.1" }}
HDD1
{{ printf "%.1f" $hdd1Used }} / {{ printf "%.1f" $hdd1Total }} TB ({{ printf "%.0f" $hdd1Pct }}%)
{{ $hdd2Pct := (.Subrequest "disk_hdd2").JSON.Float "data.result.0.value.1" }} {{ $hdd2Used := (.Subrequest "disk_hdd2_used").JSON.Float "data.result.0.value.1" }} {{ $hdd2Total := (.Subrequest "disk_hdd2_total").JSON.Float "data.result.0.value.1" }}
HDD2
{{ printf "%.1f" $hdd2Used }} / {{ printf "%.1f" $hdd2Total }} TB ({{ printf "%.0f" $hdd2Pct }}%)
{{ $hdd3Pct := (.Subrequest "disk_hdd3").JSON.Float "data.result.0.value.1" }} {{ $hdd3Used := (.Subrequest "disk_hdd3_used").JSON.Float "data.result.0.value.1" }} {{ $hdd3Total := (.Subrequest "disk_hdd3_total").JSON.Float "data.result.0.value.1" }}
HDD3
{{ printf "%.1f" $hdd3Used }} / {{ printf "%.1f" $hdd3Total }} TB ({{ printf "%.0f" $hdd3Pct }}%)
{{ $hdd4Pct := (.Subrequest "disk_hdd4").JSON.Float "data.result.0.value.1" }} {{ $hdd4Used := (.Subrequest "disk_hdd4_used").JSON.Float "data.result.0.value.1" }} {{ $hdd4Total := (.Subrequest "disk_hdd4_total").JSON.Float "data.result.0.value.1" }}
HDD4
{{ printf "%.1f" $hdd4Used }} / {{ printf "%.1f" $hdd4Total }} TB ({{ printf "%.0f" $hdd4Pct }}%)
{{ $hdd5Pct := (.Subrequest "disk_hdd5").JSON.Float "data.result.0.value.1" }} {{ $hdd5Used := (.Subrequest "disk_hdd5_used").JSON.Float "data.result.0.value.1" }} {{ $hdd5Total := (.Subrequest "disk_hdd5_total").JSON.Float "data.result.0.value.1" }}
HDD5
{{ printf "%.1f" $hdd5Used }} / {{ printf "%.1f" $hdd5Total }} TB ({{ printf "%.0f" $hdd5Pct }}%)
- type: bookmarks title: Admin Tools groups: - links: - title: Code-Server url: https://code.dooplex.hu icon: si:coder - title: ArgoCD url: https://argocd.dooplex.hu icon: si:argo - title: Gitea url: https://gitea.dooplex.hu icon: si:gitea - title: Headlamp url: https://headlamp.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/headlamp.png - title: Authentik url: https://authentik.dooplex.hu icon: si:authentik - title: Termix url: https://termix.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/termix.png - title: Longhorn (LAN Only) url: http://192.168.0.209/#/dashboard icon: https://web.dooplex.hu/static/white-icons/longhorn.png - title: Pi-hole url: https://pihole.dooplex.hu/admin icon: si:pihole - type: bookmarks title: Useful Bookmarks groups: - title: "" links: - title: GMail url: https://mail.google.com icon: si:gmail - title: Kréta url: https://klik100566001.e-kreta.hu/Intezmeny/Faliujsag icon: https://web.dooplex.hu/static/white-icons/kreta.png - title: "444" url: https://444.hu icon: https://web.dooplex.hu/static/white-icons/444.png - title: Telex url: https://telex.hu icon: https://web.dooplex.hu/static/white-icons/telex.png - title: Hardverapró url: https://hardverapro.hu icon: https://web.dooplex.hu/static/white-icons/hardverapro.png # ---------- CENTER COLUMN ---------- - size: full widgets: - type: split-column max-columns: 3 widgets: # Weather Widget (Időkép) - type: custom-api title: "Időkép – Budapest VII." url: "http://idokep-scraper.glance-system.svc.cluster.local:8000/api?v=2" cache: 30s template: | {{ $loc := .JSON.String "location.name" }} {{ if eq $loc "" }}{{ $loc = .JSON.String "place" }}{{ end }} {{ $curTemp := .JSON.Float "current.temp_c" }} {{ $curIcon := .JSON.String "current.icon_url" }} {{ $daily := .JSON.Array "daily" }} {{ $hourly := .JSON.Array "hourly" }}
{{ if $curIcon }}{{ end }}
{{ printf "%.0f" $curTemp }}°C
{{ $loc }}
Forrás: Időkép
{{ if gt (len $hourly) 0 }}
{{ range $i, $h := $hourly }}
{{ $h.String "time" }}
{{ if $h.String "icon_url" }}{{ end }}
{{ printf "%.0f" ($h.Float "temp_c") }}°
{{ end }}
{{ end }} {{ if gt (len $daily) 0 }}
{{ range $daily }}
{{ .String "dow" }} {{ .String "daynum" }}
{{ if .String "icon_url" }}{{ end }}
{{ printf "%.0f" (.Float "tmin_c") }}°
{{/* We construct the style manually to bypass Go security sanitization */}}
{{ printf "%.0f" (.Float "tmax_c") }}°
{{ end }}
{{ end }}
# Calendar Widget - type: calendar first-day-of-week: monday # To-Do List - type: to-do title: Tasks # Outline Notes iframe - type: iframe source: https://outline.dooplex.hu/collection/dooplex-server-iTAZn04AaR/recent height: 600 title: Documentation # ---------- RIGHT COLUMN ---------- - size: small widgets: - type: custom-api title: Meal for the Day cache: 5m # Served by glance-helper: stable picks for the day + "cooked" support url: http://glance-helper.glance-system.svc.cluster.local:8000/tandoor/daily parameters: count: 3 options: tandoor_url: https://tandoor.dooplex.hu template: | {{ $tandoor := .Options.StringOr "tandoor_url" "https://tandoor.dooplex.hu" }} {{ $items := .JSON.Array "items" }} {{ $total := .JSON.Int "total_recipes" }} {{ $date := .JSON.String "date" }}
Today’s picks ({{ $total }} total) Open Tandoor
{{ if lt (len $items) 1 }}
No recipes returned.
{{ else }}
{{ range $i, $r := $items }} {{ $name := $r.String "name" }} {{ $img := $r.String "image" }} {{ $url := $r.String "url" }} {{ $cook := $r.String "cook_url" }} {{ end }}
{{ end }}
- type: bookmarks title: Productivity Self-Hosted groups: - title: "" links: - title: Nextcloud url: https://nextcloud.dooplex.hu icon: si:nextcloud - title: Outline url: https://outline.dooplex.hu icon: si:outline - title: Paperless url: https://paperless.dooplex.hu icon: si:paperlessngx - title: Vaultwarden url: https://vaultwarden.dooplex.hu icon: si:bitwarden - title: Actual Budget url: https://actualbudget.dooplex.hu icon: si:actualbudget - title: Tandoor url: https://tandoor.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/tandoor.png - title: Bookstack url: https://bookstack.dooplex.hu icon: si:bookstack - type: bookmarks title: Other Self-Hosted groups: - links: - title: AdventureLog url: https://adventures.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/adventurelog.png - title: Wanderer url: https://wanderer.dooplex.hu icon: sh:wanderer - title: Plant-it url: https://plantit.dooplex.hu icon: si:leaflet - title: Workout (wger) url: https://workout.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/wger.png - title: Fileshare url: https://fileshare.dooplex.hu icon: si:files - title: Privatebin url: https://privatebin.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/privatebin.png - title: Pastes (OpenGist) url: https://paste.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/opengist.png - title: Zipline url: https://zipline.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/zipline.png # ==================== MONITORING PAGE ==================== - name: Monitoring slug: monitoring width: wide columns: - size: small widgets: - type: bookmarks title: Monitoring groups: - links: - title: Grafana url: https://grafana.dooplex.hu/d/adxgb7x/overview-dashboard?orgId=1&from=now-3h&to=now&timezone=browser icon: si:grafana - title: Uptime Kuma url: https://uptimekuma.dooplex.hu icon: si:uptimekuma - title: Prometheus (LAN Only) url: http://prometheus.home/alerts icon: si:prometheus # Glance Widget: Container Version Checker (Simplified) # # This is a more robust version that uses only Glance's documented template functions. # Add this widget to your glance.yml under a column's widgets section. # Place it right after the "DooPlex Server" widget. # # Prerequisites: # - Deploy version-checker from version-checker.yaml # - Wait ~5 minutes for initial version checks to complete - type: custom-api title: Container Versions cache: 5m url: ${PROMETHEUS_URL}/api/v1/query parameters: query: > max by (image, current_version, latest_version) ( version_checker_is_latest_version{ container_type="container", image!~"(^|.*/)(busybox|redis|alpine|nginx|mariadb|mysql|valkey)$", image!~"^longhornio.*$", image!~"(^|.*/)postgres.*$", image!~"^registry\\.k8s\\.io/ingress-nginx/.*$", current_version!~".*sha256:.*", latest_version!~".*sha256:.*" } == 0 ) subrequests: up_to_date: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: > count( max by (image) ( version_checker_is_latest_version{ container_type="container", image!~"(^|.*/)(busybox|redis|alpine|nginx|mariadb|mysql|valkey)$", image!~"^longhornio.*$", image!~"(^|.*/)postgres.*$", image!~"^registry\\.k8s\\.io/ingress-nginx/.*$", current_version!~".*sha256:.*", latest_version!~".*sha256:.*" } == 1 ) ) or vector(0) outdated: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: > count( max by (image) ( version_checker_is_latest_version{ container_type="container", image!~"(^|.*/)(busybox|redis|alpine|nginx|mariadb|mysql|valkey)$", image!~"^longhornio.*$", image!~"(^|.*/)postgres.*$", image!~"^registry\\.k8s\\.io/ingress-nginx/.*$", current_version!~".*sha256:.*", latest_version!~".*sha256:.*" } == 0 ) ) or vector(0) total: url: ${PROMETHEUS_URL}/api/v1/query parameters: query: > count( max by (image) ( version_checker_is_latest_version{ container_type="container", image!~"(^|.*/)(busybox|redis|alpine|nginx|mariadb|mysql|valkey)$", image!~"^longhornio.*$", image!~"(^|.*/)postgres.*$", image!~"^registry\\.k8s\\.io/ingress-nginx/.*$", current_version!~".*sha256:.*", latest_version!~".*sha256:.*" } ) ) or vector(0) template: | {{ $upToDate := (.Subrequest "up_to_date").JSON.Float "data.result.0.value.1" }} {{ $outdated := (.Subrequest "outdated").JSON.Float "data.result.0.value.1" }} {{ $total := (.Subrequest "total").JSON.Float "data.result.0.value.1" }} {{ $updates := .JSON.Array "data.result" }}
{{ if gt $total 0.0 }}
Current
{{ printf "%.0f" $upToDate }}
Updates
{{ printf "%.0f" $outdated }}
Total
{{ printf "%.0f" $total }}
{{ if gt $outdated 0.0 }}
{{ range $updates }}
{{ trimPrefix "ghcr.io/" (trimPrefix "docker.io/" (trimPrefix "lscr.io/" (trimPrefix "quay.io/" (.String "metric.image")))) }} {{ .String "metric.current_version" }} {{ .String "metric.latest_version" }}
{{ end }}
{{ else }}
✓ All images up to date!
{{ end }} {{ else }}
Waiting for version-checker metrics...
Check back in a few minutes
{{ end }}
- size: full widgets: # Grafana - type: iframe source: https://grafana.dooplex.hu/d/nazwb7z/overview-dashboard-for-glance?kiosk height: 1140 title: Grafana Overview Dashboard - size: small widgets: - type: custom-api title: Uptime Kuma title-url: ${UPTIME_KUMA_PUBLIC_URL} url: ${UPTIME_KUMA_URL}/api/status-page/${UPTIME_KUMA_STATUS_SLUG} subrequests: heartbeats: url: ${UPTIME_KUMA_URL}/api/status-page/heartbeat/${UPTIME_KUMA_STATUS_SLUG} cache: 10m template: | {{ $hb := .Subrequest "heartbeats" }} {{ if not (.JSON.Exists "publicGroupList") }}

Error reading response

{{ else if eq (len (.JSON.Array "publicGroupList")) 0 }}

No monitors found

{{ else }} {{ end }} # ==================== MEDIA PAGE ==================== - name: Media slug: media width: wide columns: - size: small widgets: - type: bookmarks title: Entertainment groups: - links: - title: Plex url: https://plex.dooplex.hu icon: si:plex - title: Immich (Photos) url: https://photos.dooplex.hu icon: si:immich - title: AudioBookshelf url: https://audiobookshelf.dooplex.hu icon: si:audiobookshelf - title: Calibre-Web (eBooks) url: https://books.dooplex.hu icon: si:calibreweb - title: Arcade (Retro Games) url: https://arcade.dooplex.hu icon: si:retroarch - title: Crafty Controller url: https://crafty.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/minecraftcreeper.png - title: YouTube url: https://www.youtube.com icon: si:youtube - title: Spotify url: https://open.spotify.com/ icon: si:spotify - type: bookmarks title: Media Management groups: - links: - title: Sonarr (TV Shows) url: https://sonarr.dooplex.hu icon: si:sonarr - title: Radarr (Movies) url: https://radarr.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/radarr.png - title: RadarrKids url: https://radarrkids.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/radarrkids.png - title: Prowlarr (Indexers) url: https://prowlarr.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/prowlarr.png - title: Seerr (Requests) url: https://seerr.dooplex.hu icon: https://web.dooplex.hu/static/white-icons/seerr.png - type: custom-api title: Crafty - Minecraft Server cache: 5s options: base-url: ${CRAFTY_URL} api-key: ${CRAFTY_API_TOKEN} server-id: ${CRAFTY_SERVER_ID} display-MOTD: true allow-insecure: true template: | {{/* Required config options */}} {{ $baseURL := .Options.StringOr "base-url" "" }} {{ $apiKey := .Options.StringOr "api-key" "" }} {{ $serverID := .Options.StringOr "server-id" "" }} {{/* Optional config options */}} {{ $displayMOTD := .Options.BoolOr "display-MOTD" true }} {{ $serverStats := newRequest (print $baseURL "/api/v2/servers/" $serverID "/stats") | withHeader "Authorization" (print "Bearer " $apiKey) | withHeader "Accept" "application/json" | getResponse }} {{ $is_running := $serverStats.JSON.Bool "data.running" }} {{ $online_players := $serverStats.JSON.Int "data.online" | formatNumber }} {{ $max_players := $serverStats.JSON.Int "data.max" | formatNumber }} {{ $name := $serverStats.JSON.String "data.world_name" }} {{ $size := $serverStats.JSON.String "data.world_size" }} {{ $version := $serverStats.JSON.String "data.version" }} {{ $icon := $serverStats.JSON.String "data.icon" }} {{ $server_ip := $serverStats.JSON.String "data.server_id.server_ip" }} {{ $server_port := $serverStats.JSON.String "data.server_id.server_port" }} {{ $motd := $serverStats.JSON.String "data.desc" }} {{ $server_addr := "" }} {{ if and ($is_running) (eq $server_ip "127.0.0.1") }} {{ $server_addr = printf "%s:%s" (replaceMatches "https?://" "" $baseURL) $server_port }} {{ else if $is_running }} {{ $server_addr = printf "%s:%s" $server_ip $server_port }} {{ end }} {{ $starting := false }} {{ if and ($is_running) (eq $max_players "0") (eq $version "False") }} {{ $starting = true }} {{ end }} {{ $updating := $serverStats.JSON.Bool "data.updating" }} {{ $importing := $serverStats.JSON.Bool "data.importing" }} {{ $crashed := $serverStats.JSON.Bool "data.crashed" }}
{{ if eq $icon "" }} Server icon {{ else }} Server icon {{ end }}
{{ $name }} {{ if and ($is_running) (not $starting) (not (eq $server_addr "")) }}
- {{ $server_addr }}
{{ end }}
{{ if and ($is_running) (not $starting) }} {{ if and (not (eq $motd "")) ($displayMOTD) }}
{{ replaceMatches "§." "" $motd }}
{{ end }}
{{ $version }} - {{ $online_players }}/{{ $max_players }} players - {{ $size }}
{{ else if $starting }}
Server is starting up..
{{ else if $importing }}
Server is being imported..
{{ else if $updating }}
Server is being updated..
{{ else if $crashed }}
Server has crashed!
{{ else }}
Server is offline
{{ end }}
- type: custom-api title: RomM cache: 1d url: http://${ROMM_URL}/api/stats headers: Accept: application/json template: | {{ $bytes := .JSON.Int "TOTAL_FILESIZE_BYTES" | toFloat }} {{ $tb := div $bytes 1099511627776 }} {{ $gb := div $bytes 1073741824 | toInt }}
{{ .JSON.Int "PLATFORMS" | formatNumber }}
PLATFORMS
{{ .JSON.Int "ROMS" | formatNumber }}
ROMS
{{ if ge $tb 1.0 }} {{ printf "%.2f" $tb }}TB {{ else }} {{ $gb }}GB {{ end }}
FILESIZE
- type: custom-api title: Steam Specials cache: 12h url: https://store.steampowered.com/api/featuredcategories?cc=us template: | - size: full widgets: # YouTube Videos - type: videos title: YouTube - Gaming channels: - UC4Xj6emHTXnKHUq8btUuN6A #Retromation - UC5ib5bTflXtyIkoF_l7OCHw #Olexa - UCfWybrB-Faa30sXUE6eqMIQ #Zarfen the Loot Goblin - UCto7D1L-MiRoOziCXK9uT5Q #Let's Game It Out limit: 12 collapse-after: 6 - type: videos title: YouTube - Tech channels: - UCXuqSBlHAE6Xw-yeJA0Tunw #LinusTechTips - UCdngmbVKX1Tgre699-XLlUA #Techworld with Nana - UCJa14zeVf8p6clixTOIOVyQ #Jakkuh (Jake) - UC-2YHgc363EdcusLIBbgxzg #JoeScott - UCY1kMZp36IQSyNx_9h4mpCg #Mark Rober - UC7IcJI8PUf5Z3zKxnZvTBog #The School of Life limit: 12 collapse-after: 6 - type: videos title: YouTube - Other channels: - UC9qpYwK7N9EB0-SECANa23g #Jólvanezígy - UCEFpEvuosfPGlV1VyUF6QOA #Partizán - UC_fAjvoGnqySaNM6DRfFiCA #Pottyondi - UCM-1sd-cXSuCsfWp8QMY_OQ #Telex.hu - UCdPhEv5wiw2uK6J0_wkc-RA #Bűnvadászok - UCQAeX1_gw45xb3Cg-OwEFcw #Friderikusz - UCW5OrUZ4SeUYkUg1XqcjFYA #GeoWizard limit: 12 collapse-after: 6 # Reddit - type: group title: Reddit widgets: - type: reddit subreddit: hungary show-thumbnails: true - type: reddit subreddit: selfhosted show-thumbnails: true - type: reddit subreddit: homeserver show-thumbnails: true - type: reddit subreddit: homelab show-thumbnails: true - type: reddit subreddit: kubernetes show-thumbnails: true - type: reddit subreddit: linux show-thumbnails: true - type: reddit subreddit: sysadmin show-thumbnails: true - type: reddit subreddit: technology show-thumbnails: true - type: reddit subreddit: futurology show-thumbnails: true - size: small widgets: # RSS Feeds - Add your favorite feeds here - type: rss title: News & Feeds limit: 15 collapse-after: 15 feeds: - url: https://telex.hu/rss title: telex.hu limit: 3 - url: https://444.hu/feed title: 444.hu limit: 3 - url: https://444.hu/feed title: 444.hu limit: 3 - url: https://hvg.hu/rss title: hvg.hu limit: 3 # ==================== NEXTCLOUD PAGE ==================== - name: NextCloud slug: nextcloud width: wide columns: - size: full widgets: # Nextcloud iframe - type: iframe css-class: iframe-no-tint source: https://nextcloud.dooplex.hu/apps/files/files height: 1200 title: NextCloud custom.css: | /* ========================================================================= WALLPAPER VISIBLE ========================================================================= */ html, body { height: 100%; } html { background: url("https://web.dooplex.hu/static/wallpaper-2.jpg") center / cover no-repeat fixed !important; } /* Glance containers that tend to paint over the wallpaper */ body, .page, #page-content, .page-content, .content-bounds, .page-columns, .page-column { background: transparent !important; } /* Optional readability veil (Homepage-like) */ body::before { content: ""; position: fixed; inset: 0; background: rgba(20, 10, 30, 0.25); pointer-events: none; z-index: 0; } body > * { position: relative; z-index: 1; } /* ========================================================================= ROOT VARIABLES OVERRIDE These override Glance's default theme colors at the CSS variable level ========================================================================= */ :root { /* Primary color - affects many built-in elements */ --color-primary: hsl(190, 70%, 60%) !important; /* These control various UI elements */ --color-text-highlight: #5ac8d8 !important; --color-text-accent: #5ac8d8 !important; } /* ========================================================================= GLOBAL LINK COLORS Affects all tags site-wide (bookmarks, reddit links, video titles, etc.) ========================================================================= */ a { color: #5ac8d8 !important; /* CYAN - main link color */ } a:hover { color: #7ed9e6 !important; /* LIGHTER CYAN - hover state */ } /* Visited links - slightly muted */ a:visited { color: #4ab8c8 !important; /* SLIGHTLY DARKER CYAN */ } /* ========================================================================= HEADER / NAVIGATION The top bar with Home, Media, NextCloud tabs ========================================================================= */ /* Push nav items to bottom of header and align properly */ .header.flex { align-items: flex-end !important; } .header.flex > .nav.flex { height: 100% !important; align-items: flex-end !important; padding-bottom: 0 !important; /* Remove extra padding */ } /* Nav item text styling */ .header .nav .nav-item, .header.flex > .nav.flex > .nav-item { color: #5ac8d8 !important; /* CYAN - nav text color */ font-size: 20px !important; line-height: 1 !important; padding: 8px 14px 12px 14px !important; /* top right bottom left */ letter-spacing: 0.3px !important; text-transform: uppercase !important; font-weight: 500 !important; display: flex !important; align-items: flex-end !important; height: auto !important; /* Let it size naturally */ } /* Nav item hover */ .header .nav .nav-item:hover { color: #7ed9e6 !important; /* LIGHTER CYAN on hover */ } /* Active tab underline - position closer to text */ .header .nav .nav-item-current::after, .header .nav .nav-item[aria-current="page"]::after { bottom: 4px !important; /* Closer to text */ background-color: #5ac8d8 !important; /* CYAN underline */ } .header { min-height: 80px !important; align-items: flex-end !important; } /* This matches your DOM: