A powerful command-line tool to generate framework-specific icon components from SVG files. Transform your SVG icons into fully-typed, customizable components for React, Vue, Svelte, and more.
English | įŽäŊ䏿
# Using npm
npm install -D vectify
# Using pnpm
pnpm add -D vectify
# Using yarn
yarn add -D vectify
npx vectify init
This will create a vectify.config.ts file in your project root. Select your target framework and configure the paths:
import { defineConfig } from 'vectify'
export default defineConfig({
framework: 'react',
input: './icons',
output: './src/icons',
typescript: true,
optimize: true,
generateOptions: {
index: true,
types: true,
preview: true,
},
})
Place your SVG files in the configured input directory (default: ./icons):
icons/
âââ arrow-right.svg
âââ user.svg
âââ settings.svg
npx vectify generate
This will generate icon components in your output directory:
src/icons/
âââ ArrowRight.tsx
âââ User.tsx
âââ Settings.tsx
âââ index.ts
âââ Icon.tsx
import { ArrowRight, User, Settings } from './icons'
function App() {
return (
<div>
<ArrowRight size={24} color="blue" />
<User size={32} color="#333" strokeWidth={1.5} />
<Settings className="icon" />
</div>
)
}
vectify initInitialize a new configuration file.
npx vectify init [options]
Options:
-f, --force Overwrite existing config file
-o, --output Output path for config file (default: vectify.config.ts)
vectify generateGenerate icon components from SVG files.
npx vectify generate [options]
Options:
-c, --config Path to config file (default: vectify.config.ts)
--dry-run Preview what will be generated without writing files
vectify watchWatch for changes and regenerate automatically.
npx vectify watch [options]
Options:
-c, --config Path to config file (default: vectify.config.ts)
All available options for defineConfig() are documented in the tables below.
| Parameter | Type | Default | Required | Description | Example |
|---|---|---|---|---|---|
framework |
'react' | 'vue' | 'svelte' | 'solid' | 'preact' | 'lit' | 'angular' | 'qwik' | 'astro' | 'vanilla' |
- | â | Target framework for component generation. Determines component template, export style, and file extension. | framework: 'react' |
input |
string |
'./icons' |
â | Directory containing source SVG files. Can be relative or absolute path. | input: './assets/icons' |
output |
string |
'./src/icons' |
â | Directory where generated components will be saved. | output: './components/icons' |
configDir |
string |
'.' |
â | Config file directory relative to project root. Used for resolving input/output paths when config is in a subdirectory. | configDir: '../..' |
typescript |
boolean |
true |
â | Generate TypeScript components with full type definitions. Set to false for JavaScript output. |
typescript: true |
optimize |
boolean |
true |
â | Enable SVG optimization using SVGO. Reduces file size and cleans up unnecessary attributes. | optimize: true |
keepColors |
boolean |
false |
â | Preserve original colors from SVG files. When false, uses currentColor for customizable single-color icons. When true, keeps original fill/stroke colors for multi-color icons. |
keepColors: false |
prefix |
string |
'' |
â | Prefix added to all component names. Useful for namespacing. | prefix: 'Icon' â IconArrowRight |
suffix |
string |
'' |
â | Suffix added to all component names. | suffix: 'Icon' â ArrowRightIcon |
transform |
(name: string) => string |
- | â | Custom function to transform SVG filename to component name. Overrides default PascalCase conversion and prefix/suffix. | transform: (n) => 'X' + n |
format |
boolean | 'prettier' | 'eslint' | 'biome' | FormatConfig |
false |
â | Auto-format generated files after generation. See Auto Formatting for details. | format: true |
generateOptions Object| Parameter | Type | Default | Description | Example |
|---|---|---|---|---|
index |
boolean |
true |
Generate index file with aggregated exports. Export style (default vs named) is automatically determined by framework. | index: true |
types |
boolean |
true |
Generate TypeScript declaration files (.d.ts). Only applies when typescript: true. |
types: true |
preview |
boolean |
false |
Generate interactive preview.html for browsing all icons locally. Useful for design review. |
preview: true |
cleanOutput |
boolean |
false |
Remove orphaned component files that no longer have corresponding SVG files. Helps keep output directory clean. | cleanOutput: true |
Vectify can automatically format generated files using your project's formatter. This ensures generated code matches your project's code style.
Quick Start:
export default defineConfig({
framework: 'react',
input: './icons',
output: './src/icons',
format: true, // Auto-detect and use project formatter
})
Format Options:
| Value | Description |
|---|---|
false |
Disable formatting (default) |
true |
Auto-detect formatter (biome > prettier > eslint) |
'prettier' |
Use Prettier |
'eslint' |
Use ESLint --fix |
'biome' |
Use Biome |
{ tool, args } |
Full configuration object |
Auto-Detection Priority:
When format: true, Vectify looks for config files in this order:
biome.json / biome.jsonc â Uses Biome.prettierrc* / prettier.config.* â Uses Prettiereslint.config.* / .eslintrc* â Uses ESLintFull Configuration:
export default defineConfig({
format: {
tool: 'prettier', // 'auto' | 'prettier' | 'eslint' | 'biome'
args: '--single-quote', // Additional CLI arguments
},
})
Examples:
// Auto-detect formatter
format: true
// Use specific formatter
format: 'prettier'
format: 'eslint'
format: 'biome'
// With custom arguments
format: {
tool: 'prettier',
args: '--tab-width 4',
}
// Disable formatting
format: false
watch Object| Parameter | Type | Default | Description | Example |
|---|---|---|---|---|
enabled |
boolean |
false |
Enable watch mode. Automatically regenerate components when SVG files are added, modified, or deleted in the input directory. | enabled: true |
ignore |
string[] |
- | Array of glob patterns to ignore during watch. | ignore: ['**/node_modules/**', '**/.git/**'] |
debounce |
number |
300 |
Debounce delay in milliseconds before triggering regeneration. Prevents excessive rebuilds. | debounce: 500 |
svgoConfig ObjectCustomize SVG optimization behavior. Passed directly to SVGO.
| Parameter | Type | Default | Description | Example |
|---|---|---|---|---|
plugins |
any[] |
- | Array of SVGO plugin names and configurations. See SVGO documentation for available plugins. | plugins: ['preset-default', 'removeViewBox'] |
multipass |
boolean |
- | Enable multiple optimization passes for better results. | multipass: true |
... |
any |
- | Any other SVGO-supported configuration options. | - |
hooks ObjectLifecycle hooks for customizing the generation process.
| Hook | Signature | When Called | Parameters | Return Value | Common Use Cases |
|---|---|---|---|---|---|
beforeParse |
(svg: string, fileName: string) => Promise<string> | string |
After reading SVG file, before parsing | svg: Raw SVG contentfileName: SVG filename |
Modified SVG content | Pre-process SVGs, replace colors/attributes, normalize viewBox |
afterGenerate |
(code: string, iconName: string) => Promise<string> | string |
After component code generation, before writing to file | code: Generated component sourceiconName: Component name |
Modified component code | Add comments, inject exports, customize code style |
onComplete |
(stats: GenerationStats) => Promise<void> | void |
After all icons are generated | stats: Generation statistics (see below) |
void |
Log statistics, run post-processing scripts, send notifications |
GenerationStats TypeStatistics object passed to onComplete hook.
| Property | Type | Description |
|---|---|---|
success |
number |
Number of successfully generated icons |
failed |
number |
Number of failed generations |
total |
number |
Total number of SVG files processed |
errors |
Array<{ file: string; error: string }> |
Detailed error information for failed generations |
import { defineConfig } from 'vectify'
export default defineConfig({
framework: 'react',
input: './icons',
output: './src/icons',
})
export default defineConfig({
framework: 'vue',
input: './icons',
output: './src/icons',
keepColors: true, // Preserve original SVG colors
svgoConfig: {
plugins: [
'preset-default',
{
name: 'removeAttrs',
params: { attrs: '(width|height)' },
},
],
},
})
// packages/web/vectify.config.ts
export default defineConfig({
framework: 'svelte',
configDir: '../..', // Point to monorepo root
input: '../../icons', // Shared icons directory
output: './src/icons', // Package-specific output
})
export default defineConfig({
framework: 'react',
input: './icons',
output: './src/icons',
hooks: {
beforeParse: (svg, fileName) => {
// Replace black with currentColor for customization
return svg.replace(/#000000/gi, 'currentColor')
},
afterGenerate: (code, iconName) => {
// Add JSDoc comment to each component
return `/**\n * ${iconName} icon component\n * @generated by Vectify\n */\n${code}`
},
onComplete: (stats) => {
console.log(`â Generated ${stats.success}/${stats.total} icons`)
if (stats.failed > 0) {
console.error(`â Failed: ${stats.failed}`)
stats.errors.forEach(({ file, error }) => {
console.error(` ${file}: ${error}`)
})
}
},
},
})
Export Styles:
The index file automatically uses the correct export style for your chosen framework.
Naming Strategy:
arrow-right.svg â ArrowRight)prefix and suffix are applied after conversiontransform function to completely customize namingColor Strategy:
keepColors: false - Best for single-color icons that should inherit text color. Uses currentColor and allows runtime customization via the color prop.keepColors: true - Best for multi-color brand icons. Preserves original SVG fill/stroke colors.All generated components accept the following props:
interface IconProps {
// Icon size (default: 24)
size?: number | string
// Icon color (default: 'currentColor')
color?: string
// Stroke width for stroke-based icons (default: 2)
strokeWidth?: number | string
// CSS class name
className?: string
// Accessibility: icon title
title?: string
// Accessibility: aria-label
'aria-label'?: string
// Accessibility: aria-hidden
'aria-hidden'?: boolean
// All other SVG attributes
[key: string]: any
}
// Basic usage
<IconName />
// Custom size and color
<IconName size={32} color="#3b82f6" />
// With stroke width
<IconName size={24} strokeWidth={1.5} />
// With CSS class
<IconName className="my-icon" />
// With accessibility attributes
<IconName
title="User Profile"
aria-label="User profile icon"
/>
// Hidden from screen readers
<IconName aria-hidden={true} />
// With custom SVG attributes
<IconName
size={28}
color="red"
style={{ transform: 'rotate(45deg)' }}
onClick={() => console.log('clicked')}
/>
import { ArrowRight } from './icons'
function Component() {
return <ArrowRight size={24} color="blue" />
}
<script setup>
import { ArrowRight } from './icons'
</script>
<template>
<ArrowRight :size="24" color="blue" />
</template>
<script>
import { ArrowRight } from './icons'
</script>
<ArrowRight size={24} color="blue" />
import { ArrowRight } from './icons'
function Component() {
return <ArrowRight size={24} color="blue" />
}
import { ArrowRight } from './icons'
@Component({
selector: 'app-root',
template: '<ng-container *ngComponentOutlet="ArrowRight; inputs: { size: 24, color: \'blue\' }"></ng-container>',
})
export class AppComponent {
ArrowRight = ArrowRight
}
import { ArrowRight } from './icons'
const icon = ArrowRight({ size: 24, color: 'blue' })
document.getElementById('app').appendChild(icon)
â Good:
arrow-right.svg â ArrowRight
user-profile.svg â UserProfile
settings-gear.svg â SettingsGear
â Avoid:
arrow_right.svg
UserProfile.svg
settings gear.svg
// For single-color icons (default)
keepColors: false // Uses currentColor, customizable via color prop
// For multi-color icons
keepColors: true // Preserves original colors from SVG
project/
âââ icons/ # Source SVG files
â âââ arrow-right.svg
â âââ user.svg
âââ src/
â âââ icons/ # Generated components (gitignore)
â âââ ArrowRight.tsx
â âââ User.tsx
â âââ index.ts
âââ vectify.config.ts # Configuration
Add generated files to .gitignore:
# Generated icons
src/icons/
# Keep the config
!vectify.config.ts
Add to your package.json:
{
"scripts": {
"icons": "vectify generate",
"icons:watch": "vectify watch",
"postinstall": "vectify generate"
}
}
Generate icons for multiple frameworks:
// vectify.react.config.ts
export default defineConfig({
framework: 'react',
output: './packages/react/src/icons',
})
// vectify.vue.config.ts
export default defineConfig({
framework: 'vue',
output: './packages/vue/src/icons',
})
npx vectify generate -c vectify.react.config.ts
npx vectify generate -c vectify.vue.config.ts
// apps/web/vectify.config.ts
export default defineConfig({
configDir: '../..', // Relative to project root
input: '../../icons',
output: './src/icons',
})
export default defineConfig({
hooks: {
beforeParse: async (svg, fileName) => {
// Replace colors
svg = svg.replace(/#000000/g, 'currentColor')
// Add custom attributes
svg = svg.replace('<svg', '<svg data-icon="true"')
return svg
},
afterGenerate: async (code, iconName) => {
// Add custom exports
code += `\nexport const ${iconName}Name = '${iconName}'\n`
// Add JSDoc comments
code = `/**\n * ${iconName} icon component\n */\n${code}`
return code
},
},
})
typescript: true in confignpx vectify generatekeepColors: falsekeepColors: true// Before
import { FiArrowRight } from 'react-icons/fi'
<FiArrowRight size={24} />
// After
import { ArrowRight } from './icons'
<ArrowRight size={24} />
// Before
import { Icon } from '@iconify/react'
<Icon icon="mdi:arrow-right" />
// After
import { ArrowRight } from './icons'
<ArrowRight />
Contributions are welcome! Please read our contributing guidelines first.
git checkout -b feature/amazing-feature)git commit -m 'feat: add amazing feature')git push origin feature/amazing-feature)MIT Š Xiaobing Zhu
Made with â¤ī¸ by Xiaobing Zhu