Sign inSign up

communityfirst/mapeo-icons

By communityfirst

Updated 3 months ago

Tool to generate icons for use in CoMapeo, or any other tool. Currently, the tool generates icons in

Image
Data science
Content management system
0

4.6K

communityfirst/mapeo-icons repository overview


CoMapeo Icons Logo

CoMapeo Icons

Search, colorize, and export SVG icons for CoMapeo configurations.
Translate search terms into 7 languages, find icons across multiple providers, recolor them on the fly, and download ready-to-use SVG data URIs.

Live Demo · Report Bug · Request Feature

CI Docker Node.js Nuxt License Contributors


Table of Contents
  1. About
  2. Features
  3. Screenshots
  4. Built With
  5. Related Tooling
  6. Getting Started
  7. Usage
  8. Environment Variables
  9. Project Structure
  10. Development
  11. Deployment
  12. Internationalization
  13. How It Works
  14. Contributing
  15. License
  16. Acknowledgments

About

CoMapeo Icons is a web application that bridges the gap between finding the right icon and having it ready for use in CoMapeo configurations. It enables communities — especially those working in environmental monitoring and indigenous land rights — to create visually meaningful, color-customized icons without needing design tools or technical expertise.

The app searches across multiple icon providers (Iconify, The Noun Project), automatically translates search terms into the user's language, applies custom colors via an interactive color picker, and exports optimized SVG data URIs that drop directly into CoMapeo configuration files.

(back to top)

Features

  • Multi-provider icon search — Searches Iconify by default (200K+ icons, no API key needed), with The Noun Project as a configurable fallback. Provider order is customizable.
  • Automatic translation — Search terms are translated via Bing Translate so users can search in their native language across 7 locales.
  • Live color customization — Interactive color picker with real-time preview. Icons are recolored using CSS filter generation (SPSA optimization algorithm) and SVG paint attribute replacement.
  • SVG optimization — Icons are processed through SVGO for minification and converted to data URIs via mini-svg-data-uri.
  • PNG-to-SVG tracing — Raster icons from The Noun Project are automatically traced to vector SVG using Potrace.
  • One-click download & copy — Download as .svg file or copy SVG markup / data URI directly to clipboard.
  • Fully internationalized — UI available in English, Portuguese, Spanish, Thai, Dutch, French, and Indonesian with automatic browser language detection.
  • Mobile-first responsive design — Optimized for field use on phones and tablets.
  • Docker-ready — Multi-arch images (amd64 + arm64) published to Docker Hub on every successful CI run.

(back to top)

Screenshots

Search ResultsIcon Selection + Color Picker
Search results for iconsColor picker changing icon color
Mobile Color Picker
Mobile color picker modal

(back to top)

Built With

Nuxt Vue.js TypeScript Tailwind CSS Playwright Docker

TechnologyPurpose
Nuxt 4Full-stack Vue framework (SSR + Nitro server)
Vue 3Reactive UI components (<script setup lang="ts">)
Tailwind CSSUtility-first styling
PlaywrightEnd-to-end testing
SVGOSVG optimization
PotraceRaster-to-vector tracing
bing-translate-apiSearch term translation
Husky + lint-stagedGit hooks & pre-commit linting

(back to top)

CoMapeo Category Set Spreadsheet Plugin is commonly used with CoMapeo Icons. It generates .comapeocat category files from Google Sheets and can use icons produced by this tool for CoMapeo projects.

(back to top)

Getting Started

Prerequisites
  • Node.js >= 22.18.0
  • npm (comes with Node.js)
Installation
  1. Clone the repository

    git clone https://github.com/digidem/mapeo-icons.git
    cd mapeo-icons
    
  2. Install dependencies

    npm install
    
  3. Set up environment variables

    cp .env.example .env
    

    Iconify works out of the box with no credentials. Only add The Noun Project keys if you want it as a fallback provider.

  4. Start the development server

    npm run dev
    
  5. Visit http://localhost:3000 and start searching.

(back to top)

Usage

  1. Search — Enter a term in any of the 7 supported languages. The app translates it to English before querying icon providers.
  2. Browse — Scroll through results and click an icon to select it. Use "Load more" for additional results.
  3. Colorize — Pick a color using the color picker. Icons update in real-time.
  4. Generate — Click "Generate" to process the icon through SVGO optimization and color replacement.
  5. Export — Download the .svg file or copy the SVG markup / data URI to your clipboard.

The generated SVG data URIs are ready to paste directly into a CoMapeo configuration.

(back to top)

Environment Variables

All variables are optional — the app works with zero configuration using Iconify defaults.

VariableRequiredDefaultDescription
ICONS_TO_DOWNLOADNo10Number of icons to fetch per request
ICON_PROVIDER_ORDERNonoun,iconifyComma-separated provider order
ICONIFY_API_BASE_URLNohttps://api.iconify.designIconify API base URL
ICONIFY_PREFIXESNomaki,temaki,material-symbols,mdi,tabler,ph,lucide,heroiconsComma-separated Iconify icon collections
NOUN_KEYNoThe Noun Project OAuth consumer key
NOUN_SECRETNoThe Noun Project OAuth consumer secret
CORSNoSet to all or a comma-separated list of allowed origins

Restart the dev server after changing any of these values.

(back to top)

Project Structure

