I also was quite confused about the js_of_ocaml js interface. Did not manage to achieve what i wanted and in the end I gave up and tried Brr instead. It was a much more pleasant experience. No ppx magic and the documentation is quite good.
In my case I was trying to interact with the Cloudflare worker runtime environment. So no prebuilt library was provided, I had to use the Brr FFI. Thanks to the documentation with all the examples, it was mostly a breeze.
I never got the hang of Brr; anytime I was trying to convert a JS snippet to Brr, the provided API never quite matched up with the MDN docs; I never found a good way to determine if (1) the API was not in Brr and I should bind it myself or (2) the API was in Brr, but I was not finding it.
However before people start making wrong inferences from your comments I’d like to point out that most of the time in Brr:
There is a one to one correspondance between Brr’s representation and browser APIs according to this naming convention. Sometimes a few API prefixes are factored out in a module e.g. (MIDIInput → Midi.Input).
There is an index of which browsers APIs are bound.
But of course to benefit of all that you need to read the docs.
Exhaustiveness is an explicit non-goal of the project. As far as browsers API go there’s a ton of outdated things you should not use. It’s one of the goal of brr to save your time by not binding to the useless stuff.
If I understand your post correctly, you are talking about Brr doc linking to MDN doc.
I am interested in the inverse problem: given a MDN class/function name, how easy is it to guess the corresponding Brr function to use ? This is the problem I run into all the time when manually porting from JS to OCaml.
I would argue that Brr is not optimized for this at all. There seems to be many naming quirks that makes sense for Brr internally but makes it hard to go from (JS Class, JS method) to corresponding Brr function. Examples of this include:
other small inconsistencies I can’t recall right now
Individually these are small quirks; from the perspective of “here’s a blob of JS code, rewrite it in OCaml”, these mental “pebbles” largely prevented me from ever getting into “flow state” when translating JS to Brr.
Something else: in my opinion (and I may be entirely wrong here), I think the Jsoo “class” based technique works better than a “functional” approach for the following reason.
Suppose we have:
1. a JS line that looks like:
obj.foo(arg1, arg2, arg2);
2. we know that the type of obj is Orange
that we want to translate to OCaml.
In the case of Brr, I’m not sure how to grep for this function ‘foo’ – I need to guess which module corresponds to type Orange ; then a function that is named “foo”-ish ; but things may not be arranged this way as matching MDN layout is not the highest objective
In the case of Jsoo, I grep for “class type [guess based on Orange]”, then after I find it, I get something of the form: 
class type orange = object
method ... = Js.readonly_prop / Js.method
and all the methods are there in one place, and I find the one closest to ‘foo’.
From the perspective of not reading the docs, the layout of the code and the use of classes makes it much easier to guess/find the right function name to use.
 In the class case, I don’t even have to guess, I can just do:
let obj: () = ...
and the compiler error will tell me approximately the correct class type of obj
The already mentioned index provides a map to that. MDN docs are also quite arbitrary regarding this.
In general new large well delineated APIs get their own namespacing module. For the rest I wanted to avoid to have to open dozens of modules. The state of Jsoo separatate compilation when this was done also likely got taken into account.
I’m not claiming this is the best way of distributing, but then no one proposed something better.
That’s likely a mishap, I bound thousands of entry points during different, long and boring periods. I don’t guarantee there isn’t a few occurences where I got distracted from the discipline or that the whole thing is totally consistent. This could have been reported.
I think this might be a misunderstanding of Brr and JSOO. Jsoo, in general, encourages mixing JS values in your Ocaml code, sorting of two languages meeting as one. From my usage of Brr, it is an FFI, which means it’s meant to be used only on the boundary. So your program is almost entirely “real” Ocaml values, and at the edges, where it interacts with JS, you use Brr to translate. This is simlar to how FFI works in most other situations, for example consider when you call C functions from Ocaml.