luci-app-appflow-icons
Optional, separately-installable brand icon pack for
luci-app-appflow. See parent docs/DESIGN.md section 9 for
the roadmap item and rationale this package implements.
What it is
luci-app-appflow identifies per-application traffic using the Netify Agent
(netifyd) and, on its own, renders every detected application as a
letter-tile avatar colored by category. This package adds real icons,
Netflix, YouTube, Spotify, Microsoft, and 97 other recognizable brands, for
the applications netifyd can actually detect, so the dashboard reads more
like a vendor DPI screen and less like a spreadsheet.
It is entirely optional. Installing it changes only how already-detected
traffic is drawn; it adds no detection logic, no new dependency, and no
attack surface beyond static file serving. Removing it drops the dashboard
back to letter-tile avatars, nothing else changes. Core luci-app-appflow
has no package dependency on this pack (LUCI_DEPENDS:= is deliberately
empty); the coupling is runtime-soft in both directions:
- core probes for
appflow-icons/manifest.jsonat render time and falls back cleanly when this package is absent; - this package depends on nothing and does nothing but ship static files,
it breaks nothing if
luci-app-appflowitself is ever removed or updated incompatibly.
That soft coupling is deliberate legal blast-radius isolation: every icon
here is a redrawing of a third party's trademark (see
licenses/TRADEMARKS.md), so if a rights holder
ever objects, this package is delisted or trimmed on its own, core is
untouched either way.
What's in the box
| Applications with an icon | 101 (of 416 in the Netify Agent free signature set) |
| Unique SVG files shipped | 95 (a few app tags share one icon, e.g. WhatsApp and WhatsApp/Call both use the WhatsApp mark) |
| Total SVG payload | 124,590 bytes (~122 KiB) |
| Source: simple-icons (CC0-1.0) | 75 unique files / 78 manifest entries |
| Source: dashboard-icons (Apache-2.0) | 20 unique files / 23 manifest entries |
simple-icons was preferred whenever both catalogs had a valid match, since
its CC0-1.0 collection license is unambiguous; dashboard-icons filled the
remainder. See licenses/LICENSE.simple-icons
and licenses/LICENSE.dashboard-icons for
the full license text and per-source scope notes, and
licenses/TRADEMARKS.md for why a permissive
collection license is not the same thing as a trademark clearance.
Layout
icons/
├── Makefile # LuCI feed style, PKGARCH:=all, no deps
├── README.md # this file
├── CHECKSUMS.sha256 # sha256 of every shipped svg + manifest.json
├── licenses/
│ ├── LICENSE.simple-icons # CC0-1.0 + source URL + scope note
│ ├── LICENSE.dashboard-icons # Apache-2.0 + source URL + scope note
│ └── TRADEMARKS.md # nominative-use rationale + takedown note
└── root/www/luci-static/resources/appflow-icons/
├── manifest.json # {"<netify tag>": {"file": "<svg>", "source": "..."}}
└── svg/ # 95 SVG files, source__slug.svg naming
root/ mirrors the LuCI feed convention used by the parent package
(include $(TOPDIR)/feeds/luci/luci.mk copies its contents verbatim onto
the target filesystem), landing everything under
/www/luci-static/resources/appflow-icons/ on the router, a normal LuCI
static-resource path, servable and cacheable exactly like any other
luci-static asset, no server-side code involved.
manifest.json contract
manifest.json is keyed by the exact application tag string netifyd's
definitions event reports (the same string luci-app-appflow's frontend
already receives at runtime, e.g. "netify.netflix" for Netify's own
namespaced app ids, or a plain tag like "Spotify" for nDPI protocol-space
ids, see parent docs/DESIGN.md section 2.3 for the two id spaces). Each
value names the icon file relative to svg/ and which collection it came
from:
{
"netify.netflix": { "file": "simple-icons__netflix.svg", "source": "simple-icons" },
"Skype/Teams/Call": { "file": "dashboard-icons__skype.svg", "source": "dashboard-icons" }
}
A consumer only needs to look up the detected tag in this object; a miss means "no icon shipped for this app," which is the expected, common case (315 of 416 detectable applications have none) and should fall back to a letter-tile avatar exactly as when this package isn't installed at all.
Regenerating / extending this pack
The id-to-icon mapping was curated offline against a definitions event
captured from Netify Agent 4.4.7 (416 applications), matched by exact/
normalized name against the simple-icons and dashboard-icons slug catalogs,
with no fuzzy or guessed matches, anything ambiguous (15 applications) was
left out rather than auto-picked, and only the ~100 most household-
recognizable matches ("tier1") were selected for actual SVG download and
inclusion in this package; the remainder of the matched set ("tier2", 73
applications) was identified but not bundled. manifest.json in this
package is the tier1-only, validated output of that pass: every entry here
was checked at build time to (a) reference an SVG file that exists on disk
and parses as well-formed XML with an <svg> root, and (b) use a tag that
is actually present in the current detectable-apps extraction, anything
failing either check is dropped rather than shipped. To extend coverage
(add tier2 apps, or re-run against a newer netifyd's signature set), repeat
that curation pass and re-run the same validation before regenerating
manifest.json and CHECKSUMS.sha256.
Verifying the shipped files
cd icons
sha256sum -c CHECKSUMS.sha256