Created comprehensive SSR_FIRST_ALPINE_GUIDE.md to establish SSR-first
architecture principles for Alpine.js integration.
New Guide: SSR_FIRST_ALPINE_GUIDE.md
Covers:
- SSR-first principles (state in templates, no fetch in x-init for SSR pages)
- Three page type classifications:
* Type 1: 80% SSR (Collections, Conflicts) - backend provides all data
* Type 2: SSR + Interactive (Dashboard, Admin Library) - SSR + interactivity
* Type 3: 80% JavaScript (Analytics) - x-init fetches all data (intentional)
- The SSR data fetch problem (x-init replacing SSR content)
- DOMContentLoaded cleanup strategies
- Page-by-page strategy for each type
- Authentication & SSR (server-side token injection)
- Verification checklist and testing approach
- Architecture diagram showing data flow
Key Principles:
- ❌ NEVER fetch data in x-init if data is already SSR'd
- ✅ x-init ONLY for setup (event listeners, modals)
- ✅ Data fetch ONLY after user actions
- ✅ State lives in template (x-data), not TypeScript
Updated: COLLECTIONS_CLEANUP_GUIDE.md
Changes:
- Added reference to SSR_FIRST_ALPINE_GUIDE.md as authority
- Removed two-option approach (no more choices)
- Documented that admin library SSR bug is already fixed (commit 1b9bc64)
- Simplified dashboard approach (wrap existing code in initDashboard)
- Simplified docs approach (simple setup, no data fetch)
- Updated summary to reflect completed work
- Added architecture section showing state location
Architecture Clarity:
- Templates: UI state (x-data, x-show)
- Backend: SSR data
- TypeScript: Business logic only
- No hybrid approach - follow SSR-first principles
References:
- SSR_FIRST_ALPINE_GUIDE.md - Complete SSR-first architecture
- ALPINE_COMPLETION_GUIDE.md - Full Alpine.js migration (future goal)
- PROJECT_GUIDELINES.md - Project standards
This establishes a single source of truth for SSR-first Alpine.js
architecture and removes confusion about which approach to use.
Updated COLLECTIONS_CLEANUP_GUIDE.md to present TWO approaches for
each page, giving flexibility for quick fixes vs full migration.
Two Approaches Now Available:
OPTION A: Minimal Fix (Quick)
- Fix SSR bugs by removing data fetch from init functions
- Keep x-init for setup only (event listeners, modals)
- Keep current event listener patterns
- Good for quick fixes
OPTION B: Full Alpine.js Reactive Pattern (Recommended)
- See ALPINE_COMPLETION_GUIDE.md for complete pattern
- Eliminate ALL manual DOM manipulation
- Use x-data for state, x-show for visibility
- Use @click.outside for closing dropdowns/modals
- Use x-transition for smooth animations
- No initialization functions needed
- Aligns with long-term architecture
Updates to Guide Sections:
Step 3.2 (docs.ts):
- Added Option A: Use x-init (simple)
- Added Option B: Event delegation pattern
- Recommendation: Option A (simple setup, no data fetch)
Step 3.3 (library.ts):
- Added Option A: Remove reloadLibraries() from init (quick)
- Added Option B: Full Alpine.js reactive pattern
- Shows how to eliminate manual DOM manipulation
- Recommendation: Option B for cleanest architecture
Step 3.4 (dashboard.ts):
- Added Option A: Wrap in initDashboard() function
- Added Option B: Remove DOMContentLoaded, use delegation
- Notes event delegation already exists
- Recommendation: Option A (keep current pattern)
Updated Summary Section:
- Added architecture decision point (Path 1 vs Path 2)
- Documented mixed approach as recommended
- Clear guidance on which approach to use when
- References ALPINE_COMPLETION_GUIDE.md throughout
This allows developer to choose approach based on:
- Page complexity
- Time constraints
- Learning progression
- Long-term architecture goals
The guide is now flexible enough to support both quick fixes
and full Alpine.js migration as the developer progresses
through the app page-by-page.
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.
Add detailed step-by-step guide for fixing console errors in collections
and cleaning up DOMContentLoaded listeners across multiple TypeScript files.
COLLECTIONS_CLEANUP_GUIDE.md provides:
- Complete analysis of what was broken and why
- Line-by-line instructions for fixing collections.ts Alpine.data exports
- Step-by-step guide for removing DOMContentLoaded from 5 TypeScript files
- Template x-init additions for proper Alpine.js initialization
- Verification and testing steps
This guide documents the fix for:
- Dead Alpine.js exports (addbooksToAdd, removebooksToAdd, toggleBookSelection, etc.)
- DOMContentLoaded listeners running on wrong pages (analytics, docs, library, dashboard, admin)
- Missing x-init calls in templates (analytics, docs, dashboard, library)
- Template cleanup (removing dead function calls in collections.templ)
The guide follows PROJECT_GUIDELINES.md standards with clear code examples,
file paths, and verification steps. It serves as both implementation guide
and documentation for the cleanup effort.