CreateUI Icons
GitHub RU

Icons
for production

Zero bundle size. 11 stroke weights.
Global Edge Delivery via CDN.

1700+
icons
3 KB
gzip runtime
11
stroke weights
365d
immutable cache
weight: 1.5
<createui-icon name="sparkles" stroke="1.5"></createui-icon>

11 stroke weights · one icon

Single asset on the server, weight is a query param. Proportions and anti-aliasing handled server-side — zero client runtime for the stroke math.

stroke=0.5
stroke=0.75
stroke=1
stroke=1.25
stroke=1.5
stroke=1.75
stroke=2
stroke=2.25
stroke=2.5
stroke=2.75
stroke=3

Why traditional icons hurt

Bloated Bundles

NPM icon packages add megabytes to your JS and tank LCP. Our CDN means 0 bytes in your bundle.

DOM Pollution

Inline SVGs bloat the DOM and duplicate on SSR. Mask-image keeps your markup clean.

The Stroke Gap

Standard libraries ship one weight. We deliver 11 — from hairline to bold accents.

How It Works

User Request
Edge Cache
SVG Storage

Stroke Quantization

Any `stroke` value is rounded to a 0.25 step on the server. Visually identical, but `?stroke=1.52` and `?stroke=1.5` now share a cache key — clients can't fragment the CDN with arbitrary combinations.

Immutable Caching

Every URL is versioned: /1.17.0/heart.svg?stroke=1.5 The browser caches for 365 days with zero revalidation. To update — change the version in the URL. Old versions stay alive. New version = new URL = new cache slot. Zero invalidation, zero downtime.

Browser Support

Web Components + CSS mask-image. Works in every modern browser — baseline since 2019.

  • Chrome 77+
  • Firefox 63+
  • Safari 10.1+
  • Edge 79+

Framework Integration

Copy-paste ready snippets for any stack

<script src="https://icon.createui.dev/1.17.0/createui-icons.js" defer></script>

<createui-icon name="heart" size="24" stroke="1.5"></createui-icon>
<createui-icon name="arrow-right" aria-label="Next"></createui-icon>
import '@createui-dev/icons';
import '@createui-dev/icons/types/react';

export function Button() {
  return (
    <button>
      <createui-icon name="heart" size={20} stroke={1.5} />
      Like
    </button>
  );
}
<script setup>
import '@createui-dev/icons';
</script>

<template>
  <button>
    <createui-icon name="heart" :size="20" :stroke="1.5" />
    Like
  </button>
</template>

// vite.config.ts: mark <createui-icon> as a custom element
// vue({ template: { compilerOptions: {
//   isCustomElement: (tag) => tag === 'createui-icon',
// } } })
<script>
  import '@createui-dev/icons';
</script>

<button>
  <createui-icon name="heart" size={20} stroke={1.5} />
  Like
</button>
import '@createui-dev/icons';
import '@createui-dev/icons/types/solid';

export function Button() {
  return (
    <button>
      <createui-icon name="heart" size={20} stroke={1.5} />
      Like
    </button>
  );
}
/* Raw URL — for cases where you can't ship JS */
.icon-heart {
  display: inline-block;
  width: 24px;
  height: 24px;
  background-color: currentColor;
  mask: url('https://icon.createui.dev/1.17.0/heart.svg?stroke=1.5') no-repeat center / contain;
  -webkit-mask: url('https://icon.createui.dev/1.17.0/heart.svg?stroke=1.5') no-repeat center / contain;
}

Explore Icons

