BLOG

Stories, experiments, and cool things I've developed

This all happened during my last semester in Computer Engineering at Polytechnique Montréal, and it started on October 5th, 2025.

I show up for my ethics midterm (SSH3501) on a Sunday morning at 8 a.m., during reading week, no less. Thanks Poly. Truly. Love that for us.

Anyway, I sit down, open my laptop… and immediately notice something weird: I don't need to log into my student account. Even worse, I have full internet access.

Which is… not exactly standard exam procedure.

The Meta Ethics Test?

For a second, I honestly thought it might be part of the ethics exam itself. Like, a live integrity test: "Here's the internet. Don't use it." Bold concept. Very meta.

So I write the exam, do really well (ethics exams are all kind of the same, my cheat sheet carried, as usual), and a few days later I open my email expecting grades.

Instead, I get hit with the opposite.

The Voided Exam

The email says the exam is void. Apparently, some students used the internet, and others (who took the exam in the afternoon) allegedly received questions from students who took it in the morning. Because of that, everyone was being punished. The solution? A mandatory retake. Another weekend morning. This time on Saturday. Thanks for switching it up, Poly, very generous.

The email also made it very clear that contacting anyone would be pointless. Decision final. Case closed.

Naively, I believed it… for about a few hours.

The UQAM Inspiration

Later that day, a friend told me about a similar situation at another university (UQAM), where students actually fought back, with a petition. I laughed at first. No way Polytechnique would let that slide, right?

Well. Turns out the real plot twist was buried in a long, boring PDF that almost no one ever reads: the academic regulations.

And surprise, the rules clearly state that any mid-semester change to evaluation methods requires student approval, via a majority vote. Suddenly, this didn't look so hopeless.

The Coordination Challenge

There was just one problem: I had no access to the full list of students in the course. Moodle only shows you your section, and there were eight sections total. Not ideal.

This is where things got interesting.

Each student could see their own section's list, so we crowdsourced it. I shared a Google Form, people reached out, friends contacted friends in other sections, and slowly the petition spread. It was honestly kind of wholesome, felt like high school again. A bunch of students uniting to fight the system. Something I never thought I'd see in university.

Victory (Sort Of)

After almost two weeks of back-and-forth, emails, forms, and coordination chaos, we pulled it off.

The retake exam was cancelled.

Of course, there was one last Polytechnique twist: we only got the confirmation one day before the exam. Meaning plenty of people had already wasted time re-studying, cancelled weekend plans, or postponed travel. That part sucked.

But still, justice prevailed.

The final resolution was to redistribute the weight of the exam onto the final and other course evaluations. Not perfect, but fair.

Honestly, fighting for our rights felt kind of empowering. Who knows, maybe I should've been a lawyer instead of an engineer.

Remember that performance monitoring system I built? The one I was so proud of? Well, it turns out that was just a band-aid on a much bigger problem. Let me tell you about how my portfolio's past caught up with me.

The Origin Story

When I first built this portfolio, I had just learned web development. The only framework I knew was Angular - and an old version at that. I had no concept of maintainability, code quality, or best practices. The result? One massive HTML file, one enormous SCSS file, and one absolutely monstrous TypeScript file containing my entire website.

But here's the thing - it worked. And when something works, you keep building on it. Over the years, I kept adding features: the WebGL galaxy background, the click spark effects, the decrypt animations, the Magic Bento hover effects. Each addition made the codebase more tangled, but the site kept looking better and better.

The Breaking Point

The performance monitor was my attempt to fix everything without addressing the root cause. It was like putting a turbocharger on a car with a cracked engine block. Sure, it helped - but the foundation was crumbling.

The real problems were deeper:

• No code splitting - users loaded everything at once
• No lazy loading - below-fold content blocked initial render
• Outdated Angular patterns - no modern optimization techniques
• Unmaintainable structure - any change risked breaking everything
• No SSR - poor SEO and slow initial paint

The Decision

I knew what I needed: a complete rewrite. Not a refactor. Not an upgrade. A full, ground-up rebuild using modern best practices. The choice of framework was easy - Next.js 15 with React 19, the latest and greatest, with server components, app router, and built-in optimizations.

The Migration Journey

Here's how I approached the rewrite:

1. Component Architecture
Instead of one monolithic file, I broke everything into focused components. Each section (Hero, Education, Experience, Projects, Skills, Interests) became its own module with clear responsibilities.

2. Server Components
Next.js server components meant I could render static content on the server and only hydrate interactive parts. The Hero shell renders on the server; the decrypt animation hydrates on the client.

3. Dynamic Imports
Below-fold sections are now lazy loaded with next/dynamic. Users see the hero instantly while the rest loads in the background.

4. Porting the WebGL
The trickiest part was porting the galaxy background. The GLSL shaders translated directly, but the React lifecycle required careful handling of the WebGL context - creating on mount, cleanup on unmount, and proper resize handling.

5. Asset Optimization
Every PNG became a WebP. Every image uses next/image for automatic optimization. The result? Dramatically smaller payloads.

The Results

The new portfolio is everything the old one couldn't be:

Maintainable - Clean component structure, no comments needed
Fast - Server-rendered, lazy-loaded, optimized assets
Modern - Next.js 15, React 19, latest best practices
SEO-ready - Proper meta tags, server rendering, sitemap
Buttery smooth - GPU-accelerated animations, event delegation

And the best part? That performance monitor I was so proud of? I removed it entirely. When your foundation is solid, you don't need band-aids.

Sometimes the right answer isn't to fix what's broken - it's to build something better.

It all started when my friend Salim - did I mention he's a fellow developer? Because he certainly won't let me forget it - visited my portfolio on his older Android phone. And he was right.

The Problem

My portfolio looked gorgeous on modern devices with its WebGL galaxy background, particle effects, and smooth animations. But on older phones? It was a slideshow. The frame rate would drop to 15-20 FPS, making the entire experience feel janky and unresponsive.

The Solution: Dynamic Performance Monitoring

Instead of creating a dumbed-down mobile version, I built a sophisticated performance monitoring service that adapts in real-time. Here's how it works:

1. Initial Device Detection
On load, the service checks hardware capabilities including CPU cores, available memory, GPU tier, and even battery level. It also respects user preferences like reduced motion.

2. Real-Time FPS Monitoring
The service continuously monitors frame rates using requestAnimationFrame, maintaining a rolling average over 5 seconds. If performance drops below certain thresholds (30 FPS for low, 45 FPS for medium), it automatically adjusts.

3. Dynamic Quality Adjustment
Based on performance metrics, the system adjusts:
• Galaxy star density (0.3x to 0.8x)
• Particle counts in effects (4-8 sparks)
• Animation complexity and glow intensity
• WebGL shader calculations

Secret Developer Tools

For testing and debugging, I built a hidden performance overlay that's only accessible through the browser console. It's a floating widget that displays real-time performance metrics and allows manual control over performance levels.

To access it, developers can open the console and use commands like:
perf.show() - Reveals the performance monitor
perf.setLevel('low') - Forces a specific performance tier
perf.help() - Shows all available commands

This approach keeps the UI clean for regular users while giving developers powerful debugging tools. The overlay shows current FPS, performance level, memory usage, and battery status - everything needed to diagnose performance issues across different devices.

Even Salim was impressed.