I'm doing something similar but using segwit addresses (BIP49). If you are using BIP32 with a standard derivation of m/0'/0/0 you could do something like this - See: https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.js#L35
//get a mnemonic, then seed, then root.
var mnemonic = bip39.generateMnemonic();
var seed = bip39.mnemonicToSeed(mnemonic);
var root = bitcoin.HDNode.fromSeedBuffer(seed);
//root can be transformed to your xpub and xprv
var xprv = root.toBase58();
var xpub = root.neutered().toBase58();
//You can then create the address with a derivation of m/0'/0/0
var change = 0; //0 for external (receive), 1 for internal (change)
var index = 0; //the index of the address you want to generate
var keypair = root.deriveHardened(0).derive(change).derive(index);
//or keypair = root.derivePath("m/0'/" + change + "/" + index);
var address = keypair.getAddress();
If your derivation for your addresses is m/0' (then external, then the index) Then you have the xpub for the parent m and can store xpub of m/0'/0 on the server. On the server when a user clicks the button it generates the address n/0, where n = your xpub of m/0'/0.