userdir-publish copies a built static website to a personal web directory, such as https://web.example.edu/~jdoe/, that Apache serves with mod_userdir. It uses rsync, either over SSH or to a local path when the web directory is mounted or you are logged in on the server. It removes stale files, sets permissions the web server can read, and refuses to publish a build that lacks index.html or the current .htaccess rules.
The tool requires rsync on your machine and on the server. On macOS, install GNU rsync (for instance with brew install rsync), because the built-in openrsync ignores the permission settings. Install it from PyPI:
uv tool install userdir-publishor with pipx install userdir-publish. Then run userdir-publish --help.
See rub-ep1.github.io/userdir-publish for other installation methods, configuration, group pages, and task runner integration.