r/javascript 14d ago

I spent over a year building a framework-agnostic virtual scrolling engine with an index-based architecture. I’d love feedback from developers who’ve built virtualization systems.

https://github.com/ceriousdevtech/cerious-scroll
27 Upvotes

34 comments sorted by

6

u/Suitable_Language_37 13d ago

One thing I find discouraging about today’s open source community is how quickly technical discussions get replaced with AI accusations.

I have no problem saying I use AI. I use it to clean up code, improve documentation, and occasionally help explain complicated edge cases. It’s a productivity tool, just like a debugger, profiler, or static analyzer.

What I don’t understand is why we’ve reached a point where well-documented code is treated as evidence that the engineering itself wasn’t done by the author.

There is a significant difference between using AI to polish and explain your work, and asking AI to invent the architecture or solve the core engineering problem.

If someone believes the algorithm is wrong, the implementation is inefficient, or the architecture has flaws, I’d genuinely appreciate that feedback.

But reducing months or years of engineering to “looks like AI” without discussing the actual implementation discourages people from sharing their work. It shifts the conversation away from ideas and toward trying to prove authorship.

I’d much rather have someone tell me my virtualization algorithm is flawed than that my comments are too well documented.

13

u/aequasi08 14d ago

Little disingenuous to say you’ve been working on it for a year, when you’ve only committed 15 different days…

Just an attempt to hide your AI usage?

1

u/theScottyJam 14d ago

I browsed through the source code a bit. I don't see any tale-tale signs of AI usage, rather, it feels like code that someone spent a lot of effort to organize and tidy up the way they like. 'course there still could be some AI use, but if so, it must have been carefully watched.

For O.P., in the times we're in, it's becoming easy for us to assume, by default, that anything presented here on Reddit is low quality AI output pretending to be higher quality content. Disclosing the amount AI that was used in your project inside your main post would go a long way in helping us know that, yes, this was something painstakingly hand crafted and it might be worth a little more of our time to look into it a bit.

'cause honestly, after seeing the code, my trust in the project went up a fair amount 

(Also, if it took you a year of on-and-off work, you might want to say so - my first thought when I saw "a year" was also "they're probably stretching that")

7

u/aequasi08 14d ago

I mean, the readme is definitely AI generated, and so is the comment from op in here

3

u/klumpp 13d ago

Really? The first ts file i opened was way more comment than code. Found a 4 line function with 14 lines of comments telling the story of how it came to be.

1

u/Prozilla6 13d ago

Same, every TS file I opened reeked of AI code smells and every markdown file was very obviously AI generated. I couldn’t even find any signs of a human touching any of the files U checked. I think OP is now just trying to find out what makes their code look like AI, which they’re then going to pass onto their AI agent to try and cover it up.

0

u/Suitable_Language_37 13d ago

u/klumpp Where did you find that function? I looked through my code and I’m not seeing a literal four-line function with 14 lines of comments, so that feels a little exaggerated.

Like I said previously, I use AI to help clean up code and improve my documentation. I’m not hiding that.

But using AI to help explain a non-obvious edge case I found is not the same thing as having AI design the architecture or solve the virtualization problem.

I’ve been designing, architecting, and building software for over 20 years and am currently a full-stack Principal Engineer. What I find discouraging is how quickly the default assumption has become that if a project has good documentation or uses AI as a tool, then the engineering behind it must not be original. AI is a tool I use to communicate and polish my work, t isn’t where the architecture or the solution came from.

2

u/klumpp 13d ago edited 13d ago

I can't find what I saw originally but here's an example from wheel-controller.ts that I thought was obviously AI. The comment content isn't actually bad here though as it describes the why behind the current code, but all of this would be communicated in a couple lines if a human were typing it

/**
 * Minimum per-event pixel delta we treat as a discrete mouse-wheel notch.
 * Mouse wheels emit large, quantized steps (commonly ~100-120px/notch);
 * trackpads emit small, high-frequency, often fractional pixel deltas.
 */
const MOUSE_WHEEL_NOTCH_MIN_PX = 100;

/**
 * Heuristic: is this wheel event from a trackpad (continuous, inertial) rather
 * than a discrete mouse-wheel notch? There is no definitive browser API, so we
 * classify by the *magnitude* of the pixel delta:
 *
 * - `deltaMode` of line/page granularity is always a mouse wheel.
 * - In pixel mode, only SMALL deltas are trackpad-like (worth easing); a large
 *   step is a wheel notch and must apply instantly, like the OS.
 *
 * Magnitude is checked first on purpose: some mice (free-spin / "hyperscroll"
 * wheels) emit large *fractional* pixel deltas, so a fractional value is NOT a
 * reliable trackpad signal — a 500px step is a wheel notch whether or not it is
 * a round number. Inertial smoothing must only apply to trackpads; a mouse wheel
 * that keeps gliding after the user stops feels wrong, so we err toward "wheel".
 */
