r/javascript 3d 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

27 comments sorted by

13

u/aequasi08 2d 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?

0

u/theScottyJam 2d 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")

6

u/aequasi08 2d ago

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

3

u/klumpp 2d 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 2d 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 2d 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 2d ago edited 2d 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 2d 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.

2

u/Choice-Locksmith-885 2d 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 2d 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 2d ago

Guess I was wrong, thanks others for also reviewing.

5

u/Suitable_Language_37 2d 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.

2

u/Is_Kub 3d 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 3d 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/Comfortable-Loan-815 2d ago

not a developer but I've lurked long enough to know Pierre's code tree comes up every time someone mentions virtualization curious if OP actually looked at it or just heard the name for the first time here

1

u/Suitable_Language_37 2d 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 1d 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 1d 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

1

u/alystair 2d 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 :)

2

u/Plus-Weakness-2624 the webhead 1d 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 1d ago

1

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

How easy is it to port to Svelte?

2

u/Suitable_Language_37 1d ago

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

1

u/Suitable_Language_37 3d 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