npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@web-portfolio/icons-sanity

v3.0.1

Published

Sanity Studio icon picker input, backed by the same bundled registry as @web-portfolio/icons.

Readme

@web-portfolio/icons-sanity

A Sanity Studio plugin that adds a proper icon picker field to your schema, backed by the same 633-icon library as @web-portfolio/icons. It exists because "paste an SVG into a text field" is a bad experience for content editors — they either need to know what valid SVG markup looks like, or they need you to do it for them every time a new skill or social link gets added. This plugin turns that into: click the field, search, pick an icon, done.

Browse the icon set → before you install, to see exactly what your editors will be choosing from.

npm version license

Browse icons at icons.getresume.dev

Recent changes

v3.0.0 — ESM-only, built with @sanity/plugin-kit

  • The build now uses @sanity/plugin-kit and @sanity/pkg-utils instead of a hand-rolled tsup config — the same toolchain Sanity's own plugin ecosystem uses.
  • Breaking: the package is now ESM-only. The require()/CJS entry point (main, module fields, and the require export condition) has been removed — Sanity Studio v3+ is pure ESM, so this plugin was never actually loaded via require() in practice. If you import this package with require() directly (outside a Studio config), switch to import.
  • No other behavior changed: same sanityIconPicker() export, same iconRef schema type, same peer dependencies.

97% smaller package

  • This plugin no longer bundles its own copy of the 633-icon SVG registry. It now renders icon previews through @web-portfolio/icons's <Icon> component (added as a peer dependency, see below) and only carries the lightweight search index — name, label, tags, category, no SVG markup — that the picker's search and filtering actually need.
  • Published size: 1.1 MB → 35.7 KB (tarball), 1.36 MB → 60.5 KB (unpacked JS), 577 KB → 15 KB (gzipped). Since any project using this plugin already installs @web-portfolio/icons to render the picked icon on its frontend, that icon data is no longer downloaded twice.

Security & supply chain

  • Bumped vitest to 3.2.7 and drizzle-orm to 0.45.2 across the monorepo, and pinned several transitive dependencies (esbuild, sharp, postcss, glob, js-yaml, uuid, prismjs, adm-zip, es-define-property) to patched versions via pnpm overrides.
  • Install scripts now run only for an explicit allow-list (esbuild, sharp) instead of the whole dependency tree by default.
  • Current Socket.dev score: 100 Vulnerability, 100 Quality, 100 License, 88 Maintenance, 80 Supply Chain Security. This plugin still ships zero runtime dependencies of its own — the Supply Chain number reflects Socket's scan of the full Sanity Studio peer tree (sanity, @sanity/ui, ...), not this plugin's code.

Why this plugin

If you've built a portfolio, agency site, or any Sanity project with a "skills" or "tech stack" or "connect with us" section, you've probably built some version of an icon field before. This plugin is meant to save you from doing that again:

  • 633 icons, ready to search. Tech-stack logos, social platform icons, and everyday UI icons — editors search by name, label, or tag, and can narrow to a category, no SVG knowledge required.
  • Results ranked, not just filtered. Typing go leads with go, not godot — exact matches first, then name prefixes, then everything that merely mentions the term.
  • Nothing fetched while editing. Icon markup (via @web-portfolio/icons) and search metadata (via this plugin) are both bundled at build time, so the picker opens instantly and works even if Studio is running offline.
  • Stores a name, not a blob. The field value is a plain string ("react", "github") rather than raw markup or an asset reference, which pairs directly with @web-portfolio/icons's <Icon name="..." /> on your frontend — no lookups, no asset resolution, just the name.
  • Shows what's selected. The current icon renders inline in the form alongside its label, category, and the exact string that got stored — so editors can confirm at a glance they picked the right one.
  • Built entirely from Sanity UI. Card, Dialog, Badge, Select, TextInput, Tooltip and @sanity/icons, sized off the Sanity UI space scale. It inherits your Studio's theme and light/dark scheme instead of fighting it, and respects readOnly fields and Studio's focus/presence tracking like a built-in input.

Installation

