The source code for the dice roller is available at https://github.com/AdamWrighter/dice-roller. Every push to master is automatically deployed using Cloudflare Pages.

If you compare https://dice.adamw.uk/main.js to https://github.com/AdamWrighter/dice-roller/blob/main/main.js, you will see it is the same, only https://dice.adamw.uk/main.js has been minified to improve performance.

Rolls are generated using the roll function. As of June 15, 2021 2:37 PM (GMT+1), this looks like this:

function roll(sides) {
    let thisRoll = ranNum(sides);
    if (urlParams.get('sound') == 'true') {
        sound(thisRoll, sides);
    }
    calcStats();
    return thisRoll;
}

As of June 15, 2021 2:37 PM (GMT+1), the ranNum function used in roll looks like this:

function ranNum(max) {
    return Math.floor(Math.random() * max) + 1;
}

It's really simple, and hinges entirely on JavaScript's built-in Math.random() function.

The Math.random() function returns a floating-point, pseudo-random number in the range 0 to less than 1 (inclusive of 0, but not 1) with approximately uniform distribution over that range.

To generate a dice roll using Math.random(), the float returned by Math.random() is multiplied by the number of sides of the die (max), and then 1 is added as dice start at 1, not 0. The result of this is then passed into Math.floor(), which rounds it to an integer. This is what ranNum returns.

That's it - that's all the maths that the dice roller does to generate fair rolls. As long as you trust JavaScript's built-in Math.random() function, then you can trust this dice roller.