Beyond the somewhat dated CN doc you referenced, and if you need more specifics, the best resource is really the code. For example, you can see that the tx prefix is serialized (src):
if(version == 0 || CURRENT_TRANSACTION_VERSION < version) return false;
Then just look at the
BEGIN_SERIALIZE... for the sub-fields, such as the
FIELD(vout) is defined as
std::vector<tx_out> vout; and
tx_out being (src), and so on. It's not terribly difficult when you get the hang of it.
As @koe mentioned, Zero2Monero also gives a fairly up-to-date overview. As he also points out, it's not "fixed" so to speak, which is why I'd advise to get comfortable navigating the code definitions, as outlined above.