* feat(docs): add keyboard shortcuts to the icons page
Add the shortcuts suggested in #4916 and list them on the page:
- Ctrl/Cmd + click on an icon copies its name
- Arrow keys move from the search field into the results and between
the icons
- Ctrl/Cmd + C copies the name of the selected icon
- Ctrl/Cmd + Shift + C copies the SVG of the selected icon
Icons can now be focused with the keyboard, and a keyboard button next to
the sort select opens a dialog with all shortcuts, including the existing
Ctrl/Cmd + K and Shift + click. The dialog also opens with Shift + ?
(except while typing in a field).
Closes#4916
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(docs): add copy toasts, open icons with Enter and a shared Kbd component
- Copying an icon shows a toast (vue-sonner, bottom-center) that says
whether its name or its SVG was copied
- Enter opens the selected icon's drawer
- The SVG shortcut is now Shift + C, as Ctrl/Cmd + Shift + C opens the
browser's inspect tool
- Kbd component shared by the search inputs and the shortcuts dialog
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Adjust keyboard shortcuts
* Revert customizer change
* Adjust kbd style
* Fix toaster styling
* Fix types
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Eric <eric.fennis@gmail.com>
* Upgrade deps
* Fix security alerts
* Keep incompatible consumers off minimatch 11 and file-type 21
The security overrides forced minimatch 11 and file-type 21 onto every
consumer, which broke ESLint (eslint-plugin-import-x imports the removed
makeRe) and the font build (jimp 0.22 calls file-type's removed
fromBuffer). glob 7 and @eslint/eslintrc also rely on the minimatch 3
callable export. Scope those consumers back to their compatible lines.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Remove minimatch override
* Fix font build
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* chore(deps-dev): bump react-native
Bumps the react-native-deps group with 1 update in the / directory: [react-native](https://github.com/react/react-native/tree/HEAD/packages/react-native).
Updates `react-native` from 0.88.0 to 0.88.1
- [Release notes](https://github.com/react/react-native/releases)
- [Changelog](https://github.com/react/react-native/blob/main/CHANGELOG.md)
- [Commits](https://github.com/react/react-native/commits/v0.88.1/packages/react-native)
---
updated-dependencies:
- dependency-name: react-native
dependency-version: 0.88.1
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: react-native-deps
...
Signed-off-by: dependabot[bot] <support@github.com>
* fix(deps): regenerate pnpm-lock.yaml for react-native 0.88.1
Dependabot's lockfile for this bump added a second, peer-less
`vitest@5.0.3` snapshot and pointed `@vitest/coverage-v8` / `@vitest/ui`
at it. That loaded two vitest instances, which broke snapshot tests in
lucide, lucide-react, lucide-vue and lucide-react-native ("The snapshot
state ... is not found. Did you call 'SnapshotClient.setup()'?"). It also
pulled unrelated @types/node and @babel/* bumps into other importers.
Regenerated with pnpm 11.22.0 from the base lockfile, so it now only
changes the react-native tree and hermes-compiler.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G9u8Fhnpt1Di4KhMFtKbb2
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
GitHub's `ubuntu-latest` runners now resolve to Ubuntu 26.04, and
`playwright install --with-deps chromium` fails there on Playwright 1.58.2:
Cannot install dependencies for ubuntu26.04-x64 with Playwright 1.58.2!
Error: ERROR: Playwright does not support chromium on ubuntu26.04-x64
Ubuntu 26.04 support was added in Playwright 1.61, so bump the pinned
version in all integration packages to the latest stable (1.64.1). This
fixes the `integration` job in the react, vue, svelte, solid and solid-2
workflows.
Claude-Session: https://claude.ai/code/session_01G9u8FfWcVzm87hKho1ZQcc
Co-authored-by: Claude <noreply@anthropic.com>
* chore(deps): bump the build-deps group across 1 directory with 2 updates
Bumps the build-deps group with 2 updates in the / directory: [typescript](https://github.com/microsoft/TypeScript) and [rollup](https://github.com/rollup/rollup).
Updates `typescript` from 6.0.3 to 7.0.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v6.0.3...v7.0.2)
Updates `rollup` from 4.63.1 to 4.65.0
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.63.1...v4.65.0)
---
updated-dependencies:
- dependency-name: typescript
dependency-version: 7.0.2
dependency-type: direct:development
update-type: version-update:semver-major
dependency-group: build-deps
- dependency-name: rollup
dependency-version: 4.65.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: build-deps
...
Signed-off-by: dependabot[bot] <support@github.com>
* chore(deps): keep typescript on v6 and ignore v7 major updates
TypeScript 7 (the native port) ships without the JS compiler API, which
typescript-eslint, rollup-plugin-dts, svelte-package/svelte-check, astro
check, the Angular compiler, vue-tsc and @vue/compiler-sfc all depend on.
Revert typescript to ^6.0.3, keep the rollup bump, and tell dependabot to
skip typescript major updates until the ecosystem supports v7.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Eric <eric.fennis@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Update deps
* chore(deps): use next for solid-js and @solidjs/web in Solid 2 integration
Keeps the integration on the same Solid release as @lucide/solid, so the
two no longer resolve separate solid-js copies sharing one @solidjs/signals,
which broke the declaration typecheck (TS2717 on ServerObserve.trace).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* refactor(ci): move icon preview markup into a composite action
Move generateChangedIconsCommentMarkup.mts into .github/actions/icon-preview
as its own pnpm workspace package, following the suggest-metadata action.
svgson and @lucide/helpers are now real dependencies installed with a
filtered pnpm install, replacing the ad-hoc `npm install svgson --force`.
Paths are resolved from the repo root relative to the script, so it also
works through `pnpm --filter @lucide/icon-preview-action start`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(ci): skip icon preview comment when no icons changed
When a pull request only deletes icons, CHANGED_FILES has no SVGs and the
script printed "No changed icons found" to stdout, which was then posted as
the preview comment.
The script now logs that to stderr. The action writes no markup file and
sets `has-changes=false`, the workflow skips the artifact upload, and the
comment workflow skips its steps when no artifact exists instead of failing
on the missing artifact.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ci(icon-preview): post the preview comment from a pull_request_target workflow
Like the PR title workflow, the icon preview now runs on pull_request_target
and posts its comment directly, so comment-icon-preview.yml and the
workflow_run artifact hand-off are removed.
The job checks out the base branch and runs the action from there. The
changed SVGs are read from the pull request head with `git fetch` + `git show`
into a temp directory, so no code from the pull request is checked out or run.
File names are checked against `icons/<kebab-case>.svg` before use.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Track page views (initial load + client-side navigations) with the
@openpanel/web SDK, sending to the self-hosted instance at
insights.lucide.dev. This mirrors what the current Plausible script
tracks; Plausible stays in place for the icon popularity script.
Page views are sent from VitePress' onAfterRouteChange hook (after
nextTick) so the page title is already updated. Tracking only runs in
the browser and only when VITE_OPENPANEL_CLIENT_ID is set at build time.
The SDK is bundled from npm instead of loading op1.js, which EasyPrivacy
blocks; insights.lucide.dev/api/track matches no rule in the current
EasyList/EasyPrivacy, uBlock Origin or Brave lists.
Claude-Session: https://claude.ai/code/session_01AZuxmXLjrs29erwQcePCnX
Co-authored-by: Claude <noreply@anthropic.com>
* fix(scripts): keep contributors out of metadata suggestions
The shared metadata instructions include a Contributors section asking to
add the PR author, but the suggestion schema has no contributors field, so
the model leaked it into use-cases. Strip that section from the prompt and
explicitly restrict suggestions to tags, categories and use-cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MThCx7cVXV3XWfo5C327Ci
* refactor(ci): move metadata suggestions into a dedicated composite action
Move scripts/suggestMetaData.mts to .github/actions/suggest-metadata and
wrap it in a composite action with explicit inputs. The workflow now uses
the local action; package.json scripts point to the new location.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MThCx7cVXV3XWfo5C327Ci
* chore(ci): add .env.example for testing the suggest-metadata action locally
Document the env vars the script reads, point the debug/watch scripts at
an action-local .env, and fix the USE_FILE_SYSYEM typo.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MThCx7cVXV3XWfo5C327Ci
* chore(ci): make .github/actions a pnpm workspace
Add .github/actions/* to the pnpm workspace and give the suggest-metadata
action its own package.json with its dependencies (openai, zod, dotenv,
@octokit/rest). openai, zod and dotenv move out of the root package.json;
@octokit/rest stays there for updateContributors. The workflow now only
installs the action's dependencies, and the root suggest:metadata scripts
delegate to the action package.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MThCx7cVXV3XWfo5C327Ci
* Upgrade to gpt-6-luna
---------
Co-authored-by: Claude <noreply@anthropic.com>
* test(svelte): add Vite and SvelteKit integration fixtures
Scaffold a plain Svelte + Vite app (create-vite svelte-ts) and a SvelteKit
app (sv create --template minimal) that consume the built @lucide/svelte
package. Each fixture runs a production build, svelte-check and a Vitest
Browser Mode test, wired up via test:integrations:svelte and CI.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0198HmSjcE6LwPPScwLdMtjt
* test(svelte): label Pen as canonical and Edit2 as alias in fixtures
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0198HmSjcE6LwPPScwLdMtjt
---------
Co-authored-by: Claude <noreply@anthropic.com>
* ci: split lint-code into ESLint, Prettier and JSON Schema jobs with PR annotations
- ESLint: annotations via setup-node's built-in eslint-stylish problem matcher.
- Prettier: new scripts/lintFormat.mts formats unformatted files in memory, diffs
them and emits line-level `::error` annotations with the expected code.
- JSON Schema: replace ajv-cli with a local ESLint rule (Ajv draft 2020-12) that
validates icons/categories JSON against their `$schema` and reports at the
offending property. eslint-plugin-json-schema-validator was not used because it
runs Ajv in draft-07 mode and ignores `dependentRequired`.
All annotations use workflow commands, so they work on fork PRs with a read-only token.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVxEtqNswEDq1N23taZYh8
* Improve root value check and property error handling
Enhance error reporting for JSON schema validation.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* style(lint): format jsonSchemaPlugin with Prettier
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVxEtqNswEDq1N23taZYh8
* test commit
* fix(lint): annotate syntax errors from Prettier and ESLint in PRs
- ESLint/JSON Schema jobs use a small GitHub formatter that prints `::error`
workflow commands. setup-node's eslint-stylish matcher skipped parsing errors
because they have no rule id.
- lintFormat.mts annotates Prettier syntax errors (exit code 2) at their line and
column instead of only printing stderr, and still checks the other files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVxEtqNswEDq1N23taZYh8
* ci(lint): spell check icon and category metadata with cspell annotations
- New "Spelling" job runs scripts/lintSpelling.mts, which turns cspell findings
into `::error` annotations (with cspell's suggested fix when it has one).
- cspell accepts both US and British English, ignores contributor usernames and
deprecated `alias.typo` aliases.
- Add existing search tags and domain terms to .cspell/custom-words.txt so the
current metadata passes.
- Add `lint:spelling` to `pnpm lint` and lint-staged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVxEtqNswEDq1N23taZYh8
* fix(lint): pin JSON schemas per file set and drop typo tags
- json-schema/no-invalid now takes the schema from config (icon.schema.json for
icons, category.schema.json for categories) and reports a `$schema` that
points elsewhere, so metadata can't opt out of validation.
- Remove the misspelled `frigerator` and `sterisk` tags and their allowlist entries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVxEtqNswEDq1N23taZYh8
* fix(icons): split joined-word tags into separate words
Tags like `groupchat` and `timemachine` become `group chat` and `time machine`
so they read naturally and pass the spell check without allowlisting. Where the
spaced tag already existed (`smart home`) the joined one is dropped.
cspell now skips all alias names, since they are icon names that can't change
(e.g. the deprecated `palmtree` alias).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVxEtqNswEDq1N23taZYh8
* Revert
* Try another error
* Revert error
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Updates needed to support Solid 2
* Switch to the next tag
* feat(packages): add `@lucide/solid` package for Solid 2
Solid 2's API is a breaking change from Solid 1 and is still an RC, so
`lucide-solid` stays on Solid 1 (`solid-js: ^1.4.7`) untouched and Solid 2
support ships as a new `packages/solid` package named `@lucide/solid` —
the same scheme already used by `@lucide/svelte` and `@lucide/angular`.
The package is a copy of `lucide-solid` on the `@lucide/shared` build
architecture, ported to Solid 2:
- `splitProps` -> `omit`, `solid-js/web` -> `@solidjs/web`,
`JSXElement` -> `Element`, `Context.Provider` -> `<Context value>`
- `jsxImportSource` is `@solidjs/web` in tsconfig, the esbuild step and
`ts.createProgram`; rollup externals drop the removed `solid-js/store`
- `vite-plugin-solid` -> `@solidjs/vite-plugin`
- tests keep upstream's coverage with two Solid 2 adaptations: boolean
attribute literals must be strings (`aria-hidden="false"`), and writes
are batched so the reactivity tests need a `flush()` before asserting
Rendered output is unchanged — the snapshots are byte-identical to
`lucide-solid`'s.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs(solid): fix React leftovers in the Solid guide
The Solid guide was derived from the React guide and three things were
not carried across:
- `advanced/typescript.md` still told readers the types are for "a
TypeScript React project"
- its `LucideIcon` example kept React's destructured-props signature.
The `: ButtonProps` annotation had also been dropped in the copy, so
`ButtonProps` was declared but unused and the parameters were
implicitly `any`. Destructuring props breaks reactivity in Solid —
verified: with `({ icon: Icon, label })` a changing `label` never
reaches the DOM, while `props.label` updates correctly.
- `advanced/aliased-names.md` had an orphaned `###` heading; its parent
`## Choosing import name style` was dropped during the conversion
because it documents React-only subpath exports.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: type the shared Sandpack wrapper with `SandpackProps`
The base Sandpack wrapper declared its props as
`FunctionalComponent<LucideProps>` with `LucideProps` imported from
`@lucide/vue`, which has nothing to do with a Sandpack embed. None of
the props the markdown plugin actually passes (`template`, `files`,
`options`, `customSetup`, `theme`) were declared, so they only reached
the inner `<Sandpack />` via Vue's fallthrough attributes.
Declare `SandpackProps` from `sandpack-vue3` instead and forward them
explicitly. This also removes the `@lucide/vue` import that made every
framework guide — including the Solid one, which uses this wrapper
directly — appear to reference the Vue package.
Verified with a full `vitepress build`: each framework guide's chunk
still carries its own template (react/vue/vite-svelte/vanilla/
vite-solid) and all five props reach the component.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs(solid): document the Solid 2 flavour in the getting started guide
The Solid guide teaches `lucide-solid` throughout (64 references), so
the one-line note about `@lucide/solid` left Solid 2 readers on a page
whose every install command and live example is Solid 1 — and the
packages list points `@lucide/solid` at this same page.
Replace that note with a "Using Solid 2?" callout holding its own
tabbed install group, the import-specifier swap, and a table of the
Solid 2 changes that affect code written around Lucide (`@solidjs/web`,
`jsxImportSource`, `splitProps` -> `omit`, `<Ctx value>`), linking out
to Solid's own migration guide for the rest.
The claim that both packages expose the same components and props is
checked, not assumed: `dist/types/lucide-solid.d.ts` is identical
between the two packages, and the only differences anywhere in the
public type surface are Solid's own renames (the `JSX` namespace source
and `JSXElement` -> `Element`).
Keeps one guide section for both packages, matching how upstream
handles the two Svelte packages.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(solid): port lucide-solid to Solid 2
- Icon/context/types use Solid 2 APIs: omit() instead of splitProps(),
Dynamic and JSX types from @solidjs/web.
- solid-js / @solidjs/web 2.0 (rc) as peer and dev dependencies,
babel-preset-solid 2; rollup and tsconfig updated to match.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Add integration test
* Update rollup file
* Fix tests
* Revert lucide-solid changes
* update lockfile
* Fix docs
* Format code
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Eric <eric.fennis@gmail.com>
* test(lucide-solid): add Vite and SolidStart integration fixtures
Mirror the `lucide-react` integration suite for `lucide-solid`. Both
fixtures are scaffolded by `pnpm create solid` and consume the built
package through its public entry points only:
- `integrations/lucide-solid/vite` (vanilla/basic template)
- `integrations/lucide-solid/solid-start` (solid-start-v2/basic template)
Each runs a production build, `tsc --noEmit`, and a Vitest Browser Mode
test in Chromium under a `check` script, wired into the new root
`test:integrations:solid` script and an `integration` job on the
`lucide-solid` workflow.
The showcase exercises the bare export, per-icon props, `LucideProvider`,
an alias against its canonical icon, and the `lucide-solid/icons/circle`
deep import. `lucide-solid` has no `DynamicIcon`, so the deep import
takes the place of the React fixtures' dynamic-icon block. The SolidStart
spec additionally navigates between two routes.
Both fixtures resolve the package through its `solid` export condition
and compile the raw JSX in `dist/source`; the SolidStart build bundles it
into the SSR server chunk.
Each fixture carries a second TypeScript project,
`tsconfig.declarations.json`, that compiles the showcase with
`skipLibCheck: false` so the declarations shipped in `dist/types` are
actually read. That catches a `.d.ts` pointing at a file the build never
emitted, which the app typecheck silently degrades to `any`.
`@solidjs/start@2` requires Vite 8 while the repository pins Vite 7, so
the SolidStart fixture is released from that pin by a parent-scoped
`'@lucide/integration-solid-solid-start>vite'` override. Only that
importer resolves to Vite 8; every other package stays on 7.3.6.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAmVJZqdypLNwEFhCmfsPN
* fix(solid): align SolidStart fixture with Vite 7
* Upgrade vite dependency from 7.3.6 to 8.3.2
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Update README.md to clarify Vite overrides
Removed duplicate note about bug #4846 and added a section on Vite overrides.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(docs): persist icon customizer settings
Persist icon color, size, stroke width, and absolute stroke width between page navigations and reloads.
Keep a shared icon style state across the homepage and icons page, clamp the homepage preview size to its supported range, and apply persisted absolute stroke settings after mount.
* fix(docs): avoid icon customizer hydration flicker
Initialize persisted icon settings synchronously and apply absolute stroke width before the first rendered state.
* fix(docs): restore icon styles before first paint
Apply stored icon styles from a head script before hydration, defer customizer visibility until mount, and render persisted switches on the client to avoid stale SSR classes. Keep absolute stroke state synchronized globally and cover prepaint initialization with regression tests.
* fix(site): persist icon customizer
* fix(packages/react): update vulnerable @tanstack packages
* fix(docs): persist icon customizer settings
Persist icon color, size, stroke width, and absolute stroke width between page navigations and reloads.
Keep a shared icon style state across the homepage and icons page, clamp the homepage preview size to its supported range, and apply persisted absolute stroke settings after mount.
* fix(docs): avoid icon customizer hydration flicker
Initialize persisted icon settings synchronously and apply absolute stroke width before the first rendered state.
* fix(docs): restore icon styles before first paint
Apply stored icon styles from a head script before hydration, defer customizer visibility until mount, and render persisted switches on the client to avoid stale SSR classes. Keep absolute stroke state synchronized globally and cover prepaint initialization with regression tests.
* fix(site): persist icon customizer
* fix(packages/react): update vulnerable @tanstack packages
* fix(site): generalize usePersistedIconStyle to reduce code duplication in icon customizers
* fix(site): home size slider now uses max="256", matching the sidebar
* fix(site): fix linting issues in iconStyleHead.js
* fix(site): make Switch.vue hydration safe
* fix(site): fix home icon customizer color input width
* fix(site): make home icon customizer not persistent
* fix(site): fix duplicate ids in sidebar icon customizer as well
* fix(site): various minor fixes to the customizer bl
* fix(site): revert "[default]" placeholder
---------
Co-authored-by: epifaniofrancisco <epifaniofrancisco03@gmail.com>
Mirror the lucide-react integration tests for `@lucide/vue`. Each fixture is
scaffolded with the framework's official generator (`pnpm create vue@latest`,
`pnpm create nuxt@latest`, `pnpm create vike@latest --vue`), trimmed of demo
boilerplate, and runs a production build, `vue-tsc`, and a Vitest Browser Mode
test in Chromium that renders the public `@lucide/vue` APIs (static icon,
per-instance props, `setLucideProps` context, alias vs canonical icon).
Nuxt is pinned to 4.4.8: 4.5.x requires Vite 8, which the workspace-wide
`vite: ^7.3.6` override does not allow.
Wire it up with a `test:integrations:vue` root script and an `integration`
job in the Lucide Vue workflow.
Claude-Session: https://claude.ai/code/session_01KmQsnSECZoNxh1GJ15BmdH
Co-authored-by: Claude <noreply@anthropic.com>