Will Doenlen

A tiny shader component for Astro

Here’s a small custom web component that you can use in Astro for running a WebGL fragment shader. It uses glslCanvas to take care of the boilerplate of setting up the shader so you’ll need to install that first. It also includes a classNames prop for Tailwind classes to style the canvas element. The code prop is the shader code as a string. I use Vite for builds and typically import the shader as a string from its own dedicated file with vite-plugin-glsl.

interface Props {
  code?: string;
  width?: number;
  height?: number;
  classNames?: string;

const defualtFragmentShader = `
  precision mediump float;
  uniform vec2 u_resolution;
  uniform float u_time;

  void main() {
      vec2 st = gl_FragCoord.xy/u_resolution.xy;
      gl_FragColor=vec4(st.x, st.y, abs(sin(u_time)), 1.0);

const {
  code = defualtFragmentShader,
  width = 512,
  height = 512,
  classNames = "",
}: Props = Astro.props;

  <script type="x-shader/x-fragment" set:text={code} />
  <canvas class={classNames} width={width} height={height}></canvas>
  import GlslCanvas from "glslCanvas";

  class Shader extends HTMLElement {
    constructor() {
      const canvas = this.querySelector("canvas");
      const shaderCode = (this.querySelector("script") as HTMLScriptElement)
      const sandbox = new GlslCanvas(canvas);

  customElements.define("custom-shader", Shader);

And then to use it:

import MyFragmentShader from "~/shaders/MyFragmentShader.glsl";
import Shader from "~/components/Shader.astro";

  <Shader code={MyFragmentShader} classNames="rounded" />

which will give you the following (using the default fragment shader):