npm install @web-portfolio/icons-sanity
pnpm add @web-portfolio/icons-sanity

Peer dependencies: sanity >=3, @sanity/ui >=2, @sanity/icons >=3, react >=18, styled-components >=6 (already present in any standard Sanity Studio v3 project), plus @web-portfolio/icons >=1.0.1, which renders the icons this plugin picks — install it if your Studio doesn't already have it.

Setup

Add the plugin to your Studio config:

// sanity.config.ts
import { defineConfig } from 'sanity'
import { sanityIconPicker } from '@web-portfolio/icons-sanity'

export default defineConfig({
  // ...your existing config
  plugins: [
    // ...your existing plugins
    sanityIconPicker(),
  ],
})

This registers an iconRef schema type you can use on any document or object.

Usage

Use type: 'iconRef' on any field that should store an icon:

// schemaTypes/documents/skill.ts
import { defineField, defineType } from 'sanity'

export default defineType({
  name: 'skill',
  title: 'Skill',
  type: 'document',
  fields: [
    defineField({ name: 'name', type: 'string' }),
    defineField({ name: 'icon', title: 'Icon', type: 'iconRef' }),
  ],
})

In Studio, that renders as a field editors click to open a searchable grid. They type "react" or "docker" or "mail", pick a result, and the field stores that icon's name as a plain string — e.g. "react".

What editors see

  • The collapsed field shows the chosen icon, its label, its source category, and the raw string stored in the document.
  • Clicking Select icon / Change icon opens a dialog with a search field and a category dropdown (Devicon, Material, Social, Tools, …). Results render a page at a time so the dialog opens instantly even though the whole 633-icon set is in memory.
  • Hovering a tile reveals its registry name — the exact value that gets saved.
  • A readOnly field (schema-level, or a role without write access) disables both actions and emits no patches.
  • If a document holds a name that is no longer in the bundled set — say the icon was renamed upstream — the field says so explicitly instead of rendering an empty box, and offers to replace or clear it.

Building your own input

If iconRef isn't the shape you want, the pieces are exported so you can wire the same picker into a custom schema type or reuse its matching logic:

import {
  IconPickerInput, // the input component itself
  formatCategoryLabel, // "original" -> "Devicon"
  matchesQuery, // name/label/tag matching
  rankMatch, // relevance score, lower is better
  type IconEntry, // the shape matchesQuery/rankMatch expect
} from '@web-portfolio/icons-sanity'

Social/contact links example

defineField({
  name: 'socialLinks',
  title: 'Social links',
  type: 'array',
  of: [
    defineType({
      type: 'object',
      name: 'socialLink',
      fields: [
        defineField({ name: 'icon', type: 'iconRef' }),
        defineField({ name: 'url', type: 'url' }),
      ],
    }),
  ],
})

Rendering the picked icon on your frontend

This is the part that makes the whole thing worth it — pair with @web-portfolio/icons and pass the stored string straight through as name, no transformation needed:

import { Icon } from '@web-portfolio/icons'

function SkillBadge({ skill }: { skill: { name: string; icon: string } }) {
  return (
    <span>
      <Icon name={skill.icon} size={20} />
      {skill.name}
    </span>
  )
}

What's in the icon set

633 icons from three sources, shared with @web-portfolio/icons:

  • devicon (578 icons, MIT) — programming languages, frameworks, databases, cloud platforms, dev tools.
  • Material Symbols (38 icons, Apache-2.0) — everyday UI icons: mail, call, arrows, menu, close, connected TV, bolt, translate, checklist, gift, and more.
  • Simple Icons (17 icons, CC0-1.0) — social platforms and dev-tool brands devicon doesn't cover (Instagram, YouTube, WhatsApp, MCP, LangChain, Ollama, and more).

Not sure exactly what's in there? The gallery is the fastest way to check — search or filter by category to see every icon before you commit to using it in a schema.

License

MIT — see LICENSE. Bundled icon sets keep their original licenses (devicon: MIT, Material Symbols: Apache-2.0, Simple Icons: CC0-1.0) — see the repo README for full attribution.