Behind the Build: Architecture, Canvas ASCII & Optimizations
When I started building this portfolio, I didn't want to rely on pre-packaged component libraries or a generic Astro/Next template. As a computer science student passionate about AI, low-level systems, and computer graphics, my goal was to build a tailored software architecture from scratch: fast, resilient, and powered by hand-crafted rendering algorithms.
1. The Procedural ASCII Engine & Ping-Pong Wave Animation
The signature element of the site is a custom procedural ASCII rendering engine built on HTML5 Canvas 2D. Unlike a naive DOM-based approach (where each glyph is an individual <span> element), 2D Canvas allows drawing and mutating thousands of cells at 60 FPS with zero DOM thrashing or layout reflows.
▲ Real-time render: continuous bidirectional loop (Forward Reveal → Hold → Reverse Dissolve → Hold). Hover with mouse to interact.
Mathematical Formulation of the Non-Linear Wavefront
To avoid a mechanical linear fade, each character in the matrix computes its arrival timestamp based on a diagonal wavefront distorted by a harmonic sine perturbation:
const waveDist = normX * 0.85 + normY * 0.15 + Math.sin(normX * 10 + normY * 3) * 0.025; During the bloom phase, the character undergoes high-frequency shutter oscillation by sampling glyphs across a density ramp (@, #, $, %, &, W, M, 8, 0, X, Z, *, +, =, ~, :) with deterministic per-character color and saturation offsets until the leading edge settles.
Reverse Sweep & Ping-Pong State Machine
To achieve a seamless, continuous back-and-forth loop without memory allocations or Garbage Collector spikes, the animation loop partitions a fixed 4200 ms cycle into deterministic phases:
- 0 ms → 1200 ms (Forward Sweep): Left-to-right wavefront reveal with high-frequency shutter scrambling.
- 1200 ms → 2200 ms (Resolved Hold): Fully settled state where all characters remain static.
- 2200 ms → 3400 ms (Reverse Dissolve): Inverse wavefront sweep calculated via
(1 - clampedWave), dissolving characters back into empty space. - 3400 ms → 4200 ms (Hidden Hold): Idle rest interval before seamlessly repeating the cycle.
Cursor Interaction & Kinetic Dissipation Physics
When hovered, the canvas computes pointer velocity to apply an elastic magnetic repulsion vector field. Displaced cells accumulate kinetic energy that decays exponentially with a 0.91 damping factor per frame:
// Elastic kinetic restitution and damping
state.dispX += (0 - state.dispX) * 0.15;
state.dispY += (0 - state.dispY) * 0.15;
state.kineticEnergy *= 0.91;2. Real-Time ASCII Image Rasterization Pipeline
For project showcase visuals ([AsciiImage.vue](file:///C:/Users/pault/WebstormProjects/portfolio/app/components/AsciiImage.vue)), I built a dynamic client-side rasterization pipeline. Source WebP assets are sampled into an off-screen memory canvas and converted on the fly:
- Perceived Luminance Extraction: ITU-R BT.601 photometric standard weighting (
Y = 0.299R + 0.587G + 0.114B). - Gamma & Contrast Shaping: Non-linear tone curve transformation preserving subtle shadow gradients and specular highlights.
- LUT Quantization: Direct scalar mapping from [0, 255] into pre-compiled ASCII density ramps.
- Sub-Pixel Layout Alignment: Monospace horizontal step scaling preventing glyph overlap across arbitrary viewport widths.
3. Core Architecture: Nuxt 3, Nitro & Strict TypeScript
The application is structured on Nuxt 3 with the Nitro server engine, configured for hybrid static/server rendering:
- Strict TypeScript: End-to-end typed contracts for project data models, canvas cell memory states, and Schema.org structured metadata.
- Tree-Shaking & Auto-Imports: Composition API architecture eliminating dead code and keeping runtime bundle weight minimal.
- File-Based Routing: Dynamic typed project pages (
/projects/[id].vue) with automated edge Open Graph image generation powered by Sharp.
4. Performance & Rendering Discipline
Achieving a locked 60 FPS during fast scrolling and browser zooming required strict rendering discipline:
- Single Ticker Synchronization: Lenis inertial momentum scrolling hooks directly into
gsap.ticker, eliminating frame desynchronization and redundant animation frame callbacks. - Static OKLab Glow Meshes: Removing per-frame mouse-tracking style recalculations in favor of static OKLab gradients, preventing GPU compositing bottlenecks.
- Strict CSS Containment: Extensive use of
contain: layout style painton heavy UI modules to isolate layout boundaries. - Bot & Crawler SSR Bypass: Server headers inspection detects web crawlers (Googlebot, Lighthouse) to disable resource-heavy canvas loops and serve instant pre-rendered markup.
5. Engineering Summary
This project was an opportunity to apply real systems engineering principles to frontend architecture: custom 2D canvas shader pipelines, tight memory management, rigorous static typing, and browser rendering pipeline optimization.