Skip to content

FreeIn reviewv1.0.0

Cosmos

Deep space: a folding nebula, dark dust lanes, a soft core and stars at three depths that drift with the pointer.
npx shadcn@latest add @vibebox/cosmos

Controls

1
1
<Cosmos />

About

A nebula from noise: the plane is warped by its own noise and then warped again, which makes it fold like smoke; a three-colour gradient runs through the folds and ridged noise cuts dark lanes. A soft elliptical core sits where the gas is densest. Stars are cell-based points at three scales, the nearer ones drifting further with the pointer. In warp mode the star field is sampled in log-polar coordinates and stretched radially, so the points become streaks that run outward.

Use it when

  • An AI, data or developer product wants a dark, calm hero with depth.
  • A planetarium, science or education page wants space without a stock photo.
  • A launch or countdown wants the warp look for its moment.

Skip it when

  • The brand is warm, local and tactile; use Satin or Bokeh.
  • Text must sit over the bright core.

Install

  1. 1Add the VibeBox registry to components.json:
    {
      "registries": {
        "@vibebox": "https://motion.vibeboxph.com/r/{name}.json"
      }
    }
  2. 2Add the component with the shadcn CLI:
    npx shadcn@latest add @vibebox/cosmos
  3. 3Use it:
    import { Cosmos } from "@/components/vibebox/cosmos";
    
    <Cosmos preset="nebula" className="min-h-[560px] rounded-xl">
      <div className="p-12 text-white">
        <h1 className="text-4xl font-semibold">Build for the long distance.</h1>
      </div>
    </Cosmos>

Code

3 files
components/vibebox/cosmos/cosmos.client.tsx
/**
 * VibeBox Motion · Cosmos
 * Copyright (c) 2026 VibeBox. Licensed under the VibeBox Motion Free License:
 * https://motion.vibeboxph.com/license
 * Use it in unlimited personal, commercial and client projects.
 * Do not sell or redistribute it as a component, kit, template or builder.
 */
"use client";

import type { ReactNode } from "react";
import { BackdropCanvas, type PosterSpec } from "@/lib/vibebox/backdrop-canvas";
import { cosmosPiece, presets, type CosmosPreset } from "./cosmos.shader";

export type CosmosColor = "space" | "dust" | "gas" | "core" | "star";
export type CosmosValue = "density" | "lanes" | "stars" | "warp" | "coreSize";

export type CosmosProps = {
  /** What sits on the scene: a heading, a call to action, a whole section. */
  children?: ReactNode;
  /** A named look: `nebula`, `deep`, `rose`, `ember`, `warp`. */
  preset?: CosmosPreset;
  /** Overrides single palette colours with any CSS colour. */
  colors?: Partial<Record<CosmosColor, string>>;
  /** Multiplies the preset's speed (1 keeps it, 0 holds the scene still). */
  speed?: number;
  /** Multiplies the preset's brightness. */
  intensity?: number;
  /** The pointer and touch move the scene. */
  interactive?: boolean;
  /** Accessible name; leave it out when the scene is only a background. */
  label?: string;
  /** Hold one still frame until this is false (for a gallery card). */
  still?: boolean;
  className?: string;
} & Partial<Record<CosmosValue, number>>;

const POSTER: PosterSpec = { type: "linear", from: "space", to: "space", angle: 180, blobs: [{ color: "dust", at: [25, 65], size: 55 }, { color: "gas", at: [78, 35], size: 50 }, { color: "core", at: [48, 48], size: 28 }] };

export function Cosmos({ children, preset, colors, speed, intensity, interactive = true, label, still, className, density, lanes, stars, warp, coreSize }: CosmosProps) {
  return (
    <BackdropCanvas
      slug="cosmos"
      piece={cosmosPiece}
      presets={presets}
      fallback="nebula"
      preset={preset}
      colors={colors}
      values={{ density, lanes, stars, warp, coreSize }}
      speed={speed}
      intensity={intensity}
      poster={POSTER}
      scale={0.5}
      stillTime={3}
      still={still}
      interactive={interactive}
      label={label}
      className={className}
    >
      {children}
    </BackdropCanvas>
  );
}
components/vibebox/cosmos/cosmos.shader.ts
/**
 * VibeBox Motion · Cosmos
 * Copyright (c) 2026 VibeBox. Licensed under the VibeBox Motion Free License:
 * https://motion.vibeboxph.com/license
 * Use it in unlimited personal, commercial and client projects.
 * Do not sell or redistribute it as a component, kit, template or builder.
 */
import { compose, createScenePiece, type ScenePreset } from "@/lib/vibebox/engine/backdrops";

/*
 * Deep space: a nebula of domain-warped dust in three colours with dark lanes cut through it, a
 * glowing core, and stars at three depths that drift with the pointer. `warp` stretches the stars
 * outward from the centre for a jump to light speed.
 */