mapeo-icons/
├── assets/
│   └── main.css              # Global Tailwind imports
├── components/
│   ├── ColorPickerMobile.vue  # Collapsible mobile color picker
│   ├── Footer.vue             # Page footer
│   └── Search.vue             # Search form + locale selector
├── libs/
│   └── colorize.js            # CSS filter generator (SPSA algorithm)
├── locales/                   # i18n translation bundles (7 languages)
├── pages/
│   ├── index.vue              # Landing page / search
│   ├── images.vue             # Icon grid + color selection
│   └── result.vue             # Final SVG output + download/copy
├── public/
│   ├── favicon.ico
│   ├── icon.png
│   ├── logo.webp
│   └── sw.js                  # Service worker
├── server/
│   ├── api/
│   │   ├── search.get.ts      # GET /api/search — icon search endpoint
│   │   └── generate.get.ts    # GET /api/generate — SVG generation endpoint
│   └── utils/
│       ├── iconSearch.ts      # Multi-provider search logic
│       ├── generateMapeoIcon.ts # SVG colorization + optimization
│       └── translate.ts       # Bing Translate wrapper
├── store/
│   └── README.md              # State management notes
├── tests/
│   └── e2e/
│       ├── search.spec.ts     # Search flow tests
│       ├── color-picker.spec.ts # Color picker tests
│       └── screenshots/       # Test artifacts
├── types/                     # TypeScript shims
├── Dockerfile                 # Production container definition
├── nuxt.config.js             # Nuxt configuration
├── tailwind.config.ts         # Tailwind theme
└── playwright.config.ts       # E2E test configuration

(back to top)

Development

Scripts
CommandDescription
npm run devStart the Vite-powered Nuxt dev server (localhost:3000)
npm run buildCompile the production bundle
npm run previewServe the built Nitro output locally
npm run generatePre-render the app as static files
npm testRun Playwright E2E suite (headless, port 4173)
npm run test:headedRun tests in headed browser mode
npm run test:uiRun tests in Playwright UI mode
npm run lintRun ESLint + Stylelint + Prettier checks
npm run lintfixAutofix lint issues and format all files
Testing

End-to-end tests use Playwright and model complete user journeys:

# Run all tests (boots dev server on port 4173)
npm test

# Watch tests in a browser
npm run test:headed

# Interactive UI mode with time travel debugging
npm run test:ui

Test artifacts (screenshots) are saved in tests/e2e/screenshots/.

Linting

The project uses ESLint, Stylelint, and Prettier with Husky pre-commit hooks:

# Check everything
npm run lint

# Auto-fix
npm run lintfix

Commits must follow Conventional Commits format (enforced by commitlint):

feat(search): add locale toggle
fix(images): improve color picker accessibility
chore(deps): update nuxt to v4.4.5

(back to top)

Deployment

Docker

Pre-built images are published to Docker Hub:

docker run -d \
  -p 3000:3000 \
  -e NOUN_KEY=your_key \
  -e NOUN_SECRET=your_secret \
  -e ICONS_TO_DOWNLOAD=10 \
  communityfirst/mapeo-icons:latest

Images are built for linux/amd64 and linux/arm64. The Docker build pipeline triggers automatically after CI passes on main.

Docker Compose
services:
  mapeo-icons:
    image: communityfirst/mapeo-icons:latest
    ports:
      - "3000:3000"
    environment:
      ICONS_TO_DOWNLOAD: 10
      ICON_PROVIDER_ORDER: noun,iconify
      # NOUN_KEY: your_key
      # NOUN_SECRET: your_secret
    restart: unless-stopped

(back to top)

Internationalization

The app supports 7 languages with automatic browser detection:

CodeLanguageFlag
enEnglish:us:
ptPortuguês:brazil:
esEspañol:es:
thไทย:thailand:
nlNederlands:netherlands:
frFrançais:fr:
idBahasa Indonesia:indonesia:

Translation files live in locales/*.json. To add a new language, create a new JSON file and register it in nuxt.config.js under i18n.locales.

(back to top)

How It Works

User searches "cachorro" (pt)
        │
        ▼
┌─────────────────┐     ┌──────────────────┐
│  Bing Translate  │────▶│  "dog" (en)      │
└─────────────────┘     └────────┬─────────┘
                                 │
                    ┌────────────▼────────────┐
                    │   Provider Chain         │
                    │   (configurable order)   │
                    ├──────────────────────────┤
                    │ 1. The Noun Project      │
                    │    (scrape → API)        │
                    │ 2. Iconify               │
                    │    (8 collections)       │
                    └────────────┬────────────┘
                                 │
                    ┌────────────▼────────────┐
                    │   Icon Results (URLs)    │
                    └────────────┬────────────┘
                                 │
              ┌──────────────────▼──────────────────┐
              │       Generate Endpoint              │
              │  ┌─────────────────────────────────┐ │
              │  │ SVG? → Replace fill/stroke attrs │ │
              │  │ PNG? → Potrace trace to vector   │ │
              │  └──────────────┬──────────────────┘ │
              │                 │                     │
              │  ┌──────────────▼──────────────────┐ │
              │  │ SVGO optimize → data URI         │ │
              │  └──────────────┬──────────────────┘ │
              └─────────────────┼───────────────────┘
                                │
                    ┌───────────▼───────────┐
                    │  Colored SVG download  │
                    │  / clipboard copy      │
                    └───────────────────────┘

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/amazing-feature)
  3. Commit your Changes (git commit -m 'feat(scope): add amazing feature')
  4. Push to the Branch (git push origin feature/amazing-feature)
  5. Open a Pull Request
Guidelines
  • Follow the existing code style (enforced by ESLint + Prettier + Stylelint)
  • Use <script setup lang="ts"> for Vue components
  • Write Conventional Commit messages (feat(scope): description)
  • Add or update Playwright tests for new features
  • Run npm run lint and npm test before submitting a PR
  • Update locale files if you add user-facing strings
Contributors
Contributors

(back to top)

License

Distributed under the MIT License. See LICENSE for more information.

(back to top)

Acknowledgments

(back to top)


Tag summary

Content type

Image

Digest

sha256:4175c5409

Size

345.3 MB

Last updated

3 months ago

docker pull communityfirst/mapeo-icons