# BOU 2026 — Best Project voting app A small self-hosted voting app for the 7 BOU 2026 projects. Every vote is written as a row (Name, UID, Email, Project, Timestamp) into an Excel file on the server — no external database needed. ## What's included - `server.js` — Node/Express backend. Handles voting and keeps `data/votes.xlsx` up to date. - `public/index.html` — the page voters use. - `public/admin.html` — organizer-only results page (tallies + Excel download), protected by an admin key. - `data/votes.xlsx` — created automatically on the first vote. **Not included** — don't commit it, it contains personal data (names/UIDs/emails). ## Requirements This needs a **Node.js host with persistent disk storage** — it writes to a real file, so it won't work on static hosting (GitHub Pages, S3, etc.) or on serverless platforms whose filesystem resets between requests (e.g. Vercel/Netlify functions). It runs fine on a VPS, an internal company server, Render/Railway "web service" (not "static site"), or any machine you control. Node.js 18+ is recommended. ## Setup ```bash npm install ADMIN_KEY="pick-a-real-secret" npm start ``` The app listens on port 3000 by default (override with `PORT=xxxx`). - Voters go to: `http://your-host:3000/` - You (organizer) go to: `http://your-host:3000/admin.html` and enter the `ADMIN_KEY` you set above to see live results and download the Excel file. **Set a real `ADMIN_KEY`** before sharing the link with anyone — anyone who knows the key can see all voters' names/UIDs/emails and the current tally. Without it set, the server starts with a placeholder key and prints a warning. ## How voting works - A voter fills in Name, UID, and Email, then picks one project and submits. - Votes are matched by UID: if the same UID votes again, their row is **updated** (their vote changes) rather than duplicated — so one person can't stack votes. - Writes are queued in the server so two people voting at the same instant can't corrupt the Excel file. ## Changing the project list Edit the `PROJECTS` array near the top of `server.js` (and nowhere else — the voting page loads the list from the server automatically). ## Privacy note The Excel file holds personal data (name, UID, email) for every voter. Store it somewhere access-controlled, delete it once the vote is over if you don't need to retain it, and don't commit it to a public repo.