Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/nightshade/llms.txt

Use this file to discover all available pages before exploring further.

SmokeLayer is the animated atmospheric background of Nightshade. It fills the entire viewport with three slowly drifting color blobs that bleed into one another, producing the impression of colored smoke or aurora light shifting behind the page content. It is always mounted as part of Layout and requires no props.

How it works

The component renders a fixed inset-0 container at z-0 with opacity-30 and mix-blend-screen. Inside it, three motion.div blobs drift independently using Framer Motion’s animate prop with repeat: Infinity. A hidden SVG filter applies SVG fractal noise displacement to each blob, distorting their edges so they look organic rather than like smooth circles.

The three blobs

Each blob is a heavily blurred, large rounded div positioned in a different region of the screen. They drift along x and y keyframe paths and scale up and down in a continuous loop.
BlobColor tokenSizeInitial positionLoop duration
1witch-teal/2060% × 60%Bottom-left (-bottom-[20%] -left-[10%])25 s
2witch-plum/2050% × 50%Top-right (-top-[10%] -right-[10%])30 s
3witch-turquoise/1040% × 40%Center-left (top-[30%] left-[20%])35 s
Each blob’s animation path:
Blobx keyframesy keyframesscale keyframes
10% → 20% → 0%0% → -10% → 0%1 → 1.2 → 1
20% → -30% → 0%0% → 20% → 0%1 → 1.5 → 1
30% → 40% → 0%0% → 10% → 0%1 → 1.1 → 1
All blobs use ease: "easeInOut" and repeat: Infinity. Blobs 2 and 3 have delay: 5 and delay: 10 respectively, preventing them from starting in synchrony.

SVG fractal noise filter

A hidden <svg> element defines the smoke-filter filter using two SVG filter primitives: feTurbulence generates a fractal noise field, and feDisplacementMap uses that field to warp the blob’s pixel positions.
<feTurbulence type="fractalNoise" baseFrequency="0.01" numOctaves="3" seed="5">
  <animate
    attributeName="baseFrequency"
    values="0.01;0.015;0.01"
    dur="20s"
    repeatCount="indefinite"
  />
</feTurbulence>
<feDisplacementMap in="SourceGraphic" scale="30" />
The baseFrequency attribute is itself animated, cycling between 0.01 and 0.015 over 20 seconds. This causes the noise pattern to shift slowly over time, so the blob edges never settle into a static shape. Each blob references this filter via style={{ filter: "url(#smoke-filter)" }}.
The <svg> element carrying the filter definition must be in the DOM for the url(#smoke-filter) reference to resolve. SmokeLayer renders it as a className="hidden" sibling inside the same fixed container.

Blur levels

In addition to the SVG displacement, each blob is blurred with a Tailwind blur-* utility to soften it into a hazy cloud:
BlobBlur class
1blur-[100px]
2blur-[120px]
3blur-[80px]
The combination of Gaussian blur and fractal noise displacement produces edges that look like dispersing smoke rather than smeared circles.

Mix-blend-screen

The outer container uses mix-blend-screen, which makes the blobs brighten whatever is rendered beneath them rather than painting over it. On the very dark bg-witch-dark base, this means the blobs appear as faint luminous hazes — roughly analogous to how real colored light behaves against a dark background.
Removing mix-blend-screen will make the blobs fully opaque (at 20–30% opacity), producing harsh blocks of color rather than the subtle atmospheric glow. The blend mode is essential to the effect.

Customization

Blob colors — change the Tailwind color tokens (witch-teal/20, witch-plum/20, witch-turquoise/10) on each motion.div to shift the palette. Animation speed — lower the duration values for a more restless, stormy feel; raise them for a slower, dreamlike drift. Noise seed — changing seed="5" on feTurbulence to any other integer generates a completely different noise pattern, altering the overall shape language of the smoke without changing any other values. Blob count — adding a fourth motion.div with its own color, position, duration, and delay is all that is needed to introduce another smoke layer.

Build docs developers (and LLMs) love