THE FIELD GUIDE

From the first flake
to your own forecast.

Install the package, choose a surface, and start the weather. Practical documentation for a considered integration.

GETTING STARTED

Your first snowfall.

Fluri’s packages are prepared for their first npm release. You can use the built package archives from this site today. Download them, then install the local files in your project.

Install the downloaded core
npm install ./themes-fluri-0.1.0.tgz

After registry publication, the package name is @themes/fluri. The optional adapter is @themes/fluri-react. These downloads contain compiled ESM, TypeScript declarations, README, and MIT licensing.

Start in the browser
import { createWeather } from '@themes/fluri';

const weather = createWeather({
  preset: 'gentle-snow',
  dom: { detection: 'explicit' },
});

weather.start();

// Release the effect when your page unmounts.
window.addEventListener('pagehide', () => {
  weather.destroy();
}, { once: true });
Start after the DOM exists.

Importing the library and creating an idle controller are safe during server rendering. Call start() in the browser after mount. autoStart defaults to false.

Bring your own framework.

The core uses browser APIs. Use the React adapter for automatic lifecycle cleanup, or pair the controller with your framework’s mount and unmount hooks.

For React, install both archives with React already in your application:

Install the React adapter
npm install ./themes-fluri-0.1.0.tgz ./themes-fluri-react-0.1.0.tgz
TypeScript integration
import { createWeather } from '@themes/fluri';

const weather = createWeather({
  preset: 'gentle-snow',
  dom: { detection: 'explicit' },
});

weather.start();

// Release the effect when your page unmounts.
window.addEventListener('pagehide', () => {
  weather.destroy();
}, { once: true });

Next.js integrations belong in a client component with 'use client'. The React hook starts after mount and cleans up on unmount; it is safe with Strict Mode setup replay.

Give snow a place to land.

For predictable behavior, choose explicit detection and label the elements you want to collect snow. Keep important controls and dense content clear.

Choose surfaces in HTML
<article data-weather-surface data-weather-snow-depth="14">
  Snow can settle here.
</article>
<section data-weather-ignore>
  Keep this content clear.
</section>
Register a surface in JavaScript
const unregister = weather.registerSurface(element, {
  material: 'sticky',
  maxSnowDepth: 12,
  layer: 'content',
});

// Remove this registration when it is no longer needed.
unregister();

Supported materials: flat, slippery, sticky, and no-accumulation. Explicit surfaces can override depth, accumulation, layer, and clipping behavior.

Set your forecast.

Start from one of the ten presets and override only the values you need. Configuration is validated at runtime and fully typed.

A considered starting point
const weather = createWeather({
  preset: 'gentle-snow',
  snow: {
    intensity: 0.45,
    wind: { base: 0.12, gusts: true },
    accumulation: { maxDepth: 14 },
  },
  dom: { detection: 'explicit', maxSurfaces: 60 },
  performance: { adaptive: true, maxDPR: 1.5 },
  accessibility: { reducedMotion: 'respect' },
});

Use the playground to change options live and export validated JSON. The complete API reference documents defaults, ranges, attributes, events, and plugin hooks.

Share your website, on your terms.

The library has no automatic installation reporting or visitor analytics. Owners can separately register a domain, verify control, and choose whether to share daily aggregate counts or request a public community listing. Website-owner approval does not replace any visitor consent required by the source analytics.

Register or manage a website ↗ · Read the reporting and privacy guide ↗

Keep control of the weather.

Common controller methods
Method What it does
start() Create the overlays and start the simulation.
pause() / resume() Temporarily pause or resume the effect.
stop() Stop the animation and clear its visuals.
destroy() Release overlays, listeners, observers, and plugins.
setIntensity(0.5) Change snowfall intensity from 0 to 1.
setPreset('minimal') Switch preset at runtime.
updateConfig(patch) Apply a typed partial configuration.
addSnow(8) / clearAccumulation() Add deposited snow or clear it.
trigger('gust') Trigger an intentional effect.
getMetrics() Read runtime budgets, counts, state, and timings.

Store the controller in your page or component lifecycle. Destroy it when the owning page or component leaves. A destroyed controller cannot be restarted; create a new instance for a new lifecycle.

A little Christmas, on purpose.

The Christmas module is a separate import. Choose its effects, then label the surfaces where each should appear.

Enable seasonal effects
import { christmasPack } from '@themes/fluri/christmas';

const removeChristmas = weather.use(christmasPack({
  lights: { warmth: 0.9 },
  garlands: true,
  frost: true,
}));

// Remove this plugin independently when the season ends.
removeChristmas();
Place the decorations
<nav data-weather-surface
     data-holiday-lights
     data-holiday-garland>
  A warmer welcome.
</nav>

Other supported effects include ornaments, gifts, icicles, wreaths, sparkle, and candy canes. See the API reference for each option and attribute.

Leave room for the rest of your page.

Keep adaptive performance enabled. It bounds the requested snowfall by visible area and device input class, responds to sustained late frames, and reduces rendering detail under pressure. Overflow parcels are bounded and coalesced.

  • Start with a gentle or minimal preset and explicit surfaces.
  • Use dom.maxSurfaces, snow.particleCount, performance.maxDPR, and performance.maxFPS to set your budget.
  • Measure on your own page and physical target devices.
  • Inspect getMetrics() or the playground’s Quality panel.

Performance depends on the browser, device, page styles, and effects. A local benchmark is not a cross-device guarantee.

Make motion optional.

The default accessibility.reducedMotion: 'respect' honors the operating-system reduced-motion preference. Hidden tabs suspend animation. Offer visitors an accessible pause control if you add a continuous effect.

Connect your pause button
const pause = document.querySelector('button');
pause?.addEventListener('click', () => {
  const paused = weather.getMetrics().state === 'paused';
  if (paused) weather.resume();
  else weather.pause();
  pause.setAttribute('aria-pressed', String(!paused));
});

Snow is decorative. Keep important information in normal HTML, preserve readable contrast, and test keyboard and touch behavior with the effect running.

Know the edges.

Fluri uses an approximation of supported DOM geometry, clipping, and paint order. It cannot exactly reproduce arbitrary CSS composition or a true three-dimensional simulation.

  • Closed shadow-root internals and cross-origin iframe contents are not inspectable.
  • Complex masks, perspective transforms, and some native top layers have limits.
  • Automatic surface detection is heuristic; use explicit registration for reliable control.
  • Browser emulation does not replace testing on a physical phone.
Read the complete limitations