Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/.navigation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
title: Nuxt Icon
106 changes: 106 additions & 0 deletions docs/1.usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
title: Usage
description: 'Render any of the 200,000+ Iconify icons, or your own Vue components.'
---

**Props:**
- `name` (required): icon name or global component name
- `size`: icon size (default: `1em`)
- `mode`: icon rendering mode (`svg` or `css`, default: `css`)

**Attributes**:

When using an icon from Iconify, a `<span>` or `<svg>` will be created based on the rendering mode, you can give [all the attributes](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute) of the native element.

```html
<Icon name="uil:github" style="color: black" />
```

**TailwindCSS v4**:

When using TailwindCSS v4 with the `css` mode, you should configure the `cssLayer` in Nuxt's app config:

```ts
// ~/app.config.ts
export default defineAppConfig({
icon: {
mode: 'css',
cssLayer: 'base'
}
})
```

## Iconify Dataset

You can use any name from the https://icones.js.org collection:

```html
<Icon name="uil:github" />
```

It supports the `i-` prefix (for example, `i-uil-github`).

It's highly recommended to install the icon data locally with

```bash
npm i -D @iconify-json/collection-name
```

For example, to use the `uil:github` icon, install its collection with `@iconify-json/uil`. This way the icons can be served locally or from your serverless functions, which is faster and more reliable on both SSR and client-side.

> [!NOTE]
> You may also know you can install `@iconify/json` package to include all iconify icons. This is not recommended because it will increase your server bundle size and building performance. If you choose to do so, we'd recommend to explicitly specify the collection names you need:
>
> ```ts
> export default defineNuxtConfig({
> modules: ['@nuxt/icon'],
> icon: {
> serverBundle: {
> collections: ['uil', 'mdi'] // <!--- this
> }
> }
> })
> ```

## Vue Component

When the `name` matches a global registered component, it will be rendered as that component (in this case `mode` will be ignored):

```html
<Icon name="MyComponent" />
```

