尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗A small, dependency-free web app that guides you through brushing your teeth zone by zone.
Brushing order: upper right → upper left, then lower left → lower right.
git clone https://github.com/norbsmaq/toothbrush-timer /opt/toothbrush-timer
cd /opt/toothbrush-timer
sudo ./setup-droplet.sh
The script asks for your domain name(s) and whether to enable HSTS (see below). Then it installs Docker if needed, opens ports 80 and 443 if ufw is active, turns on automatic updates, installs GoAccess for visitor stats, and starts the app. It finishes by printing the address to open.The container restarts automatically after reboots (restart: unless-stopped).
Point a DNS A record for each domain at the droplet's IP. For example, add records for both example.com and www.example.com. Then enter the domains when setup-droplet.sh asks, separated by spaces or commas:
Domains [none]: example.com www.example.com
The script warns you if a domain doesn't point at the droplet yet. Caddy gets and renews a Let's Encrypt certificate for each domain automatically, and serves the app on all of them. HTTPS is needed for the browser's keep-screen-awake feature and for installing the app on your phone. Everything else works over plain HTTP.
If you list both a domain and its www. version, the script also offers to redirect www.example.com to example.com (keeping the rest of the address). That way everyone ends up on one address, so an installed app and its saved settings always use the same one.
To change domains later, run sudo ./setup-droplet.sh again. It shows your current settings as defaults, so press Enter to keep any of them. Or edit .env directly (SITE_ADDRESS="example.com, www.example.com", REDIRECT_WWW=true) and run docker compose up -d.
By default the site sends an HSTS header. It tells browsers to always use HTTPS for your domain for the next year. Browsers ignore it over plain HTTP or an IP address, so it does no harm there.
If you're using a domain but might switch it back to plain HTTP later, answer n when the setup script asks about HSTS. Or set ENABLE_HSTS=false in .env and run docker compose up -d. Turning it off doesn't undo HSTS in browsers that have already received it; they keep it until it expires.
setup-droplet.sh turns on three kinds of automatic updates:
| What | How | When |
|---|---|---|
| Ubuntu security updates | unattended-upgrades | Daily. If an update needs a reboot, the droplet reboots at 04:00 and the app starts back up on its own. |
| Docker Engine | unattended-upgrades, from Docker's apt repository | Daily, along with the OS updates |
| The app and its Caddy web server | toothbrush-timer-update.timer runs update.sh | Daily around 03:30 |
update.sh makes the server's copy match the main branch on GitHub exactly, rebuilds on the newest Caddy image, restarts the container and removes old images. Anything pushed to main goes live on the next run. Any edits made directly to the repo's files on the server are overwritten. Your .env settings aren't part of the repo, so they're kept.
To update right away, run sudo ./update.sh. To see when the update last ran and when it runs next:
systemctl list-timers toothbrush-timer-update.timer
journalctl -u toothbrush-timer-update.service -n 50
To turn off the app auto-update: sudo systemctl disable --now toothbrush-timer-update.timer
.env is git-ignored, so your settings are kept across updates.
Caddy writes an access log for every request to logs/access.log in the app folder on the droplet. It starts a new file at 10 MB, compresses the old ones and deletes them after 90 days. setup-droplet.sh installs GoAccess, which turns the logs into a stats dashboard in your terminal. Nothing is published on the website.
To see the stats, SSH into the droplet and run:
cd /opt/toothbrush-timer
sudo ./stats.sh
It shows visitors, pages, browsers, operating systems and referrers per day, across the current and older log files. Use the arrow keys and Tab to move around, and press q to quit. Extra options are passed to GoAccess. For example, sudo ./stats.sh --ignore-crawlers hides search engine bots.
The logs include visitors' IP addresses and browser details. They stay on the droplet, readable only by root.
The app is a Progressive Web App (PWA). Once installed, it opens full-screen from your home screen and works offline.
Installing requires HTTPS, so set up a domain first (see above). Over plain http://IP it still works in the browser, but it won't install.
When you deploy a new version, an installed app picks it up the next time it's opened online.
To try the app or test changes without a server, get the code with git clone https://github.com/norbsmaq/toothbrush-timer (or Code → Download ZIP on GitHub), then either:
public/index.html in your browser. Everything works except offline mode and installing as an app.docker compose up, then open http://localhost.cd public && python3 -m http.server 8000, then open http://localhost:8000.public/ the app (index.html, style.css, app.js, icons)
manifest.webmanifest PWA manifest
sw.js service worker (offline support)
Caddyfile web server config
Dockerfile Caddy image with the app baked in
docker-compose.yml
setup-droplet.sh one-time droplet setup
update.sh pull + rebuild (run daily by a systemd timer)
stats.sh visitor stats from the access logs (GoAccess)
logs/ access logs on the server (git-ignored)