vocdoni-app

September 16, 2026 · View on GitHub

Vocdoni logo

Vocdoni is the first universally verifiable, censorship-resistant, anonymous, and self-sovereign governance protocol.
Our main aim is a trustless voting system where anyone can speak their voice and where everything is auditable.
We are engineering building blocks for a permissionless, private and censorship resistant democracy.
Explore the developer portal »

More About Us

Vocdoni Website | Web Application | Blockchain Explorer | MIT Law Publication | Contact Us

Key Repositories

Vocdoni App | Vocdoni Node | Vocdoni Integrator SDK

vocdoni-app

Vocdoni App is a React application that uses the Vocdoni Integrator SDK (including its react-components and react-providers packages) to provide a user interface for the Vocdoni voting protocol. It is built with Vite and Vike, and is deployed at https://app.vocdoni.io/.

Table of Contents

Getting Started

Rendering Architecture

The app now uses a mixed rendering model:

  • Vike handles SSR for the public pages:
    • /organization/:address
    • /processes/:id
  • The rest of the application remains client-rendered and is served through the SPA catch-all page:
    • /
    • auth and login routes
    • dashboard and backoffice routes
    • all other existing SPA routes

This keeps the migration incremental:

  • public organization and process pages get server-rendered HTML and SEO metadata
  • the existing React Router application remains the source of truth for the rest of the app
  • Vike sits on top of the current Vite app instead of replacing the SPA router entirely

Relevant entry points:

  • src/pages/organization/@address/ for the SSR organization page
  • src/pages/processes/@id/ for the SSR process page
  • src/pages/home-process/ for the SSR single-process homepage (only when HOME_PROCESS_ID is set)
  • src/pages/@catchAll/ for the SPA catch-all page
  • src/router/ for the client-side React Router application

Environment variables

You can create a .env.local file to set your custom environment variables there, here's a list of variables you can use:

  • VOCDONI_ENVIRONMENT: the vocdoni environment to be used, either dev or prod (defaults to dev).
  • BASE_URL is used to specify the public base page during build.
  • BUILD_PATH Specifies the destination of built files.
  • CUSTOM_ORGANIZATION_DOMAINS A JSON.stringified object of custom domains mapped to organization ids, to replace the homepage with their profile page.
  • HOME_PROCESS_ID a single process id that turns the app root into that process' voting page — the same view served at /<lang>/processes/<id>, server-rendered by Vike. Both / and every localized root (/en, /es, …) render it, and its <title>, description, canonical URL, hreflang alternates and structured data all describe that process, with the roots as its canonical URLs. Unset, the root keeps behaving exactly as before. It is read at runtime, so a single build/image can be pointed at a process with docker run -e HOME_PROCESS_ID=....
  • PRIMARY_COLOR the accent color of the app as a #rgb or #rrggbb hex value (e.g. #1a73e8). A full palette (tints, shades, text and focus-ring colors) is generated from it and applied to buttons, form controls, tabs and highlights in both color modes. Filled surfaces use the exact color wherever it reads at 3:1 against the page background and the closest readable shade otherwise (a very dark color in dark mode, a very pale one in light mode). Unset, the app keeps its stock black accent. It is read at runtime, so a single build/image can be recolored with docker run -e PRIMARY_COLOR=....
  • SHOW_ORG_LOGO set it to true to brand the header of process pages with the logo of the organization that created the process, instead of the Vocdoni logo. It applies to the public voting page (/<lang>/processes/<id>), its summary (/<lang>/processes/<id>/summary) and the HOME_PROCESS_ID root, which render that logo server-side — there is no client-side swap. Pages with no process behind them (the dashboard, auth, pricing…) keep the Vocdoni logo, and so does an organization that has no logo set or whose logo URL fails to load. Only the header is affected: the footer logo is always Vocdoni. It is read at runtime, so a single build/image can be branded with docker run -e SHOW_ORG_LOGO=true.

You can also start the app by prefixing these vars instead of defining your custom .env file:

