I have a simple method of having web pages, self contained, which require you to enter a password to read. In short, my script read in the original html, encrypts with AES using the password, turns that into base64, then into a javascript statement of the form
var content = ["AAAAAAAABQLgCopEUARlI2BACMAyMoAyaAAAAAAAAAAAguBQRFABAAUBA",
"CPkjKRgQIADQIigACXAoJcXAoAAAAAAABUQtwBVyQqAoAAMyW5ABGGAIyGiWAIoAAAAAAAAA",
"AEuEwKAAC5KQqAEZSMCMhWQAaMlQFAAAEuLgUEuUAAAAAAyE%3D"].join("");
and tries to decrypt this with the given password, replacing either document.body.innerHTML or the entire document with the result if successful.

Replacing the entire document, according to a stackexchange answer, is via

document.open('text/html');document.write('<!DOCTYPE HTML><html>...</html>');document.close();

The other issue is images. For this, on Linux, one can do e.g.

base64 imagename.jpg | sed "s/=/%3D/"
to get a base64 representation of an image. Then to include it, use
<img src="data:image/jpeg;base64,BASE64DATA">
where BASE64DATA is your base64 data from the previous step. This allows the file to be self-contained.