Skip to content

weburz/particle-canvas

@weburz/particle-canvas

npm version npm downloads License Status Nuxt

Zero-dependency animated particle canvas for Nuxt 4. Drop-in <ParticleCanvas /> component, ~10 KB / ~3 KB gzipped, TypeScript-first.

Status: experimental. Pre-1.0 — the API may shift.

  • ✨ Auto-imported <ParticleCanvas /> component
  • 🪶 Zero runtime dependencies
  • 🎯 SSR-safe — engine runs only in the browser via a window guard
  • 🎨 Linked-line constellations, hover/click interactions, density-aware scaling
  • 🟦 First-class TypeScript types

Install

pnpm add @weburz/particle-canvas
# or npm install / yarn add
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@weburz/particle-canvas'],
})

That's it — <ParticleCanvas /> now auto-imports and works with sensible built-in defaults (see ParticleConfig below). Add a particleCanvas block only if you want app-wide overrides:

// nuxt.config.ts — optional
export default defineNuxtConfig({
  modules: ['@weburz/particle-canvas'],

  particleCanvas: {
    // Applied to every <ParticleCanvas> that doesn't pass a `config` prop.
    // A per-component `:config` deep-merges over these for group fields
    // (linked, interaction, density).
    defaults: {
      count: 100,
      color: ['#a3c4e0', '#ffd86b'],
    },
  },
})

Usage

Drop the component anywhere — it auto-imports.

<template>
  <div class="hero">
    <ParticleCanvas
      :config="{
        count: 150,
        linked: { enable: true, distance: 140, color: '#a3c4e0', width: 1, opacity: 0.4 },
      }"
    />
    <h1>Hello</h1>
  </div>
</template>

<style scoped>
.hero { position: relative; height: 100vh; }
.hero > :first-child { position: absolute; inset: 0; }
</style>

The composable short-circuits when window is undefined, so the engine never executes during SSR. The <canvas> element itself renders identically on server and client, so there's no hydration mismatch.

Module options

Option Type Default Description
defaults ParticleConfig {} Config applied when <ParticleCanvas> is rendered without a config prop
prefix string "" Component name prefix, e.g. "Weburz"<WeburzParticleCanvas>

ParticleConfig

All fields are optional. Group fields (linked, interaction.hover, interaction.click, density) merge field-by-field over the defaults below, so you can override just the field you care about. Range pairs (size, opacity, speed) are replaced atomically — pass both min and max.

Field Default Description
count 100 Base particle count (scaled by density if enabled)
color "#FFF" Single hex color, or array for randomized colors
size { min: 1, max: 3 } Radius range in px
opacity { min: 0.3, max: 0.8 } Per-particle opacity range
speed { min: 0.2, max: 0.6 } Velocity magnitude range
direction "none" "none" | "top" | "bottom" | "left" | "right"
outMode "out" "out" (wrap) or "bounce"
linked enabled Constellation lines between nearby particles
interaction.hover repulse "grab" | "repulse" | "bubble"
interaction.click push "push" | "repulse"
density enabled Scale particle count to canvas area

API

  • <ParticleCanvas :config="..." /> — auto-imported component
  • useParticleSystem(canvasRef, config) — auto-imported composable, returns { mount, unmount }

Both are typed via the exported ParticleConfig, Particle, and RGB types.

Contribution

Local development
pnpm install
pnpm run dev:prepare   # generate Nuxt type stubs
pnpm run dev           # run the playground
pnpm run test
pnpm run lint
Pre-commit hooks

This repo uses pre-commit to enforce formatting, lint staged files, and validate commit messages (conventional-commits style, required by changelogen for the auto-generated CHANGELOG).

Install it once per clone:

# If you don't have pre-commit yet:
brew install pre-commit          # macOS / Linuxbrew
# or: pipx install pre-commit
# or: pip install --user pre-commit

# Activate the hooks in this repo:
pnpm setup:hooks

What runs on every git commit:

Hook Purpose
trailing-whitespace Strips trailing whitespace from staged lines
end-of-file-fixer Ensures every file ends with one newline
check-yaml Validates YAML syntax
check-added-large-files Rejects staged files larger than 500 KB
no-commit-to-branch Blocks direct commits to main — work on a branch and open a PR
eslint Lints staged .vue / .js / .ts files
crisp (commit-msg) Enforces conventional-commit message format (feat:, fix:, …)

Skip hooks for a single commit with git commit --no-verify (use sparingly).

Prior art

The <ParticleCanvas> API surface — particularly the effect names (grab, repulse, bubble, push) and the linked-constellation rendering — draws on particles.js by Vincent Garreau and its modern successor tsParticles by Matteo Bruni. This module is a smaller, Nuxt-native take focused on a single preset, with no runtime dependencies.

License

MIT © Weburz

About

Zero-dependency animated particle canvas for Nuxt 4. Drop-in <ParticleCanvas /> component — ~10KB minified / ~3KB gzipped, TypeScript-first.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors