WashingMachineDormitory
README.md
Laundry Status Web
A simple web app for a dorm: it shows whether the washing machine is in use or not, and until what time.
What it does
- Displays the current status: free/occupied.
- Shows which room is using the machine.
- Shows the time until the machine is no longer in use.
- Displays a countdown.
- Allows you to quickly reserve a machine for 30/45/60/90 minutes.
- Allows you to specify your own duration in minutes.
- Suggests a list of rooms based on your history.
- Prompts for a PIN in a dialog box after you tap an action.
- Prevents rebooking if the machine is already booked.
- Allows you to manually release a machine.
- Protects status changes with a PIN code.
- Keeps a history of completed wash cycles.
Technologies
- Node.js + Express
- Pure HTML/CSS/JavaScript (no framework)
- Status and history stored in JSON files (
data/status.json,data/history.json)
Variables and files
STATUS_PIN- PIN code for changing status (it is recommended to set it via.envor environment variables)TELEGRAM_BOT_TOKEN- Telegram bot token (optional, for notifications)TELEGRAM_CHAT_ID- Group chat/channel ID for notificationsTELEGRAM_API_BASE_URL- Telegram API base URL (defaulthttps://api.telegram.org)config.json- Local fallback for the PIN; do not store it in Gitdata/status.json,data/history.json- application runtime data—do not store it in Git
If config.json it happens to be created as a directory, you can skip using it entirely and set the PIN only via STATUS_PIN.
Running locally
- Install dependencies:
npm install
- Start the server:
npm start
Default PIN: 1234. The recommended way to change it is via the environment variable STATUS_PIN.
- Open in a browser:
http://localhost:3000
Run on the server
- Copy the project to the server.
- Install Node.js 18+.
- Run:
npm install
STATUS_PIN=myStrongPin PORT=3000 npm start
If you're using Nginx/Caddy, configure the reverse proxy to port 3000.
Full installation on a clean Ubuntu server
Below is the procedure using Docker Compose (recommended).
0) DNS Setup
- For the domain (for example,
wash.example.com) addAA A record pointing to the server’s IP address. - Wait for the DNS to update.
1) Update the system
sudo apt update && sudo apt upgrade -y
2) Install Docker and the Docker Compose plugin
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER
Log out (or newgrp docker), then check:
docker --version
docker compose version
3) Copy the project to the server
Option via Git:
git clone <URL_ВАШЕГО_РЕПО> laundry-status-web
cd laundry-status-web
Or download the archive and navigate to the project folder.
4) Set up the environment and start the container
cp .env.example .env
Open .env and set a complex PIN:
STATUS_PIN=очень_сложный_pin
Start:
docker compose up -d --build
Verification:
docker compose ps
docker compose logs -f
5) Install Nginx
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
6) Configure a reverse proxy for the domain
Create a file:
sudo nano /etc/nginx/sites-available/laundry-status
Content:
server {
listen 80;
server_name wash.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Enable:
sudo ln -s /etc/nginx/sites-available/laundry-status /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
7) Enable HTTPS (Let's Encrypt)
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d wash.example.com
Check for automatic certificate renewal:
sudo systemctl status certbot.timer
8) Open a port in the firewall (if UFW is enabled)
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status
9) Update the application
cd laundry-status-web
git pull
docker compose up -d --build
10) Useful diagnostics
docker compose ps
docker compose logs -f
sudo nginx -t
sudo journalctl -u nginx -f
Docker Compose
- Copy the example env file:
cp .env.example .env
- If necessary, change the PIN in
.env:
STATUS_PIN=твой_pin
For Telegram notifications, add the following to .env:
TELEGRAM_BOT_TOKEN=123456789:ABCDEF...
TELEGRAM_CHAT_ID=-1001234567890
TELEGRAM_API_BASE_URL=https://api.telegram.org
If Telegram is only accessible on the server through your proxy (for example, via x-ui), set TELEGRAM_API_BASE_URL to this proxy URL.
- Run it via Docker Compose:
docker compose up -d --build
- Open in a browser:
http://localhost:3000
API
GET /api/status- Get statusGET /api/history?limit=20- Get wash historyGET /api/rooms?limit=40- Get a list of rooms for hintsPOST /api/status/occupy- Reserve a machine- body:
{ "minutes": 60, "occupiedRoom": "417", "pin": "1234" } occupiedRoom: up to 16 characters, at least 1 digit; letters, digits, and-/_//- if the machine is occupied:
409 Conflict
- body:
POST /api/status/release- free up the machine- body:
{ "pin": "1234" }
- body:
History is stored in data/history.json, current status in data/status.json.
Telegram bot: notifications in the group chat
The app can send notifications about changes to the machine's status via Telegram.
What is sent
- When the machine is occupied (
occupied) - When the machine is manually released (
released) - When the machine is automatically released by a timer
How to set it up
- Create a bot via
@BotFatherand get a token. - Add the bot to your group chat (group or channel).
- Grant the bot permission to send messages (for a channel, add it as an administrator).
- Find out
chat_id:- send any message to the chat,
- open it in your browser
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates, - find
chat.id.
- Write down
TELEGRAM_BOT_TOKENandTELEGRAM_CHAT_IDin.env.- If you're using Telegram proxying via x-ui/your gateway, set
TELEGRAM_API_BASE_URL.
- If you're using Telegram proxying via x-ui/your gateway, set
- Restart the service:
docker compose up -d --force-recreate
If TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID are not set, notifications are disabled.
For the x-ui/Telegram API proxy:
- Specify, for example,
TELEGRAM_API_BASE_URL=https://your-domain.example/telegram. - The server must proxy the path
/bot<TOKEN>/sendMessageto the Telegram Bot API.
Releases
No releases yet.
Open issues
No open issues 🎉