docs: update Alpine.js migration guide and project guidelines

- Fix incorrect function references in ALPINE_COMPLETION_GUIDE.md
  - header.changeThemeTo -> changeTheme
  - header.logout -> logout
  - woodPaneling.change -> changeWoodPaneling
- Add SSR-first principles section to PROJECT_GUIDELINES.md
- Add page type classifications (Type 1, 2, 3)
- Fix extra asterisks on line 43
- Update to reference TypeScript instead of JavaScript
This commit is contained in:
2026-03-13 12:50:47 -04:00
parent 5670f02c7f
commit 5b7540be99
2 changed files with 678 additions and 380 deletions
+616 -358
View File
File diff suppressed because it is too large Load Diff
+60 -20
View File
@@ -4,7 +4,7 @@
### Backend & Database ### Backend & Database
-**NEVER modify backend code when working on frontend-only tasks** - ❌ **NEVER modify backend code when working on frontend-only tasks*
-**NEVER modify database schema** unless explicitly instructed for full-stack changes -**NEVER modify database schema** unless explicitly instructed for full-stack changes
-**NEVER use Docker** - use Podman only -**NEVER use Docker** - use Podman only
-**NEVER build server binaries locally** - all builds through Dockerfile/docker-compose -**NEVER build server binaries locally** - all builds through Dockerfile/docker-compose
@@ -16,7 +16,7 @@
### Testing ### Testing
-**ALWAYS use `setupTestServer()` helper from `cmd/server/tests/test_helpers_test.go`** - ✅ **ALWAYS use `setupTestServer()` helper from `cmd/server/tests/test_helpers_test.go`*
-**Share one test setup across all subtests** - call `setupTestServer()` once at test function level, not per subtest -**Share one test setup across all subtests** - call `setupTestServer()` once at test function level, not per subtest
-**Prefer table-driven tests** - use `t.Run()` with test cases instead of duplicate test functions -**Prefer table-driven tests** - use `t.Run()` with test cases instead of duplicate test functions
-**Configure database pools efficiently** - use `max_conns=1` for test pools (via `pgxpool.ParseConfig()`) to prevent connection exhaustion -**Configure database pools efficiently** - use `max_conns=1` for test pools (via `pgxpool.ParseConfig()`) to prevent connection exhaustion
@@ -27,7 +27,7 @@
### Frontend & Styling ### Frontend & Styling
-**NEVER modify backend/API for frontend features without user confirmation** - ❌ **NEVER modify backend/API for frontend features without user confirmation*
-**NEVER use custom CSS** - TailwindCSS classes only -**NEVER use custom CSS** - TailwindCSS classes only
- **⚠️ EXCEPTION**: `templates/error.templ` may have inline CSS because error pages must work when main app fails (404, server errors, CSS fails to load) - **⚠️ EXCEPTION**: `templates/error.templ` may have inline CSS because error pages must work when main app fails (404, server errors, CSS fails to load)
-**NEVER use JavaScript** - convert all to TypeScript -**NEVER use JavaScript** - convert all to TypeScript
@@ -36,11 +36,11 @@
-**DO use procedural/imperative style** as your default -**DO use procedural/imperative style** as your default
-**DO borrow functional techniques** when they simplify code -**DO borrow functional techniques** when they simplify code
-**DO avoid ideological purity** - the best paradigm is the one that fits the problem -**DO avoid ideological purity** - the best paradigm is the one that fits the problem
-**NEVER add new Dockerfiles without user confirmation** - ❌ **NEVER add new Dockerfiles without user confirmation*
-**NEVER fetch initial data via AJAX on page load** - use server-side rendering instead -**NEVER fetch initial data via AJAX on page load** - use server-side rendering instead
-**NEVER break progressive enhancement** - pages must work without JavaScript -**NEVER break progressive enhancement** - pages must work without JavaScript
**Note:** Go methods in the backend are fine and encouraged. This guideline applies to TypeScript/JavaScript frontend code only.\*\* **Note:** Go methods in the backend are fine and encouraged. This guideline applies to TypeScript/JavaScript frontend code only.
### General ### General
@@ -49,7 +49,7 @@
-**NEVER commit files with secrets** (.env, credentials.json, etc.) -**NEVER commit files with secrets** (.env, credentials.json, etc.)
-**NEVER make assumptions** - ask clarifying questions when uncertain -**NEVER make assumptions** - ask clarifying questions when uncertain
-**NEVER delete code without reading full context first** (minimum 20 lines before/after) -**NEVER delete code without reading full context first** (minimum 20 lines before/after)
-**NEVER make cascading fix-up edits without git diff review** - ❌ **NEVER make cascading fix-up edits without git diff review*
- After compilation error: STOP, review `git diff`, understand full impact - After compilation error: STOP, review `git diff`, understand full impact
- Use revert/reapply pattern instead of blind fixes - Use revert/reapply pattern instead of blind fixes
-**NEVER skip post-edit verification** - must compile after each file edit -**NEVER skip post-edit verification** - must compile after each file edit
@@ -58,8 +58,8 @@
- Run `git commit -m "<message>"` and wait for completion - Run `git commit -m "<message>"` and wait for completion
- Run `git push` and wait for completion - Run `git push` and wait for completion
- Never use `&&` to chain git commands together - Never use `&&` to chain git commands together
-**Make good organized git commits for the entire project (not just what you changed) and push - run git add, commit, push sequentially as separate commands, no need to repeatedly check status** - ✅ **Make good organized git commits for the entire project (not just what you changed) and push - run git add, commit, push sequentially as separate commands, no need to repeatedly check status*
-**Indentation is always 2 spaces unless the language prohibits it** - ✅ **Indentation is always 2 spaces unless the language prohibits it*
### Cascading Fix-up Pattern (PROHIBITED) ### Cascading Fix-up Pattern (PROHIBITED)
@@ -111,7 +111,7 @@ VERIFY → Compile successfully
1. Identify the required change 1. Identify the required change
2. Explain why you need it 2. Explain why you need it
3. Provide impact analysis 3. Provide impact analysis
4. **ASK FOR USER CONFIRMATION before proceeding** 4. **ASK FOR USER CONFIRMATION before proceeding*
### When Working on Full-Stack Tasks ### When Working on Full-Stack Tasks
@@ -129,7 +129,7 @@ VERIFY → Compile successfully
- ✅ Follow **pgx v5 standards** for all database operations - ✅ Follow **pgx v5 standards** for all database operations
- ✅ Treat schema changes as **ATOMIC** - complete success or complete rejection - ✅ Treat schema changes as **ATOMIC** - complete success or complete rejection
-**⚠️ CRITICAL: This is a pre-production application (NO production deployments exist)** -**⚠️ CRITICAL: This is a pre-production application (NO production deployments exist)*
- When `database/schema/schema.sql` is updated, local databases must be updated - When `database/schema/schema.sql` is updated, local databases must be updated
- **Option 1 (Recommended):** Recreate database with fresh schema: - **Option 1 (Recommended):** Recreate database with fresh schema:
```bash ```bash
@@ -144,7 +144,7 @@ VERIFY → Compile successfully
### Build & Deployment ### Build & Deployment
- ✅ Use **Podman** exclusively (not Docker) - ✅ Use **Podman** exclusively (not Docker)
- ✅ All builds through existing **Dockerfile** and **docker-compose.yml** - ✅ All builds through existing **Dockerfile** and **docker-compose.yml*
- ✅ Stop building server binaries - everything goes through containers - ✅ Stop building server binaries - everything goes through containers
### API Changes (Full-Stack Tasks Only) ### API Changes (Full-Stack Tasks Only)
@@ -176,7 +176,7 @@ VERIFY → Compile successfully
### Code Organization ### Code Organization
- ✅ Minimize project structure changes - ✅ Minimize project structure changes
- ✅ Place new files in **contextually appropriate directories** - ✅ Place new files in **contextually appropriate directories*
- ✅ Follow **KISS**, **DRY**, and **YAGNI** principles - ✅ Follow **KISS**, **DRY**, and **YAGNI** principles
- ✅ Use **multiple, logical git commits** with clear messages - ✅ Use **multiple, logical git commits** with clear messages
- ❌ **NEVER duplicate types between handlers and templates** - define data types in handlers, reuse directly in templates - ❌ **NEVER duplicate types between handlers and templates** - define data types in handlers, reuse directly in templates
@@ -252,7 +252,7 @@ VERIFY → Compile successfully
### Process & Continuity ### Process & Continuity
- ✅ If mid-task and receive "no response", **continue the task** - ✅ If mid-task and receive "no response", **continue the task*
- ✅ Verify no regressions before modifying/removing code - ✅ Verify no regressions before modifying/removing code
--- ---
@@ -268,11 +268,38 @@ VERIFY → Compile successfully
### Frontend Stack ### Frontend Stack
- **Rendering**: SSR-first - Go templates render initial page with all data
- **Interactivity**: Alpine.js for UI state (modals, dropdowns, transitions)
- **Dynamic Updates**: HTMX for CRUD operations (no full page reloads)
- **Styling**: TailwindCSS (no custom CSS) - **Styling**: TailwindCSS (no custom CSS)
- **Language**: TypeScript (no JavaScript) - **Language**: TypeScript (no JavaScript)
- **Templates**: HTMX with server-side rendering
- **Patterns**: Procedural/imperative with functional techniques where helpful (no OOP) - **Patterns**: Procedural/imperative with functional techniques where helpful (no OOP)
### SSR-First Principles
- ❌ **NEVER fetch initial data via AJAX** - server renders complete page
- ❌ **NEVER fetch data in Alpine x-init** - data already SSR'd
- ✅ **Use Alpine.js only for UI state** - modal visibility, dropdown toggles
- ✅ **Use HTMX for dynamic operations** - form submissions, partial page updates
- ✅ **x-init is for setup only** - event listeners, not data fetching
- ✅ **Data fetching happens after user actions** - not on page load
### Page Type Classifications
1. **Type 1: 80% SSR (most pages)**
- Backend provides all initial data
- Alpine handles modals/dropdowns only
- x-init NEVER fetches data
2. **Type 2: SSR + Interactive (dashboard, bookshelf)**
- Backend provides initial data
- Alpine handles interactivity (drag-drop, filtering)
- x-init ONLY sets up event listeners
3. **Type 3: 80% TypeScript (analytics, complex dashboards)**
- Some client-side data fetching acceptable
- Still prefer SSR when possible
### Containerization ### Containerization
- **Runtime**: Podman (not Docker) - **Runtime**: Podman (not Docker)
@@ -427,14 +454,27 @@ git checkout -- internal/handlers/auth.go
## 🏗 ARCHITECTURAL PATTERNS ## 🏗 ARCHITECTURAL PATTERNS
### Current: Hybrid SSR ### Current: SSR-First with Alpine.js + HTMX
``` ```
Browser → Go template (with data) → Display instantly Browser → Go template (SSR with all data) → Display instantly
JavaScript for interactivity (CRUD) Alpine.js for UI state (modals, dropdowns)
Shared service layer HTMX for CRUD (forms, updates)
Shared service layer (Go)
``` ```
**Layer Responsibilities:**
| Layer | Responsibility |
|-------|---------------|
| **Go Template** | SSR initial page with real data |
| **Alpine.js** | UI state only (x-data, x-show, transitions) |
| **HTMX** | Dynamic updates without page reload |
| **TypeScript** | Pure business logic (API calls, data processing) |
**See also:** `SSR_FIRST_ALPINE_GUIDE.md` and `ALPINE_COMPLETION_GUIDE.md`
Ultimately, whenever you are unsure just ask for confirmation. Ultimately, whenever you are unsure just ask for confirmation.