{"id":47338485,"url":"https://github.com/rafaelurben/tamtour-voting","last_synced_at":"2026-03-17T22:22:12.223Z","repository":{"id":315012548,"uuid":"1021481132","full_name":"rafaelurben/tamtour-voting","owner":"rafaelurben","description":"Publikumsvoting für die TamTour Basel","archived":false,"fork":false,"pushed_at":"2025-10-13T16:04:05.000Z","size":6889,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-19T21:00:02.550Z","etag":null,"topics":["tamtour","voting","voting-system"],"latest_commit_sha":null,"homepage":"https://voting.tamtour.ch","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rafaelurben.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"rafaelurben","patreon":"rafaelurben","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2025-07-17T13:10:50.000Z","updated_at":"2025-10-13T16:04:09.000Z","dependencies_parsed_at":"2025-09-16T07:59:48.833Z","dependency_job_id":"6c62d669-e196-4dfc-9996-148d9bc12b59","html_url":"https://github.com/rafaelurben/tamtour-voting","commit_stats":null,"previous_names":["rafaelurben/tamtour-voting"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rafaelurben/tamtour-voting","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelurben%2Ftamtour-voting","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelurben%2Ftamtour-voting/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelurben%2Ftamtour-voting/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelurben%2Ftamtour-voting/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rafaelurben","download_url":"https://codeload.github.com/rafaelurben/tamtour-voting/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelurben%2Ftamtour-voting/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30633245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T17:32:55.572Z","status":"ssl_error","status_checked_at":"2026-03-17T17:32:38.732Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["tamtour","voting","voting-system"],"created_at":"2026-03-17T22:22:11.529Z","updated_at":"2026-03-17T22:22:12.216Z","avatar_url":"https://github.com/rafaelurben.png","language":"Java","funding_links":["https://github.com/sponsors/rafaelurben","https://patreon.com/rafaelurben"],"categories":[],"sub_categories":[],"readme":"# tamtour-voting\n\nThis repository contains the code for the public voting system used at the \"TamTour Trophy Basel 2025\" event.\nDetails about the event can be found at [tamtour.ch](https://tamtour.ch).\n\n\u003e [!IMPORTANT]  \n\u003e This project is no longer in active development because the TamTour Trophy ended.\n\u003e See [retrospective](#retrospective) for my thoughts about this project.\n\n## Repository Structure\n\n- `.github/`: Contains GitHub Actions workflows for CI.\n- `env/`: Contains environment configuration file templates for Docker Compose and/or IDE setup.\n- `voting-frontend/`: Contains an **Angular frontend application** for user interaction.\n    - Also includes the static **result viewer** that can be displayed on a big screen to show voting results.\n- `voting-backend/`: Contains a **Spring Boot backend application** that handles authentication, voting logic and data\n  storage.\n- `docker-compose-local-db.yml`: Docker Compose file to run a local database for development purposes.\n- `docker-compose-local-full.yml`: Docker Compose file to run the full application stack locally.\n- `docker-compose-preview.yml`: Docker Compose file for deploying a preview instance, e.g. via Coolify.\n\n## Features\n\n- Login via Google OAuth2\n- Rules acceptance\n- Multiple voting categories\n- Simple voting interface with drag-and-drop functionality to rank candidates\n- Time window for voting and submissions\n- Admin interface:\n    - List and block/unblock users\n    - Create, edit and delete categories and candidates\n    - View submitted votes\n    - Disqualify and unsubmit/submit valid votes\n    - Control the result viewer\n- Result-viewer for displaying results on a big screen, controlled from the admin interface via WebSockets.\n- Dockerized for easy deployment\n\nUsers can create their voting order during the voting period and submission period. During the submission period, users\ncan submit their votes. After the submission period ends or after a vote is submitted, no further changes are possible.\nResults are not made public until the voting ends. The viewer does not support real-time updates during the voting period.\n\nTimeline: Voting period opens → Submission period opens → Submission \u0026 voting period ends\n\n## Architecture notes\n\nLocally, the backend requests are proxied though the Angular development server, which is configured in\n`voting-frontend/proxy.conf.json`.\nIn production, the backend requests are proxied through Nginx, which also serves the frontend and which is configured in\n`voting-frontend/nginx.conf`.\n\n## Retrospective\n\nThe goal of this project was to create a public voting system for a specific event, the TamTour Trophy Basel 2025. I\nwanted it to be as simple as possible with all necessary features, but without any unnecessary complexity. Overall, I am\nsatisfied with the outcome. The system worked well during the event, and users were able to vote without\nany issues.\n\n### What went well\n\n- Easy hosting and deployment using Docker and Docker Compose.\n- The Angular frontend provided a smooth user experience.\n- The Spring Boot backend was robust and handled the voting logic effectively.\n- The use of Google OAuth2 for authentication simplified user management.\n- Low resource consumption.\n\n### What could be improved\n\n- Currently, the viewer requires an internet connection to stay connected with the WebSocket. A local fallback mechanism\n  would be beneficial in case of network issues.\n- The login via Google was implemented a bit hacky due to the setup with an Angular frontend and Spring Boot backend. A\n  more elegant solution would be preferable, maybe using tools like Keycloak, Better-Auth, Auth0 or Clerk.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaelurben%2Ftamtour-voting","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frafaelurben%2Ftamtour-voting","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaelurben%2Ftamtour-voting/lists"}