const SCENE = /* glsl */ `
uniform vec3 uSpace;
uniform vec3 uDust;
uniform vec3 uGas;
uniform vec3 uCore;
uniform vec3 uStar;
uniform float uDensity;
uniform float uLanes;
uniform float uStars;
uniform float uWarp;
uniform float uCoreSize;
uniform float uSpeed;
uniform float uIntensity;

float T;

float stars(vec2 uv, float scale, float seed, float warp) {
  vec2 p = uv;
  float streak = 1.0;
  if (warp > 0.001) {
    // Stretch radially: points become lines pointing away from the middle.
    float r = length(p);
    vec2 dir = p / max(r, 0.0001);
    float ang = atan(p.y, p.x);
    p = vec2(ang * 1.2, log(r + 0.03) - T * warp * 0.5);
    streak = 0.6;
  }
  vec2 g = p * scale;
  ivec2 c = ivec2(floor(g)) + ivec2(int(seed) * 53, int(seed) * 17);
  vec2 f = fract(g);
  vec2 o = h22(c) * 0.64 + 0.18;
  float r = h2(c + ivec2(7, 2));
  vec2 d = f - o;
  if (warp > 0.001) d.y *= 0.07;
  float len = length(d);
  float tw = 0.65 + 0.35 * sin(T * (0.6 + r * 2.0) + r * 40.0);
  float size = 0.05 + r * 0.05;
  return smoothstep(size, 0.0, len) * step(0.84, r) * mix(tw, 1.0, warp);
}

void main() {
  vec2 uv = centred(gl_FragCoord.xy);
  T = uTime * uSpeed;
  float aspect = uResolution.x / uResolution.y;
  vec2 pu = vec2((uPointer.x - 0.5) * aspect, uPointer.y - 0.5);
  vec2 look = (uPointer - 0.5) * 0.06 * (0.4 + uHover);

  vec3 col = lin(uSpace);

  // The nebula: dust warped by itself twice, so it folds like smoke.
  vec2 p = (uv + look * 0.5) * 1.5;
  vec2 q = vec2(fbm(p + vec2(0.0, T * 0.02)), fbm(p + vec2(5.2, 1.3) - T * 0.015));
  vec2 r = vec2(fbm(p + 3.0 * q + vec2(1.7, 9.2) + T * 0.02), fbm(p + 3.0 * q + vec2(8.3, 2.8) - T * 0.018));
  float n = fbm(p + 3.4 * r);
  float cloud = smoothstep(0.4, 1.0, n) * uDensity;
  vec3 dust = mix(lin(uDust), lin(uGas), clamp(r.x * 1.7 - 0.25, 0.0, 1.0));
  col += dust * pow(cloud, 1.2) * 0.8;
  // Thin bright filaments where the gas folds.
  col += lin(uGas) * pow(smoothstep(0.55, 1.0, q.y), 3.0) * 0.16 * uDensity;
  // Dark lanes cut through the glow.
  float lane = smoothstep(0.52, 0.86, ridged(p * 1.6 + r * 1.6));
  col *= 1.0 - lane * 0.8 * uLanes;

  // A soft core where the nebula is densest.
  float core = exp(-length((uv - vec2(0.18, 0.04) * (1.0 + look.x * 4.0)) * vec2(0.9, 1.3)) * (3.8 / max(uCoreSize, 0.2)));
  col += lin(uCore) * core * (0.1 + 0.28 * n);

  // Stars at three depths, the near ones drifting more with the pointer.
  float s = stars(uv * 1.0 + look * 0.4, 38.0, 1.0, uWarp) * 0.8 + stars(uv + look * 0.9, 70.0, 2.0, uWarp) * 0.6 + stars(uv + look * 1.8, 120.0, 3.0, uWarp) * 0.45;
  vec3 starCol = mix(lin(uStar), vec3(1.0), 0.45);
  col += starCol * s * uStars * 1.3;
  // The odd bright star with a cross of light.
  float cross = 0.0;
  vec2 bs = uv - vec2(-0.38, 0.22) - look * 1.2;
  cross += exp(-abs(bs.x) * 90.0) * exp(-abs(bs.y) * 22.0) + exp(-abs(bs.y) * 90.0) * exp(-abs(bs.x) * 22.0);
  col += starCol * (cross * 0.28 + exp(-length(bs) * 60.0) * 1.1) * uStars * (1.0 - uWarp);

  col *= uIntensity;
  col *= 1.0 - 0.35 * smoothstep(0.5, 1.2, length(uv * vec2(0.85, 1.1)));
  fragColor = vec4(finish(col, gl_FragCoord.xy), 1.0);
}
`;

export const fragment = compose(SCENE);

export const PRESET_NAMES = ["nebula", "deep", "rose", "ember", "warp"] as const;
export type CosmosPreset = (typeof PRESET_NAMES)[number];