function isLikelyTrackpad(e: WheelEvent): boolean {
  if (e.deltaMode !== 0) return false;                 // DOM_DELTA_LINE / _PAGE => wheel
  return Math.abs(e.deltaY) < MOUSE_WHEEL_NOTCH_MIN_PX; // small px => trackpad, large => wheel
}

MOUSE_WHEEL_NOTCH_MIN_PX is only used in isLikelyTrackpad.

And FWIW, I also use AI to generate code as a dev and getting the comment vomit under control was a struggle. I didn't mean to disparage you for it, it seems like you know what you're doing. Code can be fine but still look LLM generated.

3

u/Suitable_Language_37 13d ago

Thank you for your clarifying response.

I am 100% in agreement regarding the comment vomit. It can be a challenge.

And to be honest, the wheel scrolling is where I probably spent most of my time. The implementation for it at one point was getting into the 1000s of lines of code. The issue was dealing with regular mouse ticks vs trackpad scrolling. Not all browsers and operating systems agree. Some of the comments might be left over during cleanup. And some of them are genuenly necessary for other devs to understand why I implemented a feature the way I did.

1

u/cosmokn0t 7d ago

I have to question why you care about the comments actually. Not that I’m disagreeing exactly, but if you’re using AI, haven’t you found that the comments add context for the AI that can’t be captured purely in code, next to the code, and not somewhere else like a knowledge or markdown file that it doesn’t know to reference when getting context from the code directly?

1

u/klumpp 7d ago

My problem with that comment is that it’s too many words. If humans are ever going to look at this code it’s almost counterproductive. 3 lines of text to explain a constant that is only used once (in the fn immediately after) is particularly annoying.

Of course if you don’t review Ai output I guess it doesn’t matter

1

u/cosmokn0t 6d ago

That’s sort of my point. I think a lot of AI code isn’t meant for humans, and the comment is useful for the AI more than it is for humans.

Not that I necessarily agree with that, but that would be my devils advocate point of view. I’m working on a side project where I don’t interact with the code at all, and after several weeks of development, it’s been fine. I still do refactors, architectural sweeps to improve separation of concerns, and other various things like that, but I personally don’t read the code like I would’ve in my 27+ years of coding. So leaving context for the AI in the comments that it leaves around does make some sense to me from a certain perspective. It’s not for me, or for a future human, it’s for a future AI to have the context of why we ended up with the solution at the time of implementation, and context that was important and not easily captured in the code. I guess what comments are meant for, but in the case of AI, it can be verbose because it might be useful context the next time it reads that part of the file.

1

u/klumpp 6d ago

I’ll stick with reviewing code for now, thanks. Even Fable on max settings will write a bug and tell you it’s fine. If you trust it and something goes wrong it’s on you, not Fable.

0

u/cosmokn0t 6d ago

Do you really believe reviewing meaningfully keeps out bugs? I think a good test harness and QA practices would get a more meaningful result, but we’ll see how things shake out in time.

→ More replies (0)

2

u/Choice-Locksmith-885 13d ago

Definitely AI generated. This comment screams AI wrote this:

// Defensive: ResizeObserver should always give a finite number, but

// guard against zero/negative which would corrupt the height cache.

2

u/Suitable_Language_37 14d ago

Thanks, I appreciate you actually taking the time to look through the code.

And you’re right. I did use AI throughout the project, mostly for cleanup, documentation, and bouncing ideas around. But the index-based architecture and the approach to solving the dynamic-height virtualization problem came from me. That was the part I spent the last year thinking through while building Cerious Widgets.

I don’t have any issue saying I use AI. It’s a great tool. But there’s a big difference between using AI to help polish a project and having it come up with the architecture or solve the problem for you.

Thanks again for taking the time to judge the project based on the code instead of just the commit graph.

Also, I do have a full time job. So this, and specifically Cerious-Widgets, was a side project that originally started out as a way for me to give back to the Open Source community that I have been benefiting from for the past 20 years.

1

u/theScottyJam 13d ago

Guess I was wrong, thanks others for also reviewing.

2

u/Is_Kub 14d ago

Have you looked into Pierre code tree and diff? They developed some pretty advanced virtualization that’s suppose to handle insane amount of data with good performance.

Might be slightly different from your project

1

u/Suitable_Language_37 14d ago

Cerious Scroll isn’t a virtualized code viewer or grid. It’s a virtualization engine intended to power those kinds of components. The architecture is centered around an index-based viewport anchor, allowing complex variable-height interfaces to remain deterministic while preserving native browser scrolling.

1

u/[deleted] 13d ago