VOCDONI_ENVIRONMENT=dev pnpm start
# or an example using many of them...
BUILD_PATH=build/dev BASE_URL=/vocdoni-app/dev VOCDONI_ENVIRONMENT=dev pnpm build

Custom domain names

The custom domain names environment variable allows to map custom domains to organization ids, so that the homepage rendered will be the mapped organization profile.

CUSTOM_ORGANIZATION_DOMAINS='{"deadcorp.com":"0x000000000000000000000000000000000000dead"}' pnpm build

With the example above, accessing the app via the deadcorp.com domain would render the profile of the organization with id 0x000000000000000000000000000000000000dead as the homepage of the app.

SharedCensus configuration

The SharedCensus page uses the following env vars to drive its UI:

  • PROCESS_IDS: comma-separated election IDs to display.
  • SHARED_CENSUS_ALWAYS_VISIBLE_TEXT: JSON object mapping language codes to markdown (e.g. {"en":"...", "es":"..."}) rendered via the read-only Editor. Must include the default language (first entry from LANGUAGES, default en), otherwise the build fails. Always shown at the top of the SharedCensus page.
  • SHARED_CENSUS_DISCONNECTED_TEXT: JSON object mapping language codes to markdown, shown only when the user is not connected/admin. Must include the default language if set, or the build fails.
  • SHARED_CENSUS_CONNECTED_TEXT: JSON object mapping language codes to markdown, shown only when the user is connected or an admin. Must include the default language if set, or the build fails.
  • STREAM_URL: single http(s) URL for an embeddable stream (e.g. YouTube). Validated at build time. When the session starts (connected or admin), it renders in a 16:9 player floated right so text flows around it. If only the stream is provided, it renders alone.

When neither pretext nor stream is configured, no top content is shown. When only pretext exists, it remains single-column. After sign-in, the stream (if set) appears as the second column, displacing the pretext to the left.

Available Scripts

In the project directory, you can run:

pnpm start

Runs the app in development mode with Vike + Vite.
Open http://localhost:5173 to view it in the browser (note the port may change if already used).

pnpm build

Builds the app for production to the dist folder.
The output now includes both the client bundle and the Vike SSR server bundle:

  • dist/client for browser assets
  • dist/server for the SSR entry and page server bundles

pnpm translations

Extracts all i18n strings from the code and puts them in the i18n/locales json files. The best way to work with translations is:

Branching and deploys

Three branches are linked to deploys:

  • GitHub Actions Workflow Status linked to SaaS api-dev and vochain dev.
  • GitHub Actions Workflow Status linked to SaaS api-stg and vochain LTS.
  • GitHub Actions Workflow Status linked to SaaS api-lts and vochain LTS.

Pushes and pull requests to develop and stage are validated by the GitHub Actions test workflow, which runs lint, test, and env-specific production builds.

The common flow to follow when deploying to main is passing through all the other stages:

branch from develop => merge to develop => merge to stage => merge to main

The only exception should be when fixing specific versions to a deployment, in such case, a hotfix should be created from the desired branch to be updated:

branch from stage (i.e. h/sdk-0.4.1) => PR to stage
branch from main (i.e. h/sdk-0.5.0) => PR to main

Contributing

While we welcome contributions from the community, we do not track all of our issues on Github and we may not have the resources to onboard developers and review complex pull requests. That being said, there are multiple ways you can get involved with the project.

Please review our development guidelines.

Contributions and pull requests

To avoid unnecessary review overhead, pull requests that only fix typos, whitespace, punctuation, or other minor changes without functional impact or clear added value will not be accepted. If you want to correct such issues, please open an issue first. If the change is considered necessary, it may be accepted as a dedicated pull request that groups those corrections together. Accepted contributions must provide a clear benefit, whether through functional improvements, meaningful documentation updates, or the implementation of a feature or bug fix. Minor changes should be made with consideration and strong justification to avoid unnecessary distractions for reviewers.

License License: BSL 1.1

This repository is licensed under the Business Source License 1.1.

Copyright © 2025 Vocdoni.