Posted it in another comment here already, but this is my go-to resource to figure out compatibility: https://zigbee.blakadder.com/
And pretty much any zigbee device can be compatible with any gateway. In many cases it's just whether someone has taken the time to wire it up in the software or not.
I've been running it for years, keeping up to date with the regular new versions, and haven't had any major complaints for basic use cases like: "I want to turn on <set of lights> when <arbitrary condition occurs> (e.g. sundown, certain sensors detect < X lux of light, wifi device is seen by access point based on its MAC). Super useful. Huge world of possibilities, limited only by your hardware and imagination.
I've got several outdoor and indoor hydryponics systems set up that way and it's been a joy (except for the RaspberryPi SD card dying on me, which I've since replaced with a more reliable SSD based SBC)
I've got an indoor living wall that I'm thinking of converting to hydro.
Indoors I just have relays controlling lighting and air pumps for a deep water culture system.
Home Assistant is an unwieldy monolith where spitting out the components would give you so much more control. The side that receives the data works well, however. The quality of the plotting in it is substandard, as is the inbuilt data storage and access. Configuring via YAML is painful, especially when you want derived values (e.g. calculating absolute humidity from RH sensor readings. HomeAssistant comes with no way to clean up dirty data which is something you'll see on their forums that many people request, as cheap sensors are notorious for spurious readings.
It's easy and polished which is why I and I suspect others use it, but I wish there was a modular rewrite.
If we are rewriting HomeAssistant, let's do it in Rust :) Only half joking.
That said, I refuse to write automation in YAML. Logic doesn't really belong in YAML. Declarative stuff would be decent if all you did was to specify a desired end state and let it figure out how to get to that state. But triggers with the equivalent of 'if' conditions that run actions? Let me write the IF. It makes a big difference if you say "Lights should be on between X and Y" versus "condition: after: x before: y: action: turn on". Trivial cases are easy, but when you start combining them it becomes a nightmare.
I have done a lot with NodeRED but it is... strange. It does save me from writing YAML (I do enough of that on my day job), at the expense of being weird and not easy to debug.
As for plotting data, you can send that to Prometheus or InfluxDB and go from there.
I also wish there was an alternative. And more modular "plugins". And a "HA" option. As it is, I have a single raspberry Pi that, while backed up and could be replicated if needed, will go offline for updates and the like, not able to run any automation in the mean time.
It does work though.