Overlays just cause a new pkgs object to be returned and used instead which contains whichever things the overlay adds to it.
(self: super: { jq = super.jq; })
This overlay, for example, would replace jq with itself lol
You would then either put it in a list and pass it to overlays when creating a new pkgs, or when using the nixpkgs.overlays module option used in the nvidia fix posted above (careful with the module option, it can lead to infinite recursion as it needs to be sequenced to happen before anything needs the pkgs, adding it when creating the pkgs option is preferred).
the two arguments for overlays are either called self: super: or final: prev: by convention and are the new and old pkgs sets before and after the overlay is called.