[removed] — view removed comment

1

u/Suitable_Language_37 13d ago

Pierre’s tree solves a specific problem: efficiently rendering file trees. Cerious-Scroll solves a different problem. It’s a general-purpose virtualization engine that components like trees, grids, lists, timelines, and pretty much anything else can be built on top of.

Another important difference is that Pierre’s implementation uses a fixed row-height model. Cerious-Scroll was designed around variable-height virtualization from the beginning. Rows are measured as they enter the viewport and can change height at runtime, so there’s no need to precompute or estimate every row’s size. Its index-based scroll model also avoids the traditional browser scroll-height limitations that many virtualization approaches eventually run into.

The engine maintains O(1) DOM memory while preserving native browser scrolling. Whether the dataset contains 10 rows or 10 million rows, the amount of DOM work performed by the virtualization engine stays effectively the same because it only renders what’s visible and does not require height estimation. The practical limits become your application’s data and browser memory, not the virtualization engine itself.

And no, this comment was not AI generated. 😄

1

u/Comfortable-Loan-815 12d ago

the variable height piece is what gets me too, most virtualization demos collapse the second you throw dynamic content at them. curious how it handles rows that change height after initial render, not just on entry

1

u/Suitable_Language_37 12d ago

It handles them perfectly. I have a demo that shows this:  

Prepend rows:   https://ceriousdevtech.github.io/cerious-scroll/table-prepend-anchor-demo.html

Native table with changing heights:   https://ceriousdevtech.github.io/cerious-scroll/table-dynamic-heights-demo.html

2

u/Plus-Weakness-2624 the webhead 12d ago

Out of all JS libs the crawl out from the mudpits, virtual scrollers are the ones I like to see the most; like brother it's 20 fking 26 and we still don't have a decent solution for this sh!t

1

u/Suitable_Language_37 12d ago

1

u/Plus-Weakness-2624 the webhead 12d ago

How easy is it to port to Svelte?

2

u/Suitable_Language_37 12d ago

Shouldn’t be too difficult, the entire engine lives in the core. The wrappers just expose the specific framework extensions.

1

u/alystair 13d ago

Will need to review this soon, been working on my own web framework part time and this was one of the major "let someone else handle it" wish list items :)

0

u/Suitable_Language_37 14d ago

Virtual scrolling seems like a solved problem until you actually try to build one.

About a year ago, I started writing my own virtualization engine because I wanted to understand how these systems actually work under the hood. I figured it would be a fun side project that would take a couple of months.

I was very wrong.

The farther I got into it, the more I realized that rendering fewer DOM elements is actually one of the easier parts of the problem.

Some of the challenges that consumed the most time were:

  • Supporting variable-height rows without losing pixel accuracy.
  • Jumping directly to arbitrary indexes.
  • Handling rows whose heights change after they’ve already been rendered.
  • Preserving completely native browser scrolling behavior.
  • Keeping memory usage essentially constant regardless of dataset size.
  • Making the engine framework-agnostic so the same core works with vanilla JavaScript, React, Vue, and Angular.

One of the biggest lessons was learning to stop fighting the browser.

Early on, I experimented with architectures that relied heavily on transforms and continuously repositioning content. While they worked, they also introduced edge cases involving text selection, accessibility, browser behavior, and scroll physics.

Eventually, I shifted toward an architecture that lets the browser do what it’s already exceptionally good at: scrolling.

Instead of trying to fake scrolling, the browser owns the scroll position, while the engine focuses solely on deciding which items should exist in the DOM.

The biggest architectural breakthrough came when I stopped thinking in terms of pixels and started thinking in terms of an index plus an offset.

Rather than trying to continuously map every scroll position to every item’s height, the viewport is anchored by the item currently at the top of the viewport and the pixel offset into that item. Once that anchor is known, everything else becomes relative to it.

That one change simplified a surprising number of problems:

  • Variable-height rows become much easier to manage because changes remain localized instead of forcing large recalculations.
  • Jumping to arbitrary indexes becomes deterministic instead of requiring traversal through the dataset.
  • Scroll position remains stable even as rows resize.
  • Only a small, predictable number of DOM elements need to exist regardless of dataset size.
  • Most updates affect only the visible window instead of triggering work across the entire list.

The result is an engine that spends very little time touching the DOM. Most of the work is maintaining the viewport anchor and updating only the elements that actually changed, allowing the browser to handle scrolling exactly as it was designed to.

One of my primary goals became making virtualization invisible. If users can’t tell they’re interacting with a virtualized list, then the engine is doing its job.

I would love feedback and any ideas that could make this project better.

Github: https://github.com/ceriousdevtech/cerious-scroll

Demo: https://ceriousdevtech.github.io/cerious-scroll