Skip to main content

Get started in 3 steps

1

Clone and install dependencies

Clone the repository and install all required packages:
git clone https://github.com/MateusMCG16/Matrix.git
cd Matrix
npm install
The project uses Next.js 15.3.2 with React 19 and Tailwind CSS 4. All dependencies are managed through the package manager of your choice.
2

Start the development server

Run the development server with Turbopack for fast refresh:
npm run dev
The server will start on http://localhost:3000.
The project uses --turbopack flag for faster development builds. This is configured in package.json under the dev script.
3

Explore the features

Open your browser and navigate to:

Matrix Rain controls

Once the Matrix Rain page is running, you’ll see a control panel in the top-right corner:

Speed slider

Adjust the falling speed of characters from 0.1x to 3.0x:
src/app/page.tsx
const [sliderValue, setSliderValue] = useState(100);
const speedRef = useRef(1.0);

useEffect(() => {
  speedRef.current = sliderValue / 100.0;
}, [sliderValue]);
The speed value is converted to a multiplier and applied during the animation loop.

Color picker

Select any color for the falling characters:
src/app/page.tsx
const [characterColor, setCharacterColor] = useState("#00FF00");
const colorRef = useRef("#00FF00");

// In the draw function
ctx.fillStyle = colorRef.current;
The color picker is disabled when RGB mode is active.

RGB rainbow mode

Enable dynamic rainbow colors using HSL color space:
src/app/page.tsx
const [isRgbMode, setIsRgbMode] = useState(false);
const rgbEffectTimeRef = useRef(0);

// In the draw function
if (isRgbModeRef.current) {
  rgbEffectTimeRef.current = (rgbEffectTimeRef.current + 0.5) % 360;
  const hue = (dropsRef.current[i] * 2 + rgbEffectTimeRef.current) % 360;
  ctx.fillStyle = `hsl(${hue < 0 ? hue + 360 : hue}, 100%, 50%)`;
}
Each character column gets a different hue that cycles over time.

Direction toggle

Reverse the rain direction to make characters fall upward:
src/app/page.tsx
const [isFallingDown, setIsFallingDown] = useState(true);

// Initialize drops based on direction
for (let i = 0; i < columns; i++) {
  if (isFallingDownRef.current) {
    newDrops[i] = Math.random() * -height / fontSize;
  } else {
    newDrops[i] = height / fontSize + (Math.random() * height / fontSize);
  }
}

CharCam setup

Navigate to /chars to experience the ASCII webcam:
1

Grant camera permissions

When you first visit the CharCam page, your browser will request camera access:
src/app/chars/page.tsx
const stream = await navigator.mediaDevices.getUserMedia({
  video: {
    width: { ideal: 320 },
    height: { ideal: 240 },
  },
  audio: false,
});
The application requests a lower resolution (320x240) for better performance when converting to ASCII art.
2

Watch the real-time conversion

The webcam feed is processed frame-by-frame:
src/app/chars/page.tsx
// Draw video to processing canvas at grid resolution
processingCtx.drawImage(videoRef.current, 0, 0, gridCols, gridRows);

// Get pixel data
const imageData = processingCtx.getImageData(0, 0, gridCols, gridRows);
const data = imageData.data;

// Convert each pixel to a character based on brightness
for (let y = 0; y < gridRows; y++) {
  for (let x = 0; x < gridCols; x++) {
    const i = (y * gridCols + x) * 4;
    const r = data[i];
    const g = data[i + 1];
    const b = data[i + 2];
    const brightness = (r + g + b) / 3 / 255;

    if (brightness > 0.2) {
      const char = CHARACTERS[Math.floor(Math.random() * CHARACTERS.length)];
      outputCtx.fillText(char, x * charFontSize + charFontSize / 2, y * charFontSize + charFontSize / 2);
    }
  }
}
3

Responsive rendering

The character grid automatically adjusts to screen size:
src/app/chars/page.tsx
const getCharFontSize = () => {
  if (typeof window !== "undefined") {
    if (window.innerWidth < 768) return 10; // Mobile
  }
  return 14; // Desktop
};

const newCols = Math.floor(window.innerWidth / currentFontSize);
const availableHeight = window.innerHeight - VERTICAL_OFFSET;
const newRows = Math.floor(availableHeight / currentFontSize);

Character sets used

Matrix Rain

The Matrix rain uses a combination of Japanese Katakana, Latin letters, and numbers:
src/app/page.tsx
const katakana = "アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズヅブプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン";
const latin = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const nums = "0123456789";
const characters = katakana + latin + nums;

CharCam

CharCam uses a reduced set of special characters for better visual appearance:
src/app/chars/page.tsx
const CHARACTERS = "!\"#$%&'()*+,-./:;<=>?@[\\]";

Next steps

Customize the code

Edit src/app/page.tsx to modify the Matrix rain effect or change character sets

Build for production

Run npm run build to create an optimized production build

Build docs developers (and LLMs) love