Add Lucide Icons to Astro
There’s no first-class Lucide integration for Astro. But making a custom one isn’t too hard.
This is the component I made to do the job:
If this component looks reasonable to you, copy it and go forth.
If you’d like to learn how it works, let’s get it!
Our goal
For this build, our goal is to render icons directly into an Astro site — converting Lucide’s JSON files to inline <svg>
s at build time.
This is just one of many ways to add Lucide icons to a site — the one that fits my needs best.
Initial setup
Add the lucide
package.
In the standard lucide
package, icons are exported as JSON arrays with the following contents:
[0]
: "svg"
[1]
: element attributes
[2]
: children
We need to import these JSON files and render their data as HTML
.
Render a single icon
To render a single Lucide icon:
- Import any
lucide
icon - Destructure
attributes
andchildren
array items from that icon - Reduce children nodes to HTML string
- Render an
<svg>
component- Spread
attributes
directly on the element - Apply
childElements
with theset:html
directive
- Spread
Extract LucideIcon
component
Now that we can render icons, let’s extract this code as a reusable component.
- Move the relevant code to
src/components/lucide-icon.astro
- Refactor to
icon
as a prop - Take rest
...props
so HTML and SVG attributes can be applied at the call site - Merge icon
attributes
and componentprops
- Apply munged attributes-props to exported
svg
element
Use the LucideIcon
component
To use our new LucideIcon
component, import it along with any lucide
icon.
Provide the icon JSON to LucideIcon
using the icon
prop.
Apply attributes to LucideIcon
The LucideIcon
receives props that it merges with the default lucide
values.
Use these to change SVG attributes like height
, width
, fill
, and stroke-width
.
Or apply common attributes like class
and id
.
Taking it further
My preference is to keep icon importing and SVG rendering separated. But you may find this cumbersome.
If so, create a facade for LucideIcon
that exposes your favorite icons via string
interface.
This could look something like this:
Go further with TypeScript
lucide
does not expose its IconNode
type for external use.
So, if you want to use my code above in TypeScript, you’ll need to get clever.
- Import just the type of any component.
- Infer the
IconNode
for that icon in theLucideIcon
type declaration. - Add any optional
svg
attributes you’d like to support.
(e.g.,height
,width
,fill
,stroke-width
, etc.)
That’s it!
I hope that you found this useful in building an Astro site. If you’d like to see more Astro tips and tricks, bug me on Twitter/X or Discord. 😄