From ff1979ba518a05181ee3e8c5b1ad0ec1decf0f31 Mon Sep 17 00:00:00 2001 From: Ramon Date: Mon, 27 Jul 2026 14:14:25 +0200 Subject: [PATCH] v0.7.10-beta - categorieen met kleur in de app store en bij je apps - Nieuw core/categories.py: zeventien categorieen, elk met naam (nl/en), kleur en pictogram. Kleuren zijn middentonen die in licht en donker leesbaar zijn; de interface gebruikt ze als tekstkleur op een doorzichtige variant. - Alle 96 apps ingedeeld via metadata.categories. Een app mag in meerdere categorieen zitten; 39 apps doen dat (Frigate onder domotica en media, Immich onder fotos en opslag, Kavita onder media en documenten). - Apps uit externe repos geven geen categorieen op; die worden afgeleid uit tags en omschrijving, zodat ook zij een kleur en een plek in het filter krijgen. - App store: gekleurde categoriebalk met aantallen, klikbare badges per app, werkt naast het bestaande zoekveld en de tagfilters. - Stackslijst: dezelfde balk met alleen de categorieen die je draait, gekleurde rand per kaart en klikbare badges. - Nieuw /api/categories geeft de definities met kleur, zodat interface en backend dezelfde kleur voor dezelfde categorie gebruiken. /api/stacks geeft de categorieen mee; een stack van voor deze versie valt terug op "overig" in plaats van kleurloos te blijven. - Tests: elke app heeft geldige categorieen, kleuren zijn uniek, en er staat geen categorie in het filter zonder apps. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb --- CHANGELOG.md | 39 +++++++++ VERSION | 2 +- apps/actual-budget/template.json | 19 ++++- apps/adguard-home/template.json | 20 ++++- apps/arr-stack/template.json | 6 +- apps/audiobookshelf/template.json | 5 +- apps/authelia/template.json | 5 +- apps/baby-buddy/template.json | 5 +- apps/bambuddy/template.json | 5 +- apps/baserow/template.json | 6 +- apps/beszel/template.json | 5 +- apps/bookstack/template.json | 5 +- apps/caddy/template.json | 6 +- apps/calibre-web/template.json | 6 +- apps/changedetection-io/template.json | 23 ++++- apps/cyberchef/template.json | 6 +- apps/dozzle/template.json | 20 ++++- apps/duplicati/template.json | 5 +- apps/esphome/template.json | 6 +- apps/excalidraw/template.json | 5 +- apps/filebrowser/template.json | 19 ++++- apps/firefly-iii/template.json | 5 +- apps/focalboard/template.json | 5 +- apps/forgejo-mcp/template.json | 29 +++++-- apps/forgejo/template.json | 19 ++++- apps/freshrss/template.json | 5 +- apps/frigate/template.json | 6 +- apps/ghost/template.json | 27 ++++-- apps/gotify/template.json | 23 ++++- apps/grafana/template.json | 23 ++++- apps/grocy/template.json | 5 +- apps/hedgedoc/template.json | 6 +- apps/home-assistant/template.json | 18 +++- apps/homeassistant-mcp/template.json | 29 +++++-- apps/homebridge/template.json | 5 +- apps/homepage/template.json | 5 +- apps/immich/template.json | 6 +- apps/influxdb/template.json | 6 +- apps/it-tools/template.json | 19 ++++- apps/jellyfin/template.json | 19 ++++- apps/jellyseerr/template.json | 5 +- apps/karakeep/template.json | 5 +- apps/kavita/template.json | 6 +- apps/keycloak/template.json | 5 +- apps/kimai/template.json | 6 +- apps/komga/template.json | 5 +- apps/kopia/template.json | 5 +- apps/languagetool/template.json | 6 +- apps/linkding/template.json | 22 ++++- apps/mealie/template.json | 19 ++++- apps/memos/template.json | 6 +- apps/metabase/template.json | 6 +- apps/metube/template.json | 6 +- apps/miniflux/template.json | 27 ++++-- apps/mosquitto/template.json | 6 +- apps/n8n/template.json | 23 ++++- apps/navidrome/template.json | 5 +- apps/netdata/template.json | 5 +- apps/nextcloud-aio/template.json | 20 ++++- apps/nginx-proxy-manager/template.json | 19 ++++- apps/nocodb/template.json | 6 +- apps/node-red/template.json | 6 +- apps/ntfy/template.json | 5 +- apps/octoprint/template.json | 5 +- apps/ollama/template.json | 5 +- apps/open-webui/template.json | 5 +- apps/owntracks/template.json | 6 +- apps/paperless-ngx/template.json | 28 ++++-- apps/photoprism/template.json | 5 +- apps/pihole/template.json | 24 +++++- apps/pinchflat/template.json | 6 +- apps/planka/template.json | 5 +- apps/plex/template.json | 23 ++++- apps/portainer/template.json | 18 +++- apps/prometheus/template.json | 5 +- apps/qbittorrent/template.json | 18 +++- apps/sabnzbd/template.json | 19 ++++- apps/scrypted/template.json | 6 +- apps/searxng/template.json | 6 +- apps/shlink/template.json | 6 +- apps/speedtest-tracker/template.json | 24 +++++- apps/spoolman/template.json | 5 +- apps/stirling-pdf/template.json | 19 ++++- apps/syncthing/template.json | 19 ++++- apps/tandoor/template.json | 5 +- apps/technitium-dns/template.json | 6 +- apps/teslamate/template.json | 6 +- apps/traefik/template.json | 24 +++++- apps/unifi-network/template.json | 24 +++++- apps/uptime-kuma/template.json | 18 +++- apps/vaultwarden/template.json | 22 ++++- apps/vikunja/template.json | 27 ++++-- apps/wallabag/template.json | 5 +- apps/watchtower/template.json | 5 +- apps/wg-easy/template.json | 6 +- apps/wikijs/template.json | 5 +- apps/zigbee2mqtt/template.json | 5 +- apps/zwave-js-ui/template.json | 5 +- server-up/app.py | 17 +++- server-up/core/boilerplates.py | 10 ++- server-up/core/categories.py | 106 +++++++++++++++++++++++ server-up/templates/index.html | 110 ++++++++++++++++++++++-- server-up/translations/en.json | 4 +- server-up/translations/nl.json | 4 +- tests/test_categories.py | 113 +++++++++++++++++++++++++ 105 files changed, 1286 insertions(+), 200 deletions(-) create mode 100644 server-up/core/categories.py create mode 100644 tests/test_categories.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eca7db..48ce5f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,42 @@ +# v0.7.10-beta — Categorieën met kleur, in de app store en bij je apps + +Alle 96 apps zijn ingedeeld in zeventien categorieën, elk met een eigen kleur en +pictogram. Een app mag in meerdere categorieën zitten: Frigate staat onder +Domotica én Media, Immich onder Foto's én Opslag, Kavita onder Media én +Documenten. Negenendertig apps vallen onder meer dan één. + +| | Categorie | | Categorie | +|---|---|---|---| +| 🟣 | Media | 🔵 | Netwerk | +| 🩷 | Foto's | 🔴 | Beveiliging | +| 🟢 | Downloaden | 🟠 | Opslag & backup | +| 🟩 | Domotica | 🩵 | Documenten | +| 🟦 | 3D-printen | 🟦 | Productiviteit | +| 🔷 | Communicatie | 🟩 | Financiën | +| 🌸 | Gezin & huishouden | 🟧 | Monitoring | +| 🩵 | Ontwikkeling | 🟪 | AI | +| ⬜ | Systeembeheer | | | + +**In de app store** staat een gekleurde categoriebalk met per categorie het +aantal apps. Klikken filtert; het bestaande zoekveld en de tagfilters werken +ernaast gewoon door. Elke app-kaart toont zijn categorieën als gekleurde badge, +en klikken op zo'n badge filtert er meteen op. + +**Bij je geïnstalleerde apps** staat dezelfde balk, met alleen de categorieën die +je daadwerkelijk draait. Elke stackkaart heeft een gekleurde rand in de kleur van +zijn eerste categorie, plus dezelfde klikbare badges. + +Apps uit externe repo's (zoals de ChristianLempa-boilerplates) geven geen +categorieën op. Die worden afgeleid uit hun tags en omschrijving, zodat ook zij +een kleur en een plek in het filter krijgen in plaats van als naamloze groep +buiten de indeling te vallen. + +Tests bewaken dat elke app minstens één geldige categorie heeft, dat de kleuren +onderling verschillen, en dat er geen categorie in het filter staat waar geen +enkele app onder valt. + +--- + # v0.7.00-beta — Apps koppelen, eenvoudiger instellen, geavanceerde opties verborgen ## 🔗 Apps kunnen elkaar nu bereiken diff --git a/VERSION b/VERSION index 771f51a..f7580d2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.7.00-beta +0.7.10-beta diff --git a/apps/actual-budget/template.json b/apps/actual-budget/template.json index 371ac78..2a7e0f6 100644 --- a/apps/actual-budget/template.json +++ b/apps/actual-budget/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Actual Budget", "description": "Lokaal persoonlijk financieel beheer en budgettering zonder cloudafhankelijkheid.", - "tags": ["financiën", "budget", "persoonlijk", "privacy"], - "icon": {"provider": "selfhst", "id": "actual-budget"}, - "version": {"name": "latest"} + "tags": [ + "financiën", + "budget", + "persoonlijk", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "actual-budget" + }, + "version": { + "name": "latest" + }, + "categories": [ + "financien" + ] }, "variables": [ { diff --git a/apps/adguard-home/template.json b/apps/adguard-home/template.json index b335b7e..851a3c9 100644 --- a/apps/adguard-home/template.json +++ b/apps/adguard-home/template.json @@ -3,9 +3,23 @@ "metadata": { "name": "AdGuard Home", "description": "DNS-level advertentie- en trackerblokkering voor het hele netwerk", - "tags": ["dns", "adblock", "netwerk", "privacy"], - "icon": {"provider": "selfhst", "id": "adguard-home"}, - "version": {"name": "latest"} + "tags": [ + "dns", + "adblock", + "netwerk", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "adguard-home" + }, + "version": { + "name": "latest" + }, + "categories": [ + "netwerk", + "beveiliging" + ] }, "variables": [ { diff --git a/apps/arr-stack/template.json b/apps/arr-stack/template.json index cee79ca..ab1b42b 100644 --- a/apps/arr-stack/template.json +++ b/apps/arr-stack/template.json @@ -16,7 +16,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "media", + "downloaden" + ] }, "variables": [ { diff --git a/apps/audiobookshelf/template.json b/apps/audiobookshelf/template.json index ae44b9f..b563aa2 100644 --- a/apps/audiobookshelf/template.json +++ b/apps/audiobookshelf/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "media" + ] }, "variables": [ { diff --git a/apps/authelia/template.json b/apps/authelia/template.json index 92a1779..2a9652c 100644 --- a/apps/authelia/template.json +++ b/apps/authelia/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "beveiliging" + ] }, "variables": [ { diff --git a/apps/baby-buddy/template.json b/apps/baby-buddy/template.json index 86aaba3..ca90458 100644 --- a/apps/baby-buddy/template.json +++ b/apps/baby-buddy/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "gezin" + ] }, "variables": [ { diff --git a/apps/bambuddy/template.json b/apps/bambuddy/template.json index cbf0290..427984e 100644 --- a/apps/bambuddy/template.json +++ b/apps/bambuddy/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "3d-printen" + ] }, "variables": [ { diff --git a/apps/baserow/template.json b/apps/baserow/template.json index 6c26f3f..7e746b0 100644 --- a/apps/baserow/template.json +++ b/apps/baserow/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "ontwikkeling", + "productiviteit" + ] }, "variables": [ { diff --git a/apps/beszel/template.json b/apps/beszel/template.json index 9c8f173..75bc0eb 100644 --- a/apps/beszel/template.json +++ b/apps/beszel/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "monitoring" + ] }, "variables": [ { diff --git a/apps/bookstack/template.json b/apps/bookstack/template.json index 890094a..612e86a 100644 --- a/apps/bookstack/template.json +++ b/apps/bookstack/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "documenten" + ] }, "variables": [ { diff --git a/apps/caddy/template.json b/apps/caddy/template.json index 477bc98..cdd2a77 100644 --- a/apps/caddy/template.json +++ b/apps/caddy/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "2" - } + }, + "categories": [ + "netwerk", + "beheer" + ] }, "variables": [ { diff --git a/apps/calibre-web/template.json b/apps/calibre-web/template.json index ac7c364..1ea48eb 100644 --- a/apps/calibre-web/template.json +++ b/apps/calibre-web/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "media", + "documenten" + ] }, "variables": [ { diff --git a/apps/changedetection-io/template.json b/apps/changedetection-io/template.json index b119b76..b39905c 100644 --- a/apps/changedetection-io/template.json +++ b/apps/changedetection-io/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Changedetection.io", "description": "Monitor websites op wijzigingen en ontvang meldingen zodra er iets verandert.", - "tags": ["monitoring", "websites", "alerting", "automatisering"], - "icon": {"provider": "selfhst", "id": "changedetection-io"}, - "version": {"name": "latest"} + "tags": [ + "monitoring", + "websites", + "alerting", + "automatisering" + ], + "icon": { + "provider": "selfhst", + "id": "changedetection-io" + }, + "version": { + "name": "latest" + }, + "categories": [ + "monitoring" + ] }, "variables": [ { @@ -44,7 +57,9 @@ "default": "", "required": false, "description": "Optioneel wachtwoord om de webinterface te beveiligen. Laat leeg voor geen beveiliging.", - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] } diff --git a/apps/cyberchef/template.json b/apps/cyberchef/template.json index 5799d9d..19b1f3a 100644 --- a/apps/cyberchef/template.json +++ b/apps/cyberchef/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "ontwikkeling", + "beveiliging" + ] }, "variables": [ { diff --git a/apps/dozzle/template.json b/apps/dozzle/template.json index fb0eba5..07d1168 100644 --- a/apps/dozzle/template.json +++ b/apps/dozzle/template.json @@ -3,9 +3,23 @@ "metadata": { "name": "Dozzle", "description": "Realtime Docker container log viewer in je browser. Geen data opgeslagen, lichtgewicht.", - "tags": ["docker", "logs", "monitoring", "beheer"], - "icon": {"provider": "selfhst", "id": "dozzle"}, - "version": {"name": "latest"} + "tags": [ + "docker", + "logs", + "monitoring", + "beheer" + ], + "icon": { + "provider": "selfhst", + "id": "dozzle" + }, + "version": { + "name": "latest" + }, + "categories": [ + "monitoring", + "beheer" + ] }, "variables": [ { diff --git a/apps/duplicati/template.json b/apps/duplicati/template.json index 76fb8fa..187f6cf 100644 --- a/apps/duplicati/template.json +++ b/apps/duplicati/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "opslag" + ] }, "variables": [ { diff --git a/apps/esphome/template.json b/apps/esphome/template.json index 73cad3d..40688ef 100644 --- a/apps/esphome/template.json +++ b/apps/esphome/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "stable" - } + }, + "categories": [ + "domotica", + "ontwikkeling" + ] }, "variables": [ { diff --git a/apps/excalidraw/template.json b/apps/excalidraw/template.json index 97a0a06..632e023 100644 --- a/apps/excalidraw/template.json +++ b/apps/excalidraw/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "productiviteit" + ] }, "variables": [ { diff --git a/apps/filebrowser/template.json b/apps/filebrowser/template.json index 9aaa8cf..0d2a01a 100644 --- a/apps/filebrowser/template.json +++ b/apps/filebrowser/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "File Browser", "description": "Webgebaseerde bestandsbeheerder voor je server: uploaden, downloaden, delen en bewerken.", - "tags": ["bestanden", "beheer", "cloud", "opslag"], - "icon": {"provider": "selfhst", "id": "filebrowser"}, - "version": {"name": "latest"} + "tags": [ + "bestanden", + "beheer", + "cloud", + "opslag" + ], + "icon": { + "provider": "selfhst", + "id": "filebrowser" + }, + "version": { + "name": "latest" + }, + "categories": [ + "opslag" + ] }, "variables": [ { diff --git a/apps/firefly-iii/template.json b/apps/firefly-iii/template.json index 12010d2..cc4ab3c 100644 --- a/apps/firefly-iii/template.json +++ b/apps/firefly-iii/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "financien" + ] }, "variables": [ { diff --git a/apps/focalboard/template.json b/apps/focalboard/template.json index 48c2a90..e906d08 100644 --- a/apps/focalboard/template.json +++ b/apps/focalboard/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "productiviteit" + ] }, "variables": [ { diff --git a/apps/forgejo-mcp/template.json b/apps/forgejo-mcp/template.json index f873304..4b79764 100644 --- a/apps/forgejo-mcp/template.json +++ b/apps/forgejo-mcp/template.json @@ -3,9 +3,24 @@ "metadata": { "name": "Forgejo MCP Server", "description": "MCP-server voor Forgejo en Gitea. Laat AI-assistenten zoals Claude je repositories, issues, pull requests en releases beheren via natuurlijke taal.", - "tags": ["mcp", "ai", "forgejo", "gitea", "claude"], - "icon": {"provider": "selfhst", "id": "forgejo"}, - "version": {"name": "latest"} + "tags": [ + "mcp", + "ai", + "forgejo", + "gitea", + "claude" + ], + "icon": { + "provider": "selfhst", + "id": "forgejo" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ontwikkeling", + "ai" + ] }, "variables": [ { @@ -38,7 +53,9 @@ "default": "https://jouw-forgejo-url", "required": true, "description": "Volledige URL van je Forgejo- of Gitea-instantie", - "config": {"placeholder": "https://git.example.com"} + "config": { + "placeholder": "https://git.example.com" + } }, { "name": "forgejo_token", @@ -47,7 +64,9 @@ "default": "", "required": true, "description": "Maak een token aan via Forgejo → Instellingen → Toepassingen → Access Tokens. Geef minimaal 'repository' en 'issue' schrijfrechten.", - "config": {"placeholder": "jouw-api-token"} + "config": { + "placeholder": "jouw-api-token" + } } ] } diff --git a/apps/forgejo/template.json b/apps/forgejo/template.json index 9d97cc1..2a656bf 100644 --- a/apps/forgejo/template.json +++ b/apps/forgejo/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Forgejo", "description": "Lichtgewicht zelfgehoste Git-server. Actief onderhouden community-fork van Gitea.", - "tags": ["git", "code", "versiebeheer", "ontwikkeling"], - "icon": {"provider": "selfhst", "id": "forgejo"}, - "version": {"name": "latest"} + "tags": [ + "git", + "code", + "versiebeheer", + "ontwikkeling" + ], + "icon": { + "provider": "selfhst", + "id": "forgejo" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ontwikkeling" + ] }, "variables": [ { diff --git a/apps/freshrss/template.json b/apps/freshrss/template.json index b82ec11..49f954b 100644 --- a/apps/freshrss/template.json +++ b/apps/freshrss/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "documenten" + ] }, "variables": [ { diff --git a/apps/frigate/template.json b/apps/frigate/template.json index 07fd0e8..04ef78c 100644 --- a/apps/frigate/template.json +++ b/apps/frigate/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "stable" - } + }, + "categories": [ + "domotica", + "media" + ] }, "variables": [ { diff --git a/apps/ghost/template.json b/apps/ghost/template.json index 3810ccc..0628192 100644 --- a/apps/ghost/template.json +++ b/apps/ghost/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Ghost", "description": "Professioneel blogplatform en CMS met abonnementen, nieuwsbrieven en moderne editor.", - "tags": ["blog", "cms", "publiceren", "nieuwsbrief"], - "icon": {"provider": "selfhst", "id": "ghost"}, - "version": {"name": "latest"} + "tags": [ + "blog", + "cms", + "publiceren", + "nieuwsbrief" + ], + "icon": { + "provider": "selfhst", + "id": "ghost" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten" + ] }, "variables": [ { @@ -44,7 +57,9 @@ "default": "http://localhost", "required": true, "description": "Volledige URL van je Ghost-site, inclusief protocol", - "config": {"placeholder": "https://mijn-blog.nl"} + "config": { + "placeholder": "https://mijn-blog.nl" + } } ] }, @@ -57,7 +72,9 @@ "title": "Database wachtwoord", "default": "ghost_db_pass", "required": true, - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] } diff --git a/apps/gotify/template.json b/apps/gotify/template.json index 683329b..56f4010 100644 --- a/apps/gotify/template.json +++ b/apps/gotify/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Gotify", "description": "Eenvoudige push-notificatieserver voor je eigen apparaten, scripts en apps.", - "tags": ["notificaties", "push", "messaging", "alerts"], - "icon": {"provider": "selfhst", "id": "gotify"}, - "version": {"name": "latest"} + "tags": [ + "notificaties", + "push", + "messaging", + "alerts" + ], + "icon": { + "provider": "selfhst", + "id": "gotify" + }, + "version": { + "name": "latest" + }, + "categories": [ + "communicatie" + ] }, "variables": [ { @@ -44,7 +57,9 @@ "default": "admin", "required": true, "description": "Wijzig dit na de eerste aanmelding", - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] } diff --git a/apps/grafana/template.json b/apps/grafana/template.json index 4466095..dd89dd8 100644 --- a/apps/grafana/template.json +++ b/apps/grafana/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Grafana", "description": "Visualiseer metrics, logs en traces in aanpasbare dashboards.", - "tags": ["monitoring", "dashboards", "metrics", "visualisatie"], - "icon": {"provider": "selfhst", "id": "grafana"}, - "version": {"name": "latest"} + "tags": [ + "monitoring", + "dashboards", + "metrics", + "visualisatie" + ], + "icon": { + "provider": "selfhst", + "id": "grafana" + }, + "version": { + "name": "latest" + }, + "categories": [ + "monitoring" + ] }, "variables": [ { @@ -51,7 +64,9 @@ "default": "admin", "required": true, "description": "Wijzig dit na de eerste aanmelding", - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] } diff --git a/apps/grocy/template.json b/apps/grocy/template.json index 0eb601e..f486ce3 100644 --- a/apps/grocy/template.json +++ b/apps/grocy/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "gezin" + ] }, "variables": [ { diff --git a/apps/hedgedoc/template.json b/apps/hedgedoc/template.json index 14434b7..e4eba68 100644 --- a/apps/hedgedoc/template.json +++ b/apps/hedgedoc/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "documenten", + "productiviteit" + ] }, "variables": [ { diff --git a/apps/home-assistant/template.json b/apps/home-assistant/template.json index a099c82..d09d334 100644 --- a/apps/home-assistant/template.json +++ b/apps/home-assistant/template.json @@ -3,9 +3,21 @@ "metadata": { "name": "Home Assistant", "description": "Open-source domotica platform voor het automatiseren van je slimme huis.", - "tags": ["domotica", "smart-home", "automatisering"], - "icon": {"provider": "selfhst", "id": "home-assistant"}, - "version": {"name": "stable"} + "tags": [ + "domotica", + "smart-home", + "automatisering" + ], + "icon": { + "provider": "selfhst", + "id": "home-assistant" + }, + "version": { + "name": "stable" + }, + "categories": [ + "domotica" + ] }, "variables": [ { diff --git a/apps/homeassistant-mcp/template.json b/apps/homeassistant-mcp/template.json index b885722..205342a 100644 --- a/apps/homeassistant-mcp/template.json +++ b/apps/homeassistant-mcp/template.json @@ -3,9 +3,24 @@ "metadata": { "name": "Home Assistant MCP Server", "description": "MCP-server voor Home Assistant. Laat AI-assistenten zoals Claude je slimme apparaten bedienen, automations beheren en statussen opvragen via natuurlijke taal.", - "tags": ["mcp", "ai", "home-assistant", "smarthome", "claude"], - "icon": {"provider": "selfhst", "id": "home-assistant"}, - "version": {"name": "latest"} + "tags": [ + "mcp", + "ai", + "home-assistant", + "smarthome", + "claude" + ], + "icon": { + "provider": "selfhst", + "id": "home-assistant" + }, + "version": { + "name": "latest" + }, + "categories": [ + "domotica", + "ai" + ] }, "variables": [ { @@ -45,7 +60,9 @@ "default": "http://homeassistant:8123", "required": true, "description": "URL van je Home Assistant instantie", - "config": {"placeholder": "http://192.168.1.x:8123"} + "config": { + "placeholder": "http://192.168.1.x:8123" + } }, { "name": "hass_token", @@ -54,7 +71,9 @@ "default": "", "required": true, "description": "Maak een token aan via Home Assistant → Profiel → Lange termijn toegangstokens (onderaan de pagina)", - "config": {"placeholder": "eyJ..."} + "config": { + "placeholder": "eyJ..." + } } ] } diff --git a/apps/homebridge/template.json b/apps/homebridge/template.json index 8f7d5e7..90e8a35 100644 --- a/apps/homebridge/template.json +++ b/apps/homebridge/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "domotica" + ] }, "variables": [ { diff --git a/apps/homepage/template.json b/apps/homepage/template.json index bef6048..14f1715 100644 --- a/apps/homepage/template.json +++ b/apps/homepage/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "beheer" + ] }, "variables": [ { diff --git a/apps/immich/template.json b/apps/immich/template.json index 892e659..a386079 100644 --- a/apps/immich/template.json +++ b/apps/immich/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "release" - } + }, + "categories": [ + "fotos", + "opslag" + ] }, "variables": [ { diff --git a/apps/influxdb/template.json b/apps/influxdb/template.json index 41500db..90ed6f0 100644 --- a/apps/influxdb/template.json +++ b/apps/influxdb/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "2" - } + }, + "categories": [ + "monitoring", + "ontwikkeling" + ] }, "variables": [ { diff --git a/apps/it-tools/template.json b/apps/it-tools/template.json index 64311ea..ce2adb1 100644 --- a/apps/it-tools/template.json +++ b/apps/it-tools/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "IT-Tools", "description": "Verzameling handige online tools voor developers: encoding, hashing, formattering, converters en meer.", - "tags": ["tools", "developer", "utilities", "encoding"], - "icon": {"provider": "selfhst", "id": "it-tools"}, - "version": {"name": "latest"} + "tags": [ + "tools", + "developer", + "utilities", + "encoding" + ], + "icon": { + "provider": "selfhst", + "id": "it-tools" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ontwikkeling" + ] }, "variables": [ { diff --git a/apps/jellyfin/template.json b/apps/jellyfin/template.json index 5bcb16d..b8482ec 100644 --- a/apps/jellyfin/template.json +++ b/apps/jellyfin/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Jellyfin", "description": "Gratis en open-source mediaserver voor films, series en muziek. Geen abonnement.", - "tags": ["media", "streaming", "films", "muziek"], - "icon": {"provider": "selfhst", "id": "jellyfin"}, - "version": {"name": "latest"} + "tags": [ + "media", + "streaming", + "films", + "muziek" + ], + "icon": { + "provider": "selfhst", + "id": "jellyfin" + }, + "version": { + "name": "latest" + }, + "categories": [ + "media" + ] }, "variables": [ { diff --git a/apps/jellyseerr/template.json b/apps/jellyseerr/template.json index 31e516e..1226c06 100644 --- a/apps/jellyseerr/template.json +++ b/apps/jellyseerr/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "media" + ] }, "variables": [ { diff --git a/apps/karakeep/template.json b/apps/karakeep/template.json index a61649b..ad850cd 100644 --- a/apps/karakeep/template.json +++ b/apps/karakeep/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "release" - } + }, + "categories": [ + "documenten" + ] }, "variables": [ { diff --git a/apps/kavita/template.json b/apps/kavita/template.json index 901b30e..cfbaae9 100644 --- a/apps/kavita/template.json +++ b/apps/kavita/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "media", + "documenten" + ] }, "variables": [ { diff --git a/apps/keycloak/template.json b/apps/keycloak/template.json index 2ad4b96..11b11da 100644 --- a/apps/keycloak/template.json +++ b/apps/keycloak/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "beveiliging" + ] }, "variables": [ { diff --git a/apps/kimai/template.json b/apps/kimai/template.json index eb029f6..7059562 100644 --- a/apps/kimai/template.json +++ b/apps/kimai/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "apache" - } + }, + "categories": [ + "productiviteit", + "financien" + ] }, "variables": [ { diff --git a/apps/komga/template.json b/apps/komga/template.json index c3425aa..be65e33 100644 --- a/apps/komga/template.json +++ b/apps/komga/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "media" + ] }, "variables": [ { diff --git a/apps/kopia/template.json b/apps/kopia/template.json index 8af9d6c..8b1163f 100644 --- a/apps/kopia/template.json +++ b/apps/kopia/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "opslag" + ] }, "variables": [ { diff --git a/apps/languagetool/template.json b/apps/languagetool/template.json index 52ea543..f8c6562 100644 --- a/apps/languagetool/template.json +++ b/apps/languagetool/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "productiviteit", + "documenten" + ] }, "variables": [ { diff --git a/apps/linkding/template.json b/apps/linkding/template.json index 52b5d57..fc804c0 100644 --- a/apps/linkding/template.json +++ b/apps/linkding/template.json @@ -3,9 +3,21 @@ "metadata": { "name": "Linkding", "description": "Eenvoudige zelfgehoste bladwijzerbeheerder met tags, zoekfunctie en browserextensie.", - "tags": ["bladwijzers", "links", "productiviteit"], - "icon": {"provider": "selfhst", "id": "linkding"}, - "version": {"name": "latest"} + "tags": [ + "bladwijzers", + "links", + "productiviteit" + ], + "icon": { + "provider": "selfhst", + "id": "linkding" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten" + ] }, "variables": [ { @@ -50,7 +62,9 @@ "title": "Admin wachtwoord", "default": "", "required": true, - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] } diff --git a/apps/mealie/template.json b/apps/mealie/template.json index ce53e49..4e5a9cd 100644 --- a/apps/mealie/template.json +++ b/apps/mealie/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Mealie", "description": "Receptenbeheer met maaltijdplanning, boodschappenlijsten en automatisch importeren van recepten.", - "tags": ["recepten", "koken", "maaltijdplanning", "voedsel"], - "icon": {"provider": "selfhst", "id": "mealie"}, - "version": {"name": "latest"} + "tags": [ + "recepten", + "koken", + "maaltijdplanning", + "voedsel" + ], + "icon": { + "provider": "selfhst", + "id": "mealie" + }, + "version": { + "name": "latest" + }, + "categories": [ + "gezin" + ] }, "variables": [ { diff --git a/apps/memos/template.json b/apps/memos/template.json index a8f33a2..570d3e1 100644 --- a/apps/memos/template.json +++ b/apps/memos/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "stable" - } + }, + "categories": [ + "documenten", + "productiviteit" + ] }, "variables": [ { diff --git a/apps/metabase/template.json b/apps/metabase/template.json index f2b739c..b89f7bf 100644 --- a/apps/metabase/template.json +++ b/apps/metabase/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "monitoring", + "ontwikkeling" + ] }, "variables": [ { diff --git a/apps/metube/template.json b/apps/metube/template.json index 3d68955..be5e2e4 100644 --- a/apps/metube/template.json +++ b/apps/metube/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "media", + "downloaden" + ] }, "variables": [ { diff --git a/apps/miniflux/template.json b/apps/miniflux/template.json index 3c0802c..0a027ac 100644 --- a/apps/miniflux/template.json +++ b/apps/miniflux/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Miniflux", "description": "Minimalistische en snelle RSS-lezer, zelfgehost met een opgeruimde interface.", - "tags": ["rss", "nieuws", "lezer", "feeds"], - "icon": {"provider": "selfhst", "id": "miniflux"}, - "version": {"name": "latest"} + "tags": [ + "rss", + "nieuws", + "lezer", + "feeds" + ], + "icon": { + "provider": "selfhst", + "id": "miniflux" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten" + ] }, "variables": [ { @@ -50,7 +63,9 @@ "title": "Admin wachtwoord", "default": "", "required": true, - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] }, @@ -63,7 +78,9 @@ "title": "Database wachtwoord", "default": "miniflux_db_pass", "required": true, - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] } diff --git a/apps/mosquitto/template.json b/apps/mosquitto/template.json index 9644f16..8af4263 100644 --- a/apps/mosquitto/template.json +++ b/apps/mosquitto/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "2" - } + }, + "categories": [ + "domotica", + "netwerk" + ] }, "variables": [ { diff --git a/apps/n8n/template.json b/apps/n8n/template.json index 3361263..de56886 100644 --- a/apps/n8n/template.json +++ b/apps/n8n/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "n8n", "description": "No-code/low-code workflow automatisering. Zapier-alternatief met 400+ integraties.", - "tags": ["automatisering", "workflow", "integratie"], - "icon": {"provider": "selfhst", "id": "n8n"}, - "version": {"name": "latest"} + "tags": [ + "automatisering", + "workflow", + "integratie" + ], + "icon": { + "provider": "selfhst", + "id": "n8n" + }, + "version": { + "name": "latest" + }, + "categories": [ + "productiviteit", + "ontwikkeling" + ] }, "variables": [ { @@ -51,7 +64,9 @@ "default": "localhost", "required": false, "description": "Hostname of IP van je server voor webhook-URLs. Gebruik je domeinnaam als je een reverse proxy hebt.", - "config": {"placeholder": "mijn-server.nl"} + "config": { + "placeholder": "mijn-server.nl" + } } ] } diff --git a/apps/navidrome/template.json b/apps/navidrome/template.json index 4a634f6..b3ee073 100644 --- a/apps/navidrome/template.json +++ b/apps/navidrome/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "media" + ] }, "variables": [ { diff --git a/apps/netdata/template.json b/apps/netdata/template.json index 42f7c5e..c16e5fd 100644 --- a/apps/netdata/template.json +++ b/apps/netdata/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "stable" - } + }, + "categories": [ + "monitoring" + ] }, "variables": [ { diff --git a/apps/nextcloud-aio/template.json b/apps/nextcloud-aio/template.json index 51f1492..ca01dfa 100644 --- a/apps/nextcloud-aio/template.json +++ b/apps/nextcloud-aio/template.json @@ -3,9 +3,23 @@ "metadata": { "name": "Nextcloud AIO", "description": "Nextcloud All-in-One: één container beheert automatisch alle Nextcloud-componenten.", - "tags": ["bestanden", "cloud", "productiviteit", "samenwerken"], - "icon": {"provider": "selfhst", "id": "nextcloud"}, - "version": {"name": "latest"} + "tags": [ + "bestanden", + "cloud", + "productiviteit", + "samenwerken" + ], + "icon": { + "provider": "selfhst", + "id": "nextcloud" + }, + "version": { + "name": "latest" + }, + "categories": [ + "opslag", + "documenten" + ] }, "variables": [ { diff --git a/apps/nginx-proxy-manager/template.json b/apps/nginx-proxy-manager/template.json index 0493aaf..9b993da 100644 --- a/apps/nginx-proxy-manager/template.json +++ b/apps/nginx-proxy-manager/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Nginx Proxy Manager", "description": "Reverse proxy met automatische SSL-certificaten en eenvoudige webinterface", - "tags": ["proxy", "ssl", "netwerk"], - "icon": {"provider": "selfhst", "id": "nginx-proxy-manager"}, - "version": {"name": "latest"} + "tags": [ + "proxy", + "ssl", + "netwerk" + ], + "icon": { + "provider": "selfhst", + "id": "nginx-proxy-manager" + }, + "version": { + "name": "latest" + }, + "categories": [ + "netwerk", + "beheer" + ] }, "variables": [ { diff --git a/apps/nocodb/template.json b/apps/nocodb/template.json index af57740..1abd31d 100644 --- a/apps/nocodb/template.json +++ b/apps/nocodb/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "ontwikkeling", + "productiviteit" + ] }, "variables": [ { diff --git a/apps/node-red/template.json b/apps/node-red/template.json index 8ad2373..6104b0a 100644 --- a/apps/node-red/template.json +++ b/apps/node-red/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "domotica", + "productiviteit" + ] }, "variables": [ { diff --git a/apps/ntfy/template.json b/apps/ntfy/template.json index f0efcb1..39d7dce 100644 --- a/apps/ntfy/template.json +++ b/apps/ntfy/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "communicatie" + ] }, "variables": [ { diff --git a/apps/octoprint/template.json b/apps/octoprint/template.json index 88ebba3..ff772fb 100644 --- a/apps/octoprint/template.json +++ b/apps/octoprint/template.json @@ -13,7 +13,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "3d-printen" + ] }, "variables": [ { diff --git a/apps/ollama/template.json b/apps/ollama/template.json index d9682c7..a05205c 100644 --- a/apps/ollama/template.json +++ b/apps/ollama/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "ai" + ] }, "variables": [ { diff --git a/apps/open-webui/template.json b/apps/open-webui/template.json index f075d52..47272d5 100644 --- a/apps/open-webui/template.json +++ b/apps/open-webui/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "main" - } + }, + "categories": [ + "ai" + ] }, "variables": [ { diff --git a/apps/owntracks/template.json b/apps/owntracks/template.json index ba6b6f4..e7aeff7 100644 --- a/apps/owntracks/template.json +++ b/apps/owntracks/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "gezin", + "beveiliging" + ] }, "variables": [ { diff --git a/apps/paperless-ngx/template.json b/apps/paperless-ngx/template.json index be4fb97..4edf41a 100644 --- a/apps/paperless-ngx/template.json +++ b/apps/paperless-ngx/template.json @@ -3,9 +3,23 @@ "metadata": { "name": "Paperless-ngx", "description": "Digitaal documentbeheer met OCR, slimme tags en zoekfunctie.", - "tags": ["documenten", "ocr", "archief", "productiviteit"], - "icon": {"provider": "selfhst", "id": "paperless-ngx"}, - "version": {"name": "latest"} + "tags": [ + "documenten", + "ocr", + "archief", + "productiviteit" + ], + "icon": { + "provider": "selfhst", + "id": "paperless-ngx" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten", + "opslag" + ] }, "variables": [ { @@ -51,7 +65,9 @@ "default": "", "required": true, "description": "Willekeurige lange string voor sessiebeveiliging", - "config": {"placeholder": "minimaal-50-willekeurige-tekens"} + "config": { + "placeholder": "minimaal-50-willekeurige-tekens" + } }, { "name": "db_password", @@ -59,7 +75,9 @@ "title": "Database wachtwoord", "default": "paperless_db_pass", "required": true, - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] }, diff --git a/apps/photoprism/template.json b/apps/photoprism/template.json index 0d38924..1639cd1 100644 --- a/apps/photoprism/template.json +++ b/apps/photoprism/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "fotos" + ] }, "variables": [ { diff --git a/apps/pihole/template.json b/apps/pihole/template.json index 93d4bf5..84740af 100644 --- a/apps/pihole/template.json +++ b/apps/pihole/template.json @@ -3,9 +3,23 @@ "metadata": { "name": "Pi-hole", "description": "DNS-gebaseerde advertentie- en trackerblokkering voor je hele thuisnetwerk.", - "tags": ["dns", "adblock", "privacy", "netwerk"], - "icon": {"provider": "selfhst", "id": "pi-hole"}, - "version": {"name": "latest"} + "tags": [ + "dns", + "adblock", + "privacy", + "netwerk" + ], + "icon": { + "provider": "selfhst", + "id": "pi-hole" + }, + "version": { + "name": "latest" + }, + "categories": [ + "netwerk", + "beveiliging" + ] }, "variables": [ { @@ -59,7 +73,9 @@ "default": "", "required": true, "description": "Wachtwoord voor het Pi-hole webpaneel", - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] } diff --git a/apps/pinchflat/template.json b/apps/pinchflat/template.json index 88f31d3..b3191db 100644 --- a/apps/pinchflat/template.json +++ b/apps/pinchflat/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "media", + "downloaden" + ] }, "variables": [ { diff --git a/apps/planka/template.json b/apps/planka/template.json index 9c4ca43..932d396 100644 --- a/apps/planka/template.json +++ b/apps/planka/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "1" - } + }, + "categories": [ + "productiviteit" + ] }, "variables": [ { diff --git a/apps/plex/template.json b/apps/plex/template.json index 558ea25..a88adbb 100644 --- a/apps/plex/template.json +++ b/apps/plex/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Plex", "description": "Populaire mediaserver voor films, series, muziek en foto's met apps voor alle platforms.", - "tags": ["media", "streaming", "films", "muziek"], - "icon": {"provider": "selfhst", "id": "plex"}, - "version": {"name": "latest"} + "tags": [ + "media", + "streaming", + "films", + "muziek" + ], + "icon": { + "provider": "selfhst", + "id": "plex" + }, + "version": { + "name": "latest" + }, + "categories": [ + "media" + ] }, "variables": [ { @@ -86,7 +99,9 @@ "default": "", "required": false, "description": "Haal op via plex.tv/claim om de server direct aan je account te koppelen. Verlopen na 4 minuten.", - "config": {"placeholder": "claim-xxxxxxxxxxxxxxxxxxxx"} + "config": { + "placeholder": "claim-xxxxxxxxxxxxxxxxxxxx" + } } ] } diff --git a/apps/portainer/template.json b/apps/portainer/template.json index 252db56..072a3e5 100644 --- a/apps/portainer/template.json +++ b/apps/portainer/template.json @@ -3,9 +3,21 @@ "metadata": { "name": "Portainer CE", "description": "Webgebaseerde Docker-beheerinterface voor containers, images, volumes en netwerken.", - "tags": ["docker", "beheer", "containers"], - "icon": {"provider": "selfhst", "id": "portainer"}, - "version": {"name": "latest"} + "tags": [ + "docker", + "beheer", + "containers" + ], + "icon": { + "provider": "selfhst", + "id": "portainer" + }, + "version": { + "name": "latest" + }, + "categories": [ + "beheer" + ] }, "variables": [ { diff --git a/apps/prometheus/template.json b/apps/prometheus/template.json index 0ff159c..f7f9edf 100644 --- a/apps/prometheus/template.json +++ b/apps/prometheus/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "monitoring" + ] }, "variables": [ { diff --git a/apps/qbittorrent/template.json b/apps/qbittorrent/template.json index e8e544d..9f7a4b8 100644 --- a/apps/qbittorrent/template.json +++ b/apps/qbittorrent/template.json @@ -3,9 +3,21 @@ "metadata": { "name": "qBittorrent", "description": "Open-source torrent-client met webinterface. Werkt goed samen met de ARR-stack.", - "tags": ["downloaden", "torrents", "media"], - "icon": {"provider": "selfhst", "id": "qbittorrent"}, - "version": {"name": "latest"} + "tags": [ + "downloaden", + "torrents", + "media" + ], + "icon": { + "provider": "selfhst", + "id": "qbittorrent" + }, + "version": { + "name": "latest" + }, + "categories": [ + "downloaden" + ] }, "variables": [ { diff --git a/apps/sabnzbd/template.json b/apps/sabnzbd/template.json index fde1301..b5dc46e 100644 --- a/apps/sabnzbd/template.json +++ b/apps/sabnzbd/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "SABnzbd", "description": "Usenet download-client met webinterface. Werkt samen met de ARR-stack voor automatisch downloaden via Usenet.", - "tags": ["downloaden", "usenet", "nzb", "media"], - "icon": {"provider": "selfhst", "id": "sabnzbd"}, - "version": {"name": "latest"} + "tags": [ + "downloaden", + "usenet", + "nzb", + "media" + ], + "icon": { + "provider": "selfhst", + "id": "sabnzbd" + }, + "version": { + "name": "latest" + }, + "categories": [ + "downloaden" + ] }, "variables": [ { diff --git a/apps/scrypted/template.json b/apps/scrypted/template.json index 773cc67..b5f0990 100644 --- a/apps/scrypted/template.json +++ b/apps/scrypted/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "domotica", + "media" + ] }, "variables": [ { diff --git a/apps/searxng/template.json b/apps/searxng/template.json index 4281f8e..f611460 100644 --- a/apps/searxng/template.json +++ b/apps/searxng/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "netwerk", + "beveiliging" + ] }, "variables": [ { diff --git a/apps/shlink/template.json b/apps/shlink/template.json index 829537a..af019ba 100644 --- a/apps/shlink/template.json +++ b/apps/shlink/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "stable" - } + }, + "categories": [ + "netwerk", + "ontwikkeling" + ] }, "variables": [ { diff --git a/apps/speedtest-tracker/template.json b/apps/speedtest-tracker/template.json index cedc133..b49b92f 100644 --- a/apps/speedtest-tracker/template.json +++ b/apps/speedtest-tracker/template.json @@ -3,9 +3,23 @@ "metadata": { "name": "Speedtest Tracker", "description": "Automatische internetsnelheidsmetingen met historische grafieken en statistieken.", - "tags": ["netwerk", "monitoring", "internet", "statistieken"], - "icon": {"provider": "selfhst", "id": "speedtest-tracker"}, - "version": {"name": "latest"} + "tags": [ + "netwerk", + "monitoring", + "internet", + "statistieken" + ], + "icon": { + "provider": "selfhst", + "id": "speedtest-tracker" + }, + "version": { + "name": "latest" + }, + "categories": [ + "netwerk", + "monitoring" + ] }, "variables": [ { @@ -72,7 +86,9 @@ "default": "", "required": true, "description": "Willekeurige 32-tekens encryptiesleutel, bijv. base64:xxxx...", - "config": {"placeholder": "base64:willekeurige-string-van-32-tekens"} + "config": { + "placeholder": "base64:willekeurige-string-van-32-tekens" + } } ] } diff --git a/apps/spoolman/template.json b/apps/spoolman/template.json index 3549b95..21e7756 100644 --- a/apps/spoolman/template.json +++ b/apps/spoolman/template.json @@ -13,7 +13,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "3d-printen" + ] }, "variables": [ { diff --git a/apps/stirling-pdf/template.json b/apps/stirling-pdf/template.json index e06c730..36ce866 100644 --- a/apps/stirling-pdf/template.json +++ b/apps/stirling-pdf/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Stirling PDF", "description": "Web-gebaseerde PDF-tools: samenvoegen, splitsen, omzetten, comprimeren en bewerken.", - "tags": ["pdf", "tools", "documenten", "utilities"], - "icon": {"provider": "selfhst", "id": "stirling-pdf"}, - "version": {"name": "latest"} + "tags": [ + "pdf", + "tools", + "documenten", + "utilities" + ], + "icon": { + "provider": "selfhst", + "id": "stirling-pdf" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten" + ] }, "variables": [ { diff --git a/apps/syncthing/template.json b/apps/syncthing/template.json index de4acf9..d9fe6dd 100644 --- a/apps/syncthing/template.json +++ b/apps/syncthing/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Syncthing", "description": "Gedecentraliseerde bestandssynchronisatie tussen apparaten zonder cloudopslag.", - "tags": ["sync", "bestanden", "backup", "privacy"], - "icon": {"provider": "selfhst", "id": "syncthing"}, - "version": {"name": "latest"} + "tags": [ + "sync", + "bestanden", + "backup", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "syncthing" + }, + "version": { + "name": "latest" + }, + "categories": [ + "opslag" + ] }, "variables": [ { diff --git a/apps/tandoor/template.json b/apps/tandoor/template.json index 9c906a1..fee7b86 100644 --- a/apps/tandoor/template.json +++ b/apps/tandoor/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "gezin" + ] }, "variables": [ { diff --git a/apps/technitium-dns/template.json b/apps/technitium-dns/template.json index c149dc9..68b501e 100644 --- a/apps/technitium-dns/template.json +++ b/apps/technitium-dns/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "netwerk", + "beveiliging" + ] }, "variables": [ { diff --git a/apps/teslamate/template.json b/apps/teslamate/template.json index 4d83a2b..43bf46a 100644 --- a/apps/teslamate/template.json +++ b/apps/teslamate/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "gezin", + "monitoring" + ] }, "variables": [ { diff --git a/apps/traefik/template.json b/apps/traefik/template.json index d6b84c7..5598928 100644 --- a/apps/traefik/template.json +++ b/apps/traefik/template.json @@ -3,9 +3,23 @@ "metadata": { "name": "Traefik", "description": "Moderne reverse proxy en load balancer met automatische SSL via Let's Encrypt.", - "tags": ["reverse-proxy", "ssl", "netwerk", "loadbalancer"], - "icon": {"provider": "selfhst", "id": "traefik"}, - "version": {"name": "latest"} + "tags": [ + "reverse-proxy", + "ssl", + "netwerk", + "loadbalancer" + ], + "icon": { + "provider": "selfhst", + "id": "traefik" + }, + "version": { + "name": "latest" + }, + "categories": [ + "netwerk", + "beheer" + ] }, "variables": [ { @@ -58,7 +72,9 @@ "default": "", "required": false, "description": "E-mailadres voor Let's Encrypt SSL-certificaten. Laat leeg als je geen HTTPS gebruikt.", - "config": {"placeholder": "jij@voorbeeld.nl"} + "config": { + "placeholder": "jij@voorbeeld.nl" + } } ] } diff --git a/apps/unifi-network/template.json b/apps/unifi-network/template.json index bca8882..0498475 100644 --- a/apps/unifi-network/template.json +++ b/apps/unifi-network/template.json @@ -3,9 +3,23 @@ "metadata": { "name": "Unifi Network Application", "description": "Unifi netwerkconfiguratie en -beheer. Beheert access points, switches en gateways van Ubiquiti.", - "tags": ["netwerk", "unifi", "ubiquiti", "wifi"], - "icon": {"provider": "selfhst", "id": "unifi"}, - "version": {"name": "latest"} + "tags": [ + "netwerk", + "unifi", + "ubiquiti", + "wifi" + ], + "icon": { + "provider": "selfhst", + "id": "unifi" + }, + "version": { + "name": "latest" + }, + "categories": [ + "netwerk", + "beheer" + ] }, "variables": [ { @@ -98,7 +112,9 @@ "default": "unifi_mongo_pass", "required": true, "description": "Wachtwoord voor de interne MongoDB database", - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] } diff --git a/apps/uptime-kuma/template.json b/apps/uptime-kuma/template.json index dd3978b..e8f23c3 100644 --- a/apps/uptime-kuma/template.json +++ b/apps/uptime-kuma/template.json @@ -3,9 +3,21 @@ "metadata": { "name": "Uptime Kuma", "description": "Mooie en eenvoudige uptime-monitor voor al je services en websites.", - "tags": ["monitoring", "uptime", "alerting"], - "icon": {"provider": "selfhst", "id": "uptime-kuma"}, - "version": {"name": "latest"} + "tags": [ + "monitoring", + "uptime", + "alerting" + ], + "icon": { + "provider": "selfhst", + "id": "uptime-kuma" + }, + "version": { + "name": "latest" + }, + "categories": [ + "monitoring" + ] }, "variables": [ { diff --git a/apps/vaultwarden/template.json b/apps/vaultwarden/template.json index c4ffe99..94f40b8 100644 --- a/apps/vaultwarden/template.json +++ b/apps/vaultwarden/template.json @@ -3,9 +3,21 @@ "metadata": { "name": "Vaultwarden", "description": "Lichtgewicht Bitwarden-compatibele wachtwoordkluis. Werkt met alle Bitwarden-apps.", - "tags": ["wachtwoorden", "beveiliging", "privacy"], - "icon": {"provider": "selfhst", "id": "vaultwarden"}, - "version": {"name": "latest"} + "tags": [ + "wachtwoorden", + "beveiliging", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "vaultwarden" + }, + "version": { + "name": "latest" + }, + "categories": [ + "beveiliging" + ] }, "variables": [ { @@ -51,7 +63,9 @@ "default": "", "required": false, "description": "Willekeurige geheime string voor het /admin paneel. Laat leeg om admin uit te schakelen.", - "config": {"placeholder": "willekeurige-geheime-string"} + "config": { + "placeholder": "willekeurige-geheime-string" + } } ] } diff --git a/apps/vikunja/template.json b/apps/vikunja/template.json index 09dcdd8..c6de82a 100644 --- a/apps/vikunja/template.json +++ b/apps/vikunja/template.json @@ -3,9 +3,22 @@ "metadata": { "name": "Vikunja", "description": "Open-source taakbeheer en to-do app met projecten, teams, Kanban en kalenderweergave.", - "tags": ["taken", "productiviteit", "projectbeheer", "todo"], - "icon": {"provider": "selfhst", "id": "vikunja"}, - "version": {"name": "latest"} + "tags": [ + "taken", + "productiviteit", + "projectbeheer", + "todo" + ], + "icon": { + "provider": "selfhst", + "id": "vikunja" + }, + "version": { + "name": "latest" + }, + "categories": [ + "productiviteit" + ] }, "variables": [ { @@ -51,7 +64,9 @@ "default": "", "required": true, "description": "Willekeurige geheime string voor JWT-tokenbeveiliging", - "config": {"placeholder": "willekeurige-lange-string"} + "config": { + "placeholder": "willekeurige-lange-string" + } }, { "name": "db_password", @@ -59,7 +74,9 @@ "title": "Database wachtwoord", "default": "vikunja_db_pass", "required": true, - "config": {"placeholder": "sterk-wachtwoord"} + "config": { + "placeholder": "sterk-wachtwoord" + } } ] } diff --git a/apps/wallabag/template.json b/apps/wallabag/template.json index 79ab782..879608a 100644 --- a/apps/wallabag/template.json +++ b/apps/wallabag/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "documenten" + ] }, "variables": [ { diff --git a/apps/watchtower/template.json b/apps/watchtower/template.json index cde684e..6843431 100644 --- a/apps/watchtower/template.json +++ b/apps/watchtower/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "beheer" + ] }, "variables": [ { diff --git a/apps/wg-easy/template.json b/apps/wg-easy/template.json index 50eaa1e..44c6fdf 100644 --- a/apps/wg-easy/template.json +++ b/apps/wg-easy/template.json @@ -14,7 +14,11 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "netwerk", + "beveiliging" + ] }, "variables": [ { diff --git a/apps/wikijs/template.json b/apps/wikijs/template.json index 05eedcf..75be0e2 100644 --- a/apps/wikijs/template.json +++ b/apps/wikijs/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "2" - } + }, + "categories": [ + "documenten" + ] }, "variables": [ { diff --git a/apps/zigbee2mqtt/template.json b/apps/zigbee2mqtt/template.json index a3817ed..fa8c0bb 100644 --- a/apps/zigbee2mqtt/template.json +++ b/apps/zigbee2mqtt/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "domotica" + ] }, "variables": [ { diff --git a/apps/zwave-js-ui/template.json b/apps/zwave-js-ui/template.json index d8ccc54..728fbcb 100644 --- a/apps/zwave-js-ui/template.json +++ b/apps/zwave-js-ui/template.json @@ -14,7 +14,10 @@ }, "version": { "name": "latest" - } + }, + "categories": [ + "domotica" + ] }, "variables": [ { diff --git a/server-up/app.py b/server-up/app.py index 6f41dfd..2da016a 100644 --- a/server-up/app.py +++ b/server-up/app.py @@ -15,7 +15,8 @@ from flask import Flask, Response, jsonify, render_template, request, session import core as cfg from core import audit, jobs, i18n from core import auth, docker, git, boilerplates, updater -from core import backups, compose_transform, networks, scheduler, selfupdate +from core import backups, categories, compose_transform, networks +from core import scheduler, selfupdate from core import stackupdates from core.modules import Module, CORE, discover @@ -618,6 +619,10 @@ def api_stacks(): "containers": ct, "logo_url": logo_url, "icon": icon, "network": meta.get("network", ""), "ip": meta.get("ip", ""), + # Bij installatie vastgelegd; ontbreekt dat (oudere installatie), + # dan leiden we het alsnog af uit de opgeslagen naam. + "categories": categories.normalize( + meta.get("categories"), meta.get("tags"), meta.get("name", "")), }) return jsonify(out) @@ -1306,6 +1311,8 @@ def api_store_install(): "network": net_name, "ip": net_ip if net else "", "connected": bool(verbinden and gedeeld_net), + "categories": meta.get("categories") or [], + "tags": meta.get("tags") or [], }, ensure_ascii=False, indent=2), encoding="utf-8") except Exception: pass @@ -1502,6 +1509,14 @@ def api_networks(): drivers=list(networks.DRIVERS)) +@app.route("/api/categories") +def api_categories(): + """Categoriedefinities met hun kleur, zodat de interface overal dezelfde + kleur gebruikt voor dezelfde categorie.""" + lang = (request.args.get("lang") or cfg.load().get("LANGUAGE") or "nl")[:5] + return jsonify(categories=categories.all_categories(lang)) + + @app.route("/api/apps/connectable") def api_connectable(): """Ge<0x00ef>nstalleerde apps waar een nieuwe app aan gekoppeld kan worden. diff --git a/server-up/core/boilerplates.py b/server-up/core/boilerplates.py index f849bcf..7754593 100644 --- a/server-up/core/boilerplates.py +++ b/server-up/core/boilerplates.py @@ -56,10 +56,16 @@ def metadata(d: Path) -> dict: icon_url = f"https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/{iid}.png" elif iid and (iid.startswith("http://") or iid.startswith("https://")): icon_url = iid + from core import categories as cat + tags = md.get("tags", []) or [] + beschrijving = md.get("description", "") return { "name": md.get("name") or d.name, - "description": md.get("description", ""), - "tags": md.get("tags", []) or [], + "description": beschrijving, + "tags": tags, + # Expliciet in template.json, anders afgeleid uit de tags. Zo krijgen + # ook apps uit externe repo's een zinnige indeling. + "categories": cat.normalize(md.get("categories"), tags, beschrijving), "logo_url": icon_url, "version": (md.get("version") or {}).get("name", ""), "kind": t.get("kind", "compose"), diff --git a/server-up/core/categories.py b/server-up/core/categories.py new file mode 100644 index 0000000..4312416 --- /dev/null +++ b/server-up/core/categories.py @@ -0,0 +1,106 @@ +"""Categorieën voor apps, met een kleur per categorie. + +Een app hoort bij één of meer categorieën. Ze staan in `template.json` onder +`metadata.categories`; ontbreken ze — bijvoorbeeld bij een externe repo als de +ChristianLempa-boilerplates — dan worden ze afgeleid uit de tags. + +De kleuren zijn middentonen die zowel op een lichte als op een donkere +achtergrond leesbaar blijven. De interface gebruikt ze als tekstkleur op een +doorzichtige variant van dezelfde kleur. +""" +from __future__ import annotations + +# id → (naam NL, naam EN, kleur, mdi-icoon) +CATEGORIES: dict[str, dict] = { + "media": {"nl": "Media", "en": "Media", "color": "#8b5cf6", "icon": "mdi-play-circle-outline"}, + "fotos": {"nl": "Foto's", "en": "Photos", "color": "#ec4899", "icon": "mdi-image-multiple-outline"}, + "downloaden": {"nl": "Downloaden", "en": "Downloads", "color": "#84cc16", "icon": "mdi-download-outline"}, + "domotica": {"nl": "Domotica", "en": "Home automation", "color": "#22c55e", "icon": "mdi-home-automation"}, + "3d-printen": {"nl": "3D-printen", "en": "3D printing", "color": "#14b8a6", "icon": "mdi-printer-3d-nozzle-outline"}, + "netwerk": {"nl": "Netwerk", "en": "Network", "color": "#3b82f6", "icon": "mdi-lan"}, + "beveiliging": {"nl": "Beveiliging", "en": "Security", "color": "#ef4444", "icon": "mdi-shield-lock-outline"}, + "opslag": {"nl": "Opslag & backup", "en": "Storage & backup", "color": "#f59e0b", "icon": "mdi-harddisk"}, + "documenten": {"nl": "Documenten", "en": "Documents", "color": "#0891b2", "icon": "mdi-file-document-outline"}, + "productiviteit": {"nl": "Productiviteit", "en": "Productivity", "color": "#6366f1", "icon": "mdi-checkbox-marked-outline"}, + "communicatie": {"nl": "Communicatie", "en": "Communication", "color": "#0ea5e9", "icon": "mdi-message-outline"}, + "financien": {"nl": "Financiën", "en": "Finance", "color": "#10b981", "icon": "mdi-cash-multiple"}, + "gezin": {"nl": "Gezin & huishouden", "en": "Family & home", "color": "#f472b6", "icon": "mdi-home-heart"}, + "monitoring": {"nl": "Monitoring", "en": "Monitoring", "color": "#f97316", "icon": "mdi-chart-line"}, + "ontwikkeling": {"nl": "Ontwikkeling", "en": "Development", "color": "#06b6d4", "icon": "mdi-code-braces"}, + "ai": {"nl": "AI", "en": "AI", "color": "#a855f7", "icon": "mdi-brain"}, + "beheer": {"nl": "Systeembeheer", "en": "System management", "color": "#64748b", "icon": "mdi-cog-outline"}, + "overig": {"nl": "Overig", "en": "Other", "color": "#94a3b8", "icon": "mdi-shape-outline"}, +} + +DEFAULT = "overig" + +# Trefwoorden in tags of omschrijving → categorie. Wordt alleen gebruikt als een +# template zelf geen categorieën opgeeft, zoals bij externe repo's. +_TREFWOORDEN: list[tuple[tuple[str, ...], str]] = [ + (("film", "serie", "media", "muziek", "video", "streaming", "luisterboek", + "podcast", "strips", "manga", "boeken", "ebooks", "verzoeken"), "media"), + (("foto", "fotos", "photos"), "fotos"), + (("download", "torrent", "usenet", "nzb"), "downloaden"), + (("domotica", "smart-home", "zigbee", "zwave", "mqtt", "esp32", "homekit", + "automatisering", "camera", "nvr"), "domotica"), + (("3d-printen", "bambu-lab", "printerbeheer"), "3d-printen"), + (("netwerk", "dns", "vpn", "proxy", "https", "links", "web"), "netwerk"), + (("beveiliging", "wachtwoorden", "sso", "authenticatie", "oidc", "privacy"), "beveiliging"), + (("backup", "opslag", "bestanden", "sync", "archief", "versleuteling"), "opslag"), + (("documentatie", "wiki", "kennis", "documenten", "pdf", "notities", + "markdown", "lezen", "artikelen", "bladwijzers", "rss", "nieuws"), "documenten"), + (("productiviteit", "taken", "projecten", "kanban", "uren", "planning", + "schrijven", "samenwerken", "tekenen", "diagram"), "productiviteit"), + (("meldingen", "push", "chat", "communicatie", "e-mail"), "communicatie"), + (("financien", "budget", "administratie"), "financien"), + (("gezin", "huishouden", "recepten", "voorraad", "gezondheid", "logboek"), "gezin"), + (("monitoring", "metrics", "systeem", "dashboard", "statistiek", + "realtime", "rapportage"), "monitoring"), + (("git", "ontwikkelaar", "code", "ci", "database", "spreadsheet", + "no-code", "encoding"), "ontwikkeling"), + (("ai", "llm", "machine-learning"), "ai"), + (("beheer", "docker", "containers", "updates", "onderhoud", + "infrastructuur", "startpagina", "overzicht"), "beheer"), +] + + +def all_categories(lang: str = "nl") -> list[dict]: + """Alle categorieën, in de vaste volgorde van CATEGORIES.""" + return [{"id": cid, "name": c.get(lang) or c["nl"], + "color": c["color"], "icon": c["icon"]} + for cid, c in CATEGORIES.items()] + + +def derive(tags, description: str = "") -> list[str]: + """Leid categorieën af uit tags en omschrijving. + + Voor apps uit externe repo's die zelf geen categorieën opgeven. + """ + hooi = " ".join(str(t).lower() for t in (tags or [])) + hooi += " " + (description or "").lower() + gevonden: list[str] = [] + for woorden, cat in _TREFWOORDEN: + if cat in gevonden: + continue + if any(w in hooi for w in woorden): + gevonden.append(cat) + return gevonden[:3] or [DEFAULT] + + +def normalize(waarde, tags=None, description: str = "") -> list[str]: + """Maak er een geldige, ontdubbelde lijst categorie-ids van.""" + uit: list[str] = [] + for c in (waarde or []): + c = str(c).strip().lower() + if c in CATEGORIES and c not in uit: + uit.append(c) + return uit or derive(tags, description) + + +def color(cid: str) -> str: + return CATEGORIES.get(cid, CATEGORIES[DEFAULT])["color"] + + +def name(cid: str, lang: str = "nl") -> str: + c = CATEGORIES.get(cid, CATEGORIES[DEFAULT]) + return c.get(lang) or c["nl"] diff --git a/server-up/templates/index.html b/server-up/templates/index.html index 0678d19..8f45653 100644 --- a/server-up/templates/index.html +++ b/server-up/templates/index.html @@ -256,9 +256,27 @@ tailwind.config = { Updates controleren + + +
+ + +