Many examples contain self, nixkpgks, home-manager or ...
Do I need to explicitly pass every input to outputs? If so, what does ... do? (I thought it meant infer any extra inputs from inputs) When do I need to use self?
Also, many examples contain @inputs or @attrset, while others do not have them. When are these necessary (or recommended)?
Unsure about self; as for nixpkgs, home-manager, etc., these are all inputs that you can just pass in there so that you don’t need to write inputs.nixpkgs et al everywhere, which can become verbose.
As for { ... }@inputs or inputs@{ ... }, this allows to use the entirety of inputs inside your attrset.
This is useful when you don’t expand out every single input of yours, so it just swallows any other arguments passed to the function. I think you’ll better understand if you just play with removing things in your flake.
You would need to do inputs.nixpkgs.foo instad of just nixpkgs.foo, yes. But the .url is only done in the inputs.
They’re not “inherited” but rather that this syntax allows for you to use inputs as any other variable. Moreover, there is no special behaviour with inputs and outputs in flakes. It follows all usual rules of the Nix language.