# Dev Snake

> A decorative snake grazing a contribution grid — reduced-motion safe.

A shadcn/ui block from the [@blockforge](https://blockforge.terravidhal.me) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/blockforge/dev-snake).

- Page, with a live preview: https://shadcn.exchange/r/blockforge/dev-snake
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/blockforge/dev-snake-light-93c5f6a0a0514a20.png
- Registry item: https://blockforge.terravidhal.me/r/dev-snake.json
- Categories: developer
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://blockforge.terravidhal.me/r/dev-snake.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Files

### `registry/blocks/dev-snake.tsx`

```tsx
"use client";
/**
 * A purely decorative snake that grazes across a contribution grid — a
 * light head with a fading emerald tail, sweeping row by row. Original
 * implementation of a common visual idea; no data, no interaction.
 * Freezes to a static grid under prefers-reduced-motion.
 */
import { useEffect, useMemo, useState } from "react";

import { cn } from "@/lib/utils";

const WEEKS = 53;
const DAYS = 7;
const TRAIL = 6;

const levelClass = [
  "bg-muted-foreground/12",
  "bg-emerald-500/25",
  "bg-emerald-500/45",
  "bg-emerald-500/70",
  "bg-emerald-500",
];

function baseLevel(week: number, day: number) {
  const n = (week * 7 + day) * 2654435761;
  const v = ((n ^ (n >>> 15)) >>> 0) % 100;
  if (v < 55) return 0;
  if (v < 76) return 1;
  if (v < 90) return 2;
  if (v < 97) return 3;
  return 4;
}

export default function DevSnake() {
  // Boustrophedon path: sweep each row, alternating direction.
  const path = useMemo(() => {
    const cells: Array<[number, number]> = [];
    for (let d = 0; d < DAYS; d++) {
      const cols = Array.from({ length: WEEKS }, (_, w) => w);
      if (d % 2 === 1) cols.reverse();
      for (const w of cols) cells.push([w, d]);
    }
    return cells;
  }, []);

  const [head, setHead] = useState(0);

  useEffect(() => {
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduce) return;
    const id = setInterval(() => setHead((h) => (h + 1) % path.length), 110);
    return () => clearInterval(id);
  }, [path.length]);

  // Map "week-day" → trail intensity (0..TRAIL), 0 = not on snake.
  const trail = useMemo(() => {
    const map = new Map<string, number>();
    for (let i = 0; i < TRAIL; i++) {
      const idx = (head - i + path.length) % path.length;
      const [w, d] = path[idx];
      map.set(`${w}-${d}`, TRAIL - i);
    }
    return map;
  }, [head, path]);

  // The cell just ahead of the head — about to be picked up.
  const [nextW, nextD] = path[(head + 1) % path.length];
  const nextKey = `${nextW}-${nextD}`;

  // Fuchsia snake, brightest at the head, so it reads over the muted grid.
  const snakeClass = [
    "bg-fuchsia-500/30",
    "bg-fuchsia-500/45",
    "bg-fuchsia-500/60",
    "bg-fuchsia-500/80",
    "bg-fuchsia-400",
    "bg-fuchsia-300",
  ];

  return (
    <section className="bg-background">
      <div className="mx-auto w-full max-w-4xl px-6 py-20 sm:py-24">
        <div className="mb-8">
          <h2 className="text-2xl font-semibold tracking-tight text-balance sm:text-3xl">
            Always something moving
          </h2>
          <p className="mt-2 text-muted-foreground">
            A little life for an empty state or a footer — decorative only.
          </p>
        </div>

        <div className="overflow-x-auto rounded-xl border border-border/60 bg-card p-5">
          <div
            className="grid min-w-[640px] gap-[3px]"
            style={{
              gridTemplateColumns: `repeat(${WEEKS}, minmax(0, 1fr))`,
              gridTemplateRows: `repeat(${DAYS}, minmax(0, 1fr))`,
              gridAutoFlow: "column",
            }}
          >
            {path.length > 0 &&
              Array.from({ length: WEEKS }).flatMap((_, w) =>
                Array.from({ length: DAYS }).map((_, d) => {
                  const key = `${w}-${d}`;
                  const t = trail.get(key);
                  const isHead = t === TRAIL;
                  const isPickup = key === nextKey;
                  return (
                    <span
                      key={key}
                      style={
                        isHead
                          ? { boxShadow: "0 0 7px 1px rgba(232,121,249,0.9)" }
                          : undefined
                      }
                      className={cn(
                        "aspect-square rounded-[2px] transition-colors duration-150",
                        t
                          ? snakeClass[t]
                          : isPickup
                            ? "bg-fuchsia-500/25 ring-1 ring-fuchsia-400/60"
                            : levelClass[baseLevel(w, d)],
                      )}
                    />
                  );
                }),
              )}
          </div>
        </div>
      </div>
    </section>
  );
}
```
