Skip to content

feat: migrate all examples to progressive complexity (Tier 1)#37

Merged
adnaan merged 3 commits intomainfrom
feat/progressive-migration
Mar 27, 2026
Merged

feat: migrate all examples to progressive complexity (Tier 1)#37
adnaan merged 3 commits intomainfrom
feat/progressive-migration

Conversation

@adnaan
Copy link
Copy Markdown
Contributor

@adnaan adnaan commented Mar 27, 2026

Summary

  • Upgrade livetemplate to v0.8.7 and lvt packages to latest
  • Migrate all 13 examples from lvt-* attributes to Tier 1 standard HTML (forms with method="POST" + name, button name routing, hidden inputs)
  • Only lvt-scroll (chat) and lvt-upload (avatar-upload) remain as documented Tier 2 attributes
  • Add Change() method to todos controller for Tier 1 search-as-you-type and sort-on-change
  • E2E tests use real form submissions via button.click() instead of liveTemplateClient.send() API
  • Add progressive complexity tier tracking table to README
  • Create CLAUDE.md with guidelines for future example creation

Test plan

  • ./test-all.sh passes all 11 examples (counter, chat, todos, live-preview, todos-progressive, profile-progressive, graceful-shutdown, testing/01_basic, ws-disabled, observability, production/single-host)
  • No lvt-click, lvt-submit, lvt-change, lvt-data-*, lvt-input, or lvt-debounce attributes remain in templates
  • Only lvt-scroll and lvt-upload remain as documented Tier 2 exceptions

🤖 Generated with Claude Code

adnaan and others added 2 commits March 27, 2026 13:20
Replace lvt-* attributes with standard HTML constructs across all 13
examples. Forms now use method="POST" with name attributes for action
routing, buttons use name attributes for HTTP POST fallback, and hidden
inputs replace lvt-data-* for passing data.

Only lvt-scroll (chat) and lvt-upload (avatar-upload) remain as
documented Tier 2 attributes where standard HTML has no equivalent.

Dependencies upgraded to livetemplate v0.8.7 with latest lvt packages.
README updated with progressive complexity tier tracking table.
CLAUDE.md created with guidelines for future example creation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update lvt dependency to pick up PR #289 which serves the latest client
library version. Convert all E2E tests from liveTemplateClient.send()
API calls to actual form submissions via button.click(), making tests
exercise the real user interaction path.

Add Change() method to todos controller for Tier 1 search-as-you-type
and sort-on-change (replaces removed lvt-input and lvt-change attrs).

Add button name="submit" to profile-progressive and todos-progressive
forms for client library form interception compatibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 27, 2026 19:06
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the examples repo to LiveTemplate’s “progressive complexity” Tier 1 patterns by removing most lvt-* attributes in favor of standard HTML forms/buttons and updating E2E tests to drive real form/button interactions, alongside upgrading LiveTemplate dependencies.

Changes:

  • Upgrade github.com/livetemplate/livetemplate to v0.8.7 and bump related lvt dependencies.
  • Migrate example templates from lvt-* action attributes to Tier 1 routing via <form method="POST" name="...">, <button name="...">, and hidden inputs.
  • Update chromedp E2E tests to click submit buttons (so button name is included) and adjust JSON/HTML expectations where applicable.

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
ws-disabled/ws_disabled_test.go Updates browser + HTTP tests to use Tier 1 button/form name routing and JSON validation responses.
ws-disabled/ws-disabled.tmpl Replaces lvt-submit/lvt-action with standard form + button naming.
todos/todos_test.go Switches E2E actions to button clicks and updates expectations for Change()-driven updates.
todos/todos.tmpl Replaces Tier 2 attributes with Tier 1 constructs (named forms/buttons; inline requestSubmit for toggle).
todos/controller.go Adds Change() to support Tier 1 live update bindings (search/sort).
todos-progressive/todos.tmpl Adds button naming consistent with Tier 1 routing.
todos-components/todos_test.go Updates selectors/actions to Tier 1 form/button naming.
todos-components/todos-components.tmpl Migrates component demo interactions to Tier 1 form/button naming.
progressive-enhancement/progressive_enhancement_test.go Adjusts tests to Tier 1 action encoding and JSON validation behavior.
progressive-enhancement/progressive-enhancement.tmpl Removes lvt-* action attributes in favor of Tier 1 naming.
profile-progressive/profile_progressive_test.go Makes E2E interactions more realistic via clear + sendKeys.
profile-progressive/profile.tmpl Adds submit button name for Tier 1 routing consistency.
production/single-host/app.tmpl Migrates counter actions to Tier 1 button naming.
observability/counter.tmpl Migrates counter actions to Tier 1 button naming.
login/templates/auth.html Replaces hidden lvt-action fields with named submit buttons for login/logout.
login/login_test.go Updates E2E + HTTP tests to submit via named buttons / Tier 1-encoded form data.
graceful-shutdown/counter.tmpl Migrates counter actions to Tier 1 button naming.
flash-messages/flash_test.go Updates HTTP tests to Tier 1 action encoding (button-name style).
flash-messages/flash.tmpl Migrates add/remove actions and buttons to Tier 1 forms/buttons.
counter/counter.tmpl Migrates counter actions to Tier 1 button naming.
chat/chat_e2e_test.go Updates E2E selectors to new Tier 1 form naming.
chat/chat.tmpl Migrates chat forms to method="POST" + name="..." (keeps lvt-scroll as Tier 2).
avatar-upload/avatar-upload.tmpl Migrates update profile form to Tier 1 method="POST" + name.
go.mod Bumps LiveTemplate/lvt dependencies to new versions.
go.sum Updates checksums for bumped dependencies.
README.md Replaces long example listing with progressive complexity tier tracking table.
CLAUDE.md Adds repo guidelines for progressive complexity + Tier 1/Tier 2 usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