a-arrow-down
a-arrow-up
a-large-small
accessibility
activity
air-vent
airplay
alarm-clock
alarm-clock-check
alarm-clock-minus
alarm-clock-off
alarm-clock-plus
alarm-smoke
album
align-center-horizontal
align-center-vertical
align-end-horizontal
align-end-vertical
align-horizontal-distribute-center
align-horizontal-distribute-end
align-horizontal-distribute-start
align-horizontal-justify-center
align-horizontal-justify-end
align-horizontal-justify-start
align-horizontal-space-around
align-horizontal-space-between
align-start-horizontal
align-start-vertical
align-vertical-distribute-center
align-vertical-distribute-end
align-vertical-distribute-start
align-vertical-justify-center
align-vertical-justify-end
align-vertical-justify-start
align-vertical-space-around
align-vertical-space-between
ambulance
ampersand
ampersands
amphora
anchor
angry
annoyed
antenna
anvil
aperture
app-window
app-window-mac
apple
archive
archive-restore
archive-x
armchair
arrow-big-down
arrow-big-down-dash
arrow-big-left
arrow-big-left-dash
arrow-big-right
arrow-big-right-dash
arrow-big-up
arrow-big-up-dash
arrow-down
arrow-down-0-1
arrow-down-1-0
arrow-down-a-z
arrow-down-from-line
arrow-down-left
arrow-down-narrow-wide
arrow-down-right
arrow-down-to-dot
arrow-down-to-line
arrow-down-up
arrow-down-wide-narrow
arrow-down-z-a
arrow-left
arrow-left-from-line
arrow-left-right
arrow-left-to-line
arrow-right
arrow-right-from-line
arrow-right-left
arrow-right-to-line
arrow-up
arrow-up-0-1
arrow-up-1-0
arrow-up-a-z
arrow-up-down
arrow-up-from-dot
arrow-up-from-line
arrow-up-left
arrow-up-narrow-wide
arrow-up-right
arrow-up-to-line
arrow-up-wide-narrow
arrow-up-z-a
arrows-up-from-line
asterisk
astroid
at-sign
atom
audio-lines
audio-waveform
award
axe
axis-3d
baby
backpack
badge
Browse all Lucide icons

vs. the alternatives

Bundle cost compared at 50 production icons.

Metric lucide-react@iconify/reactreact-iconsCreateUI CDN
Bundle footprint +250 KB +4 KB + on-demand HTTP +45 KB (tree-shaken) 0 KB
Runtime payload Full package in JS Async JSON per icon Full package in JS 3 KB gzip + SVG on request
Stroke weights 1 1 1 11
DOM nodes per icon 1 SVG + paths 1 SVG + paths 1 SVG + paths 0 (mask-image)
Caching per-icon HTTP immutable 365 days
Framework-agnostic React only React/Vue/Svelte React only any (Web Component)

lucide-react numbers from unpkg.com/lucide-react esm.sh bundle; react-icons estimated for 50 icons after tree-shake; @iconify/react is a runtime wrapper + async fetches. CreateUI CDN is the measured gzipped runtime bundle.

Conference talk · RU

The idea behind the project

Recording of the talk that introduced the approach behind CreateUI Icons. The talk is in Russian.

Talk recording preview

FAQ

What if the CDN goes down?

Bundle and SVG endpoints are plain nginx static on a single VDS, plus 365-day browser HTTP cache. Icons already loaded survive any downtime. Paranoid mode: use the CSS snippet from the Integration section — it reads SVGs directly via URL and works even if the web component fails to load.

Does it work with SSR (Next.js, Nuxt, Remix, Astro)?

Yes. `<createui-icon>` is a custom element — it renders as an empty tag during SSR and hydrates on the client. The mask-image approach works fully at SSR — URLs in CSS are safe for any render pipeline. This site is built with Astro and uses both.

What about tree-shaking? I don't use all 1700 icons.

You don't need to. Your bundle only contains the 3 KB gzipped runtime — it can render any icon by name. Each SVG is fetched on first use, then served from cache. You pay exactly for what the user actually sees on screen.

What if Lucide renames or removes an icon?

Every version URL is immutable — `/1.11.0/foo.svg` never changes. Even if Lucide drops `foo` in 1.12.0, your production pinned to 1.11.0 keeps working. When you upgrade, you migrate once.

Can I self-host, no CDN?

Yes. The SVG storage is a flat content-addressable store (`versions/{ver}/{name}.svg`) and the Go server in `server/` is self-hostable. Point `@createui-dev/icons` at your own origin via the `icon.ts` constant. URL format stays the same.

How is it licensed?

SVG files — Lucide ISC license. Our runtime (`@createui-dev/icons`) — MIT. CDN infrastructure — public, free, no signup. Source and config on GitHub.

How current is the icon set?

Synced with Lucide every Monday 06:00 UTC. When Lucide ships a new version, a matching `@createui-dev/icons` release goes out automatically. Current version: see the footer.

Support the project

CreateUI Icons is maintained as open-source infrastructure. The CDN runs on a personal VDS; domain and traffic are paid out of pocket. If the library solves your problem, help keep it online. A single coffee ≈ one month of domain and traffic.

SYNC STATUS
CDN version
v1.16.0
npm latest (@createui-dev/icons)
v1.16.0
Last sync
5h ago
Next sync
in 7d
Updates: every Monday, 06:00 UTC