Bitcoin HD Wallets with hardened derivation and watch-only addresses
Use the master key (call it m) to derive m/44'/0'/0'. This will give you a pair of public/private keys, let's call them xpub-a and xprv-a.
Now you can take xpub-a onto your online machine, and use xpub-a to derive receive addresses (xpub-a/0/0, xpub-a/0/1, etc) and change addresses (xpub-a/1/0, xpub-a/1/1, etc).
In this way, you've used hardened derivation concatenated with non-hardened derivation for your change and receive addresses. Your final addresses from the path of your master key (m), will then be:
Receive addresses:
m/44'/0'/0'/0/0
m/44'/0'/0'/0/1
... etc.
and Change addresses:
m/44'/0'/0'/1/0
m/44'/0'/0'/1/1
...etc...
Example using bip32:

let master = bip32.fromBase58('xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi')
let final = master.derivePath(&quot;m/44'/0'/0'/0/0&quot;)
let middle = master.derivePath(&quot;m/44'/0'/0'&quot;).neutered() // &quot;neutered&quot; removes the private key
let final2 = middle.derivePath(&quot;0/0&quot;);
// observe that final.neutered().toBase58() === final2.toBase58()