todos/todos.tmpl Outdated
style="padding-right: 2rem;"
/>
<button type="button" lvt-click="search" lvt-data-query="" onclick="this.previousElementSibling.value=''; this.style.display='none';" style="position: absolute; right: 0.5rem; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; padding: 0.25rem; color: #9ca3af; font-size: 1.25rem; line-height: 1;{{if not .SearchQuery}} display: none;{{end}}" title="Clear search">&times;</button>
<button type="button" name="search" onclick="this.previousElementSibling.value=''; this.style.display='none';" style="position: absolute; right: 0.5rem; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; padding: 0.25rem; color: #9ca3af; font-size: 1.25rem; line-height: 1;{{if not .SearchQuery}} display: none;{{end}}" title="Clear search">&times;</button>
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clear-search button clears the input value but does not dispatch an input/change event (or otherwise trigger a LiveTemplate action). With the new Change()-driven search, this can leave the server-side SearchQuery unchanged, so the list may remain filtered until the user types again. Update the onclick handler to also trigger the appropriate event (or submit an action) after clearing so the server state is updated.

Suggested change
<button type="button" name="search" onclick="this.previousElementSibling.value=''; this.style.display='none';" style="position: absolute; right: 0.5rem; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; padding: 0.25rem; color: #9ca3af; font-size: 1.25rem; line-height: 1;{{if not .SearchQuery}} display: none;{{end}}" title="Clear search">&times;</button>
<button type="button" name="search" onclick="var input=this.previousElementSibling; input.value=''; input.dispatchEvent(new Event('input', { bubbles: true })); this.style.display='none';" style="position: absolute; right: 0.5rem; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; padding: 0.25rem; color: #9ca3af; font-size: 1.25rem; line-height: 1;{{if not .SearchQuery}} display: none;{{end}}" title="Clear search">&times;</button>

Copilot uses AI. Check for mistakes.
// Wait for Delete form to be in DOM after PRG redirect from Add
chromedp.WaitReady(`form[lvt-submit="Delete"]`, chromedp.ByQuery),
chromedp.Submit(`form[lvt-submit="Delete"]`, chromedp.ByQuery),
// Wait for Delete button to be in DOM after PRG redirect from Add
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment mentions a "PRG redirect" after Add, but in this example Add/Delete return state updates (no redirects) in WebSocket-disabled/fetch mode (see ws-disabled/main.go Add/Delete). Consider rewording to avoid implying a redirect-based flow here, since it can mislead future readers/debugging.

Suggested change
// Wait for Delete button to be in DOM after PRG redirect from Add
// Wait for Delete button to appear in the DOM after the Add state update

Copilot uses AI. Check for mistakes.

---
## Examples

Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

## Examples is currently an empty section heading (it immediately jumps to ## Running Examples). Either remove the empty heading or add content under it so the README doesn't have a dead section.

Suggested change
The directories listed in the table above are individual example applications. Each folder contains a minimal, self-contained project that demonstrates a specific LiveTemplate pattern or feature.

Copilot uses AI. Check for mistakes.
- Dispatch input event after clearing search to sync server state
- Fix misleading PRG redirect comment in ws-disabled test
- Add content under empty Examples heading in README

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@adnaan adnaan merged commit ba89e20 into main Mar 27, 2026
8 checks passed
@adnaan adnaan mentioned this pull request Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants