A PHP + MySQL PWA for task management with real browser push notifications.
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS taskboard CHARACTER SET utf8mb4;"
mysql -u root -p taskboard < data/create_users.sql
mysql -u root -p taskboard < data/create_taskboard_tables.sqlEdit db.php with your MySQL credentials.
# Option A — Node.js (easiest)
npx web-push generate-vapid-keys
# Option B — PHP (after composer install)
php -r "require 'vendor/autoload.php'; \
\$k = Minishlink\WebPush\VAPID::createVapidKeys(); \
echo json_encode(\$k, JSON_PRETTY_PRINT);"Copy vapid.php.example → vapid.php and paste your keys.
composer require minishlink/web-pushThe bundled
web-push-php-master/folder is a fallback if Composer isn't available.
* * * * * php /var/www/html/taskboard/send_due_notifications.php >> /tmp/tb_notif.log 2>&1This runs every minute and sends a push notification for any task whose due time has passed.
Put your credentials in the Google Cloud Console, then update auth.php.
Browser Server
────── ──────
1. User clicks 🔔 bell
2. Notification.requestPermission()
3. SW registers (sw.js)
4. PushManager.subscribe() → push.php → push_subscriptions table
(endpoint, p256dh, auth)
Cron (every minute)
send_due_notifications.php
→ queries tasks WHERE due <= NOW() AND NOT IN notifications_sent
→ WebPush::send() → Browser push service → sw.js push event
→ sw.js shows notification toast
| File | What was fixed |
|---|---|
sw.js |
Added proper push event handler with actions; fixed notificationclick to focus existing tab |
app.js |
SW now awaited before push subscribe; getSubscription() check prevents duplicate subscriptions; re-subscribes on page reload if permission already granted |
push.php |
Accepts both { subscription: {...} } and direct {endpoint, keys} formats |
send_due_notifications.php |
Fixed SQL (board_lists table name); auto-removes stale 404/410 subscriptions; INSERT IGNORE prevents duplicate sent records |
vapid_public.php |
Better error messages for missing/empty config |
data/create_taskboard_tables.sql |
Added UNIQUE KEY on notifications_sent.task_id to prevent double-sends |
vapid.php.example |
New: key generation instructions |
Notifications not showing?
- Open DevTools → Application → Service Workers — is
sw.jsActive? - DevTools → Application → Notifications — is permission "Granted"?
- DevTools → Application → Push Messaging — is there a subscription endpoint?
- Check
data/push_debug.log— does push.php receive the subscription? - Run
php send_due_notifications.phpmanually — any errors? - Verify your VAPID keys match between
vapid.phpand what was used to create the subscription.
"Failed to subscribe" in console?
- Make sure the site is served over HTTPS (or
localhostfor dev). Push API requires a secure context. - Check that
vapid_public.phpreturns a valid base64url public key.
Cron not running?
- Test manually:
php send_due_notifications.php - Check PHP error log for exceptions.
- Make sure
notifications_senttable exists with theUNIQUE KEYontask_id.