Install script now removes index.html, QR codes, and download bundles
from existing site directories before rebuild-all regenerates them.
Preserves config.json, .onionshare-session, server.pid, and logs.
Also auto-rebuilds on serve if index.html is missing.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Existing sites kept stale index.html from old templates after upgrades.
New `voxvera rebuild-all` regenerates HTML for all sites from the
current master template while preserving keys, config, and content.
The install script now calls rebuild-all automatically after install.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
These files are not read by the build pipeline (which always generates
from index-master.html), but keeping them in sync avoids confusion.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Allows users to export onion service session keys as base64 and import
them on another instance, enabling domain migration without re-hosting.
Bump version to 0.3.3.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Switch content panel from space-between to flex-start so header
elements (title, subtitle, headline) pack tightly instead of
spreading across the full height
- Message area uses flex:1 to fill remaining space and keep footer
at the bottom
- Body editor now preserves user text when re-editing after exceeding
the 1000 character limit (previously reset to default)
- Show a yellow warning when user proceeds with over-limit body text
- Add body_over_limit_warning locale key across all 14 languages
Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Add bundled preset templates under voxvera/templates/presets/ (moved
from imports/, normalized field names to match config schema)
- New "Create From Template" option in the manage menu lets users pick
a preset (aosp, bitcoin, jesus, meshtastic, nostr, voxvera) and
customize it before publishing
- Template content is fully translated across all 14 supported languages;
the displayed content matches the user's selected language
- Rebuild HTML files with updated locale data
Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Bump version to 0.3.1 for new release with all content fixes
- Reorder install strategies: tarball first (always current with main),
pre-built binary last (can lag behind)
- Translate the "name" field across all 14 locale files
- Rebuild HTML files with updated locales
Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Stop deleting pip/pipx Python entry points by narrowing the stale
binary check to ELF/Mach-O only (not generic "executable")
- Clean up stale pip wheel cache, /tmp leftovers, ~/config.json and
~/imports/ from older VoxVera versions (preserves ~/host tor sites)
- Run hash -r after install and prompt user to do the same if command
is not found (curl|bash runs in a subshell)
Co-Authored-By: Claude Opus 4.6 <[email protected]>
The build_site() path was missing the _newlines_to_br() call when
embedding user content into the locales JSON, causing literal \n to
appear in the generated index.html files. Fixed and rebuilt both
site/index.html and voxvera/host/voxvera/index.html.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Convert <br> to real newlines before opening the editor so users see
proper paragraph breaks instead of raw markup. Ensure user-typed newlines
are converted back to <br> when embedded in the locales JSON for JS
rendering. Replace remaining \n with <br> in all import configs and
site/config.json for consistency.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Root cause: three config.json files (src, templates, host) had different
newline encodings (\n, \\n, raw newlines). The templates version had
double-escaped \\n\\n which survived the simple replace chain.
- Replace \n with <br> in all three config.json files
- Replace raw newlines with <br> in bundled host/voxvera/index.html
- Add _newlines_to_br() helper that handles all encoding variants:
real newlines, literal \n, already-converted <br>, and mixed content
- Use the helper in all four HTML injection sites in cli.py
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Default landing content in all 14 locale files used JSON \n for
paragraph breaks. These rendered as literal \n\n on Tor Browser
(no JS). Now uses <br><br> tags directly in the locale strings.
User-entered content from the editor still gets \n→<br> conversion
at build time via cli.py.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
The Debian Bookworm SSL/TLS stack (both OpenSSL for curl and GnuTLS
for git) frequently fails or hangs against GitHub. This overhaul:
- Adds wget as fallback downloader (different TLS codepath)
- Wraps all git/network ops with `timeout` to prevent hangs
- Reorders strategies: binary → tarball → shallow clone → pipx → pip
(tarball now before git-based methods since it needs no git protocol)
- Each download retries 3x with both curl and wget before giving up
- Installs wget as a system dep on apt-based distros
- Final error message gives manual download instructions
Co-Authored-By: Claude Opus 4.6 <[email protected]>
A failed binary download (or leftover from a previous install) at
~/.local/bin/voxvera shadows the pipx/pip entrypoint script. Now all
non-binary strategies detect and remove stale ELF/Mach-O binaries
before declaring success.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Add GIT_HTTP_LOW_SPEED_LIMIT/TIME to prevent git clones from hanging
- Force TLS 1.2 to work around GnuTLS negotiation bugs on older Debian
- Add curl retries, timeouts, and --retry-connrefused
- Add GitHub tarball fallback (no git clone needed at all)
- Add shallow clone (--depth 1) as final fallback
- Refactor install strategies into a clean cascade: binary → pipx →
pip git → tarball → shallow clone
Co-Authored-By: Claude Opus 4.6 <[email protected]>
User-entered line breaks were rendering as literal \n\n in the content
box because the static HTML injection didn't convert newlines to <br>
tags. Since Tor Browser disables JS, the fix must be server-side.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Sites now survive terminal close and can start automatically on boot:
- subprocess.Popen uses start_new_session=True (Unix) or
CREATE_NEW_PROCESS_GROUP (Windows) so onionshare-cli processes
are fully detached and immune to SIGHUP when the terminal exits
- New `voxvera start-all` / `stop-all` commands for non-interactive
batch control of all configured sites
- New `voxvera autostart` installs platform-appropriate boot service:
- Linux: systemd user service + loginctl enable-linger
- macOS: launchd LaunchAgent
- Windows: schtasks scheduled task on login
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Root cause: user-local werkzeug 2.0.3 in ~/.local/lib/python3.11/
site-packages shadows the system werkzeug 2.2.2, breaking Flask's
LocalProxy.unbound_message for the system onionshare-cli.
The pip3 show-based cleanup was unreliable (shows system package,
skips user-local). Two-pronged fix:
1. Set PYTHONNOUSERSITE=1 in the env passed to onionshare-cli so it
never loads packages from ~/.local — uses only system packages.
2. Install script now directly rm -rf's conflicting packages from
~/.local/lib/python3.*/site-packages/ instead of relying on pip3.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Previous pip --user installs left werkzeug 2.0.3 in ~/.local which
shadows the system werkzeug and breaks the system onionshare-cli
(Flask 2.2.2 requires werkzeug >= 2.2 for LocalProxy.unbound_message).
Changes:
- Remove flask, werkzeug, and onionshare-cli from voxvera's own
dependencies — they are onionshare's transitive deps, not ours
- Install script now cleans up stale user-local packages (werkzeug,
flask, flask-socketio, onionshare-cli, voxvera) before installing
- Prevents pip --user packages from poisoning system Python environment
Co-Authored-By: Claude Opus 4.6 <[email protected]>
The previous fix only used the system binary for non-frozen (pip/pipx)
installs. But the PyInstaller binary also needs this — it downloads
successfully but its bundled onionshare_cli import still crashes on
'No module named pkg_resources'.
Now both serve() and _internal_onionshare() unconditionally prefer the
system onionshare-cli/onionshare binary via shutil.which(), falling
back to the Python import only if no system binary exists.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Major fixes:
- Use system onionshare-cli binary directly (subprocess/execvp) instead of
importing it as a Python module, avoiding pkg_resources crashes in pipx venvs
- get_servers() now only searches DATA_DIR/host (single source of truth);
bundled example sites are seeded on first manage run then fully user-owned
- delete_server() now permanently removes sites (no ghost re-appearance)
- DATA_DIR defaults to ~/ instead of cwd, preventing sites from scattering
across directories
- Fix attachment URL logic that incorrectly overwrote valid onion URLs
Co-Authored-By: Claude Opus 4.6 <[email protected]>