refactor(library): fix SSR bug by removing data fetch from init function

CRITICAL FIX: initializeLibraryAdmin() was calling reloadLibraries()
which fetched data from the API and replaced the SSR-rendered library
list on page load, defeating the purpose of server-side rendering.

Changes in web/src/library.ts:
- Remove DOMContentLoaded listener (now uses Alpine x-init in template)
- Remove void reloadLibraries() call from initializeLibraryAdmin()
- Add comment explaining SSR provides initial data
- Add initializeLibraryAdmin to export statement
- Add initializeLibraryAdmin to Alpine.data() registration
- Keep reloadLibraries() as standalone function for use after CRUD ops

Rationale:
- SSR provides fast initial page load with library list
- x-init should ONLY setup event listeners, not fetch data
- reloadLibraries() is called after create/delete/update operations
- Follows SSR-first architecture: different pages have different
  SSR/JS ratios (analytics is 80% JS, most pages are 80% SSR)

Documentation:
- Update COLLECTIONS_CLEANUP_GUIDE.md with SSR-first strategy
- Document page-by-page review status (dashboard ✓, collections 🔄)
- Fix template references (library.templ → admin_library.templ)
- Explain why analytics fetches data (intentional for dynamic page)

This ensures the admin library page maintains SSR benefits while
still providing interactive features via Alpine.js.
This commit is contained in:
2026-03-12 17:58:36 -04:00
parent ddcd8c62e2
commit 1b9bc64b28
2 changed files with 152 additions and 86 deletions
+26 -31
View File
@@ -650,50 +650,45 @@ function initializeLibraryAdmin(): void {
createLibraryForm.addEventListener("submit", handleCreateLibrarySubmit);
}
// Load libraries from API on page load
void reloadLibraries();
}
// Initialize on DOM ready
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initializeLibraryAdmin);
} else {
initializeLibraryAdmin();
// SSR provides initial library list - no need to fetch on page load
// reloadLibraries() is called after create/delete/update operations
}
// Export functions for global access
export {
deleteLibrary,
showLibraryFolders,
addLibraryFolder,
removeLibraryFolder,
setLibraryVisibility,
loadUserVisibility,
confirmDeleteLibrary,
deleteLibrary,
editLibrary,
handleCreateLibrarySubmit,
showFolderBrowser,
navigateFolderBrowser,
selectBrowseFolder,
hideFolderBrowser,
showDeleteModal,
hideDeleteModal,
confirmDeleteLibrary,
hideFolderBrowser,
initializeLibraryAdmin,
loadUserVisibility,
navigateFolderBrowser,
removeLibraryFolder,
selectBrowseFolder,
setLibraryVisibility,
showDeleteModal,
showFolderBrowser,
showLibraryFolders,
};
Alpine.data("library", () => ({
deleteLibrary,
showLibraryFolders,
addLibraryFolder,
removeLibraryFolder,
setLibraryVisibility,
loadUserVisibility,
confirmDeleteLibrary,
deleteLibrary,
editLibrary,
handleCreateLibrarySubmit,
showFolderBrowser,
navigateFolderBrowser,
selectBrowseFolder,
hideFolderBrowser,
showDeleteModal,
hideDeleteModal,
confirmDeleteLibrary,
hideFolderBrowser,
initializeLibraryAdmin,
loadUserVisibility,
navigateFolderBrowser,
removeLibraryFolder,
selectBrowseFolder,
setLibraryVisibility,
showDeleteModal,
showFolderBrowser,
showLibraryFolders,
}));