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):
BEGIN_SERIALIZE()
VARINT_FIELD(version)
if(version == 0 || CURRENT_TRANSACTION_VERSION < version) return false;
VARINT_FIELD(unlock_time)
FIELD(vin)
FIELD(vout)
FIELD(extra)
END_SERIALIZE()
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.