
Globe Particles
FreeCreate stunning 3D particle globe visualizations.
Free · Opens the source repo
What Globe Particles does
The Globe Particles skill enables developers to create intricate 3D particle visualizations that resemble a globe, featuring a dense luminous core and a surrounding orbital ring. This skill is particularly useful for projects that require a sophisticated planetary or orbital effect without altering the overall layout of the webpage. By leveraging WebGL and Three.js, it offers a premium visual experience that stands out in data visualization and design contexts.
The implementation is straightforward, requiring minimal HTML and CSS setup. The provided code snippets allow for easy integration into existing projects, ensuring that the globe effect can be added without disrupting other elements on the page. The skill focuses on maintaining a clean structure with a dark atmospheric background, allowing the luminous particles to shine and create depth in the visualization.
The particle shaders are designed to produce crisp and luminous points, enhancing the overall aesthetic of the globe. With customizable parameters such as core color and accent color, developers can tailor the visualization to align with the design requirements of their projects. The skill is ideal for applications in data representation, user interfaces, or any creative project that benefits from a visually striking globe effect.
Overall, Globe Particles is a valuable tool for designers and developers looking to enhance their projects with a high-quality 3D visualization that is both functional and visually appealing, while not imposing any layout changes or unrelated motion systems.
When to use it
Use this skill when you want to incorporate a sophisticated globe-like particle effect into your web application without changing the overall page design.
When not to use it
This skill is not suitable for projects that require extensive layout changes or for those needing a playful or overly complex visual style.
What you can build with it
Data Visualization Dashboard
Enhance your data visualization dashboard with a 3D globe effect to represent global data points attractively.
Interactive Web Applications
Integrate the globe particles in interactive web applications to provide users with a visually engaging experience.
Creative Portfolio Projects
Use this skill in your creative portfolio to showcase your ability to implement advanced visual effects in web design.
How to install Globe Particles
View source1. Install with the skills CLI
npx skills add mengto/skills/globe-particles --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by mengtoGlobe Particles
Scope
- Apply only to a globe-like 3D particle visualization.
- Do not change full page layout, copy, or unrelated motion systems.
- Use for planetary, orbital, infrastructure, or synthesized data-globe effects.
- Keep the core neutral or white-hot and derive ring/glow accents from the design's primary color.
Visual Target
- Dense spherical core of luminous points.
- Thinner outer orbital ring or flattened disc around the sphere.
- Clear globe silhouette with tilt, depth, and layered particle density.
- Dark atmospheric background, restrained glow, clean structure, and subtle sci-fi depth.
- Premium and cinematic, not playful or noisy.
HTML And CSS
<div class="globe-particles-shell">
<canvas class="globe-particles-canvas" data-globe-particles></canvas>
</div>
.globe-particles-shell {
position: relative;
width: min(100%, 760px);
aspect-ratio: 1 / 1;
}
.globe-particles-canvas {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
display: block;
pointer-events: none;
}
Particle Shader
Use circular shader points so particles stay crisp and luminous.
const globeParticleVertex = `
attribute float a_size;
attribute float a_layer;
uniform float u_time;
uniform float u_pointSize;
varying float v_layer;
varying float v_depth;
varying float v_falloff;
void main() {
vec3 pos = position;
float breathe = 1.0 + sin(u_time * 0.65 + a_layer * 4.0) * 0.012;
pos *= breathe;
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
gl_PointSize = u_pointSize * a_size * (1.0 / max(0.18, -mvPosition.z));
gl_Position = projectionMatrix * mvPosition;
v_layer = a_layer;
v_depth = smoothstep(-1.8, 1.8, pos.z);
v_falloff = smoothstep(2.45, 0.25, length(pos));
}
`;
const globeParticleFragment = `
precision highp float;
uniform vec3 u_coreColor;
uniform vec3 u_accentColor;
varying float v_layer;
varying float v_depth;
varying float v_falloff;
void main() {
vec2 uv = gl_PointCoord - 0.5;
float d = length(uv);
float alpha = smoothstep(0.5, 0.0, d);
alpha *= alpha;
vec3 color = mix(u_coreColor, u_accentColor, smoothstep(0.35, 1.0, v_layer));
color += vec3(1.0) * v_depth * 0.08;
color = mix(color * 0.42, color, clamp(v_falloff + v_layer * 0.28, 0.0, 1.0));
alpha *= mix(0.52, 1.0, clamp(v_falloff + v_layer * 0.24, 0.0, 1.0));
gl_FragColor = vec4(color, alpha);
}
`;
Three.js Recipe
import * as THREE from "three";
function hexToRgb01(hex) {
const clean = hex.replace("#", "").trim();
const value = clean.length === 3
? clean.split("").map((char) => char + char).join("")
: clean;
return new THREE.Color(
parseInt(value.slice(0, 2), 16) / 255,
parseInt(value.slice(2, 4), 16) / 255,
parseInt(value.slice(4, 6), 16) / 255
);
}
function buildGlobeParticleGeometry(options = {}) {
const sphereCount = options.sphereCount || 2600;
const ringCount = options.ringCount || 1300;
const radius = options.radius || 1.35;
const ringRadius = options.ringRadius || 2.05;
const ringThickness = options.ringThickness || 0.12;
const total = sphereCount + ringCount;
const positions = new Float32Array(total * 3);
const sizes = new Float32Array(total);
const layers = new Float32Array(total);
for (let i = 0; i < sphereCount; i++) {
const z = Math.random() * 2 - 1;
const theta = Math.random() * Math.PI * 2;
const r = radius * (0.58 + Math.pow(Math.random(), 0.42) * 0.42);
const root = Math.sqrt(1 - z * z);
const index = i * 3;
positions[index] = Math.cos(theta) * root * r;
positions[index + 1] = Math.sin(theta) * root * r;
positions[index + 2] = z * r;
sizes[i] = 0.72 + Math.random() * 0.72;
layers[i] = Math.random() * 0.28;
}
for (let i = 0; i < ringCount; i++) {
const pointIndex = sphereCount + i;
const angle = Math.random() * Math.PI * 2;
const r = ringRadius + (Math.random() - 0.5) * ringThickness;
const y = (Math.random() - 0.5) * ringThickness * 0.58;
const index = pointIndex * 3;
positions[index] = Math.cos(angle) * r;
positions[index + 1] = y;
positions[index + 2] = Math.sin(angle) * r;
sizes[pointIndex] = 0.62 + Math.random() * 0.58;
layers[pointIndex] = 0.72 + Math.random() * 0.28;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
geometry.setAttribute("a_size", new THREE.BufferAttribute(sizes, 1));
geometry.setAttribute("a_layer", new THREE.BufferAttribute(layers, 1));
return geometry;
}
function initGlobeParticles(canvas, options = {}) {
if (!canvas) return () => {};
const renderer = new THREE.WebGLRenderer({
canvas,
antialias: true,
alpha: true,
});
renderer.setClearColor(0x000000, 0);
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, options.maxDpr || 1.6));
renderer.outputColorSpace = THREE.SRGBColorSpace;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(38, 1, 0.1, 100);
camera.position.set(0, 0, options.cameraDistance || 5.6);
const accent = options.accentColor
? new THREE.Color(options.accentColor)
: hexToRgb01(getComputedStyle(document.documentElement).getPropertyValue("--brand-accent").trim() || "#8b5cf6");
const geometry = buildGlobeParticleGeometry(options);
const material = new THREE.ShaderMaterial({
vertexShader: globeParticleVertex,
fragmentShader: globeParticleFragment,
transparent: true,
depthWrite: false,
blending: THREE.AdditiveBlending,
uniforms: {
u_time: { value: 0 },
u_pointSize: { value: options.pointSize || 18 },
u_coreColor: { value: new THREE.Color(options.coreColor || 0xf8fafc) },
u_accentColor: { value: accent },
},
});
const particles = new THREE.Points(geometry, material);
particles.rotation.x = options.tiltX ?? -0.42;
particles.rotation.z = options.tiltZ ?? 0.22;
scene.add(particles);
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const pointer = new THREE.Vector2(0, 0);
let rafId = 0;
function resize() {
const width = Math.max(1, canvas.clientWidth);
const height = Math.max(1, canvas.clientHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, options.maxDpr || 1.6));
renderer.setSize(width, height, false);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
function handlePointerMove(event) {
const rect = canvas.getBoundingClientRect();
pointer.x = ((event.clientX - rect.left) / rect.width - 0.5) * 2;
pointer.y = ((event.clientY - rect.top) / rect.height - 0.5) * 2;
}
function render(time = 0) {
const t = time * 0.001;
material.uniforms.u_time.value = t;
const mouseStrength = options.mouseStrength ?? 0.08;
const breath = reduceMotion ? 0 : Math.sin(t * 0.55) * 0.045;
particles.rotation.y = t * (options.rotationSpeed || 0.12);
particles.rotation.x = (options.tiltX ?? -0.42) + pointer.y * mouseStrength;
particles.rotation.z = (options.tiltZ ?? 0.22) + pointer.x * mouseStrength;
particles.scale.setScalar(1 + breath);
renderer.render(scene, camera);
if (!reduceMotion) rafId = requestAnimationFrame(render);
}
function handleResize() {
cancelAnimationFrame(rafId);
resize();
render();
}
resize();
render();
window.addEventListener("resize", handleResize);
window.addEventListener("pointermove", handlePointerMove);
return () => {
cancelAnimationFrame(rafId);
window.removeEventListener("resize", handleResize);
window.removeEventListener("pointermove", handlePointerMove);
geometry.dispose();
material.dispose();
renderer.dispose();
};
}
const cleanupGlobe = initGlobeParticles(document.querySelector("[data-globe-particles]"), {
sphereCount: 2600,
ringCount: 1300,
accentColor: "#8b5cf6",
radius: 1.35,
ringRadius: 2.05,
rotationSpeed: 0.12,
mouseStrength: 0.08,
});
Tuning Knobs
- Density: tune
sphereCountandringCountseparately. - Scale: tune
radius,ringRadius,ringThickness, andcameraDistance. - Color: keep
coreColorneutral; deriveaccentColorfrom the brand primary. - Motion: tune
rotationSpeed,tiltX,tiltZ,mouseStrength, and breathing amplitude. - Glow: tune
pointSize, additive blending, and particle count so the shape stays crisp. - Performance: lower particle counts or cap
maxDprbefore changing the visual structure.
Taste Rules
- The silhouette must read as a globe, not a loose starfield.
- The ring should feel orbital and tilted, not like a flat decorative underline.
- Use restrained glow; let density and depth create the premium feel.
- Keep mouse response gentle so the object drifts rather than swings.
- Put the globe over a dark background or inside a dark atmospheric shell.
Avoid
- Generic starfield noise with no spherical structure.
- Oversized particles or bloom that destroys the globe silhouette.
- Hardcoded accent colors when the design has a clear primary color.
- Wild cursor interaction or fast spinning.
- Dense fog that turns the object into a blurry blob.
Quick Checks
- Sphere and ring are distinct particle populations.
- Core reads mostly neutral or white-hot.
- Accent color appears on ring, highlights, or glow.
- Tilt reveals the ring and globe depth.
- Reduced motion renders a still or near-still object.
- Geometry, material, renderer, listeners, and RAF are cleaned up.
Frequently asked questions about Globe Particles
Similar skills
Algorithmic Art
Create generative art using p5.js and algorithmic philosophies.
Fal.ai Media Generation
Create images, videos, and audio with AI.
p5.js Production Pipeline
Create stunning generative art and interactive visuals.
ASCII Video Production
Transform videos into striking ASCII art animations.
Pixel Art
Transform images into retro pixel art and animations.
Generate Image
Create images quickly using AI providers.