Note that `MyComponent` needs to be inside `components/global/` folder (see [example](https://github.com/nuxt/icon/blob/main/playgrounds/nuxt/components/global/NuxtLogo.vue)).

> [!TIP]
> You can also change the component name with:
>
> ```ts
> export default defineNuxtConfig({
> icon: {
> componentName: 'NuxtIcon'
> }
> })
> ```

## Render Function

You can use the `Icon` component in a render function (useful if you create a functional component), for this you can import it from `#components`:

```ts
import { Icon } from '#components'
```

See an example of a `<MyIcon>` component:

```vue
<script setup>
import { Icon } from '#components'

const MyIcon = h(Icon, { name: 'uil:twitter' })
</script>

<template>
<p><MyIcon /></p>
</template>
```
36 changes: 36 additions & 0 deletions docs/2.configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: Configuration
description: 'Every option of the icon key in your Nuxt config.'
---

Configure Nuxt Icon with the `icon` key in your `nuxt.config.ts`:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
modules: ['@nuxt/icon'],
icon: {
mode: 'css',
cssLayer: 'base'
}
})
```

## Options

| Option | Default | Description |
| --- | --- | --- |
| `size` | `undefined` | **Icon Size** — Set the default icon size. |
| `class` | `''` | **CSS Class** — Set the default CSS class. |
| `mode` | `'css'` | **Default Rendering Mode** — Set the default rendering mode for the icon component |
| `aliases` | `{}` | **Icon aliases** — Define Icon aliases to update them easily without code changes. |
| `cssSelectorPrefix` | `'i-'` | **CSS Selector Prefix** — Set the default CSS selector prefix. |
| `cssLayer` | `undefined` | **CSS Layer Name** — Set the default CSS `@layer` name. |
| `cssWherePseudo` | `true` | **Use CSS `:where()` Pseudo Selector** — Use CSS `:where()` pseudo selector to reduce specificity. |
| `collections` | `null` | **Icon Collections** — List of known icon collections name. Used to resolve collection name ambiguity. e.g. `simple-icons-github` -> `simple-icons:github` instead of `simple:icons-github` When not provided, will use the full Iconify collection list. |
| `customCollections` | `null` | **Custom Icon Collections** |
| `provider` | `undefined` | **Icon Provider** — Provider to use for fetching icons - `server` - Fetch icons with a server handler - `iconify` - Fetch icons with Iconify API, purely client-side - `none` - Do not fetch icons (use client bundle only) `server` by default; `iconify` when `ssr: false` Use `{ server, client }` to set a different provider for SSR and for the browser, e.g. `{ server: \'server\', client: \'iconify\' }`. A string is the same as setting both sides. Both `server` and `client` are required in the object form. |
| `iconifyApiEndpoint` | `'https://api.iconify.design'` | **Iconify API Endpoint URL** — Define a custom Iconify API endpoint URL. Useful if you want to use a self-hosted Iconify API. Learn more: https://iconify.design/docs/api. |
| `fallbackToApi` | `true` | **Fallback to Iconify API** — Fallback to Iconify API if server provider fails to found the collection. |
| `localApiEndpoint` | `'/api/_nuxt_icon'` | **Local API Endpoint Path** — Define a custom path for the local API endpoint. |
| `fetchTimeout` | `1500` | **Fetch Timeout** — Set the timeout for fetching icons. |
| `customize` | `undefined` | **Customize callback** — Customize icon content (replace stroke-width, colors, etc...). |
241 changes: 241 additions & 0 deletions docs/3.bundles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
---
title: Server & Client Bundle
description: 'Choose how icons are served by your Nuxt server, and which ones ship with the client.'
---

## Server Bundle

Since `@nuxt/icon` v1.0, we have introduced the server bundle concept to serve the icons from Nuxt server endpoints. This keeps the client bundle lean and able to load icons on-demand, while having all the dynamic features to use icons that might not be known at build time.

### Server Bundle Mode: `local`

This mode will bundle the icon collections you have installed locally (like `@iconify-json/*`), into your server bundle as dynamic chunks. The collection data will be loaded on-demand, only when your client request icons from that collection.

### Server Bundle Mode: `remote`

Introduced in `@nuxt/icon` v1.2, you can now use the `remote` server bundle to serve the icons from a remote CDN.

```ts
export default defineNuxtConfig({
modules: [
'@nuxt/icon'
],
icon: {
serverBundle: 'remote',
},
})
```

Or you can specify the remote provider:

```ts
export default defineNuxtConfig({
modules: [
'@nuxt/icon'
],
icon: {
serverBundle: {
remote: 'jsdelivr', // 'unpkg' or 'github-raw', or a custom function
}
},
})
```

Which will make server requests to `https://cdn.jsdelivr.net/npm/@iconify-json/ph/icons.json` to fetch the icons at runtime, instead of bundling them with your server.

Under the hood, instead of bundling the collection into your server:

```ts
() => import('@iconify-json/ph/icons.json')
```

it will now use something like this, where the collections are not inlined:

```ts
() => fetch('https://cdn.jsdelivr.net/npm/@iconify-json/ph/icons.json').then(res => res.json())
```

This would be useful when server bundle size is a concern, like in serverless or worker environments.

### Server Bundle Mode: `auto`

This is the default option, where the module will pick between `local` and `remote` based your deployment environment. `local` will be preffered unless you are deploying to a serverless or worker environment, like Vercel Edge or Cloudflare Workers.

### Externalize Icons JSON

By default, Nitro will bundle the icon collections you have installed locally (like `@iconify-json/*`), into your server bundle as dynamic chunks. When you have a large number of icons, this might make your bundling process slow and memory-intensive. You can change to externalize the icons JSON files by setting `icon.serverBundle.externalizeIconsJson` to `true`.

```ts
export default defineNuxtConfig({
modules: [
'@nuxt/icon'
],
icon: {
serverBundle: {
externalizeIconsJson: true,
}
},
})
```

Note that this will require your production Node.js server to be able to import JSON files (Note that as in Node.js v22, [JSON modules are still an experimental feature](https://nodejs.org/api/esm.html#json-modules)). In the final build, it will contain statements like `() => import('@iconify-json/ph/icons.json', { with: { type: 'json' } })`.

Also note that in some serverless environments, like Cloudflare Workers, where they don't have dynamic imports, they will always be inlined regardless of this option.

This option will be ignored when `icon.serverBundle.remote` is enabled.

### Completely Disable Server Bundle

If you want to disable the server bundle completely, you can set `icon.serverBundle` to `false` and `provider` to `iconify`

```ts
export default defineNuxtConfig({
modules: [
'@nuxt/icon'
],
icon: {
provider: 'iconify',
serverBundle: false,
},
})
```

This will make requests to Iconify API every time the client requests an icon. We do not recommend doing so unless the other options are not feasible.

### Separate Server and Client Providers

`provider` can also be set separately for SSR and for the browser.

```ts
export default defineNuxtConfig({
modules: [
'@nuxt/icon'
],
icon: {
// SSR uses the server bundle through the local endpoint, the browser fetches from the Iconify API directly
provider: { server: 'server', client: 'iconify' },
iconifyApiEndpoint: 'https://icons.example.com',
serverBundle: {
collections: ['ph', 'lucide'],
},
},
})
```

- A string `provider: X` is the same as `{ server: X, client: X }`.
- The local endpoint is enabled when at least one side uses `server`, and so is the server bundle unless `serverBundle` is `false`. This is decided at build time, so overriding `provider` in `app.config.ts` does not enable or disable them.
- `provider` in `app.config.ts` is not validated: set both `server` and `client` there too. A side left out is taken from the module options when they also use the object form; otherwise it is treated as unset and falls back to the `iconify` provider.
- Unless both sides use `server`, `clientBundle.includeCustomCollections` defaults to `true`, since the client bundle is also used during SSR.

## Client Bundle

For icons that you know you are going to use frequently, you can bundle them with your client bundle to avoid network requests.

### Prefetch (Preload) Icons

If you want icons to be available on first render, use the client bundle as the prefetch mechanism:

```ts
export default defineNuxtConfig({
modules: [
'@nuxt/icon',
],
icon: {
clientBundle: {
// Explicitly pre-bundle known icons
icons: ['uil:github', 'heroicons:home'],
// Keep disabled if you only want explicit entries
scan: false,
},
},
})
```

You can also enable static scanning to pre-bundle icons referenced literally in your source files:

```ts
export default defineNuxtConfig({
modules: [
'@nuxt/icon',
],
icon: {
clientBundle: {
// Automatically includes statically-detected icon usages
scan: true,
// Keep explicit entries for dynamic icon names
icons: ['uil:github'],
},
},
})
```

If you want to disable runtime icon fetching entirely, see [Disabling Runtime Fetching](/modules/icon/custom-collections#disabling-runtime-fetching) for the `provider: 'none'` + client bundle pattern.

> [!TIP]
> Static scanning only detects literal icon names. See [Scan Components](#scan-components) for details and examples, and [Rendering Icons in Component Tests](/modules/icon/testing) for test-environment setup.

### Available Options

```ts
export default defineNuxtConfig({
modules: [
'@nuxt/icon'
],
icon: {
clientBundle: {
// list of icons to include in the client bundle
icons: [
'uil:github',
'logos:vitejs'
],

// scan all components in the project and include icons
scan: true,

// include all custom collections in the client bundle
includeCustomCollections: true,

// guard for uncompressed bundle size, will fail the build if exceeds
sizeLimitKb: 256,
},
},
})
```

`includeCustomCollections` will include all the custom collections you have defined in `icon.customCollections` in the client bundle. It's disabled by default when both sides of `provider` use `server`, and enabled otherwise (e.g. when `ssr: false` is set).

### Scan Components

When `scan` is enabled, the module will scan all the components in your project and include the icons used in the client bundle. This would significantly reduce the number of network requests needed for statically known icons, but might also increase the client bundle size depending on the number of icons used in your project.

You can also fine-tune tine scanning targets like:

```ts
export default defineNuxtConfig({
modules: [
'@nuxt/icon'
],
icon: {
clientBundle: {
scan: {
// note that when you specify those values, the default behavior will be overridden
globInclude: ['components/**/*.vue', /* ... */],
globExclude: ['node_modules', 'dist', /* ... */],
},
},
},
})
```

> [!TIP]
> Scanning is relying on static analysis, which means only literal usages will be detected. Avoid constructing the icon name dynamically whenever possible.
>
> ```vue
> <template>
> <!-- Avoid this -->
> <Icon :name="`carbon:${dark ? 'moon' : 'sun'}`" />
>
> <!-- Prefer this -->
> <Icon :name="dark ? 'carbon:moon' : 'carbon:sun'" />
> </template>
> ```
Loading
Loading