Command board.san(move) gives current move as text and you can keep it on list to save it later.
In documentation I found function chess.svg.board() which generates string with SVG image - and you can save in file using standard open(), write(), close()
Every browser can display image svg in HTML
You need only loop to create HTML with all moves and images
import chess
import chess.pgn
from io import StringIO
board = chess.Board()
pgn_string = """
1 e4 e6 2 d4 c6 3 Nf3 Nf6 4 Bg5 h6 5 Bf4 Na6 6 Bc4 d5 7 Bd3 Nxe4 8 O-O Nb4 9 Ne5 a5
10 Qg4 f5 11 Qg6+ Ke7 12 Qf7+ Kd6 13 Nc4#
"""
pgn = StringIO(pgn_string)
game = chess.pgn.read_game(pgn)
steps = []
for number, move in enumerate(game.mainline_moves()):
text = board.san(move)
print(text)
# keep current step on list
steps.append(text)
board.push(move)
#display(board)
# create string with SVG image
svg = chess.svg.board(board)
# save string in file with name `board-0.svg`, `board-1.svg`, etc.
with open(f'board-{number}.svg', 'w') as fh:
fh.write(svg)
# --- after loop ---
#print(steps)
# create string with HTML
html = ""
for number, move in enumerate(steps):
# add move
html += f'{move}</br>\n'
# add image `board-0.svg`, `board-1.svg`, etc. (with width=300 to make it smaller)
html += f'<img src="board-{number}.svg" width="300"></br>\n'
# save html in file
with open('index.html', 'w') as fh:
fh.write(html)
Screenshot from web browser:

BTW:
It needs files board-0.svg, board-1.svg, etc. to display it but you may also put string directly in HTML.
import chess
import chess.pgn
from io import StringIO
board = chess.Board()
pgn_string = """
1 e4 e6 2 d4 c6 3 Nf3 Nf6 4 Bg5 h6 5 Bf4 Na6 6 Bc4 d5 7 Bd3 Nxe4 8 O-O Nb4 9 Ne5 a5
10 Qg4 f5 11 Qg6+ Ke7 12 Qf7+ Kd6 13 Nc4#
"""
pgn = StringIO(pgn_string)
game = chess.pgn.read_game(pgn)
steps = []
for number, move in enumerate(game.mainline_moves()):
text = board.san(move)
print(text)
board.push(move)
#display(board)
# create string with SVG image (with size=300 to make it smaller)
svg = chess.svg.board(board, size=300)
# keep current step [text, svg] on list
steps.append( [text, svg])
# --- after loop ---
#print(steps)
# create string with HTML
html = ""
for number, (text, svg) in enumerate(steps):
# add move
html += f'{text}</br>\n'
# add image
html += f'{svg}</br>\n'
# save html in file
with open('index.html', 'w') as fh:
fh.write(html)