import { BUNDLED_DOCKER_ICON_IDS, DOCKER_ICON_FILES } from './dockerIconBundled'; const IMAGE_ICON_RULES: Array<{ pattern: RegExp; icon: string }> = [ // Service discovery / mesh (specific first) { pattern: /nacos/i, icon: 'nacos' }, { pattern: /polaris/i, icon: 'polaris' }, { pattern: /mosquitto/i, icon: 'mosquitto' }, { pattern: /kong/i, icon: 'kong' }, { pattern: /istio/i, icon: 'istio' }, { pattern: /linkerd/i, icon: 'linkerd' }, { pattern: /cilium/i, icon: 'cilium' }, { pattern: /envoy/i, icon: 'envoy' }, // Orchestration / IaC { pattern: /kubernetes|k8s/i, icon: 'kubernetes' }, { pattern: /k3s/i, icon: 'k3s' }, { pattern: /helm/i, icon: 'helm' }, { pattern: /rancher/i, icon: 'rancher' }, { pattern: /argo-?cd|argocd/i, icon: 'argo' }, { pattern: /nomad/i, icon: 'nomad' }, { pattern: /terraform/i, icon: 'terraform' }, { pattern: /ansible/i, icon: 'ansible' }, { pattern: /pulumi/i, icon: 'pulumi' }, { pattern: /packer/i, icon: 'packer' }, { pattern: /containerd/i, icon: 'containerd' }, { pattern: /podman/i, icon: 'podman' }, // Web / proxy { pattern: /nginx/i, icon: 'nginx' }, { pattern: /traefik/i, icon: 'traefik' }, { pattern: /caddy/i, icon: 'caddy' }, { pattern: /apache|httpd/i, icon: 'apache' }, { pattern: /tomcat/i, icon: 'tomcat' }, { pattern: /wordpress/i, icon: 'wordpress' }, { pattern: /ghost/i, icon: 'ghost' }, { pattern: /drupal/i, icon: 'drupal' }, // Language runtimes { pattern: /golang|^go$|^go[-:]/i, icon: 'golang' }, { pattern: /node|nodedotjs/i, icon: 'nodejs' }, { pattern: /python/i, icon: 'python' }, { pattern: /temurin|corretto|azul|openjdk|\bjava(?!script)\b/i, icon: 'openjdk' }, { pattern: /springboot|spring-boot|spring/i, icon: 'springboot' }, { pattern: /rust/i, icon: 'rust' }, { pattern: /deno/i, icon: 'deno' }, { pattern: /php(?!myadmin)/i, icon: 'php' }, { pattern: /ruby/i, icon: 'ruby' }, // Databases { pattern: /postgres|postgresql/i, icon: 'postgresql' }, { pattern: /mariadb|galera|percona/i, icon: 'mariadb' }, { pattern: /mysql/i, icon: 'mysql' }, { pattern: /mongo/i, icon: 'mongodb' }, { pattern: /valkey/i, icon: 'valkey' }, { pattern: /dragonfly/i, icon: 'dragonfly' }, { pattern: /redis/i, icon: 'redis' }, { pattern: /memcached/i, icon: 'memcached' }, { pattern: /clickhouse/i, icon: 'clickhouse' }, { pattern: /cockroach/i, icon: 'cockroachdb' }, { pattern: /neo4j/i, icon: 'neo4j' }, { pattern: /cassandra/i, icon: 'cassandra' }, { pattern: /couchdb/i, icon: 'couchdb' }, { pattern: /couchbase/i, icon: 'couchbase' }, { pattern: /arangodb/i, icon: 'arangodb' }, { pattern: /tidb/i, icon: 'tidb' }, { pattern: /vitess/i, icon: 'vitess' }, { pattern: /duckdb/i, icon: 'duckdb' }, { pattern: /scylla/i, icon: 'scylladb' }, { pattern: /singlestore/i, icon: 'singlestore' }, { pattern: /trino/i, icon: 'trino' }, { pattern: /presto/i, icon: 'presto' }, { pattern: /influx/i, icon: 'influxdb' }, { pattern: /timescale/i, icon: 'timescaledb' }, { pattern: /snowflake/i, icon: 'snowflake' }, { pattern: /databricks/i, icon: 'databricks' }, // Messaging / streaming { pattern: /rabbitmq/i, icon: 'rabbitmq' }, { pattern: /kafka/i, icon: 'kafka' }, { pattern: /pulsar/i, icon: 'pulsar' }, { pattern: /rocketmq/i, icon: 'rocketmq' }, { pattern: /nats/i, icon: 'nats' }, { pattern: /emqx/i, icon: 'emqx' }, { pattern: /hivemq/i, icon: 'hivemq' }, { pattern: /flink/i, icon: 'flink' }, { pattern: /nifi/i, icon: 'nifi' }, { pattern: /temporal/i, icon: 'temporal' }, // Search / analytics { pattern: /opensearch/i, icon: 'opensearch' }, { pattern: /elasticsearch/i, icon: 'elasticsearch' }, { pattern: /meilisearch/i, icon: 'meilisearch' }, { pattern: /kibana/i, icon: 'kibana' }, { pattern: /logstash/i, icon: 'logstash' }, { pattern: /solr/i, icon: 'solr' }, { pattern: /druid/i, icon: 'druid' }, { pattern: /hadoop/i, icon: 'hadoop' }, { pattern: /hbase/i, icon: 'hbase' }, { pattern: /hive(?!mq)/i, icon: 'hive' }, // Observability { pattern: /grafana/i, icon: 'grafana' }, { pattern: /prometheus/i, icon: 'prometheus' }, { pattern: /victoria(?:metrics)?|vmagent|vmalert/i, icon: 'victoriametrics' }, { pattern: /thanos/i, icon: 'thanos' }, { pattern: /jaeger/i, icon: 'jaeger' }, { pattern: /opentelemetry|otel/i, icon: 'opentelemetry' }, { pattern: /fluent-?bit/i, icon: 'fluentbit' }, { pattern: /fluentd/i, icon: 'fluentd' }, { pattern: /sentry/i, icon: 'sentry' }, { pattern: /datadog/i, icon: 'datadog' }, { pattern: /netdata/i, icon: 'netdata' }, { pattern: /icinga/i, icon: 'icinga' }, { pattern: /sonarqube/i, icon: 'sonarqube' }, // AI / ML { pattern: /ollama/i, icon: 'ollama' }, { pattern: /milvus/i, icon: 'milvus' }, { pattern: /qdrant/i, icon: 'qdrant' }, { pattern: /pytorch/i, icon: 'pytorch' }, { pattern: /tensorflow/i, icon: 'tensorflow' }, // Infra / secrets { pattern: /vaultwarden/i, icon: 'vaultwarden' }, { pattern: /vault/i, icon: 'vault' }, { pattern: /consul/i, icon: 'consul' }, { pattern: /etcd/i, icon: 'etcd' }, { pattern: /zookeeper|zoo-?keeper/i, icon: 'zookeeper' }, { pattern: /portainer/i, icon: 'portainer' }, { pattern: /harbor/i, icon: 'harbor' }, { pattern: /jfrog|artifactory|nexus/i, icon: 'jfrog' }, { pattern: /keycloak/i, icon: 'keycloak' }, { pattern: /authelia/i, icon: 'authelia' }, { pattern: /authentik/i, icon: 'authentik' }, { pattern: /tailscale/i, icon: 'tailscale' }, { pattern: /wireguard/i, icon: 'wireguard' }, { pattern: /cloudflare/i, icon: 'cloudflare' }, // CI/CD & dev tools { pattern: /jenkins/i, icon: 'jenkins' }, { pattern: /gitlab/i, icon: 'gitlab' }, { pattern: /gitea/i, icon: 'gitea' }, { pattern: /forgejo/i, icon: 'forgejo' }, { pattern: /github/i, icon: 'github' }, { pattern: /drone/i, icon: 'drone' }, { pattern: /circleci/i, icon: 'circleci' }, { pattern: /buildkite/i, icon: 'buildkite' }, { pattern: /airflow/i, icon: 'airflow' }, { pattern: /prefect/i, icon: 'prefect' }, { pattern: /spark/i, icon: 'spark' }, // Apps / CMS / collaboration { pattern: /supabase/i, icon: 'supabase' }, { pattern: /strapi/i, icon: 'strapi' }, { pattern: /directus/i, icon: 'directus' }, { pattern: /hasura/i, icon: 'hasura' }, { pattern: /pocketbase/i, icon: 'pocketbase' }, { pattern: /appwrite/i, icon: 'appwrite' }, { pattern: /mattermost/i, icon: 'mattermost' }, { pattern: /jitsi/i, icon: 'jitsi' }, { pattern: /matrix|synapse|element/i, icon: 'matrix' }, { pattern: /metabase/i, icon: 'metabase' }, { pattern: /superset/i, icon: 'superset' }, { pattern: /airbyte/i, icon: 'airbyte' }, { pattern: /bookstack/i, icon: 'bookstack' }, { pattern: /jira/i, icon: 'jira' }, { pattern: /confluence/i, icon: 'confluence' }, { pattern: /bitwarden/i, icon: 'bitwarden' }, { pattern: /listmonk/i, icon: 'listmonk' }, { pattern: /mautic/i, icon: 'mautic' }, { pattern: /adminer/i, icon: 'adminer' }, { pattern: /phpmyadmin/i, icon: 'phpmyadmin' }, // Storage / media / smart home { pattern: /minio/i, icon: 'minio' }, { pattern: /nextcloud/i, icon: 'nextcloud' }, { pattern: /homeassistant|home-assistant/i, icon: 'homeassistant' }, { pattern: /homebridge/i, icon: 'homebridge' }, { pattern: /nodered|node-red/i, icon: 'nodered' }, { pattern: /esphome/i, icon: 'esphome' }, { pattern: /tasmota/i, icon: 'tasmota' }, { pattern: /immich/i, icon: 'immich' }, { pattern: /jellyfin/i, icon: 'jellyfin' }, { pattern: /plex/i, icon: 'plex' }, { pattern: /emby/i, icon: 'emby' }, { pattern: /sonarr/i, icon: 'sonarr' }, { pattern: /radarr/i, icon: 'radarr' }, // Docker engine (before generic base images) { pattern: /^docker$|docker\/|dind/i, icon: 'docker' }, // Base images (broad — match last) { pattern: /alpine/i, icon: 'alpine' }, { pattern: /ubuntu/i, icon: 'ubuntu' }, { pattern: /debian/i, icon: 'debian' }, { pattern: /centos/i, icon: 'centos' }, { pattern: /fedora/i, icon: 'fedora' }, { pattern: /rocky/i, icon: 'rockylinux' }, { pattern: /alma/i, icon: 'almalinux' }, { pattern: /redhat|red-hat|rhel/i, icon: 'redhat' }, { pattern: /archlinux|arch-linux/i, icon: 'archlinux' }, { pattern: /opensuse|suse/i, icon: 'opensuse' }, { pattern: /gentoo/i, icon: 'gentoo' }, ]; /** Local asset base — files live in public/docker-icons/ (see scripts/sync-docker-icons.mjs) */ const DOCKER_ICON_BASE = '/docker-icons'; /** Internal icon id → Simple Icons slug (https://simpleicons.org/) */ /** Only official Simple Icons slugs — no cross-brand substitutes. */ /** Parsed at build/sync time by scripts/sync-docker-icons.mjs (not referenced at runtime). */ // eslint-disable-next-line unused-imports/no-unused-vars -- consumed by scripts/sync-docker-icons.mjs const SIMPLE_ICONS_SLUG: Record = { container: 'docker', mosquitto: 'eclipsemosquitto', kong: 'kong', istio: 'istio', linkerd: 'linkerd', cilium: 'cilium', envoy: 'envoyproxy', kubernetes: 'kubernetes', k3s: 'k3s', helm: 'helm', rancher: 'rancher', argo: 'argo', nomad: 'nomad', terraform: 'terraform', ansible: 'ansible', pulumi: 'pulumi', packer: 'packer', containerd: 'containerd', podman: 'podman', nginx: 'nginx', traefik: 'traefikproxy', caddy: 'caddy', apache: 'apache', tomcat: 'apachetomcat', wordpress: 'wordpress', ghost: 'ghost', drupal: 'drupal', golang: 'go', nodejs: 'nodedotjs', python: 'python', openjdk: 'openjdk', springboot: 'springboot', rust: 'rust', deno: 'deno', php: 'php', ruby: 'ruby', postgresql: 'postgresql', mariadb: 'mariadb', mysql: 'mysql', mongodb: 'mongodb', redis: 'redis', clickhouse: 'clickhouse', cockroachdb: 'cockroachlabs', neo4j: 'neo4j', cassandra: 'apachecassandra', couchdb: 'apachecouchdb', couchbase: 'couchbase', arangodb: 'arangodb', tidb: 'tidb', vitess: 'vitess', duckdb: 'duckdb', scylladb: 'scylladb', singlestore: 'singlestore', trino: 'trino', presto: 'presto', influxdb: 'influxdb', timescaledb: 'timescale', snowflake: 'snowflake', databricks: 'databricks', rabbitmq: 'rabbitmq', kafka: 'apachekafka', pulsar: 'apachepulsar', rocketmq: 'apacherocketmq', nats: 'natsdotio', hivemq: 'hivemq', flink: 'apacheflink', nifi: 'apachenifi', temporal: 'temporal', opensearch: 'opensearch', elasticsearch: 'elasticsearch', meilisearch: 'meilisearch', kibana: 'kibana', logstash: 'logstash', solr: 'apachesolr', druid: 'apachedruid', hadoop: 'apachehadoop', hbase: 'apachehbase', hive: 'apachehive', grafana: 'grafana', prometheus: 'prometheus', victoriametrics: 'victoriametrics', thanos: 'thanos', jaeger: 'jaeger', opentelemetry: 'opentelemetry', fluentbit: 'fluentbit', fluentd: 'fluentd', sentry: 'sentry', datadog: 'datadog', netdata: 'netdata', icinga: 'icinga', sonarqube: 'sonarqubeserver', ollama: 'ollama', milvus: 'milvus', qdrant: 'qdrant', pytorch: 'pytorch', tensorflow: 'tensorflow', vaultwarden: 'vaultwarden', vault: 'vault', consul: 'consul', etcd: 'etcd', portainer: 'portainer', harbor: 'harbor', jfrog: 'jfrog', keycloak: 'keycloak', authelia: 'authelia', authentik: 'authentik', tailscale: 'tailscale', wireguard: 'wireguard', cloudflare: 'cloudflare', jenkins: 'jenkins', gitlab: 'gitlab', gitea: 'gitea', forgejo: 'forgejo', github: 'github', drone: 'drone', circleci: 'circleci', buildkite: 'buildkite', airflow: 'apacheairflow', prefect: 'prefect', spark: 'apachespark', supabase: 'supabase', strapi: 'strapi', directus: 'directus', hasura: 'hasura', pocketbase: 'pocketbase', appwrite: 'appwrite', mattermost: 'mattermost', jitsi: 'jitsi', matrix: 'matrix', metabase: 'metabase', superset: 'apachesuperset', airbyte: 'airbyte', bookstack: 'bookstack', jira: 'jira', confluence: 'confluence', bitwarden: 'bitwarden', listmonk: 'listmonk', mautic: 'mautic', adminer: 'adminer', phpmyadmin: 'phpmyadmin', minio: 'minio', nextcloud: 'nextcloud', homeassistant: 'homeassistant', homebridge: 'homebridge', nodered: 'nodered', esphome: 'esphome', tasmota: 'tasmota', immich: 'immich', jellyfin: 'jellyfin', plex: 'plex', emby: 'emby', sonarr: 'sonarr', radarr: 'radarr', docker: 'docker', alpine: 'alpinelinux', ubuntu: 'ubuntu', debian: 'debian', centos: 'centos', fedora: 'fedora', rockylinux: 'rockylinux', almalinux: 'almalinux', redhat: 'redhat', archlinux: 'archlinux', opensuse: 'opensuse', gentoo: 'gentoo', }; export interface DockerIconTileStyle { /** Tile background (brand primary) */ background: string; /** Logo fill baked into the local SVG — chosen for contrast on `background` */ iconColor: string; } /** * Per-brand tile: brand-colored background + logo color that stays readable. * Dark tiles → white/light logos; light tiles → dark logos. */ const ICON_TILE_STYLE: Record = { container: { background: '#2496ED', iconColor: 'ffffff' }, nacos: { background: '#FF6A00', iconColor: 'ffffff' }, polaris: { background: '#006EFF', iconColor: 'ffffff' }, mosquitto: { background: '#3C5280', iconColor: 'ffffff' }, kong: { background: '#003459', iconColor: 'ffffff' }, istio: { background: '#466BB0', iconColor: 'ffffff' }, linkerd: { background: '#2BEDA7', iconColor: '000000' }, cilium: { background: '#F8C517', iconColor: '000000' }, envoy: { background: '#AC6199', iconColor: 'ffffff' }, kubernetes: { background: '#326CE5', iconColor: 'ffffff' }, k3s: { background: '#FFC61C', iconColor: '000000' }, helm: { background: '#0F1689', iconColor: 'ffffff' }, rancher: { background: '#0075A8', iconColor: 'ffffff' }, argo: { background: '#EF7B4D', iconColor: 'ffffff' }, nomad: { background: '#00CA8E', iconColor: '000000' }, terraform: { background: '#844FBA', iconColor: 'ffffff' }, ansible: { background: '#EE0000', iconColor: 'ffffff' }, pulumi: { background: '#8A3391', iconColor: 'ffffff' }, packer: { background: '#02A8EF', iconColor: 'ffffff' }, containerd: { background: '#575757', iconColor: 'ffffff' }, podman: { background: '#892CA0', iconColor: 'ffffff' }, nginx: { background: '#009639', iconColor: 'ffffff' }, traefik: { background: '#24A1C1', iconColor: 'ffffff' }, caddy: { background: '#1F88C0', iconColor: 'ffffff' }, apache: { background: '#D22128', iconColor: 'ffffff' }, tomcat: { background: '#30261C', iconColor: 'F8DC75' }, wordpress: { background: '#21759B', iconColor: 'ffffff' }, ghost: { background: '#15171A', iconColor: 'ffffff' }, drupal: { background: '#0678BE', iconColor: 'ffffff' }, golang: { background: '#00ADD8', iconColor: 'ffffff' }, nodejs: { background: '#339933', iconColor: 'ffffff' }, python: { background: '#3776AB', iconColor: 'ffffff' }, openjdk: { background: '#437291', iconColor: 'ffffff' }, springboot: { background: '#6DB33F', iconColor: 'ffffff' }, rust: { background: '#000000', iconColor: 'ffffff' }, deno: { background: '#000000', iconColor: 'ffffff' }, php: { background: '#777BB4', iconColor: 'ffffff' }, ruby: { background: '#CC342D', iconColor: 'ffffff' }, postgresql: { background: '#4169E1', iconColor: 'ffffff' }, mariadb: { background: '#003545', iconColor: 'ffffff' }, mysql: { background: '#4479A1', iconColor: 'ffffff' }, mongodb: { background: '#47A248', iconColor: 'ffffff' }, valkey: { background: '#A41E34', iconColor: 'ffffff' }, dragonfly: { background: '#5B4B8A', iconColor: 'ffffff' }, redis: { background: '#DC382D', iconColor: 'ffffff' }, memcached: { background: '#00AA00', iconColor: 'ffffff' }, emqx: { background: '#5C4B9E', iconColor: 'ffffff' }, clickhouse: { background: '#FFCC01', iconColor: '000000' }, cockroachdb: { background: '#6933FF', iconColor: 'ffffff' }, neo4j: { background: '#4581C3', iconColor: 'ffffff' }, cassandra: { background: '#1287B1', iconColor: 'ffffff' }, couchdb: { background: '#E42528', iconColor: 'ffffff' }, couchbase: { background: '#EA2328', iconColor: 'ffffff' }, arangodb: { background: '#D12C2F', iconColor: 'ffffff' }, tidb: { background: '#E7008A', iconColor: 'ffffff' }, vitess: { background: '#F16728', iconColor: 'ffffff' }, duckdb: { background: '#FFF000', iconColor: '000000' }, scylladb: { background: '#6C2BD9', iconColor: 'ffffff' }, singlestore: { background: '#AA00FF', iconColor: 'ffffff' }, trino: { background: '#DD00A1', iconColor: 'ffffff' }, presto: { background: '#5890FF', iconColor: 'ffffff' }, influxdb: { background: '#22ADF6', iconColor: 'ffffff' }, timescaledb: { background: '#FDB515', iconColor: '000000' }, snowflake: { background: '#29B5E8', iconColor: 'ffffff' }, databricks: { background: '#FF3621', iconColor: 'ffffff' }, rabbitmq: { background: '#FF6600', iconColor: 'ffffff' }, kafka: { background: '#231F20', iconColor: 'ffffff' }, pulsar: { background: '#188FFF', iconColor: 'ffffff' }, rocketmq: { background: '#D77310', iconColor: 'ffffff' }, nats: { background: '#27AAE1', iconColor: 'ffffff' }, hivemq: { background: '#FFCD00', iconColor: '000000' }, flink: { background: '#E6526F', iconColor: 'ffffff' }, nifi: { background: '#728E9B', iconColor: 'ffffff' }, temporal: { background: '#000000', iconColor: 'ffffff' }, opensearch: { background: '#005EB8', iconColor: 'ffffff' }, elasticsearch: { background: '#005571', iconColor: 'ffffff' }, meilisearch: { background: '#FF5CAA', iconColor: 'ffffff' }, kibana: { background: '#005571', iconColor: 'ffffff' }, logstash: { background: '#005571', iconColor: 'ffffff' }, solr: { background: '#D9411E', iconColor: 'ffffff' }, druid: { background: '#29F1FB', iconColor: '000000' }, hadoop: { background: '#66CCFF', iconColor: '000000' }, hbase: { background: '#BE160F', iconColor: 'ffffff' }, hive: { background: '#FDEE21', iconColor: '000000' }, grafana: { background: '#F46800', iconColor: 'ffffff' }, prometheus: { background: '#E6522C', iconColor: 'ffffff' }, victoriametrics: { background: '#621773', iconColor: 'ffffff' }, thanos: { background: '#6D41FF', iconColor: 'ffffff' }, jaeger: { background: '#2D2D2D', iconColor: '60D0E4' }, opentelemetry: { background: '#000000', iconColor: 'ffffff' }, fluentbit: { background: '#49BDA5', iconColor: 'ffffff' }, fluentd: { background: '#0E83C8', iconColor: 'ffffff' }, sentry: { background: '#362D59', iconColor: 'ffffff' }, datadog: { background: '#632CA6', iconColor: 'ffffff' }, netdata: { background: '#00AB44', iconColor: 'ffffff' }, icinga: { background: '#060606', iconColor: 'ffffff' }, sonarqube: { background: '#4E9BCD', iconColor: 'ffffff' }, ollama: { background: '#000000', iconColor: 'ffffff' }, milvus: { background: '#00A1EA', iconColor: 'ffffff' }, qdrant: { background: '#DC244C', iconColor: 'ffffff' }, pytorch: { background: '#EE4C2C', iconColor: 'ffffff' }, tensorflow: { background: '#FF6F00', iconColor: 'ffffff' }, vaultwarden: { background: '#175DDC', iconColor: 'ffffff' }, vault: { background: '#1B1F23', iconColor: 'FFEC6E' }, consul: { background: '#F24C53', iconColor: 'ffffff' }, etcd: { background: '#419EDA', iconColor: 'ffffff' }, zookeeper: { background: '#56290C', iconColor: 'ffffff' }, portainer: { background: '#13BEF9', iconColor: 'ffffff' }, harbor: { background: '#60B932', iconColor: 'ffffff' }, jfrog: { background: '#40BE46', iconColor: 'ffffff' }, keycloak: { background: '#4D4D4D', iconColor: 'ffffff' }, authelia: { background: '#113155', iconColor: 'ffffff' }, authentik: { background: '#FD4B2D', iconColor: 'ffffff' }, tailscale: { background: '#242424', iconColor: 'ffffff' }, wireguard: { background: '#88171A', iconColor: 'ffffff' }, cloudflare: { background: '#F38020', iconColor: 'ffffff' }, jenkins: { background: '#D24939', iconColor: 'ffffff' }, gitlab: { background: '#FC6D26', iconColor: 'ffffff' }, gitea: { background: '#609926', iconColor: 'ffffff' }, forgejo: { background: '#FB923C', iconColor: '000000' }, github: { background: '#181717', iconColor: 'ffffff' }, drone: { background: '#212121', iconColor: 'ffffff' }, circleci: { background: '#343434', iconColor: 'ffffff' }, buildkite: { background: '#14B8A6', iconColor: 'ffffff' }, airflow: { background: '#017CEE', iconColor: 'ffffff' }, prefect: { background: '#070E10', iconColor: 'ffffff' }, spark: { background: '#E25A1C', iconColor: 'ffffff' }, supabase: { background: '#3FCF8E', iconColor: '000000' }, strapi: { background: '#4945FF', iconColor: 'ffffff' }, directus: { background: '#6644FF', iconColor: 'ffffff' }, hasura: { background: '#1EB4D4', iconColor: 'ffffff' }, pocketbase: { background: '#B8DBE4', iconColor: '000000' }, appwrite: { background: '#FD366E', iconColor: 'ffffff' }, mattermost: { background: '#0058CC', iconColor: 'ffffff' }, jitsi: { background: '#97979A', iconColor: 'ffffff' }, matrix: { background: '#000000', iconColor: 'ffffff' }, metabase: { background: '#509EE3', iconColor: 'ffffff' }, superset: { background: '#20A6C9', iconColor: 'ffffff' }, airbyte: { background: '#615EFF', iconColor: 'ffffff' }, bookstack: { background: '#0288D1', iconColor: 'ffffff' }, jira: { background: '#0052CC', iconColor: 'ffffff' }, confluence: { background: '#172B4D', iconColor: 'ffffff' }, bitwarden: { background: '#175DDC', iconColor: 'ffffff' }, listmonk: { background: '#0052CC', iconColor: 'ffffff' }, mautic: { background: '#4E5E9E', iconColor: 'ffffff' }, adminer: { background: '#34567C', iconColor: 'ffffff' }, phpmyadmin: { background: '#F29111', iconColor: 'ffffff' }, minio: { background: '#C72E49', iconColor: 'ffffff' }, nextcloud: { background: '#0082C9', iconColor: 'ffffff' }, homeassistant: { background: '#18BCF2', iconColor: 'ffffff' }, homebridge: { background: '#491F59', iconColor: 'ffffff' }, nodered: { background: '#8F0000', iconColor: 'ffffff' }, esphome: { background: '#000000', iconColor: 'ffffff' }, tasmota: { background: '#1A1A1A', iconColor: 'ffffff' }, immich: { background: '#4250AF', iconColor: 'ffffff' }, jellyfin: { background: '#00A4DC', iconColor: 'ffffff' }, plex: { background: '#EBAF00', iconColor: '000000' }, emby: { background: '#52B54B', iconColor: 'ffffff' }, sonarr: { background: '#35C5F4', iconColor: '000000' }, radarr: { background: '#FFCC00', iconColor: '000000' }, docker: { background: '#2496ED', iconColor: 'ffffff' }, alpine: { background: '#0D597F', iconColor: 'ffffff' }, ubuntu: { background: '#E95420', iconColor: 'ffffff' }, debian: { background: '#A81D33', iconColor: 'ffffff' }, centos: { background: '#262577', iconColor: 'ffffff' }, fedora: { background: '#294172', iconColor: 'ffffff' }, rockylinux: { background: '#10B981', iconColor: 'ffffff' }, almalinux: { background: '#0F4266', iconColor: 'ffffff' }, redhat: { background: '#EE0000', iconColor: 'ffffff' }, archlinux: { background: '#1793D1', iconColor: 'ffffff' }, opensuse: { background: '#73BA25', iconColor: 'ffffff' }, gentoo: { background: '#54487A', iconColor: 'ffffff' }, }; const DEFAULT_TILE_STYLE: DockerIconTileStyle = { background: '#52525b', iconColor: 'ffffff', }; export function resolveDockerImageIcon(image: string): string { const repo = (image || '').split(':')[0].split('/').pop() || ''; for (const rule of IMAGE_ICON_RULES) { if (rule.pattern.test(repo) || rule.pattern.test(image)) { return rule.icon; } } return 'container'; } export function dockerIconTileStyle(iconId: string): DockerIconTileStyle { return ICON_TILE_STYLE[iconId] ?? DEFAULT_TILE_STYLE; } const CONTAINER_ICON_ID = 'container'; function dockerIconFileName(iconId: string): string { return DOCKER_ICON_FILES[iconId] ?? `${iconId}.svg`; } /** Local bundled asset, or null when no official icon is available. */ export function dockerIconUrl(iconId: string): string | null { if (!BUNDLED_DOCKER_ICON_IDS.has(iconId)) return null; return `${DOCKER_ICON_BASE}/${encodeURIComponent(dockerIconFileName(iconId))}`; } export interface DockerIconPresentation { /** Icon id used for tile color and logo */ displayIconId: string; iconUrl: string; /** True when showing the matched brand icon (not Docker fallback) */ isBrandIcon: boolean; } /** Official brand icon when bundled; otherwise Docker logo + Docker tile. */ export function resolveDockerIconPresentation( iconId: string, options?: { imageFailed?: boolean }, ): DockerIconPresentation { const useBrand = !options?.imageFailed && iconId !== CONTAINER_ICON_ID && BUNDLED_DOCKER_ICON_IDS.has(iconId); const displayIconId = useBrand ? iconId : CONTAINER_ICON_ID; return { displayIconId, iconUrl: `${DOCKER_ICON_BASE}/${encodeURIComponent(dockerIconFileName(displayIconId))}`, isBrandIcon: useBrand, }; }