Compare commits

...
75 Commits
Author SHA1 Message Date
thePR0M3TH3ANandClaude Opus 4.8 085ff81c1a Board: tuck per-row actions behind a ⋯ menu
The inline Edit / Re-broadcast / Delete (and Block) buttons wrapped messily in
the actions column. Replace them with a single ⋯ button per row that opens a
small popout menu with the relevant actions. Closes on outside click, Escape,
or selecting an item; the actions and their data-act wiring are unchanged.

Adds the menu markup/toggle in board.js, an "Actions" aria-label string × 14
languages, and menu/kebab styles. e2e updated to open the menu before acting.
234 e2e across all six engines.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 20:16:12 -04:00
thePR0M3TH3ANandClaude Opus 4.8 73c28f31ec Bulletin board: per-row manage (edit / re-broadcast / delete) + local Block
Add inline management to the board for the connected viewer:

- On your own flyers: Edit (links to /?edit=1#<naddr>, which the main client
  now honors by loading the flyer straight into the editor), Re-broadcast
  (re-sends the already-signed event to all relays — no signing), and Delete
  (replaceable tombstone + NIP-09, signed via the device key or NIP-07; a
  pasted-nsec connection is pointed to the editor where the key is available).
- On flyers from others: Block — a per-device blocklist of author pubkeys
  (voxvera_blocked_pubkeys) that always hides them, with a "Clear blocked"
  control. This is roadmap #1's local blocklist direction.

The board hides tombstoned flyers (newest-version-wins so a delete can't be
undone by an older copy). New non-sortable actions column; a board delete-
confirm modal; 12 new strings × 14 languages. Adds e2e for block (hide/persist/
clear), own-vs-other actions, and board delete (tombstone + NIP-09 published),
plus a ?edit=1 deep link. 234 e2e across all six engines; docs updated.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 20:06:07 -04:00
thePR0M3TH3ANandClaude Opus 4.8 9b03ada43a Flyers: edit, re-publish (keep-alive), and delete (tombstone + NIP-09)
Authors can now manage a published flyer from the editor when it's loaded from
an event (author-only — the active signing key must match the flyer's author):

- Edit: change fields and publish again; the same d-tag replaces in place.
- Re-publish (keep-alive): re-sign + re-broadcast the current content so relays
  that prune app-data don't age the flyer out. Partially addresses roadmap #4.
- Delete: belt-and-suspenders across relay behaviors —
  1) a replaceable TOMBSTONE (same kind+d, payload deleted:true + a ["deleted"]
     tag) that overwrites the flyer's content, so the board/viewer hide it even
     on relays that ignore deletions, and
  2) a NIP-09 deletion request (kind 5) for the addressable a-tag + event id.
  Confirmed via a modal; framed as best-effort, not a guarantee.

Tombstone recognition: the board's parseFlyers keeps the newest event per
(pubkey, d) and skips it when that newest version is a tombstone (so a delete
can't be reversed by an older copy arriving later); the viewer renders a
localized "This flyer was removed." state.

Adds the loaded-flyer actions UI + a delete-confirm modal, 11 new strings ×
14 languages, a Python schema test for the tombstone payload, and e2e for the
delete flow, board hiding, and the viewer removed state. 216 e2e across all six
engines; docs (spec/roadmap/README) updated.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 19:39:23 -04:00
thePR0M3TH3ANandClaude Opus 4.8 23badb03ae Add an SVG favicon (no more /favicon.ico 404)
Link a small inline SVG (site/favicon.svg, a red tile with a white "V") from
both index.html and board.html via a root-absolute href, so it resolves from
"/" and from "/board/" under Vercel cleanUrls. With an icon link present,
browsers stop auto-requesting (and 404ing on) /favicon.ico. No binary asset and
no external dependency, consistent with the self-contained client.

e2e asserts both pages declare the favicon and that /favicon.svg is served as
valid SVG. Closes the last code-finishable item in the roadmap's smaller list.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 19:19:06 -04:00
thePR0M3TH3ANandClaude Opus 4.8 2f423ceed5 Editor: build the poster naddr from the actual signing key (fix wrong-author URLs)
A flyer published via NIP-07 could get a poster naddr encoding the anonymous
device key instead of the signer: signActiveEvent signed through window.nostr
(the real key) while activeIdentity() — used to build the naddr — fell back to
the anon key whenever nip07Pubkey hadn't loaded yet (e.g. just after a reload
restored nip07 mode). The resulting poster URL pointed at the wrong author and
could never be loaded back, even though the flyer appeared on the board (which
finds events by tag, not address).

signAndPublish now resolves the concrete signing pubkey first (fetching the
NIP-07 key if needed), builds the naddr from that exact key, and refuses to
publish if the signed event's pubkey does not match the naddr — so the signer
and the poster address can no longer diverge.

Note: this prevents new broken flyers; an already-published flyer with a
mismatched naddr must be re-published to get a correct poster URL.

Test: a NIP-07 publish issued while getPublicKey is still pending now yields a
naddr whose pubkey matches the signer (fails on the old code). 192 e2e across
all six engines.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 15:53:03 -04:00
thePR0M3TH3ANandClaude Opus 4.8 0530dbc905 Bulletin board: add an Event ID column with a per-row copy button
Each flyer row now shows its event ID (shortened, full value in the title
attribute) with a Copy button that copies the full 64-char id to the clipboard
(flips to "Copied", falls back to selecting the text if the clipboard is
blocked). The column is sortable like the others. Copy is handled by a single
delegated listener on the tbody, since rows re-render on sort.

Localized the new column header (col_event_id) across all 14 languages; Copy/
Copied already existed in the board strings. Updated the column e2e test (now 6
columns) and added a test for the id cell + copy target. Docs updated.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 15:42:20 -04:00
thePR0M3TH3ANandClaude Opus 4.8 82126d52d6 Viewer: render any flyer the board lists (lenient view + board-style fetch)
A flyer could appear on the bulletin board yet fail to open in the viewer.
Two causes, both fixed so "if the board shows it, the viewer opens it":

- Over-strict view validation. The viewer ran the *authoring* validatePayload
  on fetched events (in payloadFromEvent and normalizePayload) and threw on
  length caps, a raw-HTML regex that false-positives on plain text like
  "value < x >", version, and URL scheme — refusing to render. The renderer
  already HTML-escapes every field, so the view path is now lenient: it renders
  what was published and only neutralizes unsafe URL schemes (javascript:/data:
  become no-link instead of throwing). Strict validation still gates authoring
  via buildPayloadFromForm, so we never publish junk. The mandatory t=flyer tag
  is dropped (t=voxvera + a voxvera_flyer payload is enough), matching the board.

- Fragile fetch. fetchReplaceable relied on the relay honoring an addressable
  "#d" tag filter; some relays don't, yet still return the event for a broader
  query (which is how the board finds it). It now queries by author+kind and
  matches the d-tag in-page, with a longer timeout.

Tests: a fetched flyer with HTML-ish text + a 6k body + a javascript: URL now
renders with the URL neutralized; and a flyer served by a relay that refuses
"#d" filters still resolves. 180 e2e across all six engines.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 15:29:17 -04:00
thePR0M3TH3ANandClaude Opus 4.8 be91ea7250 Roadmap: mark the trust model (#1–#2) shipped
Add a "Shipped so far" summary (board login gate, web-of-trust filter, editor
publishing identity with PIN-encrypted nsec) and refresh the review footer:
the trust model is now implemented, so #3 (centralized client distribution) is
the highest-leverage untouched item.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 10:22:27 -04:00
thePR0M3TH3ANandClaude Opus 4.8 861407cbf6 Editor: publish under your own identity (NIP-07 / nsec) with PIN-encrypted nsec
Let authors publish a flyer under a stable, identifiable key when they want
one, while keeping anonymous-by-default. The editor now signs under one of
three identities, routed through activeIdentity()/signActiveEvent():

- Anonymous (default, unchanged): the per-device key, signed locally.
- NIP-07 extension: signs via window.nostr.signEvent; the secret never
  enters the page.
- Imported nsec: decoded to a key used to sign. By default the secret lives
  only in memory for the session. "Remember on this device" stores it
  encrypted with a PIN (PBKDF2 SHA-256, 600k iterations, random salt ->
  AES-GCM-256); the plaintext secret is never written to storage. On reload a
  remembered key is locked until the PIN is entered; a session-only key falls
  back to anonymous.

The signer pill, author npub, naddr, and poster URL all follow the active
identity. New identity controls are localized across all 14 languages.

Security note (also in docs): a short numeric PIN is brute-forceable offline
if the encrypted blob leaks, so it guards casual snooping, not a targeted
attacker — the NIP-07 path is stronger, and NIP-46 is a documented follow-up.
The minimum PIN is 4 digits but longer is allowed and encouraged.

Also updates README, the client spec (new "Publishing identity" section),
the roadmap (#1/#2 marked in progress with phases shipped), and the e2e
README. Covered by the cross-engine Playwright suite (default-anonymous,
NIP-07 connect + publish, session-only nsec without persistence, invalid
nsec, PIN encrypt -> lock on reload -> wrong/right PIN -> unlock, and forget).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 10:16:53 -04:00
thePR0M3TH3ANandClaude Opus 4.8 1297a73332 Bulletin board: login gate, web-of-trust filter, and key connect methods
Gate the board behind a connected Nostr identity and filter what it shows
to the viewer's web of trust, so it is no longer an unmoderated firehose.

- Login gate: the board shows a Connect prompt instead of the table until a
  Nostr identity is connected; the connected npub is surfaced with a
  Disconnect control and remembered (pubkey only) for silent reconnect.
- Connect methods: NIP-07 extension, pasting an nsec (decoded in-page to a
  pubkey, then discarded — the board reads, never signs), or creating a new
  key (reveals the nsec to save, reuses the device key if present).
- Web-of-trust filter (NIP-02): defaults to flyers from authors in the
  viewer's follow graph, with a "Show all" opt-out. A fresh key with no
  follows is seeded from a pinned curator account so new viewers still get a
  curated board; if no trust data loads at all, it shows everything.
- Localized across all 14 languages (gate, filter, and connect strings),
  RTL included.

Covered by the cross-engine Playwright suite (gate shown/hidden, connect via
each method, pubkey-only persistence, web-of-trust filtering + show-all, and
the curator-seeded fallback).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-10 10:16:24 -04:00
thePR0M3TH3ANandClaude Opus 4.8 b92cb018c5 Roadmap: plan identity + web-of-trust gating for the bulletin board
Mark board moderation (#1) and authenticity (#2) as Planned and add a joint
"identity + web-of-trust on the board" direction:

- Login enables a trust-filtered view, not access control (you cannot gate
  writes to public relays; you filter what the board displays).
- Keep anonymous creation + printing available; require identity only to
  appear on the public board.
- Web-of-trust (NIP-02 follow graph) is the real spam defense, since keys are
  free; login alone is just a soft deterrent.
- Support NIP-07 plus nsec import / NIP-46 / promoted anon key so mobile (the
  scanned-QR audience) isn't locked out.
- Phased plan (identity → WoT filter → blocklist/report/NIP-05) and the two
  open decisions: gate viewing or not, and which login methods at launch.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 22:25:38 -04:00
thePR0M3TH3ANandClaude Opus 4.8 c8c715f438 Document known issues and roadmap
Add docs/roadmap.md capturing product/threat-model gaps that are not code
bugs, in priority order: (1) bulletin board has no moderation/abuse story,
(2) anonymous keys give no authenticity, (3) client distribution is
centralized on one domain, (4) relay permanence is overstated, (5) minimal
content-safety guardrails, plus smaller items. Each entry notes the problem,
current mitigation, why it matters, and possible directions.

Link it from the README and the spec's bulletin board section.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 22:21:34 -04:00
thePR0M3TH3ANandClaude Opus 4.8 e0ea31eaef Widen paper-size selector and balance bulletin-board link spacing
- Give the paper-size selects a min/max width so "US Letter (8.5 × 11 in)"
  is readable instead of truncated.
- Add equal spacing below the bulletin-board link to match the gap above it.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 22:15:03 -04:00
thePR0M3TH3ANandClaude Opus 4.8 7ab7e412ec Show a publish confirmation modal with the flyer URL
After Sign and publish succeeds, open a modal that tells the author the
flyer is published and shows its URL (pre-selected) with Copy and Close
buttons, so they know the process completed and where to view/share it.

- New modal markup in index.html + overlay/box styles (hidden in print).
- Closes on the Close button, backdrop click, or Escape; Copy writes the URL
  to the clipboard with a "Copied" confirmation.
- Localized for all 14 languages (published_title / published_message /
  close); the URL is result.posterUrl.
- Playwright: add a test that stubs the relay socket, publishes, and asserts
  the modal shows the localized text and the naddr poster URL. 84 tests pass
  across all engines.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 22:06:30 -04:00
thePR0M3TH3ANandClaude Opus 4.8 0044b4b797 Fix unstyled bulletin board on Vercel (cleanUrls/trailingSlash)
vercel.json sets cleanUrls + trailingSlash, so board.html is served at
/board/. Its relative asset paths (nostr-client.css, board.js, locales.js,
vendor/...) then resolved to /board/... and 404'd, leaving the page as raw
unstyled HTML stuck on "Loading…". Use root-absolute paths instead, and
point the back link at "/". Add an e2e guard asserting board.html assets are
root-absolute (the dev server can't reproduce Vercel's URL rewrites).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 21:38:26 -04:00
thePR0M3TH3ANandClaude Opus 4.8 98086a0ad4 Add bulletin board page listing recent flyers from the relays
A small screen-only link below the flyer preview (outside the printable
sheet, hidden in print) opens board.html: a spreadsheet-style list of the
most recent VoxVera flyers found on the default relays.

- Columns: title, link (the poster URL shown as "link"), posting npub,
  language, and posted date; every column is sortable (default date
  descending). Replaceable events are de-duplicated per author+d identifier,
  keeping the latest.
- board.js is independent of nostr-client.js (which exports nothing): its UI
  strings live in BOARD_UI for all 14 languages, and it reuses the vendored
  nostr-tools and locales.js (language names + RTL direction).
- The board has its own language selector that reads/writes the same
  voxvera_nostr_lang localStorage key as the main client, so the choice
  carries across pages; switching it re-localizes the chrome, headers,
  language labels, and date formatting and flips RTL.
- Untrusted relay content is escaped, and link URLs are rejected unless
  http(s) so javascript:/data: never render as a link.

Docs updated (README, spec, AGENTS). Playwright: add tests for the
out-of-sheet print-hidden link, the localized sortable columns, and the
board language selector (incl. RTL + persistence). 72 tests pass across
Chromium, Firefox, WebKit, and Android/iOS mobile emulations.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 16:28:32 -04:00
thePR0M3TH3ANandClaude Opus 4.8 127f9c3134 Locale-aware defaults: browser language list + US Letter/A4 paper size
Language inference:
- Walk navigator.languages (the full ordered preference list), not just
  navigator.language, and pick the first base language we support. A user who
  prefers e.g. Dutch then German now gets German instead of the English
  fallback. De-duplicates the default-language resolution into setDefaultText.

Paper size (US Letter + A4):
- Add A4 (210x297mm) alongside US Letter (8.5x11in). Sheet dimensions move to
  CSS custom properties (--sheet-w/--sheet-h) toggled by a paper-letter/paper-a4
  class on <html>; the tear-off column and QR codes stay fixed physical sizes
  and the content column flexes.
- @page size is injected by JS (id voxvera-page-size) since @page cannot read
  CSS variables across engines; the print block keeps margin:0 and a Letter
  default for the pre-JS state.
- Default paper is chosen from the browser locale's region subtag
  (en-US -> Letter, en-GB/de-DE -> A4) — "by location" without geolocation,
  falling back to Letter when no region is present. A manual override selector
  (topbar + viewer controls) persists in localStorage and wins over the default.
- Paper size is a local print/view preference and is never written into the
  Nostr event, so a flyer reprints on either size unchanged.
- Add paper_size/paper_letter/paper_a4 labels for all 14 languages.

Docs + tests:
- Spec gains a "Print paper size" section; AGENTS.md records the
  not-in-payload invariant; README adds a feature bullet; the field-limits
  cheat sheet gains Letter/A4 columns (re-measured per paper size).
- Playwright: add tests for navigator.languages inference, region-based paper
  default (A4 and Letter), and override persistence. 54 tests pass across
  Chromium, Firefox, WebKit, and Android/iOS mobile emulations.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 15:56:25 -04:00
thePR0M3TH3ANandClaude Opus 4.8 c5b2c20fc9 Add cross-browser e2e tests, field-limit cheat sheet, and docs
Verification:
- Add Playwright harness (e2e/) covering Chromium, Firefox, and WebKit plus
  Android/iOS mobile emulations. Smoke tests assert: default flyer renders
  with no JS/console errors, @media print hides app chrome and keeps the
  flyer, anonymous npub generation (WebCrypto), legacy /nostr/ redirect
  preserves query+hash, and event-lookup URLs show the loading state instead
  of the default flyer. All six projects pass.
- package.json/playwright.config.js wire up the projects and a managed static
  server; .gitignore excludes node_modules and Playwright output.

Docs:
- docs/flyer-field-limits.md: per-script character cheat sheet for each flyer
  field (single-line caps + multi-line guidance), measured by rendering each
  script at print size.
- README: add a Features section matching the shipping client and a
  cross-browser verification section; link the cheat sheet.
- AGENTS.md: document the e2e suite and the one-time WebKit Linux dep.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 15:29:49 -04:00
thePR0M3TH3ANandClaude Opus 4.8 562b7d1429 Show loading state on event-lookup URLs instead of default flyer
A viewer arriving via an event-lookup URL (naddr/nevent/note/hex in the
query or #fragment) previously saw the default placeholder flyer flash
before the real event resolved. Now it renders a localized "Loading
content..." state, and a "Could not load this flyer." state on fetch
failure. Default flyer content now appears only on the bare main URL.

- Add loading_content and load_failed labels for all 14 languages
- Add renderStatusPreview() rendering a minimal flyer sheet with a single
  centered, direction-aware message (no tear-offs, no QR)
- Render loading state synchronously before fetch in the URL-event path,
  failed state in the catch handler
- Add .flyer-status-message CSS

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 13:46:43 -04:00
thePR0M3TH3ANandClaude Opus 4.8 77bfef1bbe Serve client at site root; redirect legacy /nostr/
The /nostr/ path was a leftover from when the site also hosted a Tor
client. The app is Nostr-only now, so move the client to the site root
and shorten poster URLs to https://voxvera.org/#naddr1... (drops both
/nostr/ and the ?addr= query key, for a cleaner/smaller tear-off QR).

- Move site/nostr/{nostr-client.js,css,locales.js,vendor} to site/.
- site/index.html is now the client; site/nostr/index.html is a redirect
  stub that forwards /nostr/ to / while preserving the query string and
  #naddr fragment, so older poster URLs and printed QR codes still
  resolve.
- Carry the naddr in the URL fragment (#) instead of ?addr=; the viewer
  reads query, fragment, or the full URL, so old links keep working.
- Update README, AGENTS.md, and the spec to the new paths.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 10:49:36 -04:00
thePR0M3TH3ANandClaude Opus 4.8 828ac3a624 Tolerate whitespace in pasted event ID lookups
The Load Event field requires 64 contiguous hex chars, but the event ID
printed on a tear-off tab wraps across two lines, so copying it back in
pastes as two 32-char halves separated by a newline/space and failed to
match. Strip inner whitespace before matching the raw hex id, which also
tolerates a pasted "Event ID:" label prefix. naddr/note/nevent inputs are
unaffected.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 10:37:07 -04:00
thePR0M3TH3ANandClaude Opus 4.8 aedb381dfb Improve flyer tear-offs, shorten poster URL, adaptive tracking
- Tear-off tabs: single hyperlinked statement (no printed URL), with
  "Share and reprint." on its own line; localize "Click to open this
  poster." across all 14 languages.
- Show the full event ID, bottom-anchored on each tab, split into two
  32-char lines at max readable monospace size.
- Shorten the poster URL by encoding the naddr with a single relay hint
  instead of the full relay list (~233 -> ~171 chars) for an easier-to-
  scan QR; still a standard naddr, older URLs resolve unchanged.
- Add per-script letter-spacing policy (ls-full/ls-cjk/ls-none) to fit
  more text per line where safe, and turn tracking off for Arabic,
  Persian, and Hindi (fixes broken cursive joins / combining marks).
- Move the "field too long" warning inline under the offending field
  instead of a single bottom status line.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-09 10:13:55 -04:00
thePR0M3TH3AN 9baf5fb195 fixed mobile 2026-06-06 14:38:19 -04:00
thePR0M3TH3AN fd272888ec Move VoxVera credit below footer message 2026-06-06 14:31:14 -04:00
thePR0M3TH3AN d273843bb1 Improve flyer editing and add demos 2026-06-06 14:26:40 -04:00
thePR0M3TH3AN 20d5e64326 Localize Nostr editor status UI 2026-06-06 09:28:10 -04:00
thePR0M3TH3AN c08f8509db Truncate visible tear-off URLs 2026-06-06 09:19:23 -04:00
thePR0M3TH3AN c53f87dd95 Update default flyer copy for Nostr 2026-06-05 16:01:32 -04:00
thePR0M3TH3AN 83b4133780 Add Vercel static deployment config 2026-06-05 13:59:27 -04:00
thePR0M3TH3AN 1bda451604 Flag flyer language in Nostr events 2026-06-05 13:33:18 -04:00
thePR0M3TH3AN 5afda54a21 Keep content URL separate from poster URL 2026-06-05 10:18:03 -04:00
thePR0M3TH3AN 9aa90773e6 Remove legacy Tor app from main 2026-06-05 10:13:41 -04:00
thePR0M3TH3AN ee13d3fd03 Localize Nostr flyer side tabs 2026-06-05 10:01:57 -04:00
thePR0M3TH3AN 8619261c78 Localize Nostr language controls 2026-06-05 08:51:18 -04:00
thePR0M3TH3AN 3738204ede Keep viewer controls in layout 2026-06-05 08:29:40 -04:00
thePR0M3TH3AN fc50962bf4 Center Nostr viewer controls 2026-06-05 08:22:46 -04:00
thePR0M3TH3AN 0f94d640ac added language selector 2026-06-04 22:30:50 -04:00
thePR0M3TH3AN 46fa306c31 Localize VoxVera Nostr client 2026-06-04 22:06:22 -04:00
thePR0M3TH3AN d415eb26a3 Add VoxVera Nostr static client 2026-06-04 20:15:50 -04:00
thePR0M3TH3AN 285d730369 chore: release v0.3.12 2026-03-19 22:52:47 -04:00
thePR0M3TH3AN f5403448a7 fix: stabilize docker runtime smoke checks 2026-03-19 22:49:05 -04:00
thePR0M3TH3AN 6822b8e496 fix: add docker runtime smoke job to ci 2026-03-19 22:36:36 -04:00
thePR0M3TH3AN 83e9e3d511 feat: harden docker runtime validation 2026-03-19 22:30:28 -04:00
thePR0M3TH3AN 004cce2a4f chore: release v0.3.11 2026-03-19 22:05:16 -04:00
thePR0M3TH3AN ec0abd856c chore: release v0.3.10 2026-03-19 21:45:02 -04:00
thePR0M3TH3AN 7724ac78a7 chore: release v0.3.9 2026-03-19 21:36:04 -04:00
thePR0M3TH3AN c1a5e608de chore: release v0.3.8 2026-03-19 16:53:04 -04:00
thePR0M3TH3AN 44cf452f67 chore: release v0.3.7 2026-03-19 16:36:46 -04:00
thePR0M3TH3AN 4e49762a85 docs: add linux hosting validation runbook 2026-03-19 16:24:22 -04:00
thePR0M3TH3AN 2de7ea073c feat: add autostart lifecycle controls 2026-03-19 16:15:51 -04:00
thePR0M3TH3AN 2dd0cf4ed8 fix: install smoke test dependencies in ci 2026-03-19 16:03:55 -04:00
thePR0M3TH3AN 6c4d6d6aef feat: formalize platform runtime contracts 2026-03-19 15:57:50 -04:00
thePR0M3TH3AN e6ff21c069 chore: release v0.3.6 2026-03-17 16:16:17 -04:00
thePR0M3TH3AN 1fcb86ac8b chore: release v0.3.5 2026-03-17 15:35:17 -04:00
thePR0M3TH3AN 2b29d71ac5 chore: release v0.3.4 2026-03-17 14:18:42 -04:00
thePR0M3TH3ANandClaude Opus 4.6 46360ca6ea fix(install): clean stale generated files from site dirs before rebuild
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]>
2026-03-16 21:46:14 -04:00
thePR0M3TH3ANandClaude Opus 4.6 03b1c51e27 feat(rebuild): add rebuild-all command and auto-rebuild on install
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]>
2026-03-16 21:39:34 -04:00
thePR0M3TH3ANandClaude Opus 4.6 fc628fb9a0 fix(templates): sync bundled index.html copies with master template
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]>
2026-03-16 21:33:47 -04:00
thePR0M3TH3ANandClaude Opus 4.6 91391b1dd7 fix(lint): add missing Console() instances in export/import key functions
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-16 21:12:35 -04:00
thePR0M3TH3ANandClaude Opus 4.6 d61a7b4c92 feat(keys): add Export Keys / Import Keys to per-site menu with 14-language support
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]>
2026-03-16 21:04:34 -04:00
thePR0M3TH3ANandClaude Opus 4.6 2dabd93809 bump(v0.3.2): version bump for new release
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-16 19:51:37 -04:00
thePR0M3TH3ANandClaude Opus 4.6 ee5024678d fix(ui): tighten header spacing, preserve body edits on retry, add over-limit warning
- 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]>
2026-03-16 19:41:40 -04:00
thePR0M3TH3ANandClaude Opus 4.6 445375e098 feat(templates): add "Create From Template" menu with 14-language support
- 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]>
2026-03-16 18:55:38 -04:00
thePR0M3TH3ANandClaude Opus 4.6 9067596083 bump(v0.3.1): version bump, prefer tarball install, translate locale names
- 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]>
2026-03-16 14:57:08 -04:00
thePR0M3TH3ANandClaude Opus 4.6 d732b355d7 fix(install): clean up stale state, fix binary detection, and add hash reset
- 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]>
2026-03-16 14:02:49 -04:00
thePR0M3TH3ANandClaude Opus 4.6 bcc8616851 fix(content): apply newline-to-br conversion in build_site locale embedding and rebuild HTML
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]>
2026-03-16 13:54:04 -04:00
thePR0M3TH3ANandClaude Opus 4.6 c9f2546e1d fix(content): complete newline/br round-trip for editor and all content sources
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]>
2026-03-16 13:46:28 -04:00
thePR0M3TH3ANandClaude Opus 4.6 6189ae321e fix(content): robust newline-to-br conversion across all content sources
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]>
2026-03-16 13:17:12 -04:00
thePR0M3TH3ANandClaude Opus 4.6 945557cd0f fix(locales): replace \n with <br> in default content across all languages
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]>
2026-03-16 13:04:53 -04:00
thePR0M3TH3ANandClaude Opus 4.6 389d1f05a5 fix(install): add wget fallback, timeouts on all operations, reorder strategies
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]>
2026-03-16 11:58:53 -04:00
thePR0M3TH3ANandClaude Opus 4.6 ba3c63749d fix(install): remove stale binary when pipx/pip fallback succeeds
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]>
2026-03-16 11:49:45 -04:00
thePR0M3TH3ANandClaude Opus 4.6 6839f67311 fix(install): resilient install with timeouts, retries, and tarball fallback
- 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]>
2026-03-16 11:46:37 -04:00
thePR0M3TH3ANandClaude Opus 4.6 b4a74a32f4 fix(cli): convert newlines to <br> in static HTML for Tor compatibility
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]>
2026-03-16 11:39:26 -04:00
thePR0M3TH3ANandClaude Opus 4.6 bc64d1c3b5 feat(cli): persistent servers, start-all/stop-all, autostart on boot (v0.3.0)
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]>
2026-03-16 11:00:44 -04:00
thePR0M3TH3ANandClaude Opus 4.6 b5ab447207 fix(cli): set PYTHONNOUSERSITE=1 for onionshare-cli subprocess, robust cleanup (v0.2.19)
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]>
2026-03-16 10:14:39 -04:00
3021 changed files with 18197 additions and 481005 deletions

