Get started in 3 steps
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.
Start the development server
Run the development server with Turbopack for fast refresh: 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.
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:
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:
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:
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:
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:
Grant camera permissions
When you first visit the CharCam page, your browser will request camera access: 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.
Watch the real-time conversion
The webcam feed is processed frame-by-frame: // 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 );
}
}
}
Responsive rendering
The character grid automatically adjusts to screen size: 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:
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:
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