export const presets: Record<CosmosPreset, ScenePreset> = {
  nebula: {
    colors: { space: "#04030c", dust: "#6a35ff", gas: "#ff3fa4", core: "#9fd0ff", star: "#dfe8ff" },
    values: { density: 1, lanes: 1, stars: 1, warp: 0, coreSize: 1, speed: 0.7, intensity: 1 },
  },
  deep: {
    colors: { space: "#010207", dust: "#10307a", gas: "#27b6d8", core: "#6fb7ff", star: "#cfe4ff" },
    values: { density: 0.75, lanes: 0.8, stars: 1.1, warp: 0, coreSize: 0.8, speed: 0.5, intensity: 1 },
  },
  rose: {
    colors: { space: "#0b0510", dust: "#a3216e", gas: "#ff9a6a", core: "#ffd6c0", star: "#ffe9dd" },
    values: { density: 0.95, lanes: 1, stars: 0.9, warp: 0, coreSize: 1.1, speed: 0.6, intensity: 1 },
  },
  ember: {
    colors: { space: "#080302", dust: "#8a2a0e", gas: "#ffb13a", core: "#fff0c0", star: "#fff2d8" },
    values: { density: 0.9, lanes: 1.1, stars: 0.8, warp: 0, coreSize: 1, speed: 0.6, intensity: 1 },
  },
  warp: {
    colors: { space: "#02030a", dust: "#1a2a8a", gas: "#2fa8ff", core: "#bfe0ff", star: "#e6f0ff" },
    values: { density: 0.55, lanes: 0.5, stars: 0.6, warp: 1, coreSize: 0.7, speed: 1, intensity: 0.85 },
  },
};

export const cosmosPiece = createScenePiece("cosmos", fragment);
components/vibebox/cosmos/index.tsx
/**
 * VibeBox Motion · Cosmos
 * Copyright (c) 2026 VibeBox. Licensed under the VibeBox Motion Free License:
 * https://motion.vibeboxph.com/license
 * Use it in unlimited personal, commercial and client projects.
 * Do not sell or redistribute it as a component, kit, template or builder.
 */
export { Cosmos, type CosmosProps, type CosmosColor, type CosmosValue } from "./cosmos.client";
export { PRESET_NAMES as COSMOS_PRESETS, presets as cosmosPresets, type CosmosPreset } from "./cosmos.shader";

Props

PropTypeDefaultDescription
childrenReactNode—What sits on the scene: a heading, a call to action, a whole section.
preset"nebula" | "deep" | "rose" | "ember" | "warp""nebula"The look: nebula, deep, rose, ember, warp.
colors{ space?: string; dust?: string; gas?: string; core?: string; star?: string }—Overrides single palette colours with any CSS colour: space (empty space), dust (the dust, in the thick of the nebula), gas (the gas, along its folds), core (the core's glow), star (the stars).
speednumber1Multiplies the preset's speed; 0 holds the scene still.
intensitynumber1Multiplies the preset's brightness, 0.5 to 1.4.
densitynumber1How much nebula fills the sky (0 to 1.5; each look sets its own).
lanesnumber1How dark the lanes cut through the glow (0 to 1.5; each look sets its own).
starsnumber1How many stars show (0 to 1.5; each look sets its own).
warpnumber00 holds the stars, 1 streaks them outward (0 to 1; each look sets its own).
coreSizenumber1How wide the core's glow spreads (0.3 to 1.6; each look sets its own).
interactivebooleantrueThe pointer shifts the stars at their own depths.
labelstring—Accessible name; leave it out when the scene is only a background.
stillbooleanfalseHold one composed frame until false (a gallery card that plays on hover).
classNamestring—Merged with cn(); give it a size and a radius.

Accessibility and motion

Keyboard
Not focusable; content on it keeps its own focus order.
Screen readers
Decorative by default; with label it is an image with that name.
Touch
A finger moves the scene like the cursor does; scrolling is never blocked.
Reduced motion
One still frame of the nebula; no drift, twinkle or warp.

Edge cases and limits

  • The warp look is busy; use it for a moment (a launch), not a whole page.
  • The bright corner star sits at the same place on every size; move copy off it.
  • On very small screens lower stars to keep the field calm.
  • Green and violet aurora curtains over a mountain ridge and stars

    Aurora

    Free

    Curtains of northern light over a night sky and a mountain ridge, drawn toward the pointer.

    Backgrounds · WebGL2

  • Warm amber bokeh lights of different sizes on a dark background

    Bokeh

    Free

    Out-of-focus lights in three depths, brighter at the rim and drifting with the pointer.

    Backgrounds · WebGL2

  • A dusk skyline of lit towers under an orange and violet sky

    A skyline of lit windows against a glowing sky, with a road of light trails in front.

    Backgrounds · WebGL2

↑ ↓ to move↵ to openesc to close