Dashboard Icons

repository·main·Indexed 27 days ago

https://github.com/homarr-labs/dashboard-icons

A curated collection of over 1800 icons for services, applications, and tools designed for dashboards and app directories. Provides icons in SVG, PNG, and WebP formats accessible via jsDelivr CDN or GitHub. Includes documentation for running the Dashboard Icons Web App, configuring GitHub OAuth, importing external icons from selfh.st, and managing icon metadata and workflows via PocketBase and GitHub API.

Tokens
10.5K
Snippets
26
Records
36
Agent score
93%

What's inside dashboard-icons

  1. Use Dashboard Icons via CDN

    main

    You can reference icons directly in your applications using a CDN. The recommended method is via jsDelivr. Use the following URL pattern to construct the link:

    <Base URL>/<Format>/<Icon Name>.<Format>

    Base URL options:

    • jsDelivr (recommended): https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons
    • GitHub Direct: https://raw.githubusercontent.com/homarr-labs/dashboard-icons/main
    <img src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/plex.svg" alt="Plex">
  2. Trigger the Add Icon Workflow via GitHub API

    main

    You can programmatically trigger the .github/workflows/add-icon.yml workflow using the GitHub REST API. This is useful for backend services or webhooks that need to initiate the icon import process. You must use a GitHub token with the workflow scope. The workflow requires a submissionId (the PocketBase record ID) and an optional dryRun flag.

    curl -X POST \
      -H "Authorization: Bearer $GITHUB_TOKEN" \
      -H "Accept: application/vnd.github+json" \
      https://api.github.com/repos/<OWNER>/<REPO>/actions/workflows/add-icon.yml/dispatches \
      -d '{
        "ref": "main",
        "inputs": {
          "submissionId": "SUBMISSION_RECORD_ID",
          "dryRun": "false"
        }
      }'
  3. Implement custom variant logic in `IconDetails`

    main

    When rendering icon details, use getVariantDefinition and groupVariantsByCategory to handle both preset and custom variants. To ensure a consistent UI, sort variants so that preset variants appear before custom ones.

    import { getVariantDefinition, groupVariantsByCategory } from "@/lib/variant-definitions"
    
    // Sort variants: preset variants first, then custom variants alphabetically
    const sortedVariants = allVariants.sort((a, b) => {
      const aDef = getVariantDefinition(a)
      const bDef = getVariantDefinition(b)
      if (aDef.preset && !bDef.preset) return -1
      if (!aDef.preset && bDef.preset) return 1
      return a.localeCompare(b)
    })
  4. Create a GitHub Actions workflow to sync external icons

    main

    To automate the icon synchronization process, create a new workflow file at .github/workflows/sync-<yoursource>.yml. This workflow runs on a schedule or can be triggered manually. It installs dependencies, fetches your source's manifest, and executes the importer script.

    Required Repository Secrets

    To allow the workflow to communicate with the backend, you must configure the following secrets in your GitHub repository:

    • PB_URL: The PocketBase instance URL (e.g., https://pb.dashboardicons.com).
    • PB_ADMIN: The PocketBase superuser email.
    • PB_ADMIN_PASS: The PocketBase superuser password.
    name: Sync yoursource icons
    
    on:
      schedule:
        - cron: "0 5 * * *"        # Daily at 05:00 UTC (adjust as needed)
      workflow_dispatch:            # Manual trigger
    
    jobs:
      sync:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
    
          - uses: pnpm/action-setup@v4
    
          - uses: actions/setup-node@v4
            with:
              node-version: 20
              cache: pnpm
              cache-dependency-path: web/pnpm-lock.yaml
    
          - run: cd web && pnpm install --frozen-lockfile
    
          - name: Fetch yoursource manifests
            run: |
              cd web
              mkdir -p data/sources/yoursource
              curl -fsSL https://example.com/manifest.json -o data/sources/yoursource/index.json
    
          - name: Import external icons
            env:
              NEXT_PUBLIC_POCKETBASE_URL: ${{ secrets.PB_URL }}
              PB_ADMIN: ${{ secrets.PB_ADMIN }}
              PB_ADMIN_PASS: ${{ secrets.PB_ADMIN_PASS }}
            run: cd web && pnpm exec tsx scripts/import-yoursource.ts
  5. Checklist for adding an external icon source

    main

    When adding a new external icon source, ensure you have completed the following tasks:

    Required Tasks

    • Added source ID to ExternalSourceId union in constants.ts
    • Added full config entry to EXTERNAL_SOURCES in constants.ts
    • Created PocketBase migration adding source to the source select field
    • Written importer script at scripts/import-<source>.ts
    • Added .gitignore exception for the importer
    • Created GitHub Actions workflow at .github/workflows/sync-<source>.yml
    • Added remotePatterns entry in next.config.ts
    • Added Playwright tests in tests/external-icons.spec.ts
    • Updated README.md with source documentation

    Verification Steps

    • Verified: url_templates has explicit keys for every format+theme combination
    • Verified: variants are merged if applicable (e.g. -color as primary)
    • Verified locally: importer runs with --dry-run, icons appear in browse, detail page renders
    • Verified: source filter dropdown shows new source with its icon
    • Verified: themed previews work in both light and dark modes
    • Verified: CMD+K search returns new source icons with badge
    • Verified: hero hover popover shows new source count
    • Verified: pnpm build generates static pages for all new slugs
  6. Install and set up the Dashboard Icons Web App

    main

    To run the Dashboard Icons Web App locally, ensure you have Node.js 18+ and pnpm installed. Follow these steps:

    1. Clone the repository.
    2. Install dependencies:
      pnpm install
    3. Create a .env file in the root directory with the following variables:
      GITHUB_TOKEN=your_github_token
      NEXT_PUBLIC_POCKETBASE_URL=http://127.0.0.1:8090
    4. Start the development server:
      pnpm dev
    pnpm install
    # After setting up .env
    pnpm dev
  7. Import external icons from selfh.st

    main

    The application can display external icon metadata from selfh.st/icons using the external_icons PocketBase collection. This allows using icons hosted on jsDelivr without local storage.

    Prerequisites

    If the collection does not exist, import data/sources/selfhst/external_icons.collection.json in the PocketBase admin UI under Collections before running the importer. This JSON defines the fields, public rules (listRule: "", viewRule: ""), and the (source, slug) unique index.

    Import Process

    1. Download the required metadata files:
      mkdir -p data/sources/selfhst
      curl -fsSL https://raw.githubusercontent.com/selfhst/icons/main/index.json -o data/sources/selfhst/index.json
      curl -fsSL https://raw.githubusercontent.com/selfhst/icons/main/index-consolidated.json -o data/sources/selfhst/index-consolidated.json
      curl -fsSL https://raw.githubusercontent.com/selfhst/icons/main/tags.json -o data/sources/selfhst/tags.json
    2. Run the import script:
      PB_ADMIN=admin@example.com PB_ADMIN_PASS=your-password \
      NEXT_PUBLIC_POCKETBASE_URL=http://127.0.0.1:8090 \
      bun run scripts/import-selfhst.ts

    Icon URL Pattern

    External icons are served via jsDelivr using the following pattern: https://cdn.jsdelivr.net/gh/selfhst/icons/<format>/<slug>.<format>

    Note: Every external icon card and detail page must display Icons by selfh.st/icons (CC BY 4.0).

    mkdir -p data/sources/selfhst
    curl -fsSL https://raw.githubusercontent.com/selfhst/icons/main/index.json -o data/sources/selfhst/index.json
    curl -fsSL https://raw.githubusercontent.com/selfhst/icons/main/index-consolidated.json -o data/sources/selfhst/index-consolidated.json
    curl -fsSL https://raw.githubusercontent.com/selfhst/icons/main/tags.json -o data/sources/selfhst/tags.json
    
    PB_ADMIN=admin@example.com PB_ADMIN_PASS=your-password \
    NEXT_PUBLIC_POCKETBASE_URL=http://127.0.0.1:8090 \
    bun run scripts/import-selfhst.ts
  8. Request or update icons

    main

    To add or update icons in the collection, use the following methods:

    Preferred Method (Fastest)

    1. Visit dashboardicons.com.
    2. Use the built-in submission form to add or update icons. This allows for faster review and publishing by Homarr Labs admins.

    Alternative Method (Slower)

    1. Review the Contribution Guidelines.
    2. Submit a request using the GitHub issue templates.
    3. Provide service details and optionally upload the icon file.
  9. Generate feature screenshots using the screenshot script

    main

    You can automatically capture screenshots of the SVG Customizer feature in various states using the provided script. This requires the development server to be running in a separate terminal.

    1. In one terminal, start the web development server:
      npm run dev:web
    2. In another terminal, run the screenshot script:
      cd web
      npm run screenshots
    npm run screenshots
  10. Update PocketBase migration for external icons

    main

    The source field in the external_icons collection is a select type with an allowlist. When adding a new source, you must create a new migration file in web/backend/pb_migrations/ to add your new source ID to the values array of the source field.

    /// <reference path="../pb_data/types.d.ts" />
    migrate((app) => {
      const collection = app.findCollectionByNameOrId("external_icons")
      const sourceField = collection.fields.find(f => f.name === "source")
      sourceField.values = ["selfhst", "yoursource"]
      return app.save(collection)
    }, (app) => {
      const collection = app.findCollectionByNameOrId("external_icons")
      const sourceField = collection.fields.find(f => f.name === "source")
      sourceField.values = ["selfhst"]
      return app.save(collection)
    })
  11. Implement Dynamic Variant Rendering

    main

    When building UI components to display icons, use getVariantDefinition() to retrieve metadata (labels, descriptions, and icons) for any variant. This allows the UI to support both preset variants (like light or dark) and custom user-defined variants dynamically.

    Rendering Logic Pattern:

    1. Retrieve all variant names from iconData.variants and iconData.wordmark.
    2. Sort variants so that presets appear first, followed by custom variants in alphabetical order.
    3. Map through the sorted list and use getVariantDefinition(variantName) to render the appropriate section.
    import { getVariantDefinition, groupVariantsByCategory } from "@/lib/variant-definitions"
    
    // Sort: preset variants first, then custom variants alphabetically
    const sortedVariants = allVariants.sort((a, b) => {
      const aDef = getVariantDefinition(a)
      const bDef = getVariantDefinition(b)
      if (aDef.preset && !bDef.preset) return -1
      if (!aDef.preset && bDef.preset) return 1
      return a.localeCompare(b)
    })
  12. Run Playwright E2E tests in the web package

    main

    The web package includes a Playwright E2E test suite for the SVG Icon Customizer feature. To run these tests, navigate to the web directory and use the available npm scripts.

    Running all tests

    cd web
    npm run test:e2e

    Running tests interactively

    Use the UI mode to interact with the tests visually:

    npm run test:e2e:ui

    Other test commands

    • Debug mode: npm run test:e2e:debug
    • Chromium project only: npm run test:e2e:chromium
    • Headed mode: npm run test:e2e:headed
    • View report: npm run test:e2e:report
    cd web
    npm run test:e2e