diff --git a/public/index.php b/public/index.php
index 3c9c66d..ad135ad 100644
--- a/public/index.php
+++ b/public/index.php
@@ -1925,6 +1925,7 @@ if (str_starts_with($route, '/api/')) {
diff --git a/public/plugins/collab-buckets/collab-buckets.js b/public/plugins/collab-buckets/collab-buckets.js
index 8713873..283533a 100644
--- a/public/plugins/collab-buckets/collab-buckets.js
+++ b/public/plugins/collab-buckets/collab-buckets.js
@@ -908,10 +908,18 @@ async function init() {
startPolling();
}
+// Defer init until the CSRF token is live — `checkAuth()` sets it async on
+// boot, and firing POST /api/collab-buckets/poll before that racing lookup
+// resolves returns 403. If the token is already in the util state when we
+// load (e.g. fast reload, cached session), kick off init straight away.
+function bootWhenCsrfReady() {
+ if (hyprcrd?.util?.csrf?.()) { init(); return; }
+ hyprcrd?.hooks?.on?.('csrf.ready', () => init());
+}
if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', init, { once: true });
+ document.addEventListener('DOMContentLoaded', bootWhenCsrfReady, { once: true });
} else {
- init();
+ bootWhenCsrfReady();
}
hyprcrd.registerPlugin?.({