Skip to main content

Prerequisites

Before you begin, ensure you have:
  • Node.js 22 or later installed (download here)
  • Yarn package manager (npm i yarn -g)
  • Basic familiarity with the command line
Prefer not to install anything locally? Use GitHub Codespaces to run Consensus entirely in your browser.

Installation and setup

1

Clone and install dependencies

git clone <repository-url>
cd consensus-voting-system
yarn install
2

Build the project

Compile TypeScript source code to JavaScript:
yarn build
3

Seed the database

Populate the database with sample elections, voters, and admin accounts:
yarn db:seed
This creates sample data including:
4

Start the server

Launch the Consensus application:
yarn start
The server will start at http://localhost:3000. You’ll see system data printed to the console:
Consensus E-Voting System running on http://0.0.0.0:3000

=== System Data ===

Admins (1):
  - admin (System Administrator)

Voters (2):
  - Alice Johnson ([email protected]) [APPROVED]
  - Bob Smith ([email protected]) [APPROVED]

Elections (3):
  - Local Council Election 2024 [FPTP] - Status: ACTIVE
  - University Student Union President [STV] - Status: ACTIVE
  - Sports Club Captain Election [AV] - Status: ACTIVE

Casting your first vote

Now that Consensus is running, let’s walk through the voter experience.
1

Register or log in as a voter

Navigate to http://localhost:3000 in your browser.You can either:
  • Register a new account: Click “Register” and fill out the form
  • Use a seeded account: Click “Login” and use:
New registrations require admin approval by default. Use seeded accounts for immediate access, or enable auto-approval in admin settings.
2

View available elections

After logging in, you’ll be redirected to the voter dashboard at /dashboard.The dashboard shows:
  • Your voter registration status
  • Elections available for voting
  • Your recent voting history
Click on any active election to proceed to voting.
3

Cast your vote

The voting interface adapts to the election type:For FPTP elections (First Past The Post):
  • Select one candidate by clicking their radio button
  • Click “Cast Vote”
For STV/AV elections (ranked voting):
  • Drag and drop candidates to rank them in order of preference
  • Your first choice goes at the top
  • Click “Cast Vote” when your ranking is complete
if (election.electionType === ElectionType.FPTP) {
    // FPTP: single candidate selection
    dto.candidateID = body.candidateID;
}
4

Receive your confirmation

After successfully casting your vote, you’ll receive:
  • A unique confirmation code (e.g., CONS-ABC123-XYZ789)
  • The timestamp of your vote
  • Option to print a receipt for your records
Your vote is anonymous and cannot be changed once submitted. The confirmation code proves you voted but does not reveal your choice.
You can view all your confirmations at /confirmations.

Exploring admin features

To explore election management and administration:
1

Log in as admin

Log out if you’re logged in as a voter, then navigate to /admin.Use the seeded admin credentials:
  • Username: admin
  • Password: admin123
On first login, you’ll be prompted to change the default password.
2

Access the admin dashboard

The admin dashboard at /admin/dashboard provides:
  • Overview of all elections and their statuses
  • Voter registration management
  • System statistics (total voters, active elections, votes cast)
  • Quick actions for election management
3

Create a new election

Click “Create Election” and fill out:
  • Name: e.g., “Department Representative Election”
  • Type: Choose FPTP, STV, or AV
  • Start/End Dates: Set the voting period
  • Description: Election details for voters
After creating the election, add candidates with:
  • Name
  • Party/affiliation
  • Biography
4

Manage voters

In the Voters section, you can:
  • Approve or reject pending registrations
  • View all registered voters
  • Manually create voter accounts
  • Remove voters if needed
public registerVoter(dto: VoterRegistrationDTO, autoApprove = false): Voter {
    // Check if email already exists
    const existing = this.voterRepository.findByEmail(dto.email);
    if (existing) {
        throw new Error("A voter with this email already exists");
    }

    const status = autoApprove ? RegistrationStatus.APPROVED : RegistrationStatus.PENDING;
    const voter = new Voter(randomUUID(), dto.name, dto.email, dto.password, status, new Date());
    
    this.voterRepository.save(voter);
    return voter;
}
5

View election results

Once an election ends or is closed manually:
  • Navigate to the election details page
  • Click “Calculate Results”
  • View winner(s) and detailed vote breakdowns
Results are calculated using the appropriate algorithm based on election type:
  • FPTP: Simple majority
  • STV: Quota-based proportional representation
  • AV: Instant runoff with preference transfers

Development mode

For development with hot-reloading:
yarn dev
This watches for file changes and automatically rebuilds and restarts the server.

Running tests

yarn test

What’s next?

Installation Guide

Learn about Docker deployment and production setup

Architecture Overview

Understand the system design and patterns

Troubleshooting

Change the port in src/config.ts or set the PORT environment variable:
PORT=8080 yarn start
Reset and reseed the database:
yarn db:reset
yarn db:seed
This will delete all existing data.
Either:
  • Wait for an admin to approve your registration
  • Ask an admin to enable auto-approval in system settings
  • Use a pre-seeded voter account from yarn db:seed

Build docs developers (and LLMs) love