It's easy, but also not so easy.
Firstly, it's going to be tougher in 1.16.1 with so many srg names still. It made my eyes bleed enough that I gave up, and am waiting for new/better mappings, or the new system to come out so I can at least contribute while my eyes bleed.
But the way the overworld does it is in net.minecraft.world.gen.layer the LayerUtil class sets it all up (this is done in the OverworldBiomeProvider constructor) Then the BiomeProvider requests the biome from the layer in its getNoiseBiome method. (it's fairly complicated how it generates the world, you'd have to read through the code, I'm slooooowly working on understanding how the vanilla layer worldgen works)
You CAN just override getNoiseBiome in your custom BiomeProvider, and return biomes there however you'd like.
There's a reason there aren't "tutorials" all over the internet for doing this, because it's not really simple, no matter how you slice it
*edit: Annnnd I missed a few of the methods you were unsure of. That's what I get for trying to think first thing in the am lol. Anyhow, looking at vanilla overworld provider, func_230320_a_ returns a new instance of your BiomeProvider and func_230319_a_ returns a Codec for your BiomeProvider. I can't explain the whole Codec thing in too much detail, because it's still really new to me, but from what I understand it handles serialization/deserialization of data, looks like maybe settings in this case. In the vanilla OverworldBiomeProvider it is set up at the top of the class, maybe someone can explain it, or if you look at it you can implement it.