Where and when should the coinbase transaction(including the miner key) be added? I'm making a simple demonstrator program, pretty much a simplified bitcoin clone based mostly on the original whitepaper.

Please bear with me, because I haven't found a way to describe the problem more concisely.

My blockchain is based on this tutorial.

However, it completely ignores the transaction part, so I've based the transactions on this part of the original documentation:

As specified here, my transactions consist of the next owner's public key and the signature of last transaction signed by the previous owner. I also added the amount being transferred (I'm not using the in/out system for the sake of simplicity).

Since each transaction needs a hash of a previous one, I also created a coinbase transaction. It only contains  the mined amount and the miner's public key (to know whom to give the mined amount). This allows for the first regular transaction in a block to have a previous transaction to hash and sign.

However, that also means that the miner key has to be specified before the first transaction is made (since all future transactions require that the coinbase's hash stays the same). 
At the same time, it does not make sense to specify the miner before they have mined a block.
In other words, this would require the transaction user to know a priori who will mine the block with their transaction.

My assumption so far was that a coinbase transaction is added to the unconfirmed transaction list after the previous block is mined, and new transactions refer to it. Then the whole list is put into a block which is then mined. However that assumption led to the aforementioned problems.

The only possible solution which I could come up with is using the last transaction hash from the previous block to sign a new transaction, effectively bypassing the coinbase transaction. But that doesn't seem right to me.

Please, tell me if I'm missing something, or got the wrong idea somewhere.

Where and when should the coinbase transaction(including the miner key) be added?

Or should I scrap that idea completely and use the "bypass" method?

PS. I've already tried searching various wikis and questions, but nothing realy gave me a clear solution to this. 
Especially, this answer is too vague
The coinbase transaction is created when the miner creates the template for the block which they attempt to mine. Unlike regular transactions, it does not have regular inputs. The miner simply specifies the outputs to spend the coins, where the sum of the output amounts must be less than or equal to the total amount of fees in the block plus the subsidy. The coinbase is always positioned as the first transaction in the block.

The coinbase transaction has the same structure as regular transactions, but for each txIn it has, any txOutPoint should just have a zero value (there is no previous txid to refer to). The scriptSig can contain arbitrary information, as miners do not need to sign anything. Miners add information to the scriptSig such as their name, or additional source of entropy for mining. Additionally, some consensus rules which have been soft forked into Bitcoin require that the scriptSig contains the block height and a merkle root of wtxids (for segwit).

The process is roughly like this:


Miner creates a coinbase template which spends some not yet known amount of money to one or more outputs.
Miner sorts transactions in the mempool by highest paying fee per weight unit (per byte in original), and picks some number of transactions such that their serialized size plus the serialized size of the coinbase is not greater than the block size limit.
They sum all fees paid in the included transactions and add it to the subsidy to create an amount that the block is worth.
They update the coinbase template with at most this amount being spent (it is possible to not claim the full amount of fees or the subsidy, but overclaiming produces an invalid block).
The miner computes the merkle root of all of these transactions txids (where the txid is the double-SHA of the serialized transaction), taken as a binary tree ordered by the position the transaction is serialized in the block. The coinbase is explicitly the first transaction.
The miner inserts this merkle root into a block header with the 5 other required fields (version, prevBlockHash, target, nonce and timestamp) and serializes it.
The miner repeatedly attempts double-SHA256 on the block header until the resulting digest, when taken as an integer, is numerically less than or equal to what is required by the target in the header. The miner modifies the nonce, or occasionally timestamp for each double-SHA256 attempt so that a different digest is produced, but the other fields of the header remain unchanged.
At some regular interval, if the miner has not yet found a successful hash, or if a new block is received, they compute a new template by starting this process from the beginning, which can take new information and may provide a higher reward. They discard the previous template they were working on. If a new block was found, any transactions which were included in the block are dropped from the mempool.