No files matched your search

-8
View File
@@ -1,8 +0,0 @@
{
"name": "VoxVera",
"build": {
"dockerfile": "../Dockerfile",
"context": ".."
},
"workspaceFolder": "/workspace/VoxVera"
}
-3
View File
@@ -1,3 +0,0 @@
[flake8]
max-line-length = 120
ignore = E501,E741,E401,E402
-149
View File
@@ -1,149 +0,0 @@
name: Build Standalone Binaries
on:
push:
tags:
- 'v*'
workflow_dispatch:
jobs:
build:
name: Build for ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, windows-latest, macos-latest]
include:
- os: ubuntu-22.04
artifact_name: voxvera-linux-x86_64
- os: windows-latest
artifact_name: voxvera-windows.exe
- os: macos-latest
artifact_name: voxvera-macos-x86_64
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install --upgrade setuptools pkg_resources || pip install --upgrade setuptools
pip install -r requirements.txt
pip install .
pip install pyinstaller pyinstaller-hooks-contrib
- name: Download Tor Binaries
shell: bash
run: |
chmod +x scripts/download_tor.sh
./scripts/download_tor.sh
- name: Build with PyInstaller
shell: bash
run: |
if [ "$RUNNER_OS" == "Windows" ]; then SEP=";"; else SEP=":"; fi
pyinstaller --onefile \
--collect-all pkg_resources \
--collect-all setuptools \
--hidden-import pkg_resources \
--hidden-import setuptools \
--hidden-import jaraco.text \
--hidden-import jaraco.functools \
--hidden-import jaraco.context \
--hidden-import more_itertools \
--hidden-import packaging \
--hidden-import platformdirs \
--collect-all onionshare_cli \
--collect-all flask_socketio \
--collect-all engineio \
--collect-all socketio \
--collect-all eventlet \
--collect-all gevent \
--add-data "voxvera/locales${SEP}voxvera/locales" \
--add-data "voxvera/src${SEP}voxvera/src" \
--add-data "voxvera/templates${SEP}voxvera/templates" \
--add-data "voxvera/resources${SEP}voxvera/resources" \
--add-data "requirements.txt${SEP}." \
--name "${{ matrix.artifact_name }}" \
voxvera/cli.py
- name: Build .deb (Linux)
if: matrix.os == 'ubuntu-22.04'
run: |
mkdir -p voxvera/resources/bin
cp dist/${{ matrix.artifact_name }} voxvera/resources/bin/voxvera-linux-x86_64
chmod +x packaging/build_deb.sh
./packaging/build_deb.sh dist/${{ matrix.artifact_name }}
- name: Build AppImage (Linux)
if: matrix.os == 'ubuntu-22.04'
run: |
mkdir -p voxvera/resources/bin
cp dist/${{ matrix.artifact_name }} voxvera/resources/bin/voxvera-linux-x86_64
chmod +x packaging/build_appimage.sh
./packaging/build_appimage.sh dist/${{ matrix.artifact_name }}
- name: Build Flatpak (Linux)
if: matrix.os == 'ubuntu-22.04'
run: |
mkdir -p voxvera/resources/bin
cp dist/${{ matrix.artifact_name }} voxvera/resources/bin/voxvera-linux-x86_64
sudo apt-get update
sudo apt-get install -y flatpak flatpak-builder
chmod +x packaging/build_flatpak.sh
./packaging/build_flatpak.sh dist/${{ matrix.artifact_name }} || echo "Flatpak build failed"
- name: Build .dmg (macOS)
if: matrix.os == 'macos-latest'
run: |
mkdir -p voxvera/resources/bin
cp dist/${{ matrix.artifact_name }} voxvera/resources/bin/voxvera-macos-x86_64
chmod +x packaging/build_dmg.sh
./packaging/build_dmg.sh dist/${{ matrix.artifact_name }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: binaries-${{ matrix.os }}
path: |
dist/${{ matrix.artifact_name }}
voxvera/resources/bin/*.deb
voxvera/resources/bin/*.dmg
voxvera/resources/bin/*.AppImage
voxvera/resources/bin/*.flatpak
publish:
name: Create GitHub Release
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Flatten artifacts for release
run: |
mkdir -p release_assets
find artifacts -type f -exec cp {} release_assets/ \;
ls -R release_assets/
- name: Release
uses: softprops/action-gh-release@v2
with:
files: |
release_assets/*
fail_on_unmatched_files: false
overwrite: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+12 -10
View File
@@ -2,24 +2,26 @@ name: CI
on:
push:
branches: [ main ]
branches: [main]
pull_request:
jobs:
lint-test:
static-client:
runs-on: ubuntu-latest
timeout-minutes: 15
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
python-version: "3.12"
- name: Install Python test dependencies
run: |
python -m pip install --upgrade pip
pip install flake8
pip install -e ".[test]"
- name: Lint
run: flake8 voxvera tests --exclude=voxvera/vendor --ignore=E501,W503,W293,E402,E306,E704,E261,F841,E302,F401,E401,F541
- name: Test
run: pytest tests/ -v
- name: Check frontend JavaScript
run: node --check site/nostr/nostr-client.js
- name: Run tests
run: pytest -q
-31
View File
@@ -1,31 +0,0 @@
name: E2E
on:
push:
pull_request:
jobs:
e2e:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y tor
python -m pip install --upgrade pip
pip install -e ".[e2e]"
- name: Run end-to-end tests
run: ci/test-e2e.sh
continue-on-error: true
- name: Upload logs
if: always()
uses: actions/upload-artifact@v4
with:
name: ci-logs
path: ci-logs/
+23 -51
View File
@@ -1,59 +1,31 @@
# Temporary files
*.tmp
tmp*/
# Python
__pycache__/
*.py[cod]
.pytest_cache/
*.egg-info/
.venv/
venv/
.venv
!voxvera/
!voxvera/resources/**
!voxvera/src/**
# OS and editor files
# Node/browser tooling
node_modules/
# Playwright e2e output
test-results/
playwright-report/
playwright/.cache/
# Build and local output
build/
dist/
ci-logs/
# OS/editor noise
.DS_Store
Thumbs.db
*~
*.swp
__pycache__/
*.pyc
# Build and distribution artifacts
dist/
build/
*.egg-info/
# Electron app artifacts
gui/electron/node_modules/
gui/electron/dist/
gui/electron/build/
gui/electron/out/
# Generated host directories
host/*
!host/voxvera/
# CI logs
ci-logs/
# Onionshare logs and session files
# Local browser/debug artifacts
*.log
*.onionshare-session
gui/electron/package-lock.json
voxvera/src/config.json
voxvera/src/index.html
voxvera/src/nostr.html
voxvera/src/qrcode-content.png
voxvera/src/qrcode-tear-offs.png
# PyInstaller
*.spec
dist_bin/
voxvera/resources/bin/*
!voxvera/resources/bin/.gitkeep
site/download/*.zip
!site/download/voxvera-source.zip
site/download/*.exe
site/download/*.deb
site/download/*.dmg
site/download/*.AppImage
site/download/*.flatpak
site/download/voxvera-linux
site/download/voxvera-linux-x86_64
*.pdf
.vercel
+39 -31
View File
@@ -1,42 +1,50 @@
# AI Agent Instructions for VoxVera
# AI Agent Instructions For VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
`main` is the Nostr static-client branch. The old Tor/OnionShare CLI application is preserved on `legacy-tor`.
## Core Mandates
## Current Architecture
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
- Active frontend: `site/` (`index.html`, `nostr-client.js`, `nostr-client.css`, `locales.js`)
- Bulletin board: `site/board.html` + `site/board.js` (standalone page listing recent flyers from the relays; escapes untrusted relay content and rejects non-http(s) link URLs)
- Static deployment root: `site`
- Browser dependencies: vendored under `site/vendor/`
- Legacy path: `site/nostr/index.html` is a redirect stub forwarding old `/nostr/` poster URLs and QR codes to the root
- Python helper package: `voxvera/nostr/`
- Design plan: `docs/nostr-static-client-spec.md`
## Localization Protocol
## Guardrails
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
- Do not reintroduce the legacy Tor CLI, OnionShare runtime, installer, Electron manager, bundled Tor binaries, generated old flyer site, or packaging workflows on `main`.
- Keep the Nostr client static and host-agnostic.
- Do not load frontend dependencies from CDNs.
- Treat Nostr event content as untrusted. Escape rendered content and reject unsafe schema input.
- Preserve print behavior: app controls must not print or shift the flyer sheet in print output.
- Preserve the old flyer visual language unless the user explicitly asks for a redesign.
- Paper size (US Letter / A4) is a local print/view preference (`localStorage`), defaulted from the browser locale region. Never write it into the Nostr event — a flyer must reprint on either size without changing the source event.
## Universal Mirroring
## Localization
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
- Use `site/locales.js` for flyer content defaults.
- Use `NOSTR_UI` in `site/nostr-client.js` for editor/viewer controls and Nostr-specific labels.
- Add translations for every supported language when adding user-facing strings.
- Check right-to-left languages when touching layout.
## Verification Checklist
## Verification
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
Run:
---
```bash
node --check site/nostr-client.js
pytest -q
```
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
For visual or print changes, also run a local static server and inspect the site root (`/`) in a browser.
Cross-browser end-to-end tests live in `e2e/` (Playwright; Chromium, Firefox, WebKit, plus mobile emulations). Run them after changes that touch rendering, print, key generation, URL/redirect handling, or the loading state:
```bash
npm install && npx playwright install
npm run test:e2e
```
WebKit/Safari on Linux needs `sudo npx playwright install-deps` once. See `e2e/README.md`. Test tooling is a dev dependency only — it must not pull runtime frontend dependencies from CDNs or otherwise weaken the static, host-agnostic client.
+30 -35
View File
@@ -1,45 +1,40 @@
# Contributing to VoxVera
# Contributing To VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
VoxVera `main` is a static Nostr client. Keep contributions focused on the browser editor/viewer, Nostr event validation, printable flyer rendering, and static deployment.
## Adding a New Language
## Frontend
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
- Edit the active app under `site/nostr/`.
- Keep dependencies vendored under `site/nostr/vendor/`; do not rely on CDNs.
- Preserve viewer mode as a flyer-first experience.
- Keep editor, load, print, language, and other controls hidden from print output.
- Verify print layout after changes that affect the flyer surface.
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
## Localization
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
The static client currently uses `site/nostr/locales.js` plus the `NOSTR_UI` table in `site/nostr/nostr-client.js`.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
When adding user-facing text:
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
- Add translations for every supported language.
- Check right-to-left languages in the browser where layout may be affected.
- Keep side-tab strings short enough for tear-off strips.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
## Nostr Schema
---
Python validation helpers live in `voxvera/nostr/`. Keep the schema conservative:
Together, we can ensure that truth remains accessible to everyone, everywhere.
- Reject raw HTML in user-supplied flyer fields.
- Reject unsupported URL schemes.
- Keep attachments out of V1 events unless the spec is deliberately expanded.
## Verification
Run:
```bash
node --check site/nostr/nostr-client.js
pytest -q
```
For UI work, also run a local static server and inspect `/nostr/` in a browser.
-22
View File
@@ -1,22 +0,0 @@
FROM python:3.11-slim
# Install system dependencies (only runtime)
RUN apt-get update && apt-get install -y \
tor onionshare-cli \
&& rm -rf /var/lib/apt/lists/*
# Copy VoxVera source
COPY . /opt/voxvera
WORKDIR /opt/voxvera
# Install VoxVera and its Python dependencies
RUN pip install .
# Prepare flyers volume
RUN mkdir /flyers && ln -s /flyers /opt/voxvera/host
VOLUME /flyers
# VoxVera expects to run in /opt/voxvera for local assets
WORKDIR /opt/voxvera
CMD ["voxvera", "quickstart"]
-5
View File
@@ -1,5 +0,0 @@
include voxvera/templates/**
include voxvera/src/**
include voxvera/resources/**
include voxvera/locales/**
include voxvera/resources/bin/**
+59 -50
View File
@@ -1,78 +1,87 @@
# VoxVera
**Anonymous Information Distribution Engine**
VoxVera is a static, Nostr-powered flyer client.
Generate printable flyers with QR codes linking to Tor (.onion) hidden services. VoxVera is built for activists, journalists, and anyone who needs to spread a message securely and anonymously.
The active app lives at the site root ([`site/`](site/)). It lets anyone author flyer content, publish it as a public Nostr event, and re-render or reprint the flyer later from a Nostr address or event ID — no application server. The frontend is intentionally self-contained: Nostr relays store the content, and any static host can serve the client.
---
The previous Tor/OnionShare CLI version is preserved on the `legacy-tor` branch.
## Installation
## Features
VoxVera is designed for maximum portability and censorship resistance.
- **Author and publish.** Fill in the flyer fields and publish them as a Nostr `30078` parameterized replaceable event. Republishing with the same flyer name replaces the previous version.
- **Anonymous by default, your identity if you want it.** The editor signs flyers under one of three identities: an **anonymous** per-device key (default, no setup), a **NIP-07 browser extension** (your secret never touches the page), or an **imported `nsec`**. An imported key signs in-memory for the session; tick "Remember on this device" to keep it, encrypted with a PIN (PBKDF2 → AES-GCM) — the plaintext secret is never stored. A short PIN is a convenience lock, not protection against a targeted attacker (see the [spec](docs/nostr-static-client-spec.md#publishing-identity)); the extension path is stronger.
- **Publish confirmation.** After signing and publishing, a modal shows the new flyer's URL to copy, so authors know they're done and where to find it (localized, like everything else).
- **Edit, re-publish, and delete your flyers.** Because flyers are replaceable events, the author can edit one in place (same key + Flyer Name keeps the same URL), re-publish it as a keep-alive so relays don't age it out, or delete it. Delete publishes a replaceable **tombstone** (so VoxVera hides it even where relays ignore deletions) **and** a NIP-09 deletion request — best-effort, author-only.
- **Open from a link or ID.** Load a flyer from an `naddr`, `nevent1`, `note1`, raw 64-char event ID, or `nostr:` URL. The lookup field tolerates copy/paste whitespace and newlines, so an event ID copied off a printed tear-off (where it wraps across two lines) still resolves.
- **Short, scannable poster URLs.** Each poster URL is a standard NIP-19 `naddr` carrying a single relay hint, placed in the URL `#fragment` (no `?addr=` query). Shorter URLs make the tear-off QR code easier to scan. Older relay-list `naddr`s and `?addr=` URLs still resolve.
- **Tear-off tabs.** The printable flyer has ten tear-off tabs. Each tab is a single hyperlinked call to action (the URL is the link, not printed as text) and prints the full event ID so anyone can re-find the flyer by typing it.
- **Loading state on shared links.** Opening a poster/event link shows a localized "Loading content…" placeholder (and a "Could not load this flyer." state on failure) instead of the default flyer; the default sample content appears only on the bare site URL.
- **14 languages with RTL support.** Flyer content and UI are localized; right-to-left scripts render correctly. Letter-spacing is applied per script so cursive (Arabic/Persian) and combining (Devanagari) scripts are not broken — see [the spec](docs/nostr-static-client-spec.md#letter-spacing-by-script).
- **US Letter and A4.** Print size defaults to the right paper for the visitor's country (from the browser locale's region — `en-US` → Letter, `en-GB` → A4, no geolocation), with a manual override. Paper size is a local print preference and is never written into the event. See the [spec](docs/nostr-static-client-spec.md#print-paper-size).
- **Fits-the-page editing.** Fields that would overflow the printable sheet are rejected as you type, with an inline error under the affected field. See the [field length cheat sheet](docs/flyer-field-limits.md) for how much text fits each field per language and paper size.
- **QR codes.** The tear-off QR points at the poster URL (re-open and reprint); the main flyer QR points at the creator's content URL.
- **Bulletin board (members-only, trust-filtered).** A small screen-only link below the flyer preview (outside the printed sheet, never printed) opens a spreadsheet-style page of the most recent flyers found on the relays — title, link, posting npub, language, date, and event ID (with a copy button) — sortable by any column. Viewing the board requires connecting a Nostr identity — via a NIP-07 browser extension, by pasting a private key (`nsec`, decoded in-page and never stored), or by creating a new key (revealed so you can save it). The board then shows only flyers from authors in your **web of trust** (your NIP-02 follow graph), with a "Show all" opt-out. A brand-new key with no follows is seeded from a curated trust anchor so the board is never an unmoderated firehose. On your own flyers the board offers inline **Edit / Re-broadcast / Delete**; on others' it offers a local **Block** (a per-device hide list). Connecting is not required to author or print flyers, which stay fully anonymous. See the [roadmap](docs/roadmap.md) for the phased trust model.
- **Self-contained.** No build step and no CDNs — Nostr and QR libraries are vendored under `site/vendor/`.
### 1. Standalone Binaries (Recommended)
Download the zero-dependency executable for your OS:
- 🐧 [**Linux**](https://github.com/PR0M3TH3AN/VoxVera/releases/latest/download/voxvera-linux)
- 🪟 [**Windows**](https://github.com/PR0M3TH3AN/VoxVera/releases/latest/download/voxvera-windows.exe)
- 🍏 [**macOS**](https://github.com/PR0M3TH3AN/VoxVera/releases/latest/download/voxvera-macos)
## What Is In `main`
### 2. Universal Mirroring (The "Viral" Method)
If you found a physical VoxVera flyer, scan it and click **"Download"**. You will receive a `voxvera-portable.zip` containing the full tool, all dependencies, and all 14 languages—ready to run offline.
- `site/index.html`, `site/nostr-client.js`, `site/nostr-client.css`, `site/locales.js`: static editor/viewer client
- `site/board.html`, `site/board.js`: bulletin-board page listing recent flyers from the relays
- `site/vendor/`: vendored browser dependencies for Nostr and QR generation
- `site/nostr/index.html`: redirect stub so legacy `/nostr/` poster URLs and QR codes still resolve
- `site/CNAME`: custom-domain target
- `voxvera/nostr/`: small Python schema/validation helpers
- `docs/nostr-static-client-spec.md`: design notes and development plan
- `docs/flyer-field-limits.md`: per-language field length cheat sheet
- `docs/roadmap.md`: known issues and future development directions
## Local Development
Run the static site from the repo root:
### 3. One-Line Installer (Linux/macOS)
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
python3 -m http.server 8768 --directory site
```
### 4. Developer / Python Install
```bash
pip install .
voxvera vendorize # Optional: pull dependencies locally for offline use
Then open:
```text
http://127.0.0.1:8768/
```
---
No build command is required for the frontend.
## Key Features
## Vercel
* **Universal Mirroring**: Every flyer acts as a mirror for the tool itself. The "Download" button provides a portable version of VoxVera, creating a decentralized distribution network.
* **Standalone Binaries**: Zero-install executables for high-security environments.
* **Global Multi-Script Support**: Native support for 14 languages including **Arabic (RTL)**, **Hebrew (RTL)**, **Hindi (Devanagari)**, **Japanese/Chinese (CJK)**, and **Russian (Cyrillic)**.
* **Tor-Safe Architecture**: 100% static HTML flyers. Works perfectly in Tor "Safest" mode with **JavaScript completely disabled**.
* **Integrated Server Manager**: `voxvera manage` provides an interactive UI to handle multiple flyers, monitor Tor bootstrapping, and manage persistent .onion URLs.
* **Secure Migration**: Bulk export and import of flyers and their unique Tor identity keys via `~/voxvera-exports/`.
Point Vercel at this repository on `main`.
---
- Framework preset: Other
- Root directory: repo root
- Build command: leave empty
- Output directory: `site`
## Documentation
The client is served from the domain root (`site/index.html`). `site/nostr/index.html` is a redirect stub that forwards the legacy `/nostr/` path to the root while preserving the query/fragment, so older poster URLs and printed QR codes still resolve.
VoxVera is available in multiple languages. Select your preferred language for the detailed usage guide:
## Verification
| Language | Documentation | Contributing | Agent Guide |
| :--- | :--- | :--- | :--- |
| 🇺🇸 **English** | [usage.md](docs/en/usage.md) | [CONTRIBUTING.md](docs/en/CONTRIBUTING.md) | [AGENTS.md](docs/en/AGENTS.md) |
| 🇪🇸 **Español** | [usage.md](docs/es/usage.md) | [CONTRIBUTING.md](docs/es/CONTRIBUTING.md) | [AGENTS.md](docs/es/AGENTS.md) |
| 🇩🇪 **Deutsch** | [usage.md](docs/de/usage.md) | [CONTRIBUTING.md](docs/de/CONTRIBUTING.md) | [AGENTS.md](docs/de/AGENTS.md) |
| 🇫🇷 **Français** | [usage.md](docs/fr/usage.md) | [CONTRIBUTING.md](docs/fr/CONTRIBUTING.md) | [AGENTS.md](docs/fr/AGENTS.md) |
| 🇷🇺 **Русский** | [usage.md](docs/ru/usage.md) | [CONTRIBUTING.md](docs/ru/CONTRIBUTING.md) | [AGENTS.md](docs/ru/AGENTS.md) |
| 🇮🇱 **עברית** | [usage.md](docs/he/usage.md) | [CONTRIBUTING.md](docs/he/CONTRIBUTING.md) | [AGENTS.md](docs/he/AGENTS.md) |
| 🇸🇦 **العربية** | [usage.md](docs/ar/usage.md) | [CONTRIBUTING.md](docs/ar/CONTRIBUTING.md) | [AGENTS.md](docs/ar/AGENTS.md) |
| 🇯🇵 **日本語** | [usage.md](docs/ja/usage.md) | [CONTRIBUTING.md](docs/ja/CONTRIBUTING.md) | [AGENTS.md](docs/ja/AGENTS.md) |
| 🇮🇳 **हिन्दी** | [usage.md](docs/hi/usage.md) | [CONTRIBUTING.md](docs/hi/CONTRIBUTING.md) | [AGENTS.md](docs/hi/AGENTS.md) |
| 🇰🇪 **Kiswahili** | [usage.md](docs/sw/usage.md) | [CONTRIBUTING.md](docs/sw/CONTRIBUTING.md) | [AGENTS.md](docs/sw/AGENTS.md) |
```bash
node --check site/nostr-client.js # client syntax
pytest -q # Nostr source schema
```
---
### Cross-browser end-to-end tests
## Roadmap (v0.2.0)
[Playwright](https://playwright.dev) smoke tests run the client on Chromium, Firefox, and WebKit (Safari's engine), plus Android/iOS mobile emulations — covering rendering, the `@media print` path, WebCrypto key generation, the `/nostr/` redirect, and the loading state.
We are actively working on:
- **PGP Signing**: Cryptographic proof of tool integrity.
- **Nostr Integration**: Automated social amplification.
- **Template Gallery**: Visual styles for protests, alerts, and art.
- **Self-Healing Network**: Automated decentralized updates.
```bash
npm install
npx playwright install # download the browser engines
npm run test:e2e
```
See [ROADMAP-v0.2.0.md](docs/roadmap-v0.2.0.md) for details.
See [`e2e/README.md`](e2e/README.md) for per-engine coverage and the one-time Linux step for WebKit (`sudo npx playwright install-deps`).
---
The Python tests only cover the Nostr source schema. The frontend is static; the Playwright suite covers engine behavior, but real Safari/iOS print and clipboard behavior is still worth a manual pass before a release.
## License
-97
View File
@@ -1,97 +0,0 @@
# VoxVera Release Process
**⚠️ ATTENTION AI AGENTS (CRITICAL WORKFLOW):**
Do **NOT** automatically package, tag, or push a new release after completing a set of changes. Releases should **ONLY** be triggered when the user explicitly requests one (e.g., "Package a release now" or "Let's release this").
Instead of releasing immediately, you must append a summary of your completed work to the `UPCOMING_RELEASE.md` file. This allows development to span multiple context sessions and ensures that new releases contain a substantial amount of value. When a release is finally requested, use the contents of `UPCOMING_RELEASE.md` to format the GitHub Release notes, and then clear the document for the next cycle.
This document outlines the mandatory steps to perform before every release to ensure code quality, cross-language integrity, and professional distribution assets.
## 1. Pre-Flight Checks (Quality Assurance)
Before any release, the codebase must pass all internal quality checks **without taking any shortcuts**. All tests must be rigorous, use real data where appropriate, and passing them should be a true mark of quality.
### Run Tests
Ensure all core CLI, E2E, and Integrity tests pass:
```bash
pytest tests/
```
*Note: The `test_integrity.py` check is critical as it verifies that all 14+ language locales have synchronized keys and all binary bundles are 100% self-contained.*
### Run Linting
Ensure the code adheres to style guidelines (no trailing whitespace, proper spacing, etc.):
```bash
# Using flake8 (excluding vendored dependencies)
flake8 voxvera/ --exclude=voxvera/vendor/
```
## 2. Update & Generate Localized Assets
Before releasing, you must ensure that **all documentation accurately reflects the new features and functions** introduced in the release.
All documentation and site templates must be synchronized with the translation system. This ensures that any changes to documentation are reflected across all 14+ supported languages.
### Synchronize Documentation
If you have modified any documentation templates in `docs/templates/` (which you should, to cover new features), you **must** use the translation system to regenerate the localized documentation before release:
```bash
# Regenerate docs/ folders for all languages from templates and locales
python3 -m voxvera.cli build-docs
```
### Synchronize Site Assets
The main `site/` directory (including QRs, HTML, and portable Zips) must also be refreshed to include the latest binary names and locale strings:
```bash
# Refresh site/ directory
python3 -m voxvera.cli build-site
```
## 3. Build Distribution Binaries
Standardized binaries and AppImages must be generated for the current platform.
### Standard Binary
Generates an architecture-specific binary (e.g., `voxvera-linux-x86_64`) in `voxvera/resources/bin/`.
```bash
./scripts/build_binaries.sh
```
### AppImage (Linux)
Wraps the standard binary into a self-contained AppImage.
```bash
./packaging/build_appimage.sh
```
### Flatpak (Linux)
Generates a standalone `.flatpak` bundle. Requires `flatpak-builder`.
```bash
./packaging/build_flatpak.sh
```
### Debian Package (Linux)
Generates a `.deb` package for Debian/Ubuntu systems.
```bash
./packaging/build_deb.sh
```
### DMG (macOS)
Generates a `.dmg` installer for macOS (must be run on macOS).
```bash
./packaging/build_dmg.sh
```
## 4. Release Execution
1. **Version Bump:** Update `__version__` in `voxvera/__init__.py` and `version` in `pyproject.toml`.
2. **Commit & Tag:**
```bash
git add .
git commit -m "chore: release vX.Y.Z"
git tag -a vX.Y.Z -m "VoxVera vX.Y.Z"
git push origin main --tags
```
## 5. Automated Releases (GitHub Actions)
The repository is configured with a **Build Standalone Binaries** workflow that automatically runs when a new tag (`v*`) is pushed. This workflow:
- Builds native executables for **Linux**, **Windows (.exe)**, and **macOS**.
- Automatically attaches these binaries to the corresponding GitHub Release.
This ensures that Windows users receive a professional `voxvera-windows.exe` rather than having to rely on `.bat` or `.sh` scripts.
-1
View File
@@ -1 +0,0 @@
-203
View File
@@ -1,203 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Robustness: ensure we are in the project root
cd "$(dirname "$0")/.."
LOG_DIR="$(pwd)/ci-logs"
mkdir -p "$LOG_DIR"
# Use a subshell for tee to avoid issues with some shell environments
exec > >(tee "$LOG_DIR/run.log") 2>&1
echo "Starting E2E verification at $(date)"
# Install VoxVera
if [ -n "${VOXVERA_BIN:-}" ] && [ -f "$VOXVERA_BIN" ]; then
voxvera_cmd="$VOXVERA_BIN"
echo "Using provided VoxVera binary: $voxvera_cmd" >&2
else
echo "Installing VoxVera in editable mode..."
python3 -m pip install --break-system-packages -e ".[e2e]"
voxvera_cmd="$(command -v voxvera || echo "$HOME/.local/bin/voxvera")"
fi
echo "VoxVera command: $voxvera_cmd"
# Generate demo flyer
echo "Initializing demo flyer..."
"$voxvera_cmd" --lang en init --template voxvera <<EOI
DemoUser
voxvera
EOI
echo "Building demo flyer..."
"$voxvera_cmd" --lang en build
# Verify build output exists in host/
folder_name="voxvera"
host_dir="voxvera/host/$folder_name"
if [ ! -d "$host_dir" ]; then
echo "CRITICAL: Host directory $host_dir not found!" >&2
ls -R voxvera/host/ || true
exit 1
fi
ls -R "$host_dir" >>"$LOG_DIR/tree.txt"
# Verify essential files
for f in index.html config.json; do
if [ ! -f "$host_dir/$f" ]; then
echo "CRITICAL: Missing $f in $host_dir" >&2
exit 1
fi
done
echo "Build output verified in $host_dir"
# Run pytest unit tests
echo "Running pytest unit tests..."
python3 -m pytest tests/ -v 2>&1 | tee "$LOG_DIR/pytest.log"
# Optional network tests
if [ "${VOXVERA_E2E_OFFLINE:-}" != "1" ]; then
echo "Starting network-dependent tests..."
# GitHub Actions Ubuntu runners have Tor pre-installed and running as a service.
# We stop it to ensure we can run our own instance with known configuration on default ports.
echo "Stopping system Tor service if running..."
sudo systemctl stop tor || true
# Kill any lingering tor processes
sudo pkill -x tor || true
echo "Starting a fresh Tor instance on default ports (9050/9051)..."
mkdir -p "$LOG_DIR/tor_data"
tor --SocksPort 9050 --ControlPort 9051 --CookieAuthentication 0 --DataDirectory "$LOG_DIR/tor_data" >"$LOG_DIR/tor.log" 2>&1 &
TOR_PID=$!
# Wait for Tor to bootstrap
echo "Waiting for Tor to bootstrap (up to 120s)..."
BOOTSTRAPPED=0
for i in {1..120}; do
if grep -q "Bootstrapped 100%" "$LOG_DIR/tor.log"; then
echo "Tor bootstrapped successfully."
BOOTSTRAPPED=1
break
fi
[ $((i % 10)) -eq 0 ] && echo "... still bootstrapping Tor ($i s) ..."
sleep 1
done
if [ $BOOTSTRAPPED -eq 0 ]; then
echo "CRITICAL: Tor failed to bootstrap after 120s" >&2
tail -n 20 "$LOG_DIR/tor.log"
kill ${TOR_PID:-} || true
exit 1
fi
# Start OnionShare
echo "Starting OnionShare..."
# Explicitly set environment variables that OnionShare-cli respects
export TOR_SOCKS_PORT=9050
export TOR_CONTROL_PORT=9051
onionshare-cli --website --public \
--persistent "$host_dir/.onionshare-session" \
-v \
"$host_dir" >"$LOG_DIR/onionshare.log" 2>&1 &
OS_PID=$!
# Check if OnionShare process is still alive after a few seconds
sleep 5
if ! kill -0 $OS_PID 2>/dev/null; then
echo "CRITICAL: OnionShare-cli failed to start" >&2
cat "$LOG_DIR/onionshare.log"
kill ${TOR_PID:-} || true
exit 1
fi
# Wait for URL with timeout and feedback
echo "Waiting for OnionShare to generate URL (up to 120s)..."
URL=""
for i in {1..120}; do
# Use -a to process as text even if there are binary chars (ANSI codes)
if grep -aEo 'http[s]?://[a-z2-7]{56}\.onion' "$LOG_DIR/onionshare.log" | head -n1 >"$LOG_DIR/url.txt"; then
URL=$(cat "$LOG_DIR/url.txt" | tr -d '\r\n ')
if [ -n "$URL" ]; then
echo "Successfully generated Onion URL: $URL"
break
fi
fi
[ $((i % 10)) -eq 0 ] && echo "... still waiting ($i s) ..."
sleep 1
done
if [ -z "$URL" ]; then
echo "CRITICAL: Onion URL not found after 120s" >&2
echo "--- Last 20 lines of OnionShare log ---"
tail -n 20 "$LOG_DIR/onionshare.log"
kill $OS_PID || true
kill ${TOR_PID:-} || true
exit 1
fi
# Robustness: Manually update the config.json with the URL so verification passes
# and the site is actually using the live onion address.
echo "Updating $host_dir/config.json with live URL: $URL"
python3 <<EOF
import json
import os
path = "$host_dir/config.json"
with open(path, 'r') as f:
data = json.load(f)
data['url'] = "$URL"
with open(path + '.new', 'w') as f:
json.dump(data, f, indent=2)
os.replace(path + '.new', path)
EOF
echo "Verifying content of $host_dir/config.json:"
cat "$host_dir/config.json"
# Verify URL in config
if ! grep -Fq "$URL" "$host_dir/config.json"; then
echo "CRITICAL: URL $URL not found in $host_dir/config.json" >&2
cat "$host_dir/config.json"
kill $OS_PID || true
kill ${TOR_PID:-} || true
exit 1
fi
# Re-build to update QR codes with live onion URL
echo "Re-building site with live URL..."
"$voxvera_cmd" --lang en build --config "$host_dir/config.json"
# Fetch page via Tor (retry a few times as circuits can be flaky)
echo "Verifying reachability via Tor (on port 9050)..."
FETCHED=0
for attempt in {1..5}; do
echo "Attempt $attempt..."
if curl --socks5-hostname 127.0.0.1:9050 -fsSL "$URL" | grep -q '<title>'; then
echo "Success: Site is reachable via Tor."
FETCHED=1
break
fi
sleep 10
done
if [ $FETCHED -eq 0 ]; then
echo "WARNING: Site could not be reached via Tor after 5 attempts, but OnionShare is running."
# In CI, we might skip hard failure if Tor network is exceptionally slow/blocked
fi
# Clean up
echo "Cleaning up..."
kill $OS_PID || true
kill ${TOR_PID:-} || true
wait $OS_PID 2>/dev/null || true
else
echo "Skipping network-dependent tests (VOXVERA_E2E_OFFLINE=1)" >&2
fi
echo "E2E verification complete at $(date)"
exit 0
+18
View File
@@ -0,0 +1,18 @@
# Data Center Construction Protest Demo Flyer
Use these values in the VoxVera editor for a civic protest or public-comment demo.
| Field | Value |
| --- | --- |
| Relays | `wss://relay.damus.io`, `wss://nos.lol`, `wss://relay.primal.net` |
| Flyer Name | `data-center-protest` |
| Language | `en` |
| Page title | `Data Center Protest Flyer` |
| Title | `PUBLIC HEARING` |
| Subtitle | `NO BLANK CHECK FOR BIG TECH` |
| Headline | `STOP THE DATA CENTER LAND GRAB` |
| Content | `A proposed data center project could strain local power, water, roads, and public budgets while leaving residents with noise, traffic, and long-term infrastructure costs. Attend the public hearing, ask for full environmental review, and demand binding limits before any approval.` |
| URL message | `Scan for meeting time, talking points, and public-comment instructions.` |
| Content URL | `https://example.com/data-center-hearing` |
| Footer message | `BRING NEIGHBORS - SPEAK DURING PUBLIC COMMENT` |
+18
View File
@@ -0,0 +1,18 @@
# Presbyterian Gospel Tract Demo Flyer
Use these values in the VoxVera editor for a Reformed Presbyterian gospel tract demo.
| Field | Value |
| --- | --- |
| Relays | `wss://relay.damus.io`, `wss://nos.lol`, `wss://relay.primal.net` |
| Flyer Name | `presbyterian-gospel-tract` |
| Language | `en` |
| Page title | `Presbyterian Gospel Tract` |
| Title | `CHRIST SAVES SINNERS` |
| Subtitle | `REPENT AND BELIEVE THE GOSPEL` |
| Headline | `THE GOOD NEWS OF JESUS CHRIST` |
| Content | `God is holy, and all men have sinned against Him. Yet God sent His eternal Son, Jesus Christ, to take on true humanity, obey perfectly, die for sinners, and rise again. Salvation is by grace alone, through faith alone, in Christ alone. Turn from sin and trust the Lord Jesus Christ.` |
| URL message | `Scan to read Scripture, a short catechism, and a local church invitation.` |
| Content URL | `https://example.com/gospel` |
| Footer message | `FOR BY GRACE ARE YE SAVED THROUGH FAITH - EPHESIANS 2:8` |
+18
View File
@@ -0,0 +1,18 @@
# Yard Sale Demo Flyer
Use these values in the VoxVera editor as a practical neighborhood-sale demo.
| Field | Value |
| --- | --- |
| Relays | `wss://relay.damus.io`, `wss://nos.lol`, `wss://relay.primal.net` |
| Flyer Name | `yard-sale-saturday` |
| Language | `en` |
| Page title | `Saturday Yard Sale` |
| Title | `YARD SALE` |
| Subtitle | `SATURDAY 8 AM TO 2 PM` |
| Headline | `TOOLS, BOOKS, TOYS, AND HOME GOODS` |
| Content | `Stop by this Saturday for a family yard sale with useful household items, kids clothes, books, tools, small furniture, toys, and kitchen goods. Prices are marked to move. Cash is preferred, and early visitors are welcome after 8 AM.` |
| URL message | `Scan for address, photos, and any weather updates.` |
| Content URL | `https://example.com/yard-sale` |
| Footer message | `SATURDAY ONLY - PLEASE PARK ALONG THE STREET` |
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-130
View File
@@ -1,130 +0,0 @@
# الاستخدام التفصيلي
يغطي هذا الدليل سير عمل واجهة سطر الأوامر (CLI) الشائعة. راجع `docs/docker.md` للحصول على تعليمات Docker و `docs/templates.md` لقوالب المنشورات المتاحة.
## المتطلبات الأساسية
تم تصميم VoxVera ليكون سهل النقل للغاية ويتطلب الحد الأدنى من تبعيات النظام.
### 1. الملفات الثنائية المستقلة (موصى به)
يمكنك تنزيل ملفات ثنائية مستقلة بدون تبعيات لنظام التشغيل الخاص بك:
- **Linux:** `voxvera-linux`
- **Windows:** `voxvera-windows.exe`
- **macOS:** `voxvera-macos`
تتضمن هذه الملفات الثنائية كل ما يلزم لتشغيل VoxVera (باستثناء `onionshare-cli`).
### 2. المثبت بنقرة واحدة
بدلاً من ذلك، قم بالتثبيت عبر البرمجية النصية المؤتمتة الخاصة بنا:
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### 3. تثبيت Python اليدوي
إذا كنت تفضل التشغيل من المصدر:
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # Debian/Ubuntu
```
## خطوة بخطوة
1. **التهيئة:** قم بتشغيل `voxvera init` واتبع المطالبات. سيُطلب منك اختيار لغتك أولاً.
2. **البناء:** قم بإنشاء أصول المنشور. ينشئ كل بناء تلقائياً ملف `voxvera-portable.zip` في مجلد المنشور، مما يسمح للآخرين بتنزيل الأداة الكاملة مباشرة من منشورك.
```bash
voxvera build
```
3. **الخدمة:** انشر المنشور عبر Tor:
```bash
voxvera serve
```
يكتشف هذا تلقائياً نسخة Tor الخاصة بك، ويبدأ OnionShare، ويكتب عنوان .onion الناتج في روابط المنشور القابلة للنزع.
## دعم اللغة
VoxVera مترجم بالكامل. يمكنك تغيير تفضيل اللغة الخاص بك بشكل دائم باستخدام المبدل التفاعلي أو اختصار مباشر:
- **المبدل التفاعلي:** `voxvera lang`
- **اختصار مباشر:** `voxvera --lang ar` (يضبط التفضيل على العربية)
### اللغات المدعومة:
- **الإنجليزية:** `en`
- **الإسبانية:** `es` (اسم مستعار: `--idioma`)
- **الألمانية:** `de` (اسم مستعار: `--sprache`)
- **العربية:** `ar`
يمكنك أيضاً فرض لغة معينة لأمر واحد دون تغيير تفضيلك الدائم:
- **الإنجليزية:** `voxvera --lang en check`
- **العربية:** `voxvera --lang ar check`
تكتشف المنشورات الناتجة تلقائياً لغة متصفح الزائر وتبدل نص واجهة المستخدم وفقاً لذلك.
## إدارة الخوادم
إدارة منشورات متعددة وهويات Tor الخاصة بها من قائمة تفاعلية واحدة:
```bash
voxvera manage
```
الميزات:
- **--- إنشاء موقع/منشور جديد ---**: ابدأ تسلسل الإعداد الكامل.
- **--- تشغيل جميع المواقع ---**: تشغيل أو إيقاف جميع المنشورات في أسطولك دفعة واحدة.
- **الحالة في الوقت الفعلي**: عرض روابط .onion النشطة ومؤشرات تقدم تمهيد Tor.
- **التحكم الفردي**: تصدير إلى Zip مواقع معينة إلى ZIP أو حذفها.
## مراجة شاملة (التوزيع الفيروسي)
لضمان بقاء VoxVera متاحاً حتى لو تم فرض رقابة على المستودعات المركزية، يعمل كل منشور كمرآة للأداة.
عندما تستضيف منشوراً، يوفر زر **"تحميل الأداة والكود"** في الصفحة المقصودة ملف `voxvera-portable.zip` يحتوي على:
- كود المصدر الكامل وجميع اللغات المدعومة.
- جميع تبعيات Python (مضمنة مسبقاً).
- ملفات Tor الثنائية لجميع الأنظمة.
يتيح ذلك لأي شخص يقوم بمسح منشورك أن يصبح موزعاً جديداً لأداة VoxVera.
## التصدير والنسخ الاحتياطي
قم بنسخ هويات Tor الفريدة الخاصة بك احتياطياً (حتى لا يتغير رابط .onion الخاص بك أبداً) أو انقل منشوراتك إلى جهاز آخر.
- **تصدير موقع واحد**: `voxvera export <folder_name>`
- **تصدير جميع المواقع**: `voxvera export-all`
**مكان التخزين:** يتم حفظ جميع الصادرات كملفات ZIP في مجلد يسمى `voxvera-exports` في دليل الصفحة الرئيسية للمستخدم (`~/voxvera-exports/`) على جميع الأنظمة.
## الاستيراد والاستعادة
استعد إعدادك بالكامل على جهاز جديد بنقل ملفات ZIP الخاصة بك إلى `~/voxvera-exports/` وتشغيل:
```bash
voxvera import-multiple
```
## النقل والتشغيل بدون إنترنت
إذا كنت بحاجة إلى تشغيل VoxVera على جهاز لا يتوفر فيه اتصال بالإنترنت، يمكنك "تضمين" التبعيات أولاً:
```bash
voxvera vendorize
```
يقوم هذا بتنزيل جميع مكتبات Python المطلوبة في `voxvera/vendor/`. ستعطي الأداة بعد ذلك الأولوية لهذه الملفات المحلية، مما يسمح لها بالعمل بدون `pip install`.
## استيراد جماعي (JSON)
لإنشاء منشورات بشكل جماعي من ملفات تكوين JSON متعددة، ضعها في مجلد `imports/` وشغل:
```bash
voxvera batch-import
```
## كيف تعمل الروابط
يحتوي كل منشور على رابطين منفصلين:
- **رابط قابل للنزع** (يتم إنشاؤه تلقائياً): عنوان .onion حيث يتم استضافة المنشور.
- **رابط المحتوى** (يتم تكوينه بواسطة المستخدم): URL خارجي يشير إلى موقع ويب أو فيديو أو تنزيل.
لا تحتاج إلى إدخال عنوان .onion يدوياً؛ يتولى VoxVera ذلك تلقائياً خلال مرحلة `serve`.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-136
View File
@@ -1,136 +0,0 @@
# Detaillierte Verwendung
Diese Anleitung deckt gängige CLI-Workflows ab. Informationen zu Docker finden Sie unter `docs/docker.md` und verfügbare Flyer-Vorlagen unter `docs/templates.md`.
## Voraussetzungen
VoxVera ist auf hohe Portabilität ausgelegt und erfordert minimale Systemabhängigkeiten.
### 1. Eigenständige Binärdateien (Empfohlen)
Sie können eigenständige Binärdateien ohne Abhängigkeiten für Ihr Betriebssystem herunterladen:
- **Linux:** `voxvera-linux`
- **Windows:** `voxvera-windows.exe`
- **macOS:** `voxvera-macos`
Diese Binärdateien enthalten alles, was zum Ausführen von VoxVera erforderlich ist (außer `onionshare-cli`).
### 2. Ein-Zeilen-Installer
Alternativ können Sie die Installation über unser automatisiertes Skript vornehmen:
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### 3. Manuelle Python-Installation
Wenn Sie lieber aus dem Quellcode ausführen möchten:
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # Debian/Ubuntu
```
## Schritt für Schritt
1. **Initialisieren:** Führen Sie `voxvera init` aus und folgen Sie den Anweisungen. Sie werden zuerst aufgefordert, Ihre Sprache auszuwählen.
2. **Bauen:** Erstellen Sie die Flyer-Assets. Jeder Build erstellt automatisch eine `voxvera-portable.zip` im Flyer-Ordner, sodass andere das komplette Tool direkt von Ihrem Flyer herunterladen können.
```bash
voxvera build
```
3. **Bereitstellen:** Veröffentlichen Sie den Flyer über Tor:
```bash
voxvera serve
```
Dies erkennt automatisch Ihre Tor-Instanz, startet OnionShare und schreibt die generierte .onion-Adresse in die Abreiß-Links des Flyers.
## Sprachunterstützung
VoxVera ist vollständig lokalisiert. Sie können Ihre Sprachpräferenz dauerhaft über den interaktiven Selektor oder eine direkte Verknüpfung ändern:
- **Interaktiver Selektor:** `voxvera lang`
- **Direkte Verknüpfung:** `voxvera --lang de` (setzt die Präferenz auf Deutsch)
### Unterstützte Sprachen:
- **Englisch:** `en`
- **Spanisch:** `es` (Alias: `--idioma`)
- **Deutsch:** `de` (Alias: `--sprache`)
- **Russisch:** `ru`
- **Hebräisch:** `he`
- **Arabisch:** `ar`
- **Französisch:** `fr`
- **Japanisch:** `ja`
- **Hindi:** `hi`
- **Suaheli:** `sw`
Sie können auch eine bestimmte Sprache für einen einzelnen Befehl erzwingen, ohne Ihre dauerhafte Präferenz zu ändern:
- **Englisch:** `voxvera --lang en check`
- **Deutsch:** `voxvera --sprache de check`
Die generierten Flyer erkennen automatisch die Browsersprache des Besuchers und schalten den UI-Text entsprechend um.
## Server-Verwaltung
Verwalten Sie mehrere Flyer und deren Tor-Identitäten über ein einziges interaktives Menü:
```bash
voxvera manage
```
Funktionen:
- **--- Neue Website/Flyer erstellen ---**: Starten Sie die vollständige Setup-Sequenz.
- **--- Alle Websites starten ---**: Starten oder stoppen Sie alle Flyer in Ihrer Flotte auf einmal.
- **Echtzeit-Status**: Zeigen Sie aktive .onion-URLs und Tor-Bootstrapping-Fortschrittsanzeigen an.
- **Individuelle Steuerung**: Als Zip exportieren Sie bestimmte Seiten in eine ZIP-Datei oder löschen Sie sie.
## Universelle Spiegelung (Virale Verteilung)
Um sicherzustellen, dass VoxVera auch dann zugänglich bleibt, wenn zentrale Repositories zensiert werden, fungiert jeder Flyer als Spiegel für das Tool.
Wenn Sie einen Flyer hosten, bietet die Schaltfläche **"Tool & Quellcode herunterladen"** auf der Landingpage eine `voxvera-portable.zip` an, die Folgendes enthält:
- Den vollständigen Quellcode und alle unterstützten Sprachen.
- Alle Python-Abhängigkeiten (vorinstalliert).
- Plattformübergreifende Tor-Binärdateien.
Dies ermöglicht es jedem, der Ihren Flyer scannt, ein neuer Distributor des VoxVera-Tools zu werden.
## Export & Sicherung
Sichern Sie Ihre eindeutigen Tor-Identitäten (damit sich Ihre .onion-URL nie ändert) oder verschieben Sie Ihre Flyer auf einen anderen Computer.
- **Einzelne Seite exportieren:** `voxvera export <folder_name>`
- **Alle Seiten exportieren:** `voxvera export-all`
**Speicherort:** Alle Exporte werden als ZIP-Dateien in einem Ordner namens `voxvera-exports` im Home-Verzeichnis des Benutzers (`~/voxvera-exports/`) auf allen Plattformen gespeichert.
## Import & Wiederherstellung
Stellen Sie Ihr gesamtes Setup auf einem neuen Computer wieder her, indem Sie Ihre ZIP-Dateien nach `~/voxvera-exports/` verschieben und Folgendes ausführen:
```bash
voxvera import-multiple
```
## Portabilität & Offline-Nutzung
Wenn Sie VoxVera auf einem Computer ohne Internetzugang ausführen müssen, können Sie die Abhängigkeiten zuerst lokal bereitstellen:
```bash
voxvera vendorize
```
Dies lädt alle erforderlichen Python-Bibliotheken in `voxvera/vendor/` herunter. Das Tool priorisiert dann diese lokalen Dateien, sodass es ohne `pip install` ausgeführt werden kann.
## Batch-Import (JSON)
Um Flyer in großen Mengen aus mehreren JSON-Konfigurationsdateien zu generieren, legen Sie diese im Verzeichnis `imports/` ab und führen Sie Folgendes aus:
```bash
voxvera batch-import
```
## Wie URLs funktionieren
Jeder Flyer hat zwei separate URLs:
- **Abreiß-Link** (automatisch generiert): Die .onion-Adresse, unter der der Flyer gehostet wird.
- **Inhalts-Link** (vom Benutzer konfiguriert): Eine externe URL, die auf eine Website, ein Video oder einen Download verweist.
Sie müssen die .onion-Adresse nicht manuell eingeben; VoxVera erledigt dies automatisch während der `serve`-Phase.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-138
View File
@@ -1,138 +0,0 @@
# Detailed Usage
This guide covers common CLI workflows. See `docs/docker.md` for Docker instructions and `docs/templates.md` for available flyer templates.
## Prerequisites
VoxVera is designed to be highly portable. You can run it directly from the source code on any platform with Python installed.
### 1. Automated Install (Recommended)
The easiest way to install VoxVera is using our cross-platform installer script:
**Linux / macOS:**
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
**Windows (PowerShell):**
```powershell
irm https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.ps1 | iex
```
### 2. Manual Source Install
If you have downloaded the source code ZIP:
1. **Extract** the ZIP file.
2. **Open a terminal** in the extracted folder.
3. **Run the setup script**:
- **Linux/macOS:** `./setup.sh`
- **Windows:** `.\voxvera-install.sh` (or run `python -m pip install .`)
## Uninstallation
If you wish to remove VoxVera from your system, you can use the provided uninstall scripts from the source directory. This will safely remove the CLI tool and any downloaded dependencies.
- **Linux / macOS:** Run `./uninstall.sh`
- **Windows (PowerShell):** Run `.\uninstall.ps1`
*Note: Uninstallation will not delete your generated flyers or your `.onion` keys stored in the `~/voxvera-exports` or local `host/` folders.*
## Step-by-Step
1. **Initialize:** Run `voxvera init` and follow the prompts. You will be asked to select your language first.
2. **Build:** Generate the flyer assets. Every build automatically creates a `voxvera-portable.zip` in the flyer's folder, allowing others to download the full tool directly from your flyer.
```bash
voxvera build
```
3. **Serve:** Publish the flyer over Tor:
```bash
voxvera serve
```
This automatically detects your Tor instance, starts OnionShare, and writes the generated .onion address into the flyer's tear-off links.
## Language Support
VoxVera is fully localized. You can change your language preference permanently using either the interactive selector or a direct shortcut:
- **Interactive Selector:** `voxvera lang`
- **Direct Shortcut:** `voxvera --lang de` (sets preference to German)
### Supported Languages:
- **English:** `en`
- **Spanish:** `es` (alias: `--idioma`)
- **German:** `de` (alias: `--sprache`)
You can also force a specific language for a single command without changing your permanent preference:
- **English:** `voxvera --lang en check`
- **German:** `voxvera --sprache de check`
- **Spanish:** `voxvera --idioma es check`
The generated flyers automatically detect the visitor's browser language and switch the UI text accordingly.
## Server Management
Manage multiple flyers and their Tor identities from a single interactive menu:
```bash
voxvera manage
```
Features:
- **--- Create New Site/Flyer ---**: Start the full setup sequence.
- **--- Start All Sites ---**: Launch or shut down every flyer in your fleet at once.
- **Real-time Status**: View active `.onion` URLs and Tor bootstrapping progress indicators.
- **Individual Control**: Export to Zip specific sites to ZIP or delete them.
## Universal Mirroring (Viral Distribution)
To ensure VoxVera remains accessible even if central repositories are censored, every flyer acts as a mirror for the tool.
When you host a flyer, the **"Download Source Code"** button on the landing page provides a `voxvera-source.zip` containing:
- The full source code and all supported languages.
- Installation and setup scripts for all platforms.
- Complete documentation and templates.
This allows anyone who scans your flyer to become a new distributor of the VoxVera tool.
## Export & Backup
Back up your unique Tor identities (so your `.onion` URL never changes) or move your flyers to another machine.
- **Export a single site**: `voxvera export <folder_name>`
- **Export all sites**: `voxvera export-all`
**Storage location:** All exports are saved to `~/voxvera-exports/` on all platforms.
## Import & Recovery
Restore your entire setup on a new machine by moving your ZIP files to `~/voxvera-exports/` and running:
```bash
voxvera import-multiple
```
## Portability & Offline Use
If you need to run VoxVera on a machine without internet access, you can "vendorize" the dependencies first:
```bash
voxvera vendorize
```
This downloads all required Python libraries into `voxvera/vendor/`. The tool will then prioritize these local files, allowing it to run without `pip install`.
## Batch Import (JSON)
To bulk-generate flyers from multiple JSON configuration files, place them in the `imports/` directory and run:
```bash
voxvera batch-import
```
## How URLs Work
Each flyer has two separate URLs:
- **Tear-off link** (auto-generated): The .onion address where the flyer is hosted.
- **Content link** (user-configured): An external URL pointing to a website, video, or download.
You do not need to manually enter the .onion address; VoxVera handles this automatically during the `serve` phase.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-136
View File
@@ -1,136 +0,0 @@
# Uso detallado
Esta guía cubre los flujos de trabajo de CLI comunes. Consulte `docs/docker.md` para obtener instrucciones de Docker y `docs/templates.md` para conocer las plantillas de volantes disponibles.
## Prerrequisitos
VoxVera está diseñado para ser altamente portátil y requiere un mínimo de dependencias del sistema.
### 1. Binarios independientes (Recomendado)
Puede descargar binarios independientes sin dependencias para su sistema operativo:
- **Linux:** `voxvera-linux`
- **Windows:** `voxvera-windows.exe`
- **macOS:** `voxvera-macos`
Estos binarios incluyen todo lo necesario para ejecutar VoxVera (excepto `onionshare-cli`).
### 2. Instalador de una sola línea
Alternativamente, instale a través de nuestro script automatizado:
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### 3. Instalación manual de Python
Si prefiere ejecutar desde la fuente:
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # Debian/Ubuntu
```
## Paso a paso
1. **Inicializar:** Ejecute `voxvera init` y siga las instrucciones. Se le pedirá que seleccione su idioma primero.
2. **Construir:** Genere los activos del volante. Cada construcción crea automáticamente un `voxvera-portable.zip` en la carpeta del volante, lo que permite que otros descarguen la herramienta completa directamente desde su volante.
```bash
voxvera build
```
3. **Servir:** Publique el volante sobre Tor:
```bash
voxvera serve
```
Esto detecta automáticamente su instancia de Tor, inicia OnionShare y escribe la dirección .onion generada en los enlaces desprendibles del volante.
## Soporte de idiomas
VoxVera está totalmente localizado. Puede cambiar su preferencia de idioma de forma permanente utilizando el selector interactivo o un acceso directo:
- **Selector interactivo:** `voxvera lang`
- **Acceso directo:** `voxvera --lang es` (establece la preferencia en español)
### Idiomas soportados:
- **Inglés:** `en`
- **Español:** `es` (alias: `--idioma`)
- **Alemán:** `de` (alias: `--sprache`)
- **Ruso:** `ru`
- **Hebreo:** `he`
- **Árabe:** `ar`
- **Francés:** `fr`
- **Japonés:** `ja`
- **Hindi:** `hi`
- **Swahili:** `sw`
También puede forzar un idioma específico para un solo comando sin cambiar su preferencia permanente:
- **Inglés:** `voxvera --lang en check`
- **Español:** `voxvera --idioma es check`
Los volantes generados detectan automáticamente el idioma del navegador del visitante y cambian el texto de la interfaz en consecuencia.
## Gestión de servidores
Gestione múltiples volantes y sus identidades de Tor desde un único menú interactivo:
```bash
voxvera manage
```
Características:
- **--- Crear Nuevo Sitio/Volante ---**: Inicie la secuencia de configuración completa.
- **--- Iniciar Todos los Sitios ---**: Inicie o apague todos los volantes de su flota a la vez.
- **Estado en tiempo real**: Vea las URL .onion activas e indicadores de progreso de arranque de Tor.
- **Control individual**: Exportar a Zip sitios específicos a ZIP o elimínelos.
## Espejo universal (Distribución viral)
Para garantizar que VoxVera siga siendo accesible incluso si los repositorios centrales son censurados, cada volante actúa como un espejo para la herramienta.
Cuando hospeda un volante, el botón **"Descargar Herramienta y Código"** en la página de inicio proporciona un `voxvera-portable.zip` que contiene:
- El código fuente completo y todos los idiomas soportados.
- Todas las dependencias de Python (pre-vendeurizadas).
- Binarios de Tor multiplataforma.
Esto permite que cualquier persona que escanee su volante se convierta en un nuevo distribuidor de la herramienta VoxVera.
## Exportación y respaldo
Haga una copia de seguridad de sus identidades únicas de Tor (para que su URL .onion nunca cambie) o mueva sus volantes a otra máquina.
- **Exportar un solo sitio**: `voxvera export <nombre_carpeta>`
- **Exportar todos los servicios**: `voxvera export-all`
**Lugar de almacenamiento:** Todas las exportaciones se guardan como archivos ZIP en una carpeta llamada `voxvera-exports` en el directorio de inicio del usuario (`~/voxvera-exports/`) en todas las plataformas.
## Importación y recuperación
Restaure toda su configuración en una nueva máquina moviendo sus archivos ZIP a `~/voxvera-exports/` y ejecutando:
```bash
voxvera import-multiple
```
## Portabilidad y uso sin conexión
Si necesita ejecutar VoxVera en una máquina sin acceso a Internet, primero puede "vendeurizar" las dependencias:
```bash
voxvera vendorize
```
Esto descarga todas las librerías de Python requeridas en `voxvera/vendor/`. La herramienta dará prioridad a estos archivos locales, lo que le permitirá ejecutarse sin `pip install`.
## Importación por lotes (JSON)
Para generar volantes de forma masiva a partir de múltiples archivos de configuración JSON, colóquelos en el directorio `imports/` y ejecute:
```bash
voxvera batch-import
```
## Cómo funcionan las URL
Cada volante tiene dos URL separadas:
- **Enlace desprendible** (generado automáticamente): La dirección .onion donde se hospeda el volante.
- **Enlace de contenido** (configurado por el usuario): Una URL externa que apunta a un sitio web, video o descarga.
No es necesario ingresar manualmente la dirección .onion; VoxVera lo maneja automáticamente durante la fase de `serve`.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-130
View File
@@ -1,130 +0,0 @@
# راهنمای استفاده تفصیلی
این راهنما جریان‌های کاری معمول رابط سطر فرمان (CLI) را پوشش می‌دهد. برای دستورالعمل‌های داکر به `docs/docker.md` و برای قالب‌های اعلامیه موجود به `docs/templates.md` مراجعه کنید.
## پیش‌نیازها
ووکس‌ورا (VoxVera) به گونه‌ای طراحی شده است که بسیار قابل حمل باشد و به حداقل وابستگی‌های سیستم نیاز داشته باشد.
### ۱. فایل‌های اجرایی مستقل (توصیه شده)
می‌توانید فایل‌های اجرایی (Binary) مستقل و بدون نیاز به وابستگی را برای سیستم‌عامل خود دانلود کنید:
- **لینوکس:** `voxvera-linux`
- **ویندوز:** `voxvera-windows.exe`
- **مک:** `voxvera-macos`
این فایل‌ها شامل تمام موارد لازم برای اجرای ووکس‌ورا هستند (به جز `onionshare-cli`).
### ۲. نصب‌کننده تک‌خطی
همچنین می‌توانید از طریق اسکریپت خودکار ما نصب را انجام دهید:
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### ۳. نصب دستی پایتون
اگر ترجیح می‌دهید از سورس کد استفاده کنید:
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # دبیان/اوبونتو
```
## گام به گام
۱. **راه‌اندازی:** دستور `voxvera init` را اجرا کرده و مراحل را دنبال کنید. در ابتدا از شما خواسته می‌شود زبان خود را انتخاب کنید.
۲. **ساخت:** دارایی‌های اعلامیه را ایجاد کنید. هر بار که عملیات ساخت انجام می‌شود، یک فایل `voxvera-portable.zip` به طور خودکار در پوشه اعلامیه ساخته می‌شود که به دیگران اجازه می‌دهد ابزار کامل را مستقیماً از اعلامیه شما دانلود کنند.
```bash
voxvera build
```
۳. **میزبانی:** اعلامیه را روی شبکه تور منتشر کنید:
```bash
voxvera serve
```
این دستور به طور خودکار تور شما را شناسایی کرده، OnionShare را راه‌اندازی می‌کند و آدرس .onion تولید شده را در پیوندهای جداشونده اعلامیه می‌نویسد.
## پشتیبانی از زبان‌ها
ووکس‌ورا کاملاً بومی‌سازی شده است. می‌توانید اولویت زبان خود را به طور دائم با استفاده از انتخاب‌گر تعاملی یا میان‌بر مستقیم تغییر دهید:
- **انتخاب‌گر تعاملی:** `voxvera lang`
- **میان‌بر مستقیم:** `voxvera --lang fa` (تنظیم اولویت روی فارسی)
### زبان‌های پشتیبانی شده:
- **انگلیسی:** `en`
- **اسپانیایی:** `es` (نام مستعار: `--idioma`)
- **آلمانی:** `de` (نام مستعار: `--sprache`)
- **فارسی:** `fa`
همچنین می‌توانید بدون تغییر اولویت دائمی، یک زبان خاص را برای یک دستور واحد اجبار کنید:
- **انگلیسی:** `voxvera --lang en check`
- **فارسی:** `voxvera --lang fa check`
اعلامیه‌های تولید شده به طور خودکار زبان مرورگر بازدیدکننده را تشخیص داده و متن رابط کاربری را بر اساس آن تغییر می‌دهند.
## مدیریت سرورها
چندین اعلامیه و هویت‌های تور آن‌ها را از یک منوی تعاملی واحد مدیریت کنید:
```bash
voxvera manage
```
ویژگی‌ها:
- **--- ایجاد سایت/اعلامیه جدید ---**: شروع توالی کامل تنظیمات.
- **--- اجرای همه سایت‌ها ---**: راه‌اندازی یا توقف همزمان تمام اعلامیه‌های شما.
- **وضعیت لحظه‌ای**: مشاهده آدرس‌های .onion فعال و نشانگرهای پیشرفت تور.
- **کنترل فردی**: صدور به صورت زیپ سایت‌های خاص به فرمت ZIP یا حذف آن‌ها.
## آینه‌سازی همگانی (توزیع ویروسی)
برای اطمینان از اینکه ووکس‌ورا حتی در صورت سانسور مخازن مرکزی در دسترس باقی می‌ماند، هر اعلامیه به عنوان یک آینه برای این ابزار عمل می‌کند.
وقتی اعلامیه‌ای را میزبانی می‌کنید، دکمه **"دانلود ابزار و کد منبع"** در صفحه فرود، یک فایل `voxvera-portable.zip` شامل موارد زیر ارائه می‌دهد:
- سورس کد کامل و تمامی زبان‌های پشتیبانی شده.
- تمامی وابستگی‌های پایتون (از پیش بسته‌بندی شده).
- فایل‌های اجرایی تور برای تمامی پلتفرم‌ها.
این کار به هر کسی که اعلامیه شما را اسکن می‌کند اجازه می‌دهد تا به توزیع‌کننده جدیدی برای ابزار ووکس‌ورا تبدیل شود.
## صدور و پشتیبان‌گیری
از هویت‌های تور منحصر به فرد خود پشتیبان بگیرید (تا آدرس .onion شما هرگز تغییر نکند) یا اعلامیه‌های خود را به سیستم دیگری منتقل کنید.
- **صدور یک سایت واحد:** `voxvera export <folder_name>`
- **صدور تمامی سایت‌ها:** `voxvera export-all`
**محل ذخیره‌سازی:** تمامی موارد صادر شده به صورت فایل ZIP در پوشه‌ای به نام `voxvera-exports` در پوشه خانگی کاربر (`~/voxvera-exports/`) در تمامی پلتفرم‌ها ذخیره می‌شوند.
## وارد کردن و بازیابی
با انتقال فایل‌های ZIP خود به پوشه `~/voxvera-exports/` و اجرای دستور زیر، کل تنظیمات خود را در یک سیستم جدید بازیابی کنید:
```bash
voxvera import-multiple
```
## قابلیت حمل و استفاده آفلاین
اگر نیاز دارید ووکس‌ورا را روی سیستمی بدون دسترسی به اینترنت اجرا کنید، می‌توانید ابتدا وابستگی‌ها را به صورت محلی ذخیره کنید:
```bash
voxvera vendorize
```
این دستور تمامی کتابخانه‌های پایتون مورد نیاز را در پوشه `voxvera/vendor/` دانلود می‌کند. ابزار سپس این فایل‌های محلی را در اولویت قرار می‌دهد و اجازه می‌دهد بدون نیاز به `pip install` اجرا شود.
## وارد کردن گروهی (JSON)
برای تولید انبوه اعلامیه‌ها از چندین فایل تنظیمات JSON، آن‌ها را در پوشه `imports/` قرار داده و اجرا کنید:
```bash
voxvera batch-import
```
## آدرس‌های URL چگونه کار می‌کنند
هر اعلامیه دارای دو آدرس URL جداگانه است:
- **پیوند جداشونده** (تولید خودکار): آدرس .onion که اعلامیه در آن میزبانی می‌شود.
- **پیوند محتوا** (تنظیم توسط کاربر): یک آدرس URL خارجی که به یک وب‌سایت، ویدیو یا فایل دانلود اشاره می‌کند.
نیازی نیست آدرس .onion را به صورت دستی وارد کنید؛ ووکس‌ورا در مرحله میزبانی (`serve`) این کار را به طور خودکار انجام می‌دهد.
+74
View File
@@ -0,0 +1,74 @@
# Flyer Field Length Cheat Sheet
How much text fits in each flyer field, by script.
VoxVera does **not** impose a fixed character count. The editor measures the
rendered flyer live and rejects a keystroke the moment a field would overflow
the printable sheet (you'll see an inline "too long" error under that field).
So the real limit is enforced for you as you type — the numbers below are
practical guidance for drafting copy, sizing translations, or prompting an LLM
to write flyer text that will fit on the first try.
Capacity varies by **script** (not by individual language) and by **paper
size**, for these reasons:
1. The flyer body font is monospace (`Courier New`), so within a script every
character takes the same width regardless of upper/lowercase.
2. Per-script letter-spacing policy (`ls-full` / `ls-cjk` / `ls-none`, see
[`nostr-static-client-spec.md`](nostr-static-client-spec.md#letter-spacing-by-script)).
3. Glyph width differs by script — CJK glyphs are full-width (≈2× a Latin
character), Devanagari fallback glyphs are narrower, etc.
4. **Paper size.** A4 (210×297mm) is slightly narrower and taller than US
Letter (8.5×11in), so single-line fields hold ~2 fewer characters on A4
while the body holds a little more. Both sizes are shown below.
## Single-line fields (hard caps)
**Title**, **Subtitle**, and **Headline** are single-line: they never wrap, so
these are the limits people actually run into. Counts are characters
(codepoints), shown as **Letter / A4**.
| Languages | Title & Headline | Subtitle |
|---|---|---|
| Latin & Cyrillic & Hebrew — en, es, de, fr, pt, sw, tr, ru, he | ~28 / ~26 | ~32 / ~30 |
| Arabic & Persian — ar, fa | ~28 / ~27 | ~38 / ~36 |
| Devanagari — hi | ~36 / ~35 | ~51 / ~48 |
| CJK — ja, zh | ~17 / ~16 | ~23 / ~21 |
## Multi-line fields (generous)
**Body** (content), **Link message** (`url_message`), and **Footer**
(`footer_message`) wrap across multiple lines, so they hold far more and are
bounded only by the remaining height of the sheet.
| Languages | Body (content) — Letter / A4 |
|---|---|
| Latin & Cyrillic & Hebrew | ~1,900 / ~2,000 (a few hundred words) |
| Arabic & Persian | ~1,850 / ~1,930 |
| Devanagari — hi | ~2,450 / ~2,545 |
| CJK — ja, zh | ~1,170 / ~1,220 |
`url_message` and `footer_message` share the lower portion of the sheet and can
hold roughly 1,200–4,800 characters depending on script, but for a readable
flyer keep the link message to a sentence and the footer to a short line.
The **URL** field is a link, not body copy — keep it short both because it's
shown verbatim on the flyer and because it becomes the main QR code (shorter
URLs scan more reliably).
## Notes and caveats
- **Approximate.** These come from rendering each script in a headless browser
at true print size for both Letter (8.5×11in) and A4 (210×297mm). The
Latin/Cyrillic numbers (`Courier New`) are the most reliable; numbers for
Hebrew, Arabic, Persian, Devanagari, and CJK depend on the system fallback
font, which can differ slightly between devices and from print output.
- **The app is authoritative.** If the editor accepts your text it fits; if it
rejects it, shorten it. Treat this sheet as a target, not a contract.
- **Redaction markup counts.** Wrapping text in `~~double tildes~~` renders it
struck-through; the four `~` characters count toward the field length even
though they don't appear on the flyer.
- **Re-measuring.** If the flyer layout, font, or letter-spacing policy
changes, these numbers should be re-derived by rendering each script at print
size and binary-searching each field for the largest run of characters that
does not overflow the field target or the sheet.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-130
View File
@@ -1,130 +0,0 @@
# Utilisation détaillée
Ce guide couvre les flux de travail CLI courants. Consultez `docs/docker.md` pour les instructions Docker et `docs/templates.md` pour les modèles de flyers disponibles.
## Prérequis
VoxVera est conçu pour être hautement portable et nécessite un minimum de dépendances système.
### 1. Binaires autonomes (Recommandé)
Vous pouvez télécharger des binaires autonomes sans dépendance pour votre système d'exploitation :
- **Linux :** `voxvera-linux`
- **Windows :** `voxvera-windows.exe`
- **macOS :** `voxvera-macos`
Ces binaires incluent tout le nécessaire pour exécuter VoxVera (sauf `onionshare-cli`).
### 2. Installateur en une ligne
Alternativement, installez via notre script automatisé :
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### 3. Installation Python manuelle
Si vous préférez exécuter à partir des sources :
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # Debian/Ubuntu
```
## Étape par étape
1. **Initialiser :** Exécutez `voxvera init` et suivez les instructions. Il vous sera demandé de choisir votre langue en premier.
2. **Construire :** Générez les fichiers du flyer. Chaque construction crée automatiquement un `voxvera-portable.zip` dans le dossier du flyer, permettant aux autres de télécharger l'outil complet directement depuis votre flyer.
```bash
voxvera build
```
3. **Servir :** Publiez le flyer sur Tor :
```bash
voxvera serve
```
Ceci détecte automatiquement votre instance Tor, démarre OnionShare et écrit l'adresse .onion générée dans les liens détachables du flyer.
## Support linguistique
VoxVera est entièrement localisé. Vous pouvez changer votre préférence linguistique de manière permanente en utilisant soit le sélecteur interactif, soit un raccourci direct :
- **Sélecteur interactif :** `voxvera lang`
- **Raccourci direct :** `voxvera --lang fr` (définit la préférence sur le français)
### Langues supportées :
- **Anglais :** `en`
- **Espagnol :** `es` (alias : `--idioma`)
- **Allemand :** `de` (alias : `--sprache`)
- **Français :** `fr`
Vous pouvez également forcer une langue spécifique pour une seule commande sans changer votre préférence permanente :
- **Anglais :** `voxvera --lang en check`
- **Français :** `voxvera --lang fr check`
Les flyers générés détectent automatiquement la langue du navigateur du visiteur et adaptent le texte de l'interface en conséquence.
## Gestion des serveurs
Gérez plusieurs flyers et leurs identités Tor à partir d'un seul menu interactif :
```bash
voxvera manage
```
Fonctionnalités :
- **--- Créer un nouveau site/flyer ---** : Démarre la séquence de configuration complète.
- **--- Démarrer tous les sites ---** : Lance ou arrête tous les flyers de votre flotte en une seule fois.
- **Statut en temps réel** : Visualisez les URL .onion actives et les indicateurs de progression de l'amorçage Tor.
- **Contrôle individuel** : Exporter en Zip des sites spécifiques vers ZIP ou supprimez-les.
## Mise en miroir universelle (Distribution virale)
Pour garantir que VoxVera reste accessible même si les dépôts centraux sont censurés, chaque flyer agit comme un miroir pour l'outil.
Lorsque vous hébergez un flyer, le bouton **"Télécharger l'outil et le code"** sur la page d'accueil fournit un `voxvera-portable.zip` contenant :
- Le code source complet et toutes les langues supportées.
- Toutes les dépendances Python (pré-vendues).
- Les binaires Tor multiplateformes.
Cela permet à quiconque scanne votre flyer de devenir un nouveau distributeur de l'outil VoxVera.
## Exportation & Sauvegarde
Sauvegardez vos identités Tor uniques (pour que votre URL .onion ne change jamais) ou déplacez vos flyers vers une autre machine.
- **Exporter un seul site** : `voxvera export <nom_du_dossier>`
- **Exporter tous les sites** : `voxvera export-all`
**Lieu de stockage :** Toutes les exportations sont sauvegardées dans `~/voxvera-exports/` sur toutes les plateformes.
## Importation & Récupération
Restaurez toute votre configuration sur une nouvelle machine en déplaçant vos fichiers ZIP vers `~/voxvera-exports/` et en exécutant :
```bash
voxvera import-multiple
```
## Portabilité & Utilisation hors ligne
Si vous devez exécuter VoxVera sur une machine sans accès à Internet, vous pouvez d'abord "vendeuriser" les dépendances :
```bash
voxvera vendorize
```
Ceci télécharge toutes les bibliothèques Python requises dans `voxvera/vendor/`. L'outil donnera alors la priorité à ces fichiers locaux, lui permettant de s'exécuter sans `pip install`.
## Importation par lot (JSON)
Pour générer en masse des flyers à partir de plusieurs fichiers de configuration JSON, placez-les dans le répertoire `imports/` et exécutez :
```bash
voxvera batch-import
```
## Comment fonctionnent les URL
Chaque flyer possède deux URL distinctes :
- **Lien détachable** (auto-généré) : L'adresse .onion où le flyer est hébergé.
- **Lien de contenu** (configuré par l'utilisateur) : Une URL externe pointant vers un site web, une vidéo ou un téléchargement.
Vous n'avez pas besoin de saisir manuellement l'adresse .onion ; VoxVera s'en occupe automatiquement pendant la phase `serve`.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-138
View File
@@ -1,138 +0,0 @@
# Detailed Usage
This guide covers common CLI workflows. See `docs/docker.md` for Docker instructions and `docs/templates.md` for available flyer templates.
## Prerequisites
VoxVera is designed to be highly portable. You can run it directly from the source code on any platform with Python installed.
### 1. Automated Install (Recommended)
The easiest way to install VoxVera is using our cross-platform installer script:
**Linux / macOS:**
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
**Windows (PowerShell):**
```powershell
irm https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.ps1 | iex
```
### 2. Manual Source Install
If you have downloaded the source code ZIP:
1. **Extract** the ZIP file.
2. **Open a terminal** in the extracted folder.
3. **Run the setup script**:
- **Linux/macOS:** `./setup.sh`
- **Windows:** `.\voxvera-install.sh` (or run `python -m pip install .`)
## Uninstallation
If you wish to remove VoxVera from your system, you can use the provided uninstall scripts from the source directory. This will safely remove the CLI tool and any downloaded dependencies.
- **Linux / macOS:** Run `./uninstall.sh`
- **Windows (PowerShell):** Run `.\uninstall.ps1`
*Note: Uninstallation will not delete your generated flyers or your `.onion` keys stored in the `~/voxvera-exports` or local `host/` folders.*
## Step-by-Step
1. **Initialize:** Run `voxvera init` and follow the prompts. You will be asked to select your language first.
2. **Build:** Generate the flyer assets. Every build automatically creates a `voxvera-portable.zip` in the flyer's folder, allowing others to download the full tool directly from your flyer.
```bash
voxvera build
```
3. **Serve:** Publish the flyer over Tor:
```bash
voxvera serve
```
This automatically detects your Tor instance, starts OnionShare, and writes the generated .onion address into the flyer's tear-off links.
## Language Support
VoxVera is fully localized. You can change your language preference permanently using either the interactive selector or a direct shortcut:
- **Interactive Selector:** `voxvera lang`
- **Direct Shortcut:** `voxvera --lang de` (sets preference to German)
### Supported Languages:
- **English:** `en`
- **Spanish:** `es` (alias: `--idioma`)
- **German:** `de` (alias: `--sprache`)
You can also force a specific language for a single command without changing your permanent preference:
- **English:** `voxvera --lang en check`
- **German:** `voxvera --sprache de check`
- **Spanish:** `voxvera --idioma es check`
The generated flyers automatically detect the visitor's browser language and switch the UI text accordingly.
## Server Management
Manage multiple flyers and their Tor identities from a single interactive menu:
```bash
voxvera manage
```
Features:
- **--- צור אתר/פלייר חדש ---**: Start the full setup sequence.
- **--- הפעל את כל האתרים ---**: Launch or shut down every flyer in your fleet at once.
- **Real-time Status**: View active `.onion` URLs and Tor bootstrapping progress indicators.
- **Individual Control**: ייצא ל-Zip specific sites to ZIP or delete them.
## Universal Mirroring (Viral Distribution)
To ensure VoxVera remains accessible even if central repositories are censored, every flyer acts as a mirror for the tool.
When you host a flyer, the **"הורד כלי וקוד מקור"** button on the landing page provides a `voxvera-source.zip` containing:
- The full source code and all supported languages.
- Installation and setup scripts for all platforms.
- Complete documentation and templates.
This allows anyone who scans your flyer to become a new distributor of the VoxVera tool.
## Export & Backup
Back up your unique Tor identities (so your `.onion` URL never changes) or move your flyers to another machine.
- **Export a single site**: `voxvera export <folder_name>`
- **Export all sites**: `voxvera export-all`
**Storage location:** All exports are saved to `~/voxvera-exports/` on all platforms.
## Import & Recovery
Restore your entire setup on a new machine by moving your ZIP files to `~/voxvera-exports/` and running:
```bash
voxvera import-multiple
```
## Portability & Offline Use
If you need to run VoxVera on a machine without internet access, you can "vendorize" the dependencies first:
```bash
voxvera vendorize
```
This downloads all required Python libraries into `voxvera/vendor/`. The tool will then prioritize these local files, allowing it to run without `pip install`.
## Batch Import (JSON)
To bulk-generate flyers from multiple JSON configuration files, place them in the `imports/` directory and run:
```bash
voxvera batch-import
```
## How URLs Work
Each flyer has two separate URLs:
- **Tear-off link** (auto-generated): The .onion address where the flyer is hosted.
- **Content link** (user-configured): An external URL pointing to a website, video, or download.
You do not need to manually enter the .onion address; VoxVera handles this automatically during the `serve` phase.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-130
View File
@@ -1,130 +0,0 @@
# विस्तृत उपयोग
यह गाइड सामान्य CLI वर्कफ्लो को कवर करती है। डॉकर निर्देशों के लिए `docs/docker.md` और उपलब्ध फ्लायर टेम्पलेट्स के लिए `docs/templates.md` देखें।
## पूर्वापेक्षाएँ (Prerequisites)
VoxVera को अत्यधिक पोर्टेबल बनाने के लिए डिज़ाइन किया गया है और इसके लिए न्यूनतम सिस्टम निर्भरता की आवश्यकता होती है।
### 1. स्टैंडअलोन बाइनरी (अनुशंसित)
आप अपने ऑपरेटिंग सिस्टम के लिए स्टैंडअलोन, शून्य-निर्भरता बाइनरी डाउनलोड कर सकते हैं:
- **Linux:** `voxvera-linux`
- **Windows:** `voxvera-windows.exe`
- **macOS:** `voxvera-macos`
इन बाइनरी में VoxVera चलाने के लिए आवश्यक सब कुछ शामिल है (`onionshare-cli` को छोड़कर)।
### 2. वन-लाइन इंस्टॉलर
वैकल्पिक रूप से, हमारी स्वचालित स्क्रिप्ट के माध्यम से इंस्टॉल करें:
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### 3. मैनुअल पायथन इंस्टॉलेशन
यदि आप सोर्स से चलाना पसंद करते हैं:
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # Debian/Ubuntu
```
## चरण-दर-चरण (Step-by-Step)
1. **आरंभ करें (Initialize):** `voxvera init` चलाएँ और संकेतों का पालन करें। आपसे सबसे पहले अपनी भाषा चुनने के लिए कहा जाएगा।
2. **बिल्ड (Build):** फ्लायर एसेट्स जेनरेट करें। प्रत्येक बिल्ड स्वचालित रूप से फ्लायर के फ़ोल्डर में एक `voxvera-portable.zip` बनाता है, जिससे अन्य लोग सीधे आपके फ्लायर से पूरा टूल डाउनलोड कर सकते हैं।
```bash
voxvera build
```
3. **सर्व (Serve):** फ्लायर को Tor पर प्रकाशित करें:
```bash
voxvera serve
```
यह स्वचालित रूप से आपके Tor इंस्टेंस का पता लगाता है, OnionShare शुरू करता है, और जेनरेट किए गए .onion एड्रेस को फ्लायर के टियर-ऑफ लिंक में लिख देता है।
## भाषा समर्थन (Language Support)
VoxVera पूरी तरह से स्थानीयकृत (localized) है। आप इंटरैक्टिव सेलेक्टर या सीधे शॉर्टकट का उपयोग करके अपनी भाषा प्राथमिकता को स्थायी रूप से बदल सकते हैं:
- **इंटरैक्टिव सेलेक्टर:** `voxvera lang`
- **सीधा शॉर्टकट:** `voxvera --lang hi` (प्राथमिकता को हिन्दी पर सेट करता है)
### समर्थित भाषाएं:
- **अंग्रेजी:** `en`
- **स्पेनिश:** `es` (उपनाम: `--idioma`)
- **जर्मन:** `de` (उपनाम: `--sprache`)
- **हिन्दी:** `hi`
आप अपनी स्थायी प्राथमिकता को बदले बिना किसी एक कमांड के लिए एक विशिष्ट भाषा को बाध्य (force) भी कर सकते हैं:
- **अंग्रेजी:** `voxvera --lang en check`
- **हिन्दी:** `voxvera --lang hi check`
जेनरेट किए गए फ्लायर्स स्वचालित रूप से विज़िटर की ब्राउज़र भाषा का पता लगाते हैं और उसके अनुसार UI टेक्स्ट बदलते हैं।
## सर्वर प्रबंधन (Server Management)
एक ही इंटरैक्टिव मेनू से कई फ्लायर्स और उनकी Tor पहचान प्रबंधित करें:
```bash
voxvera manage
```
विशेषताएं:
- **--- नई साइट/फ्लायर बनाएँ ---**: पूरा सेटअप अनुक्रम शुरू करें।
- **--- सभी साइटें शुरू करें ---**: अपने बेड़े के सभी फ्लायर्स को एक साथ शुरू या बंद करें।
- **वास्तविक समय स्थिति**: सक्रिय `.onion` URL और Tor बूटस्ट्रैपिंग प्रगति संकेतक देखें।
- **व्यक्तिगत नियंत्रण**: विशिष्ट साइटों को ZIP में ज़िप में निर्यात करें करें या उन्हें हटा दें।
## यूनिवर्सल मिररिंग (वायरल वितरण)
यह सुनिश्चित करने के लिए कि VoxVera केंद्रीय रिपॉजिटरी सेंसर होने पर भी सुलभ रहे, प्रत्येक फ्लायर टूल के लिए मिरर के रूप में कार्य करता है।
जब आप फ्लायर होस्ट करते हैं, तो लैंडिंग पेज पर **"टूल और कोड डाउनलोड करें"** बटन एक `voxvera-portable.zip` प्रदान करता है जिसमें शामिल हैं:
- पूरा सोर्स कोड और सभी समर्थित भाषाएं।
- सभी पायथन निर्भरताएँ (pre-vendored)।
- क्रॉस-प्लेटफ़ॉर्म Tor बाइनरी।
यह आपके फ्लायर को स्कैन करने वाले किसी भी व्यक्ति को VoxVera टूल का नया वितरक बनने की अनुमति देता है।
## निर्यात और बैकअप (Export & Backup)
अपनी अनूठी Tor पहचान का बैकअप लें (ताकि आपका `.onion` URL कभी न बदले) या अपने फ्लायर्स को दूसरी मशीन पर ले जाएं।
- **एकल साइट निर्यात करें**: `voxvera export <folder_name>`
- **सभी साइटें निर्यात करें**: `voxvera export-all`
**भंडारण स्थान:** सभी निर्यात सभी प्लेटफ़ॉर्म पर उपयोगकर्ता की होम डायरेक्टरी (`~/voxvera-exports/`) में ZIP फ़ाइलों के रूप में सहेजे जाते हैं।
## आयात और पुनर्प्राप्ति (Import & Recovery)
अपनी ZIP फ़ाइलों को `~/voxvera-exports/` में ले जाकर और चलाकर एक नई मशीन पर अपना पूरा सेटअप पुनर्स्थापित करें:
```bash
voxvera import-multiple
```
## पोर्टेबिलिटी और ऑफलाइन उपयोग
यदि आपको बिना इंटरनेट एक्सेस वाली मशीन पर VoxVera चलाने की आवश्यकता है, तो आप पहले निर्भरताओं को "वेंडराइज़" (vendorize) कर सकते हैं:
```bash
voxvera vendorize
```
यह `voxvera/vendor/` में सभी आवश्यक पायथन लाइब्रेरी डाउनलोड करता है। टूल फिर इन स्थानीय फ़ाइलों को प्राथमिकता देगा, जिससे यह `pip install` के बिना चल सकेगा।
## बैच आयात (JSON)
कई JSON कॉन्फ़िगरेशन फ़ाइलों से थोक में फ्लायर्स जेनरेट करने के लिए, उन्हें `imports/` डायरेक्टरी में रखें और चलाएँ:
```bash
voxvera batch-import
```
## URL कैसे काम करते हैं
प्रत्येक फ्लायर के दो अलग-अलग URL होते हैं:
- **टियर-ऑफ लिंक** (स्वचालित रूप से जेनरेट): वह .onion एड्रेस जहाँ फ्लायर होस्ट किया गया है।
- **सामग्री लिंक** (उपयोगकर्ता-कॉन्फ़िगर): वेबसाइट, वीडियो या डाउनलोड की ओर इशारा करने वाला एक बाहरी URL।
आपको मैन्युअल रूप से .onion एड्रेस दर्ज करने की आवश्यकता नहीं है; `serve` चरण के दौरान VoxVera इसे स्वचालित रूप से संभालता है।
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-130
View File
@@ -1,130 +0,0 @@
# 詳細な使い方
このガイドでは、一般的なCLIワークフローについて説明します。Dockerの手順については `docs/docker.md` を、利用可能なフライヤーテンプレートについては `docs/templates.md` を参照してください。
## 前提条件
VoxVeraは高いポータビリティを実現するように設計されており、システムへの依存関係は最小限です。
### 1. スタンドアロンバイナリ (推奨)
お使いのオペレーティングシステムに合わせて、依存関係のないスタンドアロンバイナリをダウンロードできます。
- **Linux:** `voxvera-linux`
- **Windows:** `voxvera-windows.exe`
- **macOS:** `voxvera-macos`
これらのバイナリには、VoxVeraの実行に必要なすべてのものが含まれています(`onionshare-cli` を除く)。
### 2. ワンラインインストーラー
または、自動スクリプトを使用してインストールします。
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### 3. 手動でのPythonインストール
ソースから実行したい場合:
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # Debian/Ubuntu
```
## ステップ・バイ・ステップ
1. **初期化:** `voxvera init` を実行し、プロンプトに従います。最初に言語を選択するよう求められます。
2. **ビルド:** フライヤーのアセットを生成します。ビルドを実行するたびに、フライヤーのフォルダ内に `voxvera-portable.zip` が自動的に作成されます。これにより、他の人があなたのフライヤーから直接ツール一式をダウンロードできるようになります。
```bash
voxvera build
```
3. **公開:** Torを介してフライヤーを公開します。
```bash
voxvera serve
```
これにより、実行中のTorインスタンスが自動的に検出され、OnionShareが起動し、生成された .onion アドレスがフライヤーの切り取りセクションのリンクに書き込まれます。
## 言語サポート
VoxVeraは完全にローカライズされています。インタラクティブセレクターまたは直接ショートカットを使用して、言語設定を永続的に変更できます。
- **インタラクティブセレクター:** `voxvera lang`
- **直接ショートカット:** `voxvera --lang ja` (日本語に設定)
### サポートされている言語:
- **英語:** `en`
- **スペイン語:** `es` (エイリアス: `--idioma`)
- **ドイツ語:** `de` (エイリアス: `--sprache`)
- **日本語:** `ja`
永続的な設定を変更せずに、単一のコマンドに対して特定の言語を強制することもできます。
- **英語:** `voxvera --lang en check`
- **日本語:** `voxvera --lang ja check`
生成されたフライヤーは、訪問者のブラウザ言語を自動的に検出し、UIテキストをそれに応じて切り替えます。
## サーバー管理
単一のインタラクティブメニューから、複数のフライヤーとそのTorアイデンティティを管理できます。
```bash
voxvera manage
```
機能:
- **--- 新規サイト/フライヤー作成 ---**: セットアップシーケンスを最初から開始します。
- **--- すべてのサイトを開始 ---**: 管理下のすべてのフライヤーを一括で起動またはシャットダウンします。
- **リアルタイムステータス**: アクティブな .onion URLやTorの起動プログレスインジケーターを表示します。
- **個別制御**: 特定のサイトをZIPに Zipとしてエクスポート したり、削除したりできます。
## ユニバーサルミラーリング(バイラル拡散)
中央のリポジトリが検閲された場合でもVoxVeraを利用し続けられるように、すべてのフライヤーがツールのミラーとして機能します。
フライヤーをホストすると、ランディングページの **「ツールとソースをダウンロード」** ボタンから以下のものを含む `voxvera-portable.zip` が提供されます。
- すべてのサポート言語を含む完全なソースコード。
- すべてのPython依存関係(事前ベンダー化済み)。
- クロスプラットフォームのTorバイナリ。
これにより、あなたのフライヤーをスキャンした誰もが、VoxVeraツールの新しい配布者になることができます。
## エクスポートとバックアップ
独自のTorアイデンティティ(.onion URLが変更されないようにするため)をバックアップしたり、フライヤーを別のマシンに移動したりできます。
- **単一サイトのエクスポート**: `voxvera export <フォルダ名>`
- **全サイトのエクスポート**: `voxvera export-all`
**保存場所:** すべてのエクスポートは、すべてのプラットフォームでユーザーのホームディレクトリにある `~/voxvera-exports/` フォルダに保存されます。
## インポートと復元
ZIPファイルを `~/voxvera-exports/` に移動して以下を実行することで、新しいマシンでセットアップ全体を復元できます。
```bash
voxvera import-multiple
```
## ポータビリティとオフライン利用
インターネット接続のないマシンでVoxVeraを実行する必要がある場合は、まず依存関係を「ベンダー化」できます。
```bash
voxvera vendorize
```
これにより、必要なすべてのPythonライブラリが `voxvera/vendor/` にダウンロードされます。ツールはこれらのローカルファイルを優先的に使用するため、 `pip install` なしで実行できるようになります。
## 一括インポート (JSON)
複数のJSON設定ファイルからフライヤーを一括生成するには、それらを `imports/` ディレクトリに配置して以下を実行します。
```bash
voxvera batch-import
```
## URLの仕組み
各フライヤーには2つの異なるURLがあります。
- **切り取り用リンク** (自動生成): フライヤーがホストされている .onion アドレス。
- **コンテンツリンク** (ユーザー設定): ウェブサイト、動画、またはダウンロードを指す外部URL。
.onion アドレスを手動で入力する必要はありません。VoxVeraが `serve` フェーズ中に自動的に処理します。
-99
View File
@@ -1,99 +0,0 @@
# Multi-Language Support Developer Plan
This document outlines the strategy for implementing a token-based multi-language system in VoxVera, covering the CLI, the generated landing page, and documentation.
## 1. Core Architecture: The Token System
All translatable strings will be centralized in JSON files located in `voxvera/locales/`. This allows for easy addition of new languages by simply dropping a new file.
- **Storage:** `voxvera/locales/{lang_code}.json` (e.g., `en.json`, `es.json`).
- **Structure:**
```json
{
"meta": {
"language_name": "English",
"flag": "🇺🇸"
},
"cli": {
"welcome": "Welcome to VoxVera Setup",
"select_lang": "Select your preferred language",
"folder_prompt": "Enter folder name for this flyer:"
},
"web": {
"title": "VoxVera - Anonymous Flyers",
"download_btn": "Download Flyer",
"onion_link_desc": "Scan to view on Tor",
"change_lang": "Change Language"
}
}
```
## 2. CLI Implementation (`voxvera/cli.py`)
The CLI will be updated to handle localization from the start of the user interaction.
### Workflow:
1. **Initial Detection:** On startup, the CLI checks the system locale (`LANG` env var or `locale` module).
2. **Language Selection:** The first prompt in `voxvera init` will be a language selector, defaulting to the detected system locale.
3. **Session Loading:** Once selected, the CLI loads the corresponding JSON. All subsequent `InquirerPy` prompts will use these tokens.
4. **Configuration:** The chosen language code is saved in the flyer's `config.json` as a preference for that specific project.
## 3. Web Implementation (`voxvera/src/index-master.html`)
The landing page will support dynamic language switching without requiring server-side logic (essential for Tor-hidden services).
### Detection Logic:
- **Avoid IP-based Detection:** Since VoxVera is hosted on Tor, IP lookups return the Tor Exit Node location, not the user's.
- **Browser-based Detection:** Use `navigator.language` to detect the user's browser preference.
- **Persistence:** Save the user's manual choice in `localStorage`.
### Frontend Components:
1. **Attributes:** Use `data-i18n="web.token_name"` on HTML elements.
2. **Language Switcher:** A dropdown menu or text-link list (e.g., "EN | ES | FR") placed next to the **Download** button.
3. **I18n Engine:** A lightweight JavaScript snippet injected during the build process that:
- Loads the bundled locale data.
- Detects the best language (Manual Selection > Browser Setting > English Fallback).
- Updates all `data-i18n` elements.
## 4. Build System Updates (`voxvera/build.py`)
The `build` process will be updated to bundle the necessary translations.
- **Multi-bundle:** By default, all available `web` tokens from all locale files will be injected into a single `<script>` tag in the final `index.html`. This ensures instant switching even when offline or on slow Tor connections.
- **Asset Optimization:** Minify the locale JSON data before injection to keep the HTML lightweight.
## 5. Portable & Viral Distribution Model
To ensure VoxVera is truly censorship-resistant, every generated flyer will serve as a mirror for the entire tool, including all supported languages and dependencies.
### Key Requirements:
- **Zero-Dependency Execution:** All Python libraries (from `requirements.txt`) will be bundled into a `voxvera/vendor/` directory. The CLI will be updated to prioritize this local path.
- **Pre-Bundled Tor:** The existing `voxvera/resources/tor/` binaries for Linux, Mac, and Windows will be included in every distribution.
- **Universal Language Bundle:** Every `voxvera-portable.zip` will include the full `voxvera/locales/` directory, ensuring that a user who downloads the tool from an English flyer can immediately switch it to Spanish, French, or any other supported language.
### The "Mirror" Workflow:
1. **Build Phase:** When `voxvera build` is executed, it assembles a `voxvera-portable.zip` containing:
- The full `voxvera/` source code.
- The `vendor/` library directory.
- All `locales/*.json` files.
- Cross-platform Tor binaries.
- A `voxvera-run.sh` / `voxvera-run.bat` entry point.
2. **Injection:** This ZIP is automatically placed in the `voxvera/host/<folder_name>/download/` directory of the generated flyer.
3. **User Access:** The landing page's "Download" button is updated to explicitly offer the "Full Portable Tool & Source," allowing the recipient to become a new node in the distribution network.
## 6. Documentation (`docs/`)
Documentation will follow a subdirectory structure for maximum compatibility with GitHub/Markdown renderers.
- **Structure:**
- `docs/en/usage.md`
- `docs/es/usage.md`
- **Maintenance:** A master English file will serve as the source of truth for all translations.
## 6. Implementation Phases
1. **Phase 1 (Audit):** Extract all hardcoded strings from `cli.py` and `index-master.html` into `en.json`.
2. **Phase 2 (CLI):** Implement the language selector and token loader in `cli.py`.
3. **Phase 3 (Web):** Update the HTML template with `data-i18n` attributes and the JS switcher.
4. **Phase 4 (Build):** Update `build.py` to inject the locale bundle.
5. **Phase 5 (Expansion):** Add a second language (e.g., Spanish) to verify the system.
+340
View File
@@ -0,0 +1,340 @@
# VoxVera Nostr Static Client Spec
Status: `main` is the Nostr static-client branch. The legacy Tor/OnionShare CLI version is preserved on `legacy-tor`.
## Goal
VoxVera should let anyone publish, fetch, and print flyer content without a centralized application server.
The static client is responsible for:
- rendering the flyer
- generating QR codes
- authoring a normalized Nostr flyer payload
- generating anonymous browser-side Nostr keys
- signing and publishing replaceable Nostr events
- fetching events by raw event ID, `note1`, `nevent1`, or `naddr`
- rendering fetched content safely
Nostr relays store the flyer source content. Static hosts only serve the client.
## Active Files
```text
site/
index.html (the client)
nostr-client.css
nostr-client.js
locales.js
board.html (bulletin board page)
board.js
favicon.svg (inline SVG site icon)
CNAME
vendor/
nostr-tools/
qrcode-generator/
nostr/
index.html (redirect stub for legacy /nostr/ URLs)
voxvera/
nostr/
schema.py
tests/
test_nostr_schema.py
```
## Deployment
The deployable static root is `site`.
No build command is required. Vercel should use:
- root directory: repository root
- output directory: `site`
- build command: empty
The client is served from the root (`site/index.html`). `site/nostr/index.html` is a redirect stub that forwards the legacy `/nostr/` path to the root, preserving the query string and `#naddr` fragment, so poster URLs and QR codes printed before the move still resolve.
## Event Model
Recommended event kind: `30078` parameterized replaceable event.
Required tags:
- `["d", "voxvera:<slug>"]`
- `["t", "voxvera"]`
- `["t", "flyer"]`
Recommended language tags:
- `["language", "<lang>"]`
- `["L", "ISO-639-1"]`
- `["l", "<lang>", "ISO-639-1"]`
The payload `lang` field is authoritative. The language tags exist for relay/search metadata and as a fallback for older events whose payload omitted `lang`.
Payload:
```json
{
"type": "voxvera_flyer",
"version": 1,
"folder_name": "voxvera",
"name": "Vox Vera Printable Flyers",
"lang": "en",
"title": "TOP SECRET",
"subtitle": "DO ~~NOT~~ DISTRIBUTE",
"headline": "OPERATION VOX VERA",
"content": "Flyer body text",
"url_message": "Follow this link to learn more.",
"url": "https://creator.example/action",
"tear_off_link": "https://voxvera.org/nostr/#naddr1...",
"footer_message": "0110010",
"qr_target": "flyer_url"
}
```
The UI labels `folder_name` as `Flyer Name`; it acts as the event slug, not a local hosting folder.
## QR Target
Default behavior: `qr_target: "flyer_url"`.
`url` is always the creator-controlled content destination shown in the body of the flyer. The editor must not overwrite this field with generated app URLs.
When publishing, the client computes the replaceable-event `naddr` and writes the generated poster URL to `tear_off_link`. The tear-off tabs and tear-off QR code point at `tear_off_link`, so people can re-open and reprint the flyer. The main flyer QR code points at `url`, so viewers can visit the creator's intended destination.
The `naddr` is encoded with a **single relay hint** (the primary configured relay) instead of the full relay list. This keeps the poster URL short and its tear-off QR code easy to scan — a typical poster URL drops from ~233 characters (full list) to ~171 — while still pointing a fresh viewer at a relay that has the event. Viewers also fall back to `DEFAULT_RELAYS`, which is where flyers are published by default. This stays a standard NIP-19 `naddr`, so any Nostr client can resolve it, and older relay-bearing `naddr` URLs continue to decode and resolve unchanged.
The naddr is carried in the URL **fragment** (`#naddr1...`) rather than a `?addr=` query parameter. The fragment is shorter (less QR clutter), needs no URL-encoding, and never reaches the static host. `getUrlEventReference` reads the naddr from query params, the fragment, or anywhere in the full URL, so older `?addr=` poster URLs and printed QR codes still resolve.
Supported values:
- `flyer_url`: tear-off QR points to the hosted client URL for the poster
- `content_url`: QR points to the payload's content URL
- `nostr_event`: QR points to the Nostr source identifier when available
## Safety
Nostr content is untrusted.
The client and schema helper must:
- reject raw HTML in flyer text fields
- escape rendered flyer content
- reject unsafe URL schemes such as `javascript:` and `data:`
- keep attachments unsupported in V1
- avoid remote frontend dependencies
## Publishing identity
The editor signs flyer events under one of three identities, chosen in the
identity controls (`activeIdentity` / `signActiveEvent` in `nostr-client.js`):
- **Anonymous (default).** The per-device key in `localStorage`
(`voxvera_nostr_anon_secret_hex`); signs locally with `finalizeEvent`.
Unchanged behavior — no connection required. "Generate anonymous npub" rolls a
fresh device key.
- **Browser extension (NIP-07).** Signs via `window.nostr.signEvent`; the secret
never enters the page. The pubkey is fetched with `getPublicKey()`.
- **Private key (nsec).** The user pastes an `nsec`; it is decoded to a secret
key used to sign with `finalizeEvent`. By default the secret lives **only in
memory** for the session. If the user ticks "Remember on this device", the
secret is encrypted with a PIN and stored as `voxvera_identity_nsec_enc`; the
plaintext secret is never written to storage.
The chosen mode is remembered in `voxvera_identity_mode` (and the npub in
`voxvera_identity_npub` for display). On reload: NIP-07 re-fetches the pubkey;
a remembered nsec shows a **locked** state until the PIN is entered (`unlock`);
a session-only nsec falls back to anonymous. `naddr`/poster-URL/`author npub`
outputs all reflect the active identity.
**PIN encryption details.** PBKDF2 (`SHA-256`, 600k iterations, random 16-byte
salt) derives an AES-GCM-256 key (random 12-byte IV); the blob stores
`{v, iters, salt, iv, ct}` base64. A minimum 4-digit numeric PIN is enforced,
but longer PINs are allowed and encouraged.
> **Security caveat (documented deliberately).** A short numeric PIN has a tiny
> keyspace (a 4-digit PIN is ~10,000 combinations), so if the encrypted blob is
> exfiltrated (targeted XSS, or devtools access on a shared/stolen device) it is
> brute-forceable offline regardless of PBKDF2 cost. PIN-at-rest protects against
> casual snooping and untargeted localStorage scraping, **not** a determined or
> targeted attacker. The NIP-07 extension path (secret never in the page) is the
> stronger option; a NIP-46 remote signer is a future addition. See
> [`roadmap.md`](roadmap.md).
## Editing, re-publishing, and deleting flyers
Because flyers are addressable replaceable events (`kind 30078`, identified by
`(pubkey, d)` where `d = voxvera:<slug>`), the author can manage a published
flyer by re-publishing under the same key + Flyer Name. When a flyer is loaded
from an event, the editor shows author-only actions (`#loaded-flyer-actions`):
- **Edit** — change fields and publish again; the same `d` tag replaces the
prior version in place, keeping the same `naddr`/poster URL.
- **Re-publish (keep-alive)** — re-sign and re-broadcast the current content so
relays that prune app-data don't age the flyer out (`republishCurrentFlyer`).
- **Delete** (`deleteLoadedFlyer`) — two layers, for robustness across relays:
1. a **replaceable tombstone** (`buildTombstoneEvent`) — same `(kind, d)`, with
`deleted: true` in the payload and a `["deleted"]` tag, so it *overwrites*
the flyer's content; relays honoring replaceable semantics now serve the
tombstone, and
2. a **NIP-09 deletion request** (`buildDeletionEvent`, kind `5`) referencing
the addressable `a` tag (`30078:<pubkey>:voxvera:<slug>`) and the event id,
asking relays to drop it entirely.
All three are **author-only**: the active signing key must match the loaded
flyer's author (`resolveActivePubkey`), and `signAndPublish` refuses to publish
if the signed key diverges from the address. **Tombstone recognition:** the
board's `parseFlyers` keeps the newest event per `(pubkey, d)` and skips it if
that newest version is a tombstone (so a delete can't be undone by an older copy
arriving later); the viewer shows a localized "This flyer was removed." state
(`isFlyerTombstone`). Deletion is **best-effort** — relays that ignore both
replaceable overwrites and NIP-09 may still serve the original — so it is framed
as a request, not a guarantee.
## Print paper size
The flyer supports two print sizes: **US Letter** (8.5×11in) and **A4**
(210×297mm), covering every country whose language the client supports (Letter
in North America and a few Latin American countries; A4 everywhere else,
including the EU, Russia, China, Japan, and the Middle East).
- Dimensions live in CSS custom properties `--sheet-w` / `--sheet-h`, switched
by a `paper-letter` / `paper-a4` class on `<html>` (`applyPaperSize` in
`nostr-client.js`). The tear-off column (`3.75in`) and QR codes (`1.25in`)
stay fixed physical sizes; the content column flexes to the sheet width.
- The print `@page { size: … }` is injected by JS (an element with id
`voxvera-page-size`), because `@page size` cannot read CSS custom properties
across engines. The static `@media print` block keeps `margin: 0` and a
Letter default for the pre-JS state.
- The default is chosen from the **region subtag** of the browser locale
(`preferredPaperSize` — e.g. `en-GB` → A4, `en-US` → Letter). This is "by
location" without geolocation, using the same signal as language. When no
locale carries a region, it falls back to Letter.
- A user override (the paper-size selector) is stored in `localStorage`
(`voxvera_paper`) and wins over the region default.
- **Paper size is a local print/view preference and is never written into the
Nostr event.** A flyer authored on Letter reprints on A4 for a European
viewer without changing the source event. The live fit-check protects
authoring on whichever size is active; switching to a narrower size after
authoring can ellipsis-truncate a maxed-out single-line field.
Field capacity therefore varies by paper size; see
[`flyer-field-limits.md`](flyer-field-limits.md).
## Bulletin board
`site/board.html` + `site/board.js` are a standalone page that lists the most
recent flyers found on the default relays as a sortable, spreadsheet-style
table: **title**, **link** (the poster URL, rendered as the word "link"),
**posting npub**, **language**, **posted date**, and the **event ID** (shown
shortened, full value in the title attribute, with a per-row copy button). Any
column header sorts (default is date descending); replaceable events are
de-duplicated per author+`d` identifier, keeping the latest.
- The entry point is a small screen-only link below the flyer preview
(`.board-link`, label `bulletin_board`), outside the printable sheet. It must
never print (hidden in the `@media print` block alongside the other app
chrome).
- **The board is gated behind a connected Nostr identity.** On load it shows a
login gate (`#board-gate`) instead of the table, with three ways to connect:
a **NIP-07** extension (`window.nostr.getPublicKey()`), **pasting an `nsec`**
(decoded in-page to derive the pubkey, then discarded — the secret is never
stored or transmitted), or **creating a new key** (reuses this device's anon
key in `voxvera_nostr_anon_secret_hex` if present, else generates one, and
reveals the `nsec` with a save-it warning before continuing). On success it
reveals the table and surfaces the connected npub (`#board-identity`) with a
Disconnect control. The board only ever needs the *pubkey* (it reads, never
signs), so the connected pubkey is remembered in `localStorage`
(`voxvera_connected_pubkey`, shared with the main client) and a return visit
reconnects from it directly — no prompt or re-entry, any method. This is
**not access control** — the events are public on the relays regardless — it
establishes the *viewer's* identity for the web-of-trust filter below.
Authoring and printing flyers stays fully anonymous and never requires
connecting.
- **Web-of-trust filter (NIP-02).** Once connected, the board fetches the
viewer's contact list (kind 3) and defaults to showing only flyers whose
author is in the viewer's follow graph (degree 1) plus the viewer themself. A
**"Show all"** checkbox opts out to the full relay firehose. A viewer with no
follow list of their own (a fresh key) is **seeded** from a pinned curator
account's follows (`FALLBACK_CURATOR_PUBKEY` in `board.js`), so a brand-new
viewer still gets a curated board. If no trust data can be fetched at all, the
board falls back to showing everything so it is never mysteriously empty. The
`#board-filter-note` explains which mode is active (following / seeded / all),
and re-localizes with the language selector. See [`roadmap.md`](roadmap.md)
for the phased plan (Phase 1 = the gate; Phase 2 = this filter; Phase 3 =
degree-2 trust, blocklist/report, NIP-05 badges).
- `board.js` is independent of `nostr-client.js` (which exports nothing), so its
UI strings live in `BOARD_UI` (all supported languages); it reuses the
vendored nostr-tools and `locales.js` (for language names + RTL direction).
- The board has its own language selector. It reads/writes the same
`voxvera_nostr_lang` localStorage key as the main client, so the chosen
language carries across both pages, and switching it re-localizes the chrome,
column headers, language labels, and date formatting (and flips RTL).
- Relay content is untrusted: titles and npubs are escaped, and link URLs are
rejected unless `http:`/`https:` (so `javascript:`/`data:` never render as a
link).
- The npub column is forward-looking — anonymous keys today, but a stable
identity per author maps cleanly onto this view later.
- **Per-row actions** (behind a per-row **⋯ menu**). On flyers the connected
viewer authored, the menu offers
**Edit** (a link to `/?edit=1#<naddr>`, which loads the flyer in the editor),
**Re-broadcast** (re-sends the already-signed event to all relays — no signing
needed), and **Delete** (tombstone + NIP-09; the board signs via the device
key or NIP-07, and for a pasted-nsec connection it points to the editor). On
flyers from others it shows **Block** — a per-device blocklist of author
pubkeys (`voxvera_blocked_pubkeys`) that always hides them, with a "Clear
blocked" control. The blocklist is local "hide this," separate from the
web-of-trust filter (roadmap #1).
The login gate (Phase 1) and the web-of-trust filter (Phase 2) are in place.
Remaining gaps — degree-2 trust, a blocklist/report flow, NIP-05 badges, and
making the bootstrap curator configurable — are tracked in
[`roadmap.md`](roadmap.md).
## Localization
Flyer defaults come from `site/locales.js`.
Nostr editor/viewer controls and Nostr-specific flyer labels come from `NOSTR_UI` in `site/nostr-client.js`.
Language changes should:
- publish the selected flyer language in payload `lang`
- publish matching Nostr language tags
- infer language from event tags if a fetched payload omits `lang`
- update default flyer content while the flyer is still using default content
- preserve user-authored or fetched event content
- update editor/viewer tool labels
- update printed side-tab labels
- respect RTL direction metadata
### Letter-spacing by script
Flyer text uses tighter letter-spacing than the original design to fit more
characters per line, but `letter-spacing` is not script-neutral, so it is
applied per script via a policy class on the flyer `.container`
(`LETTER_SPACING_POLICY` in `nostr-client.js`; `ls-full` / `ls-cjk` / `ls-none`
rules and `--ls-*` variables in `nostr-client.css`):
- `full` — Latin, Cyrillic, Hebrew: reduced positive tracking on the display
fields plus a slight negative on body/URL to reclaim line width.
- `cjk` — Japanese, Chinese: tracking is clamped to `0` and never negative, so
full-width glyphs do not overlap.
- `none` — Arabic, Persian, Hindi: letter-spacing is turned off entirely. These
are cursive or complex scripts where any tracking breaks the letter joins or
detaches combining marks. (This also corrected the prior behavior, which
applied the design's display tracking to every language unconditionally.)
When adding a language, classify its script in `LETTER_SPACING_POLICY` (default
is `full`) and verify the headline, subtitle, and body render correctly in the
browser.
## Verification
```bash
node --check site/nostr-client.js
pytest -q
```
For UI work, also verify browser rendering and print output from a local static server.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-130
View File
@@ -1,130 +0,0 @@
# Uso Detalhado
Este guia cobre os fluxos de trabalho comuns da CLI. Veja `docs/docker.md` para instruções do Docker e `docs/templates.md` para modelos de panfletos disponíveis.
## Pré-requisitos
O VoxVera foi projetado para ser altamente portátil e requer dependências mínimas do sistema.
### 1. Binários Independentes (Recomendado)
Você pode baixar binários independentes e sem dependências para o seu sistema operacional:
- **Linux:** `voxvera-linux`
- **Windows:** `voxvera-windows.exe`
- **macOS:** `voxvera-macos`
Estes binários incluem tudo o que é necessário para executar o VoxVera (exceto o `onionshare-cli`).
### 2. Instalador de Linha Única
Alternativamente, instale através do nosso script automatizado:
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### 3. Instalação Manual via Python
Se preferir executar a partir do código-fonte:
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # Debian/Ubuntu
```
## Passo a Passo
1. **Inicializar:** Execute `voxvera init` e siga as instruções. Você será solicitado a selecionar seu idioma primeiro.
2. **Construir:** Gere os arquivos do panfleto. Cada construção cria automaticamente um `voxvera-portable.zip` na pasta do panfleto, permitindo que outros baixem a ferramenta completa diretamente do seu panfleto.
```bash
voxvera build
```
3. **Servir:** Publique o panfleto via Tor:
```bash
voxvera serve
```
Isso detecta automaticamente sua instância do Tor, inicia o OnionShare e escreve o endereço .onion gerado nos links destacáveis do panfleto.
## Suporte a Idiomas
O VoxVera é totalmente localizado. Você pode alterar sua preferência de idioma permanentemente usando o seletor interativo ou um atalho direto:
- **Seletor Interativo:** `voxvera lang`
- **Atalho Direto:** `voxvera --lang pt` (define a preferência para português)
### Idiomas Suportados:
- **Inglês:** `en`
- **Espanhol:** `es` (alias: `--idioma`)
- **Alemão:** `de` (alias: `--sprache`)
- **Português:** `pt`
Você também pode forçar um idioma específico para um único comando sem alterar sua preferência permanente:
- **Inglês:** `voxvera --lang en check`
- **Português:** `voxvera --lang pt check`
Os panfletos gerados detectam automaticamente o idioma do navegador do visitante e alteram o texto da interface adequadamente.
## Gerenciamento de Servidores
Gerencie vários panfletos e suas identidades Tor a partir de um único menu interativo:
```bash
voxvera manage
```
Recursos:
- **--- Criar Novo Site/Panfleto ---**: Inicia a sequência completa de configuração.
- **--- Iniciar Todos os Sites ---**: Inicia ou encerra todos os panfletos da sua frota de uma só vez.
- **Status em Tempo Real**: Visualize URLs .onion ativas e indicadores de progresso de inicialização do Tor.
- **Controle Individual**: Exportar para Zip sites específicos para ZIP ou exclua-os.
## Espelhamento Universal (Distribuição Viral)
Para garantir que o VoxVera permaneça acessível mesmo se os repositórios centrais forem censurados, cada panfleto atua como um espelho para a ferramenta.
Quando você hospeda um panfleto, o botão **"Baixar Ferramenta e Código"** na página inicial fornece um `voxvera-portable.zip` contendo:
- O código-fonte completo e todos os idiomas suportados.
- Todas as dependências Python (pré-vendidas).
- Binários Tor multiplataforma.
Isso permite que qualquer pessoa que escaneie seu panfleto se torne um novo distribuidor da ferramenta VoxVera.
## Exportação e Backup
Faça backup de suas identidades Tor exclusivas (para que sua URL .onion nunca mude) ou mova seus panfletos para outra máquina.
- **Exportar um único site**: `voxvera export <nome_da_pasta>`
- **Exportar todos os sites**: `voxvera export-all`
**Local de armazenamento:** Todas as exportações são salvas como arquivos ZIP em uma pasta chamada `voxvera-exports` no diretório inicial do usuário (`~/voxvera-exports/`) em todas as plataformas.
## Importação e Recuperação
Restaure toda a sua configuração em uma nova máquina movendo seus arquivos ZIP para `~/voxvera-exports/` e executando:
```bash
voxvera import-multiple
```
## Portabilidade e Uso Offline
Se precisar executar o VoxVera em uma máquina sem acesso à internet, você pode "venderizar" as dependências primeiro:
```bash
voxvera vendorize
```
Isso baixa todas as bibliotecas Python necessárias para `voxvera/vendor/`. A ferramenta priorizará esses arquivos locais, permitindo que ela funcione sem `pip install`.
## Importação em Lote (JSON)
Para gerar panfletos em massa a partir de vários arquivos de configuração JSON, coloque-os no diretório `imports/` e execute:
```bash
voxvera batch-import
```
## Como as URLs Funcionam
Cada panfleto tem duas URLs separadas:
- **Link destacável** (gerado automaticamente): O endereço .onion onde o panfleto está hospedado.
- **Link de conteúdo** (configurado pelo usuário): Uma URL externa apontando para um site, vídeo ou download.
Você não precisa inserir manualmente o endereço .onion; o VoxVera lida com isso automaticamente durante a fase de `serve`.
-93
View File
@@ -1,93 +0,0 @@
# VoxVera Roadmap & Technical Specification (v0.2.0)
This document outlines the next major evolution of the VoxVera project, focusing on trust, social amplification, visual versatility, and network resilience.
---
## 1. Integrity & Trust (PGP Signing)
**Goal:** Provide cryptographic proof that the `voxvera-portable.zip` provided by a flyer has not been tampered with by the hoster.
### Technical Requirements
- **CLI:** Add `voxvera sign <folder_name>` command.
- **Dependency:** Use a lightweight PGP implementation (e.g., `python-gnupg` or `pgpy`) to sign the portable ZIP.
- **Storage:** Generate a `.sig` or `.asc` file alongside the ZIP in the `download/` folder.
- **Web:** The landing page will look for `voxvera-portable.zip.asc`. If found, a **"Verified Source"** badge with the signer's Fingerprint will appear next to the download button.
### Implementation Phases
1. **Phase 1:** Add PGP key generation/import logic to `voxvera init`.
2. **Phase 2:** Update `build_assets` to optionally sign the generated ZIP.
3. **Phase 3:** Update `index-master.html` to display verification status.
---
## 2. Nostr Integration (Social Amplification)
**Goal:** Bridge the physical world (flyers) with the decentralized digital world (Nostr) by automatically broadcasting live .onion sites.
### Technical Requirements
- **CLI:** Add `voxvera serve --nostr` flag.
- **Workflow:** When a site goes live and the `.onion` URL is generated, the tool posts a "Flyer Event" to a list of configured Nostr relays.
- **Identity:** Users can provide an existing NSEC or have VoxVera generate a "Flyer Identity" (new NPUB) for that specific server.
- **Metadata:** Include tags for the flyer title, headline, and the `.onion` link.
### Implementation Phases
1. **Phase 1:** Add `nostr` and `bech32` to the `vendor/` directory.
2. **Phase 2:** Implement a background broadcast thread in `serve()`.
3. **Phase 3:** Add "View on Nostr" links to the flyer footer.
---
## 3. The "Tear-off" Designer (Template Gallery)
**Goal:** Expand the utility of VoxVera to new use cases like missing person alerts, protest organizing, and artistic distribution.
### Technical Requirements
- **Restructuring:** Move from a single `voxvera` template to a category-based system:
- `/templates/default/` (The original Operation VoxVera style)
- `/templates/minimal/` (Clean, text-heavy)
- `/templates/alert/` (High-contrast, for emergencies)
- `/templates/art/` (Image-focused)
- **CLI:** Update `voxvera init` to include a visual description and selector for templates.
### Implementation Phases
1. **Phase 1:** Refactor `copy_template` to support categories.
2. **Phase 2:** Design and implement 3 new HTML/CSS templates.
3. **Phase 3:** Allow templates to define their own custom character limits (e.g., "Alert" might allow larger headlines).
---
## 4. Self-Healing Network (Update Logic)
**Goal:** Ensure the decentralized "Viral" network stays current with security fixes and features.
### Technical Requirements
- **Discovery:** The tool will check a "Source of Truth" (e.g., `voxvera.org/version.json` or a hardcoded list of onion mirrors).
- **Notification:** `voxvera manage` will show a 🌟 or ⚠️ next to the version number if an update is available.
- **Update Workflow:** Provide a `voxvera update` command that downloads the latest `voxvera-portable.zip` and safely replaces the `vendor/` and `voxvera/` directories.
### Implementation Phases
1. **Phase 1:** Implement version-checking logic via Tor SOCKS proxy.
2. **Phase 2:** Add update notifications to the management menu.
3. **Phase 3:** (Advanced) Implement "In-Place" updates for the vendored dependencies.
---
## 5. GUI Modernization
**Goal:** Transition the Electron wrapper from a CLI mirror to a rich, visual dashboard.
### Technical Requirements
- **Flyer Cards:** Replace the text list with visual "cards" showing the flyer's headline and a mini QR preview.
- **Tor Dashboard:** A dedicated tab showing all active hidden services, their uptime, and their `.onion` links.
- **One-Click Actions:** Visual buttons for "Export All," "Start All," and "New Flyer."
- **Direct Log Stream:** A collapsible panel to see the OnionShare logs in real-time.
### Implementation Phases
1. **Phase 1:** Update the IPC bridge between Electron and the Python CLI.
2. **Phase 2:** Redesign the frontend using a modern, dark-themed CSS framework (keeping it local-first).
3. **Phase 3:** Add a "Theme Preview" during the flyer creation process.
---
## Summary of Impact
By completing this roadmap, VoxVera moves from a standalone utility to a **Decentralized Information Ecosystem**.
- **Security** is solved via PGP.
- **Reach** is solved via Nostr.
- **Versatility** is solved via the Template Gallery.
- **Sustainability** is solved via Update Logic.
+270
View File
@@ -0,0 +1,270 @@
# VoxVera Roadmap & Known Issues
This document captures known limitations and the development directions that
would address them. None of these are code bugs — they are product- and
threat-model-level gaps in the current static Nostr client. They are listed
roughly in priority order: the trust model (#1–#2) is the highest-leverage area
because almost every other risk flows from it being undefined.
Status legend: **Open** (not started) · **Partial** (some mitigation exists) ·
**Planned** (committed direction) · **In progress** (partially shipped).
## Shipped so far (2026-06-10)
The trust model (#1–#2) has moved from undefined to implemented:
- **Bulletin board login gate** — viewing the board requires a connected Nostr
identity (NIP-07 extension, a pasted `nsec`, or a generated key).
- **Web-of-trust filter** — the board defaults to flyers from authors in the
viewer's NIP-02 follow graph, seeded from a curator account for fresh keys,
with a "Show all" opt-out (so it is no longer an unmoderated firehose).
- **Editor publishing identity** — authors can publish anonymously (default),
via NIP-07, or with an imported `nsec` that is optionally PIN-encrypted at
rest (PBKDF2 → AES-GCM; plaintext never stored).
- **Flyer management (edit / re-publish / delete)** — an author can edit a
loaded flyer (re-publish replaces in place via the `d` tag), re-publish as a
keep-alive, or delete it. Delete is belt-and-suspenders: a replaceable
**tombstone** (so the board/viewer hide it even on relays that ignore NIP-09)
plus a **NIP-09** deletion request. Best-effort, author-only. These actions are
available in the editor and inline on the bulletin board (Edit / Re-broadcast /
Delete on your own rows).
- **Local blocklist** — a per-device "Block" on the board hides flyers from any
author you didn't post (separate from the web-of-trust filter), with a clear
control. This is the local blocklist direction from #1.
All of the above is localized across the 14 languages and covered by the
cross-engine Playwright suite. **What remains** on #1–#2 is polish (degree-2
trust, blocklist/report, NIP-05 badges, an identified-vs-anonymous display) plus
the editor follow-ups noted under the *Planned direction* section. **#3–#5 are
still fully open** — distribution centralization (#3) is now the
highest-leverage untouched item.
---
## 1. Bulletin board has no moderation or abuse story — **In progress**
> Direction agreed and **Phases 1–2 shipped**: the board requires a connected
> Nostr identity to view, and it now filters to flyers from the viewer's NIP-02
> web of trust (with a bootstrap seed for new keys). See *Planned direction:
> identity + web-of-trust on the board* below (jointly addresses #1 and #2).
> Remaining: degree-2 trust, blocklist/report, NIP-05 badges (Phase 3).
**Problem.** `board.html` lists every Nostr event tagged `t=voxvera` / `t=flyer`
from the public default relays, with no filtering, verification, or moderation.
Anyone can publish a kind-`30078` event with those tags and immediately appear
on the board — including spam, hostile titles, or links to harmful content, all
under VoxVera's branding.
**Current mitigation (Partial on safety, not abuse).** Relay content is treated
as untrusted: titles and npubs are HTML-escaped, and link URLs are rejected
unless `http(s)` (so `javascript:`/`data:` never render). This prevents script
injection but does nothing about spam or unwanted-but-valid content.
**Why it matters.** A static client cannot rate-limit or moderate server-side,
so the board is trivially gameable the moment it is used adversarially. This is
the single biggest liability for promoting the board publicly.
**Possible directions.**
- Client-side curation: an allowlist of npubs (a "follows"/featured set) so the
default view shows only vetted authors.
- A local, user-controlled blocklist / "hide this" with `localStorage`
persistence (per-device, no server needed). **✅ Shipped** — the board's
per-row **Block** (`voxvera_blocked_pubkeys`).
- A dedicated VoxVera relay (or relay set) that applies its own admission
policy, with the public relays as fallback.
- A "report" affordance that records to a relay/list a curator can act on.
- Make the unfiltered firehose an explicit opt-in mode, not the default.
Depends on **#2** (without identity, allowlists/blocklists are weak).
## 2. Anonymous keys give no authenticity or accountability — **In progress**
> Phases 1–2 shipped: the board viewer connects a real Nostr identity (NIP-07)
> and the board is filtered by that viewer's web of trust (with a curator seed
> for new keys), so spam from unknown authors is hidden by default. The **editor
> now lets authors publish under their own identity too** — NIP-07, an imported
> `nsec` (optionally PIN-encrypted at rest), or stay anonymous (default) — so a
> flyer can carry a stable, identifiable author when the creator wants one.
> Authenticity *display* on the board (NIP-05 badges, an identified/anonymous
> distinction) remains ahead.
**Problem.** The client generates a fresh anonymous key per browser, so the
board's "Posted by" npub is effectively random and there is no way to verify a
flyer came from who it claims. The trust model is currently empty.
**Why it matters.** Authenticity underpins the board, "report"/blocklist
features, and any notion of a trusted author. Without stable identity, #1 has no
foundation to build on.
**Possible directions.**
- Optional persistent identity: let a user keep/reuse a key (or import one) and
associate it with their flyers, while keeping anonymous-by-default.
- First-class NIP-07 support for users who already have a Nostr identity.
- Optional NIP-05 / verified handle display on the board.
- A clear UI distinction between "anonymous" and "identified" flyers.
The npub column on the board was built deliberately forward-looking so this
maps in cleanly.
## Planned direction: identity + web-of-trust on the board
Jointly addresses #1 and #2. The goal is to make the board accountable without
abandoning anonymous-by-default authoring.
**Key reality that shapes the design.** You cannot gate *writing* to public
relays — anyone can publish a `t=voxvera` event directly, never touching this
client. So a "login required to post" button is only a soft deterrent; it can't
bound what is on the board. The real lever is **filtering what the board
displays**. Login's actual job is to supply the *viewer's* identity so the
board can show them flyers from people they trust.
**Principles.**
- **Login enables a trust-filtered view; it is not access control.** The data
is public on relays regardless, so hiding it in the UI is cosmetic. Treat
login as "we know who you are, so we can show you a trustworthy board."
- **Keep anonymous creation + printing fully available.** The core authoring
tool must not require a persistent, linkable identity (activist threat model).
Identity is required only to *appear on the public board*, not to make/print a
flyer.
- **Web-of-trust is the actual spam defense, not login.** NIP-07 keys are free
and unlimited, so "must have a key" alone just makes a spammer generate one.
Filtering by the viewer's NIP-02 follow graph (degree 1, optionally
follows-of-follows) is what raises the cost.
- **Don't lock out mobile.** NIP-07 (`window.nostr`) needs a desktop extension,
but scanned-QR flyers open on phones. "Login" should support NIP-07 **plus**
nsec import (with warnings) and/or NIP-46 remote signer, and/or promoting the
existing anonymous key to a kept identity.
**Phased plan.**
- **Phase 1 — Identity. ✅ Shipped.** The board (`board.html` / `board.js`) shows
a login gate instead of the table until the viewer connects. Three methods: a
NIP-07 extension (`window.nostr.getPublicKey()`), pasting an `nsec`, or creating
a new key (see decision 2 below). On success it reveals the table, surfaces the
connected npub with a Disconnect control, and remembers the pubkey in
`localStorage` (`voxvera_connected_pubkey`) so a return visit reconnects from
the pubkey alone — no prompt or re-entry, regardless of method. Anonymous
create/print is untouched — connecting is required only to *view the board*.
- **Phase 2 — Web-of-trust filter. ✅ Shipped.** On connect the board fetches
the viewer's NIP-02 contact list (kind 3) and defaults to flyers from authors
in their follow graph (degree 1) plus themselves, with a **"Show all"**
opt-out. **Bootstrap seed:** a viewer with no follow list of their own (a
fresh key) is seeded from a pinned curator account's follows
(`FALLBACK_CURATOR_PUBKEY` in `board.js` =
`npub15jnttpymeytm80hatjqcvhhqhzrhx6gxp8pq0wn93rhnu8s9h9dsha32lx`), so a brand-
new viewer still gets a curated board instead of the unmoderated firehose. If
no trust data can be fetched at all, the board falls back to showing
everything (never mysteriously empty). Covered by the cross-engine e2e suite
(followed-only view + show-all opt-out; curator-seeded fallback).
- **Phase 3 — Optional / next.** Degree-2 trust (follows-of-follows), a local
blocklist / "hide this", report-to-list, and NIP-05 verified badges. Also:
the bootstrap curator is currently a single hardcoded pubkey — consider making
it configurable or a small curated set.
**Decisions made (2026-06-10).**
1. **Board viewing: login-required.** The board is blank (a Connect prompt)
until a Nostr identity is connected — framed as a members' space rather than a
public discovery surface.
2. **Login methods: NIP-07 + nsec import + key generation. ✅ Shipped.** The gate
offers three ways in: a NIP-07 browser extension, pasting a private key
(`nsec`), or creating a new key. The nsec is decoded **in-page** to derive the
pubkey and then discarded — only the pubkey is persisted, since the board only
reads (never signs). "Create a new key" reuses this device's existing
anonymous key if present (so it doesn't orphan an editor identity) or
generates one, and reveals the `nsec` with a "save this — we can't recover it"
warning before continuing. This **resolves the earlier mobile-lockout
trade-off**: a phone visitor with no extension can now generate or paste a key
to view the board. Covered by the cross-engine e2e suite (nsec import +
pubkey-only persistence + reload restore; invalid nsec; key generation +
reveal + connect).
**Follow-ups this opens.**
- **In-page nsec handling.** Pasting a secret key into a web page is inherently
riskier than a NIP-07 extension that keeps the key isolated; the input is a
password field, the value is cleared after use, and nothing is transmitted, but
a NIP-46 remote signer would be a safer mobile path to add later.
- **Editor identity (shipped).** The editor now signs under anon / NIP-07 /
imported nsec. A remembered nsec is PIN-encrypted at rest (PBKDF2 600k →
AES-GCM); plaintext is never stored. **Known weakness:** a short numeric PIN is
brute-forceable offline if the encrypted blob leaks — it guards casual snooping,
not a targeted attacker. Next: NIP-46 remote signer; an attempt-limit / lockout
on repeated wrong PINs; and optionally encrypting the anonymous device key the
same way (today it is stored in plaintext, as before).
- **Editor vs board identity are independent.** The editor's publishing identity
and the board's viewing identity are stored separately and don't yet sync; a
future pass could share one connected identity across both pages.
## 3. Client distribution is centralized (a single chokepoint) — **Open**
**Problem.** The content lives on decentralized relays, but the *client* is one
domain (`voxvera.org`) on a centralized host (Vercel). A censor can block the
domain and most users are stuck, which undercuts the censorship-resistance
premise even though the backend is robust.
**Current mitigation (Partial).** The client is fully static and host-agnostic,
so it *can* be served from any static host or mirror — but discovery and trust
of mirrors is unsolved, so in practice users depend on the canonical domain.
**Possible directions.**
- Document and support official mirrors (IPFS/IPNS, other static hosts) with a
verifiable build (subresource integrity / reproducible hash).
- A one-file/offline build users can save and reopen (`file://`) — verify
WebCrypto/clipboard degrade gracefully off a secure context.
- Revisit the dropped Tor/onion distribution path as an *optional* mirror (kept
off `main` per current guardrails, but a documented option).
- Publish the client itself to a content-addressed network so the front door is
not a single DNS name.
## 4. Relay permanence is overstated — **Partial**
> Partial mitigation shipped: the editor now has a **Re-publish (keep-alive)**
> action, so an author can refresh a flyer before relays age it out. The durable
> fix (a pinned/dedicated relay) is still open.
**Problem.** The app depends on a few general-purpose relays
(`relay.damus.io`, `nos.lol`, `relay.primal.net`) that can prune app-data kinds,
rate-limit, or drop events. "Your flyer is still there later" is therefore not
guaranteed. The single relay hint in the `naddr` also reduces fetch robustness
for events not on the default set.
**Possible directions.**
- Run/pin a dedicated VoxVera relay (or several) so published flyers have a
durable home, with the public relays as redundancy.
- Let authors configure and embed their own preferred relays.
- Consider a re-broadcast / "keep alive" helper for important flyers.
- Reconsider how many relay hints to embed in the poster `naddr` (tradeoff:
URL length / QR density vs. fetch robustness — see the QR Target notes in the
spec).
## 5. Content-safety guardrails are minimal — **Open**
**Problem.** Beyond HTML-escaping and URL-scheme rejection, there is nothing
preventing the tool (and especially the public board) from being used to author
or surface illegal/harmful content carrying VoxVera's branding.
**Possible directions.** Tie this to #1/#2: curation, reporting, and a clear
terms/acceptable-use stance for any hosted board. A purely local authoring tool
has a smaller surface than a public discovery board, so scope decisions here
should follow the board's trust model.
---
## Smaller / lower-priority items
- **Field-fit is layout-measured, not a fixed cap.** Robust, but capacity
varies with font availability and zoom; the
[cheat sheet](flyer-field-limits.md) is explicitly approximate. Fine as-is;
noted so it is not mistaken for a contract.
- **Favicon — ✅ done.** A small inline SVG (`site/favicon.svg`) is linked from
both pages, so browsers no longer request (and 404 on) `/favicon.ico`.
- **WebKit/Safari coverage in CI** needs `libavif16` on Linux runners
(`sudo npx playwright install-deps`); headless WebKit is also not a perfect
stand-in for real Safari/iOS print + clipboard behavior, so a real-device
pass before releases is still worth it.
---
*Reviewed 2026-06-10. The trust model (#1–#2) is now implemented — see "Shipped
so far" above. The highest-leverage untouched item is now #3 (the client is a
single centralized domain), since it most undercuts the censorship-resistance
premise even with the backend on decentralized relays.*
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-130
View File
@@ -1,130 +0,0 @@
# Подробное руководство
Это руководство охватывает основные рабочие процессы CLI. См. `docs/docker.md` для инструкций по Docker и `docs/templates.md` для доступных шаблонов листовок.
## Предварительные требования
VoxVera разработан как высокопортативный инструмент и требует минимум системных зависимостей.
### 1. Автономные бинарные файлы (Рекомендуется)
Вы можете скачать автономные исполняемые файлы без зависимостей для вашей операционной системы:
- **Linux:** `voxvera-linux`
- **Windows:** `voxvera-windows.exe`
- **macOS:** `voxvera-macos`
Эти файлы включают все необходимое для запуска VoxVera (кроме `onionshare-cli`).
### 2. Однострочный установщик
Или установите с помощью нашего автоматического скрипта:
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### 3. Ручная установка через Python
Если вы предпочитаете запускать из исходного кода:
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # Debian/Ubuntu
```
## Шаг за шагом
1. **Инициализация:** Запустите `voxvera init` и следуйте подсказкам. Вам будет предложено сначала выбрать язык.
2. **Сборка:** Сгенерируйте ресурсы листовки. Каждая сборка автоматически создает файл `voxvera-portable.zip` в папке листовки, позволяя другим скачивать полный инструмент прямо с вашей листовки.
```bash
voxvera build
```
3. **Запуск:** Опубликуйте листовку через Tor:
```bash
voxvera serve
```
Это автоматически обнаружит ваш экземпляр Tor, запустит OnionShare и запишет сгенерированный .onion адрес в отрывные ссылки листовки.
## Поддержка языков
VoxVera полностью локализован. Вы можете изменить свои языковые предпочтения навсегда, используя интерактивный селектор или прямой ярлык:
- **Интерактивный селектор:** `voxvera lang`
- **Прямой ярлык:** `voxvera --lang ru` (устанавливает русский язык)
### Поддерживаемые языки:
- **Английский:** `en`
- **Испанский:** `es` (алиас: `--idioma`)
- **Немецкий:** `de` (алиас: `--sprache`)
- **Русский:** `ru`
Вы также можете принудительно использовать определенный язык для одной команды, не меняя постоянные настройки:
- **Английский:** `voxvera --lang en check`
- **Русский:** `voxvera --lang ru check`
Сгенерированные листовки автоматически определяют язык браузера посетителя и соответствующим образом переключают текст интерфейса.
## Управление серверами
Управляйте несколькими листовками и их Tor-идентификаторами из единого интерактивного меню:
```bash
voxvera manage
```
Возможности:
- **--- Создать новый сайт/листовку ---**: Запуск полной последовательности настройки.
- **--- Запустить все сайты ---**: Запуск или остановка всех листовок в вашем парке одновременно.
- **Статус в реальном времени**: Просмотр активных .onion URL и индикаторов прогресса загрузки Tor.
- **Индивидуальный контроль**: Экспорт в Zip определенных сайтов в ZIP или их удаление.
## Универсальное зеркалирование (Вирусное распространение)
Чтобы VoxVera оставался доступным, даже если центральные репозитории будут подвергнуты цензуре, каждая листовка выступает в качестве зеркала для инструмента.
Когда вы хостите листовку, кнопка **"Скачать инструмент и код"** на целевой странице предоставляет `voxvera-portable.zip`, содержащий:
- Полный исходный код и все поддерживаемые языки.
- Все зависимости Python (пре-вендоризованные).
- Кроссплатформенные бинарные файлы Tor.
Это позволяет любому, кто сканирует вашу листовку, стать новым распространителем инструмента VoxVera.
## Экспорт и резервное копирование
Создавайте резервные копии своих уникальных Tor-идентификаторов (чтобы ваш .onion URL никогда не менялся) или переносите листовки на другую машину.
- **Экспорт одного сайта**: `voxvera export <имя_папки>`
- **Экспорт всех сайтов**: `voxvera export-all`
**Место хранения:** Все экспорты сохраняются в виде ZIP-файлов в папке `voxvera-exports` в домашнем каталоге пользователя (`~/voxvera-exports/`) на всех платформах.
## Импорт и восстановление
Восстановите всю свою настройку на новой машине, переместив ZIP-файлы в `~/voxvera-exports/` и запустив:
```bash
voxvera import-multiple
```
## Портативность и работа оффлайн
Если вам нужно запустить VoxVera на машине без доступа к Интернету, вы можете сначала «вендоризовать» зависимости:
```bash
voxvera vendorize
```
Это загрузит все необходимые библиотеки Python в `voxvera/vendor/`. Инструмент будет отдавать приоритет этим локальным файлам, что позволит ему работать без `pip install`.
## Пакетный импорт (JSON)
Чтобы массово генерировать листовки из нескольких конфигурационных файлов JSON, поместите их в директорию `imports/` и запустите:
```bash
voxvera batch-import
```
## Как работают URL-адреса
У каждой листовки есть два отдельных URL-адреса:
- **Отрывная ссылка** (автоматически генерируется): .onion адрес, по которому размещена листовка.
- **Ссылка на контент** (настраивается пользователем): Внешний URL, указывающий на веб-сайт, видео или загрузку.
Вам не нужно вручную вводить .onion адрес; VoxVera обрабатывает это автоматически на этапе `serve`.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `cli.token_name` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-130
View File
@@ -1,130 +0,0 @@
# Maelezo ya Matumizi
Mwongozo huu unashughulikia taratibu za kawaida za CLI. Angalia `docs/docker.md` kwa maelekezo ya Docker na `docs/templates.md` kwa violezo vya vipeperushi vinavyopatikana.
## Mahitaji ya Awali
VoxVera imeundwa kuwa rahisi kubebeka na inahitaji vitegemezi vichache vya mfumo.
### 1. Programu Zinazojitegemea (Zinazopendekezwa)
Unaweza kupakua programu zinazojitegemea na zisizo na vitegemezi kwa mfumo wako wa uendeshaji:
- **Linux:** `voxvera-linux`
- **Windows:** `voxvera-windows.exe`
- **macOS:** `voxvera-macos`
Programu hizi zinajumuisha kila kitu kinachohitajika ili kuendesha VoxVera (isipokuwa `onionshare-cli`).
### 2. Kisakinishi cha Mstari Mmoja
Vinginevyo, sakinisha kupitia hati yetu ya kiotomatiki:
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
### 3. Usakinishaji wa Mwongozo wa Python
Ikiwa unapendelea kuendesha kutoka kwenye chanzo:
```bash
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
sudo apt install tor onionshare-cli # Debian/Ubuntu
```
## Hatua kwa Hatua
1. **Anzisha:** Endesha `voxvera init` na ufuate maelekezo. Utaulizwa kuchagua lugha yako kwanza.
2. **Jenga:** Tengeneza rasilimali za kipeperushi. Kila ujenzi huunda kiotomatiki faili ya `voxvera-portable.zip` kwenye folda ya kipeperushi, ikiruhusu wengine kupakua zana nzima moja kwa moja kutoka kwenye kipeperushi chako.
```bash
voxvera build
```
3. **Tumia:** Chapisha kipeperushi kupitia Tor:
```bash
voxvera serve
```
Hii hutambua kiotomatiki mfumo wako wa Tor, inaanzisha OnionShare, na kuandika anwani ya .onion iliyozalishwa kwenye viungo vya kipeperushi.
## Usaidizi wa Lugha
VoxVera imetafsiriwa kikamilifu. Unaweza kubadilisha upendeleo wako wa lugha kwa kudumu ukitumia kiteuzi shirikishi au njia ya mkato ya moja kwa moja:
- **Kiteuzi Shirikishi:** `voxvera lang`
- **Njia ya Mkato ya Moja kwa Moja:** `voxvera --lang sw` (inaweka upendeleo kuwa Kiswahili)
### Lugha Zinazotumika:
- **Kiingereza:** `en`
- **Kihispania:** `es` (jina mbadala: `--idioma`)
- **Kijerumani:** `de` (jina mbadala: `--sprache`)
- **Kiswahili:** `sw`
Unaweza pia kulazimisha lugha maalum kwa amri moja bila kubadilisha upendeleo wako wa kudumu:
- **Kiingereza:** `voxvera --lang en check`
- **Kiswahili:** `voxvera --lang sw check`
Vipeperushi vilivyozalishwa hutambua kiotomatiki lugha ya kivinjari cha mgeni na kubadilisha maandishi ya UI ipasavyo.
## Usimamizi wa Seva
Simamia vipeperushi vingi na utambulisho wao wa Tor kutoka kwenye menyu moja shirikishi:
```bash
voxvera manage
```
Vipengele:
- **--- Unda Tovuti/Kipeperushi Kipya ---**: Anza mchakato mzima wa usanidi.
- **--- Anzisha Tovuti Zote ---**: Anzisha au simamisha vipeperushi vyote kwenye kundi lako kwa mpigo mmoja.
- **Hali ya Wakati Halisi**: Angalia URL za .onion zinazofanya kazi na viashiria vya maendeleo ya kuanza kwa Tor.
- **Udhibiti wa Kibinafsi**: Hamisha kama Zip tovuti maalum kwenye ZIP au uzifute.
## Uakisi wa Ulimwengu (Usambazaji wa Virusi)
Ili kuhakikisha VoxVera inaendelea kupatikana hata kama hifadhi kuu zitadhibitiwa, kila kipeperushi hufanya kazi kama kioo cha zana hiyo.
Unapohifadhi kipeperushi, kitufe cha **"Pakua Zana na Chanzo"** kwenye ukurasa wa kutua hutoa `voxvera-portable.zip` iliyo na:
- Chanzo kamili na lugha zote zinazotumika.
- Vitegemezi vyote vya Python (vilivyowekwa mapema).
- Programu za Tor za mifumo mbalimbali.
Hii inaruhusu kila mtu anayekagua kipeperushi chako kuwa msambazaji mpya wa zana ya VoxVera.
## Hamisha na Hifadhi Nakala
Hifadhi nakala za utambulisho wako wa kipekee wa Tor (ili URL yako ya .onion isibadilike kamwe) au hamisha vipeperushi vyako kwenye mashine nyingine.
- **Hamisha tovuti moja**: `voxvera export <jina_la_folda>`
- **Hamisha tovuti zote**: `voxvera export-all`
**Mahali pa kuhifadhi:** Hamisho zote zinahifadhiwa kwenye `~/voxvera-exports/` kwenye mifumo yote.
## Ingiza na Rejesha
Rejesha usanidi wako wote kwenye mashine mpya kwa kuhamisha faili zako za ZIP kwenda `~/voxvera-exports/` na uendeshe:
```bash
voxvera import-multiple
```
## Uwezo wa Kubebeka na Matumizi ya Nje ya Mtandao
Ikiwa unahitaji kuendesha VoxVera kwenye mashine isiyo na ufikiaji wa mtandao, unaweza kupakua vitegemezi kwanza:
```bash
voxvera vendorize
```
Hii inapakua maktaba zote za Python zinazohitajika kwenye `voxvera/vendor/`. Kisha zana itatoa kipaumbele kwa faili hizi za kienyeji, ikiruhusu iendeshe bila `pip install`.
## Ingiza kwa Wingi (JSON)
Ili kuzalisha vipeperushi kwa wingi kutoka kwa faili nyingi za usanidi wa JSON, ziweke kwenye folda ya `imports/` na uendeshe:
```bash
voxvera batch-import
```
## Jinsi URL Zinavyofanya Kazi
Kila kipeperushi kina URL mbili tofauti:
- **Kiungo cha kutolewa** (kinachozalishwa kiotomatiki): Anwani ya .onion ambapo kipeperushi kinahifadhiwa.
- **Kiungo cha maudhui** (kilichosanidiwa na mtumiaji): URL ya nje inayoelekeza kwenye tovuti, video, au upakuaji.
Huna haja ya kuingiza anwani ya .onion kwa mikono; VoxVera inashughulikia hili kiotomatiki wakati wa awamu ya `serve`.
-42
View File
@@ -1,42 +0,0 @@
# AI Agent Instructions for VoxVera
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
## Core Mandates
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
## Localization Protocol
When adding a new language or updating an existing one:
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
- **Landing Page**:
- Directly update the `const locales` object in `site/index.html`.
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
- **Documentation**:
- Master templates live in `docs/templates/`.
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
## Universal Mirroring
VoxVera propagates through its own flyers.
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
## Verification Checklist
Before finishing a task, ensure you have:
1. Run unit tests: `pytest tests/test_cli.py`.
2. Verified the localization: `voxvera --lang {lang} check`.
3. Rebuilt the documentation: `voxvera build-docs`.
4. Synchronized the public site: `voxvera build-site`.
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
---
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
-45
View File
@@ -1,45 +0,0 @@
# Contributing to VoxVera
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
## Adding a New Language
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
### 1. The Token File
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
- Use `en.json` as your master template.
- **`meta`**: Include the native language name and a flag emoji.
- **`cli`**: Translate all strings used in the terminal interface.
- **`web`**: Translate strings used on the generated landing pages and flyers.
- **`landing`**: Translate the specific content for the official VoxVera website.
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
### 2. The Landing Page
The main landing page (`site/index.html`) must be synchronized to include your new language.
- Open `site/index.html` and add your language to the `const locales` object in the `<script>` tag.
- Run `voxvera build-site` to refresh the public assets and ensure the pre-rendered HTML matches your new locale.
### 3. Documentation
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
- Use the templates in `docs/templates/` as your guide.
- You can use `{{t('cli.token_name')}}` to reference terminal commands automatically.
### 4. Build and Verify
Run the following commands to verify your changes:
- `voxvera --lang {lang_code} check` (Verify CLI translation)
- `voxvera build-docs` (Generate localized manuals)
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
- Open `site/index.html` in a browser and test the language switcher.
## Code Contributions
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
- **Style**: Follow the existing coding style (PEP 8 for Python).
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
---
Together, we can ensure that truth remains accessible to everyone, everywhere.
-16
View File
@@ -1,16 +0,0 @@
# Docker Usage
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
`ghcr.io/voxvera/voxvera`.
```bash
# pull the image
docker pull ghcr.io/voxvera/voxvera:latest
# run voxvera quickstart with flyers stored in ./flyers
mkdir -p flyers
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
```
The container uses `/flyers` as the working directory and runs `voxvera quickstart`
by default. All generated flyer files will appear in the mounted `flyers` folder.
-14
View File
@@ -1,14 +0,0 @@
# Flyer Templates
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
```bash
voxvera init --template <name>
```
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
Available templates:
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
- **voxvera** – example flyer showcasing the VoxVera project.
-60
View File
@@ -1,60 +0,0 @@
# Troubleshooting
This page collects common issues encountered when hosting or accessing flyers.
## Tor connectivity
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
## Tor port detection
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
```bash
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
```
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
## Firewall rules
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
- Corporate or university firewalls can block the hidden service ports required by Tor.
## SELinux
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
## OnionShare crashes
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
`host/<folder_name>/onionshare.log` for details. Common causes:
- Tor is not running (`sudo systemctl start tor`)
- A port conflict with another service
- Missing `onionshare-cli` (run `voxvera check`)
## Onion URL changed unexpectedly
The onion URL is tied to the Ed25519 keypair stored in
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
keypair (and URL) will be generated on the next `voxvera serve`. The
`voxvera import` command preserves this file automatically, but manual
deletion of the `host/` directory will destroy it.
## QR codes not generated
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
## Electron GUI
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
## Missing dependencies
Run `voxvera check` to verify your setup. The command checks for required
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
external tools (`onionshare-cli`), then prints a summary of anything
missing. To install everything:
```bash
# Recommended: use the install script (handles Tor + OnionShare too)
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
# Or reinstall just the Python package
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
```
-138
View File
@@ -1,138 +0,0 @@
# Detailed Usage
This guide covers common CLI workflows. See `docs/docker.md` for Docker instructions and `docs/templates.md` for available flyer templates.
## Prerequisites
VoxVera is designed to be highly portable. You can run it directly from the source code on any platform with Python installed.
### 1. Automated Install (Recommended)
The easiest way to install VoxVera is using our cross-platform installer script:
**Linux / macOS:**
```bash
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
```
**Windows (PowerShell):**
```powershell
irm https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.ps1 | iex
```
### 2. Manual Source Install
If you have downloaded the source code ZIP:
1. **Extract** the ZIP file.
2. **Open a terminal** in the extracted folder.
3. **Run the setup script**:
- **Linux/macOS:** `./setup.sh`
- **Windows:** `.\voxvera-install.sh` (or run `python -m pip install .`)
## Uninstallation
If you wish to remove VoxVera from your system, you can use the provided uninstall scripts from the source directory. This will safely remove the CLI tool and any downloaded dependencies.
- **Linux / macOS:** Run `./uninstall.sh`
- **Windows (PowerShell):** Run `.\uninstall.ps1`
*Note: Uninstallation will not delete your generated flyers or your `.onion` keys stored in the `~/voxvera-exports` or local `host/` folders.*
## Step-by-Step
1. **Initialize:** Run `voxvera init` and follow the prompts. You will be asked to select your language first.
2. **Build:** Generate the flyer assets. Every build automatically creates a `voxvera-portable.zip` in the flyer's folder, allowing others to download the full tool directly from your flyer.
```bash
voxvera build
```
3. **Serve:** Publish the flyer over Tor:
```bash
voxvera serve
```
This automatically detects your Tor instance, starts OnionShare, and writes the generated .onion address into the flyer's tear-off links.
## Language Support
VoxVera is fully localized. You can change your language preference permanently using either the interactive selector or a direct shortcut:
- **Interactive Selector:** `voxvera lang`
- **Direct Shortcut:** `voxvera --lang de` (sets preference to German)
### Supported Languages:
- **English:** `en`
- **Spanish:** `es` (alias: `--idioma`)
- **German:** `de` (alias: `--sprache`)
You can also force a specific language for a single command without changing your permanent preference:
- **English:** `voxvera --lang en check`
- **German:** `voxvera --sprache de check`
- **Spanish:** `voxvera --idioma es check`
The generated flyers automatically detect the visitor's browser language and switch the UI text accordingly.
## Server Management
Manage multiple flyers and their Tor identities from a single interactive menu:
```bash
voxvera manage
```
Features:
- **{{t('cli.manage_create_new')}}**: Start the full setup sequence.
- **{{t('cli.manage_start_all')}}**: Launch or shut down every flyer in your fleet at once.
- **Real-time Status**: View active `.onion` URLs and Tor bootstrapping progress indicators.
- **Individual Control**: {{t('cli.manage_action_export')}} specific sites to ZIP or delete them.
## Universal Mirroring (Viral Distribution)
To ensure VoxVera remains accessible even if central repositories are censored, every flyer acts as a mirror for the tool.
When you host a flyer, the **"{{t('web.download_button')}}"** button on the landing page provides a `voxvera-source.zip` containing:
- The full source code and all supported languages.
- Installation and setup scripts for all platforms.
- Complete documentation and templates.
This allows anyone who scans your flyer to become a new distributor of the VoxVera tool.
## Export & Backup
Back up your unique Tor identities (so your `.onion` URL never changes) or move your flyers to another machine.
- **Export a single site**: `voxvera export <folder_name>`
- **Export all sites**: `voxvera export-all`
**Storage location:** All exports are saved to `~/voxvera-exports/` on all platforms.
## Import & Recovery
Restore your entire setup on a new machine by moving your ZIP files to `~/voxvera-exports/` and running:
```bash
voxvera import-multiple
```
## Portability & Offline Use
If you need to run VoxVera on a machine without internet access, you can "vendorize" the dependencies first:
```bash
voxvera vendorize
```
This downloads all required Python libraries into `voxvera/vendor/`. The tool will then prioritize these local files, allowing it to run without `pip install`.
## Batch Import (JSON)
To bulk-generate flyers from multiple JSON configuration files, place them in the `imports/` directory and run:
```bash
voxvera batch-import
```
## How URLs Work
Each flyer has two separate URLs:
- **Tear-off link** (auto-generated): The .onion address where the flyer is hosted.
- **Content link** (user-configured): An external URL pointing to a website, video, or download.
You do not need to manually enter the .onion address; VoxVera handles this automatically during the `serve` phase.
Loaded 100 of 3021 files, more files were not shown because too many files have changed in this diff. Show more