Skip to content
Development
Skill

/webgl-card-effects

Standalone WebGL fragment shaders for card visual effects: holographic foil, shimmer, rarity glow.

From plugin
vexjoy-agent
420123 skills198 agents12 commands77 hooks
Install
$ npx -y skills add notque/vexjoy-agent --skill webgl-card-effects --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/webgl-card-effects

Context preview

The summary Claude sees to decide when to auto-load this skill.

Standalone WebGL fragment shaders for card visual effects: holographic foil, shimmer, rarity glow.

SKILL.md

webgl-card-effects.SKILL.md
name: webgl-card-effects
promoted_to: distinctive-frontend-design
description: "Standalone WebGL fragment shaders for card visual effects: holographic foil, shimmer, rarity glow."
agent: typescript-frontend-engineer
user-invocable: false
command: /card-effects
allowed-tools:
  - Read
  - Write
  - Bash
  - Grep
  - Glob
  - Edit
routing:
  triggers:
    - card effects
    - holographic
    - foil effect
    - card shimmer
    - card glow
    - shader card
    - WebGL card
    - rarity effects
    - Balatro effect
    - card visual effects
  pairs_with:
    - typescript-frontend-engineer
    - ui-design-engineer
  complexity: Medium
  category: frontend

WebGL Card Effects Skill

Overview

This skill adds GPU-accelerated visual effects to React card components using standalone WebGL2 fragment shaders — no Three.js, no R3F, no external library required. It targets deckbuilder games and card UIs where rarity tiers should feel visually distinct, not just differentiated by a CSS `box-shadow` value.

**Scope**: Holographic foil overlays, metallic shimmer bands, rarity-driven energy pulses, and interactive tilt-shine effects mounted directly on React card components. The canonical target is `FramedCard.tsx` in a React 19 / Vite / Tailwind project with a rarity system (starter → common → uncommon → rare → legendary).

**Not in scope**: 3D transformations, texture loading, post-processing pipelines, or any Three.js scene management. For those, use `threejs-builder`.

**Key constraint**: Browsers cap WebGL contexts at roughly 8–16 total per page. This skill uses a single shared WebGL2 context with blit-to-2D-canvas output per card, avoiding the per-card context problem entirely. See `references/shader-integration-react.md` for the full singleton pattern.

---

Instructions

Phase 1: ASSESS

**Goal**: Understand which effects are needed and confirm the card component structure before writing any code.

**Step 1: Read the card component**

Read these files before writing anything:

  • `src/components/cards/FramedCard.tsx` — component structure, hover state, rarity prop flow
  • `src/components/cards/cardStyles.ts` — `CARD_SIZE_CONFIG` for pixel dimensions, rarity string values

Confirm:

  • How rarity reaches the component (prop name, TypeScript type, exact string values)
  • Whether `isHovered` state already exists in the component
  • Which sizes are rendered in contexts that justify shader cost (xl/lg only — xs/sm are too small)
  • Whether `showShine` / `card-shine` CSS exists and needs coordination

**Step 2: Select effect tier per rarity**

| Rarity | WebGL? | Effect | |--------|--------|--------| | starter / common | No | CSS shimmer only — no WebGL overhead | | uncommon | Yes (subtle) | Metallic band shimmer, very low opacity | | rare | Yes (medium) | Moving shimmer + blue hue shift + edge pulse | | legendary | Yes (full) | Rainbow holographic foil, mouse-reactive tilt |

**Step 3: Confirm React version**

Check `package.json` for the React version. This skill assumes React 19 (ref as prop, no forwardRef). If the project uses React 18, canvas refs require `useRef` + standard ref passing.

**Gate**: Rarity values confirmed, CARD_SIZE_CONFIG read, effect tiers decided. Proceed only when this gate passes.

---

Phase 2: BUILD

**Goal**: Write working GLSL shaders and the WebGL initialization harness.

Load `references/card-shader-patterns.md` now.

**Step 1: Create the shader strings module**

Create `src/components/cards/effects/cardShaders.ts`. This file holds:

  • The shared vertex shader (passthrough UV coordinates)
  • Three fragment shader strings: `SHIMMER_FRAG`, `RARE_FRAG`, `LEGENDARY_FRAG`
  • A `rarityToUniform(rarity: string): number` mapping function

Every shader must expose this exact uniform interface:

uniform float u_time;        // seconds elapsed, JS wraps at 1000.0
uniform float u_rarity;      // 0.0=starter/common, 0.25=uncommon, 0.5=rare, 1.0=legendary
uniform float u_hover;       // 0.0 to 1.0, lerped by JavaScript each frame
uniform vec2  u_mouse;       // normalized card-space [0,1] mouse position
uniform vec2  u_resolution;  // canvas pixel dimensions (width, height)
uniform float u_upgraded;    // 0.0 or 1.0 — upgraded cards get slightly more intense effect

**Step 2: Create the WebGL harness hook**

Create `src/components/cards/effects/useCardShader.ts`.

Load `references/shader-integration-react.md` for the full hook source. The hook must:

  • Use the shared WebGL2 context singleton (not create a new context per card)
  • Accept `{ rarity, isHovered, isUpgraded, enabled }` as input
  • Return a `RefObject<HTMLCanvasElement>` that the component attaches to the canvas element
  • Pause the animation loop when the card is off-screen (IntersectionObserver)
  • Run at 30fps maximum via delta-time throttle
  • Clean up the RAF loop and observer on unmount

**Step 3: Shader construction for each tier**

Load `references/balatro-shader-breakdown.md` for the legendary holographic shader GLSL source.

For rare: use the shimmer band + hue shift layer from the breakdown, omit the rainbow foil layer.

For uncommon: use only the metallic band pass (single moving highlight), opacity 0.3 maximum.

**Gate**: Run `npx tsc --noEmit`. Zero TypeScript errors. Open browser console and verify `gl.getShaderInfoLog()` returns empty string for all shaders.

---

Phase 3: INTEGRATE

**Goal**: Mount the canvas overlay on `FramedCard.tsx` and wire rarity/hover state into the shader uniforms.

**Step 1: Derive render decision**

Inside `FramedCard`, after the existing `const shouldShine` line:

const shouldRenderShader =
  ['uncommon', 'rare', 'legendary'].includes(rarity) &&
  size !== 'xs' &&
  size !== 'sm';

**Step 2: Call the hook**

const shaderCanvasRef = useCardShader({
  rarity,
  isHovered,
  isUpgraded,
  enabled: shouldRenderShader,
});

**Step 3: Add the canvas overlay to JSX**

Inside the `motion.div` return, immediately after the frame `<img>` elem

Read more
Ships withvexjoy-agent

Essays and writing behind this toolkit live at vexjoy.com. VexJoy Agent connects plain-English requests to specialist agents, skills, and workflows. /do selects the knowledge and tools needed for your task.

Get the whole plugin

Other skills on vexjoy-agent.