diff --git a/avatar-upload/README.md b/avatar-upload/README.md
new file mode 100644
index 0000000..8a082e0
--- /dev/null
+++ b/avatar-upload/README.md
@@ -0,0 +1,166 @@
+# Avatar Upload Example
+
+A simple example demonstrating LiveTemplate's file upload feature with avatar upload functionality.
+
+## Features
+
+- đ¸ **Image Upload**: Upload JPEG, PNG, or GIF avatars
+- đ **Real-time Progress**: WebSocket chunked upload with live progress tracking
+- â
**Validation**: Automatic file type and size validation (5MB limit)
+- đ¨ **Beautiful UI**: Gradient design with smooth animations
+- đ **Live Updates**: Profile updates instantly without page reload
+
+## What This Example Demonstrates
+
+### Upload Configuration
+```go
+func (s *ProfileStore) AllowUploads() map[string]livetemplate.UploadConfig {
+ return map[string]livetemplate.UploadConfig{
+ "avatar": {
+ Accept: []string{"image/jpeg", "image/png", "image/gif"},
+ MaxFileSize: 5 * 1024 * 1024, // 5MB
+ MaxEntries: 1, // Single file
+ AutoUpload: false, // Manual upload on form submit
+ ChunkSize: 256 * 1024, // 256KB chunks
+ },
+ }
+}
+```
+
+### Upload Processing
+```go
+func (s *ProfileStore) ConsumeUpload(ctx context.Context, name string, entries []*livetemplate.UploadEntry) error {
+ for _, entry := range entries {
+ // Move from temp to permanent location
+ permanentPath := filepath.Join("uploads", fmt.Sprintf("avatar-%s%s", entry.ID, ext))
+ os.Rename(entry.TempPath, permanentPath)
+
+ // Update store with new avatar
+ s.AvatarPath = permanentPath
+ s.AvatarURL = "/" + permanentPath
+ }
+ return nil
+}
+```
+
+### Template Helpers
+```html
+
+
+
+{{range .lvt.Uploads "avatar"}}
+
+
{{.ClientName}} - {{.Progress}}%
+
+ {{if .Error}}
{{.Error}} {{end}}
+
+{{end}}
+```
+
+## Running the Example
+
+### 1. Install Dependencies
+
+```bash
+cd /Users/adnaan/code/livetemplate/examples/avatar-upload
+go mod download
+```
+
+### 2. Run the Server
+
+```bash
+go run main.go
+```
+
+The server will start at http://localhost:8080
+
+### 3. Try It Out
+
+1. Open http://localhost:8080 in your browser
+2. Click "Choose File" and select an image (JPEG, PNG, or GIF)
+3. Click "Save Profile"
+4. Watch the real-time progress bar as your file uploads
+5. See your avatar appear instantly when upload completes!
+
+## Upload Strategies
+
+This example uses **WebSocket Chunked Upload**:
+- â
Real-time progress tracking
+- â
Handles large files efficiently (256KB chunks)
+- â
Non-blocking uploads
+- â
Works with LiveTemplate's reactive updates
+
+## File Structure
+
+```
+avatar-upload/
+âââ main.go # Server code with ProfileStore
+âââ avatar-upload.tmpl # HTML template with upload UI
+âââ go.mod # Dependencies (uses local livetemplate)
+âââ README.md # This file
+âââ uploads/ # Created at runtime for uploaded avatars
+```
+
+## Testing Different Scenarios
+
+### Valid Upload
+- Upload a JPEG, PNG, or GIF under 5MB
+- â
Should show progress and complete successfully
+
+### File Too Large
+- Upload an image over 5MB
+- â Should show validation error
+
+### Invalid File Type
+- Upload a non-image file (e.g., .txt, .pdf)
+- â Should show "file type not accepted" error
+
+### Multiple Files
+- Try selecting multiple images
+- âšī¸ Only the first will be accepted (MaxEntries: 1)
+
+## Code Quality
+
+This example demonstrates:
+- â
Clean separation of concerns (Store pattern)
+- â
Proper error handling
+- â
File validation and security
+- â
Temp file cleanup
+- â
LiveTemplate best practices
+
+## Next Steps
+
+Want to extend this example?
+
+1. **Add S3 Upload**: Replace local storage with S3 presigner
+2. **Multiple Avatars**: Change `MaxEntries` to allow multiple images
+3. **Image Cropping**: Add client-side cropping before upload
+4. **Drag & Drop**: Add drag-and-drop file selection
+5. **Auto-Upload**: Set `AutoUpload: true` for instant uploads
+
+## Learn More
+
+- [Upload Documentation](../../livetemplate/.worktrees/feature-uploads/docs/uploads.md)
+- [LiveTemplate Documentation](https://github.com/livetemplate/livetemplate)
+- [Other Examples](../)
+
+## Troubleshooting
+
+**Upload not working?**
+- Check browser console for errors
+- Ensure WebSocket connection is established (look for green indicator)
+- Verify file meets validation criteria (type, size)
+
+**Progress not updating?**
+- Make sure you're using WebSocket (not HTTP fallback)
+- Check that ChunkSize is set appropriately
+- Verify client library is loaded
+
+**Files not saving?**
+- Check that `uploads/` directory exists (created automatically)
+- Verify file permissions on the uploads directory
+- Check server logs for errors
+
+---
+
+Built with â¤ī¸ using [LiveTemplate v0.3.0](https://github.com/livetemplate/livetemplate)
diff --git a/avatar-upload/avatar-upload.tmpl b/avatar-upload/avatar-upload.tmpl
new file mode 100644
index 0000000..30a7983
--- /dev/null
+++ b/avatar-upload/avatar-upload.tmpl
@@ -0,0 +1,317 @@
+
+
+
+
+
+ Avatar Upload Example - LiveTemplate
+
+
+
+
+
Profile Settings
+
Upload your avatar and update your profile
+
+
+ đ¸ Accepted: JPEG, PNG, GIF âĸ Max size: 5MB âĸ WebSocket chunked upload with real-time progress
+
+
+
+
+ {{if .AvatarURL}}
+
+ {{else}}
+ {{slice .Name 0 1}}
+ {{end}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/avatar-upload/go.mod b/avatar-upload/go.mod
new file mode 100644
index 0000000..3d094e2
--- /dev/null
+++ b/avatar-upload/go.mod
@@ -0,0 +1,25 @@
+module github.com/livetemplate/examples/avatar-upload
+
+go 1.25.3
+
+require github.com/livetemplate/livetemplate v0.3.0
+
+require (
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+ github.com/gabriel-vasile/mimetype v1.4.10 // indirect
+ github.com/go-playground/locales v0.14.1 // indirect
+ github.com/go-playground/universal-translator v0.18.1 // indirect
+ github.com/go-playground/validator/v10 v10.28.0 // indirect
+ github.com/google/uuid v1.6.0 // indirect
+ github.com/gorilla/websocket v1.5.3 // indirect
+ github.com/leodido/go-urn v1.4.0 // indirect
+ github.com/redis/go-redis/v9 v9.16.0 // indirect
+ github.com/tdewolff/minify/v2 v2.24.3 // indirect
+ github.com/tdewolff/parse/v2 v2.8.3 // indirect
+ golang.org/x/crypto v0.42.0 // indirect
+ golang.org/x/net v0.44.0 // indirect
+ golang.org/x/sys v0.36.0 // indirect
+ golang.org/x/text v0.29.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
+)
diff --git a/avatar-upload/go.sum b/avatar-upload/go.sum
new file mode 100644
index 0000000..1ea0169
--- /dev/null
+++ b/avatar-upload/go.sum
@@ -0,0 +1,146 @@
+dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
+dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
+github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
+github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
+github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
+github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
+github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
+github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
+github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
+github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
+github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
+github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
+github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
+github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
+github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
+github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
+github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
+github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
+github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
+github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
+github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
+github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
+github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
+github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
+github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
+github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
+github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
+github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
+github.com/livetemplate/livetemplate v0.3.0 h1:k3cpsiOmWcjS+S/e5rvydbi6nY86ipnWd801B5hgL5M=
+github.com/livetemplate/livetemplate v0.3.0/go.mod h1:PYS1hH2a6o7d9LID96780l/HHSGJIJS70kBnVO1mIUA=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
+github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
+github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o=
+github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
+github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
+github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
+github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
+github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
+github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
+github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
+github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
+github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
+github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
+github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
+github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
+github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
+github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
+github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/redis/go-redis/v9 v9.16.0 h1:OotgqgLSRCmzfqChbQyG1PHC3tLNR89DG4jdOERSEP4=
+github.com/redis/go-redis/v9 v9.16.0/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
+github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
+github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8=
+github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
+github.com/tdewolff/minify/v2 v2.24.3 h1:BaKgWSFLKbKDiUskbeRgbe2n5d1Ci1x3cN/eXna8zOA=
+github.com/tdewolff/minify/v2 v2.24.3/go.mod h1:1JrCtoZXaDbqioQZfk3Jdmr0GPJKiU7c1Apmb+7tCeE=
+github.com/tdewolff/parse/v2 v2.8.3 h1:5VbvtJ83cfb289A1HzRA9sf02iT8YyUwN84ezjkdY1I=
+github.com/tdewolff/parse/v2 v2.8.3/go.mod h1:Hwlni2tiVNKyzR1o6nUs4FOF07URA+JLBLd6dlIXYqo=
+github.com/tdewolff/test v1.0.11 h1:FdLbwQVHxqG16SlkGveC0JVyrJN62COWTRyUFzfbtBE=
+github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
+github.com/testcontainers/testcontainers-go v0.39.0 h1:uCUJ5tA+fcxbFAB0uP3pIK3EJ2IjjDUHFSZ1H1UxAts=
+github.com/testcontainers/testcontainers-go v0.39.0/go.mod h1:qmHpkG7H5uPf/EvOORKvS6EuDkBUPE3zpVGaH9NL7f8=
+github.com/testcontainers/testcontainers-go/modules/redis v0.39.0 h1:p54qELdCx4Gftkxzf44k9RJRRhaO/S5ehP9zo8SUTLM=
+github.com/testcontainers/testcontainers-go/modules/redis v0.39.0/go.mod h1:P1mTbHruHqAU2I26y0RADz1BitF59FLbQr7ceqN9bt4=
+github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
+github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
+github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
+github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
+go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
+go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
+go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
+go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
+go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
+go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
+golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
+golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
+golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
+golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
+golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
+golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
+golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/avatar-upload/main.go b/avatar-upload/main.go
new file mode 100644
index 0000000..1870754
--- /dev/null
+++ b/avatar-upload/main.go
@@ -0,0 +1,133 @@
+package main
+
+import (
+ "context"
+ "embed"
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "path/filepath"
+
+ "github.com/livetemplate/livetemplate"
+)
+
+//go:embed *.tmpl
+var templates embed.FS
+
+// ProfileStore manages user profile with avatar upload
+type ProfileStore struct {
+ Name string
+ Email string
+ AvatarPath string
+ AvatarURL string
+}
+
+// AllowUploads configures avatar upload
+func (s *ProfileStore) AllowUploads() map[string]livetemplate.UploadConfig {
+ return map[string]livetemplate.UploadConfig{
+ "avatar": {
+ Accept: []string{"image/jpeg", "image/png", "image/gif"},
+ MaxFileSize: 5 * 1024 * 1024, // 5MB
+ MaxEntries: 1, // Single file
+ AutoUpload: false, // Manual upload on form submit
+ ChunkSize: 256 * 1024, // 256KB chunks
+ },
+ }
+}
+
+// ConsumeUpload processes uploaded avatar
+func (s *ProfileStore) ConsumeUpload(ctx context.Context, name string, entries []*livetemplate.UploadEntry) error {
+ if name != "avatar" {
+ return nil
+ }
+
+ // Create uploads directory if it doesn't exist
+ uploadsDir := "uploads"
+ if err := os.MkdirAll(uploadsDir, 0755); err != nil {
+ return fmt.Errorf("failed to create uploads directory: %w", err)
+ }
+
+ for _, entry := range entries {
+ // Generate permanent filename
+ ext := filepath.Ext(entry.ClientName)
+ permanentPath := filepath.Join(uploadsDir, fmt.Sprintf("avatar-%s%s", entry.ID, ext))
+
+ // Move from temp to permanent location
+ if err := os.Rename(entry.TempPath, permanentPath); err != nil {
+ // If rename fails (different filesystem), try copy
+ if err := copyFile(entry.TempPath, permanentPath); err != nil {
+ return fmt.Errorf("failed to save avatar: %w", err)
+ }
+ os.Remove(entry.TempPath) // Clean up temp file
+ }
+
+ // Update store with new avatar
+ s.AvatarPath = permanentPath
+ s.AvatarURL = "/" + permanentPath
+
+ log.Printf("Avatar saved: %s (original: %s, size: %d bytes)", permanentPath, entry.ClientName, entry.ClientSize)
+ }
+
+ return nil
+}
+
+// copyFile copies a file from src to dst
+func copyFile(src, dst string) error {
+ data, err := os.ReadFile(src)
+ if err != nil {
+ return err
+ }
+ return os.WriteFile(dst, data, 0644)
+}
+
+// UpdateProfile handles profile update form submission
+func (s *ProfileStore) UpdateProfile(ctx context.Context, data livetemplate.ActionData) error {
+ name, _ := data.String("name")
+ email, _ := data.String("email")
+
+ s.Name = name
+ s.Email = email
+
+ log.Printf("Profile updated: name=%s, email=%s", s.Name, s.Email)
+ return nil
+}
+
+func main() {
+ // Parse port from environment or use default
+ port := os.Getenv("PORT")
+ if port == "" {
+ port = "8080"
+ }
+
+ // Create LiveTemplate instance
+ lt := livetemplate.Must(livetemplate.New("avatar-upload",
+ livetemplate.WithTemplateFS(templates),
+ livetemplate.WithDevMode(true),
+ )
+
+ // Create initial store
+ store := &ProfileStore{
+ Name: "John Doe",
+ Email: "john@example.com",
+ }
+
+ // Create handler with upload support
+ handler := lt.NewHandler(store)
+
+ // Serve static files (for uploaded avatars)
+ http.Handle("/uploads/", http.StripPrefix("/uploads/", http.FileServer(http.Dir("uploads"))))
+
+ // Mount the LiveTemplate handler
+ http.Handle("/", handler)
+
+ // Start server
+ addr := ":" + port
+ log.Printf("đ Avatar upload example running at http://localhost%s", addr)
+ log.Printf("đ¸ Upload an avatar to see the upload feature in action!")
+ log.Printf("đ Uploaded files will be saved to ./uploads/")
+
+ if err := http.ListenAndServe(addr, nil); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/avatar-upload/run.sh b/avatar-upload/run.sh
new file mode 100755
index 0000000..99f21a5
--- /dev/null
+++ b/avatar-upload/run.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# Simple script to run the avatar upload example
+
+cd "$(dirname "$0")"
+
+echo "đ Starting Avatar Upload Example..."
+echo "đ Server will run at http://localhost:8082"
+echo ""
+
+# Set PORT and run
+PORT=8082 go run main.go
diff --git a/chat/go.mod b/chat/go.mod
index fca41b0..98ea487 100644
--- a/chat/go.mod
+++ b/chat/go.mod
@@ -4,7 +4,7 @@ go 1.25
require (
github.com/chromedp/chromedp v0.14.2
- github.com/livetemplate/livetemplate v0.1.1
+ github.com/livetemplate/livetemplate v0.3.0
)
require (
@@ -30,6 +30,7 @@ require (
golang.org/x/net v0.44.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.29.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
)
// TODO: Add github.com/livetemplate/lvt v0.1.0 after it's tagged
diff --git a/chat/go.sum b/chat/go.sum
index c06aa39..c26c4d1 100644
--- a/chat/go.sum
+++ b/chat/go.sum
@@ -80,8 +80,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/livetemplate/livetemplate v0.1.1 h1:DS8VXLOvdHqtSbk+Zr6+znCHgRvU9qD6os3ABY9DOlA=
-github.com/livetemplate/livetemplate v0.1.1/go.mod h1:SobBok7X09b1oxEIHEAvABTRhGqRjCfMpUAY7E7XeHg=
+github.com/livetemplate/livetemplate v0.3.0 h1:k3cpsiOmWcjS+S/e5rvydbi6nY86ipnWd801B5hgL5M=
+github.com/livetemplate/livetemplate v0.3.0/go.mod h1:PYS1hH2a6o7d9LID96780l/HHSGJIJS70kBnVO1mIUA=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
@@ -159,5 +159,7 @@ golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/chat/main.go b/chat/main.go
index ff856a7..9f73f26 100644
--- a/chat/main.go
+++ b/chat/main.go
@@ -148,7 +148,7 @@ func main() {
// Uses default AnonymousAuthenticator - each browser gets its own session (via cookie)
// Tabs in same browser share state
// Configure via LVT_* environment variables (e.g., LVT_DEV_MODE=true)
- tmpl := livetemplate.New("chat", envConfig.ToOptions()...)
+ tmpl := livetemplate.Must(livetemplate.New("chat", envConfig.ToOptions()...))
// Mount handler
http.Handle("/", tmpl.Handle(state))
diff --git a/counter/go.mod b/counter/go.mod
index b858890..5b7d691 100644
--- a/counter/go.mod
+++ b/counter/go.mod
@@ -5,7 +5,7 @@ go 1.25
require (
github.com/chromedp/chromedp v0.14.2
github.com/gorilla/websocket v1.5.3
- github.com/livetemplate/livetemplate v0.1.1
+ github.com/livetemplate/livetemplate v0.3.0
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0
)
@@ -31,4 +31,5 @@ require (
golang.org/x/net v0.46.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.30.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
)
diff --git a/counter/go.sum b/counter/go.sum
index ef2b61e..ddb7b28 100644
--- a/counter/go.sum
+++ b/counter/go.sum
@@ -80,8 +80,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/livetemplate/livetemplate v0.1.1 h1:DS8VXLOvdHqtSbk+Zr6+znCHgRvU9qD6os3ABY9DOlA=
-github.com/livetemplate/livetemplate v0.1.1/go.mod h1:SobBok7X09b1oxEIHEAvABTRhGqRjCfMpUAY7E7XeHg=
+github.com/livetemplate/livetemplate v0.3.0 h1:k3cpsiOmWcjS+S/e5rvydbi6nY86ipnWd801B5hgL5M=
+github.com/livetemplate/livetemplate v0.3.0/go.mod h1:PYS1hH2a6o7d9LID96780l/HHSGJIJS70kBnVO1mIUA=
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0 h1:WQcir+LsmAlaihnnRdLUiGefy2J+cnpoRMrzJgNoF4k=
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0/go.mod h1:+MkJVOR/rgGWe6xEVnjRSRCKhjM1KkpeaheqS9UHjM8=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
@@ -161,5 +161,7 @@ golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/counter/main.go b/counter/main.go
index 06e4903..59c90de 100644
--- a/counter/main.go
+++ b/counter/main.go
@@ -60,7 +60,7 @@ func main() {
// Create template with environment-based configuration
// Configuration is loaded from LVT_* environment variables
- tmpl := livetemplate.New("counter", envConfig.ToOptions()...)
+ tmpl := livetemplate.Must(livetemplate.New("counter", envConfig.ToOptions()...))
// Mount handler - auto-handles initial page, WebSocket, and HTTP actions
http.Handle("/", tmpl.Handle(state))
diff --git a/graceful-shutdown/go.mod b/graceful-shutdown/go.mod
index fa9b915..e4768aa 100644
--- a/graceful-shutdown/go.mod
+++ b/graceful-shutdown/go.mod
@@ -3,7 +3,7 @@ module graceful-shutdown
go 1.25
require (
- github.com/livetemplate/livetemplate v0.1.1
+ github.com/livetemplate/livetemplate v0.3.0
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0
)
@@ -31,4 +31,5 @@ require (
golang.org/x/net v0.44.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.29.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
)
diff --git a/graceful-shutdown/go.sum b/graceful-shutdown/go.sum
index d0f43c1..090c207 100644
--- a/graceful-shutdown/go.sum
+++ b/graceful-shutdown/go.sum
@@ -80,8 +80,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/livetemplate/livetemplate v0.1.1 h1:DS8VXLOvdHqtSbk+Zr6+znCHgRvU9qD6os3ABY9DOlA=
-github.com/livetemplate/livetemplate v0.1.1/go.mod h1:SobBok7X09b1oxEIHEAvABTRhGqRjCfMpUAY7E7XeHg=
+github.com/livetemplate/livetemplate v0.3.0 h1:k3cpsiOmWcjS+S/e5rvydbi6nY86ipnWd801B5hgL5M=
+github.com/livetemplate/livetemplate v0.3.0/go.mod h1:PYS1hH2a6o7d9LID96780l/HHSGJIJS70kBnVO1mIUA=
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0 h1:WQcir+LsmAlaihnnRdLUiGefy2J+cnpoRMrzJgNoF4k=
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0/go.mod h1:+MkJVOR/rgGWe6xEVnjRSRCKhjM1KkpeaheqS9UHjM8=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
@@ -161,5 +161,7 @@ golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/graceful-shutdown/main.go b/graceful-shutdown/main.go
index 551f943..8ca92ad 100644
--- a/graceful-shutdown/main.go
+++ b/graceful-shutdown/main.go
@@ -63,7 +63,7 @@ func main() {
}
// Create template with environment-based configuration
- tmpl := livetemplate.New("counter", envConfig.ToOptions()...)
+ tmpl := livetemplate.Must(livetemplate.New("counter", envConfig.ToOptions()...))
// Get the LiveHandler for shutdown control
handler := tmpl.Handle(state)
diff --git a/observability/go.mod b/observability/go.mod
index 2f0e03a..6fdb33c 100644
--- a/observability/go.mod
+++ b/observability/go.mod
@@ -3,7 +3,7 @@ module observability
go 1.25
require (
- github.com/livetemplate/livetemplate v0.1.1
+ github.com/livetemplate/livetemplate v0.3.0
github.com/livetemplate/lvt v0.0.0-20251103070549-7ffea37f50da
)
@@ -31,6 +31,7 @@ require (
golang.org/x/net v0.44.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.29.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
)
// TODO: Add github.com/livetemplate/lvt v0.1.0 after it's tagged
diff --git a/observability/go.sum b/observability/go.sum
index 1ad4ca6..8fbd5b2 100644
--- a/observability/go.sum
+++ b/observability/go.sum
@@ -80,8 +80,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/livetemplate/livetemplate v0.1.1 h1:DS8VXLOvdHqtSbk+Zr6+znCHgRvU9qD6os3ABY9DOlA=
-github.com/livetemplate/livetemplate v0.1.1/go.mod h1:SobBok7X09b1oxEIHEAvABTRhGqRjCfMpUAY7E7XeHg=
+github.com/livetemplate/livetemplate v0.3.0 h1:k3cpsiOmWcjS+S/e5rvydbi6nY86ipnWd801B5hgL5M=
+github.com/livetemplate/livetemplate v0.3.0/go.mod h1:PYS1hH2a6o7d9LID96780l/HHSGJIJS70kBnVO1mIUA=
github.com/livetemplate/lvt v0.0.0-20251103070549-7ffea37f50da h1:ZONdEpB9vxj4xyJlQ1t3I/sIxkllrKu5fWadFL60nsA=
github.com/livetemplate/lvt v0.0.0-20251103070549-7ffea37f50da/go.mod h1:1/HRPggC3loru3AB6GYQdMWP1bJhuCGZERD36GlLEw0=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
@@ -161,5 +161,7 @@ golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/observability/main.go b/observability/main.go
index ed05fb2..c68b512 100644
--- a/observability/main.go
+++ b/observability/main.go
@@ -119,7 +119,7 @@ func main() {
// Create template with environment-based configuration
// Template operations are now automatically logged!
// Configuration is loaded from LVT_* environment variables
- tmpl := livetemplate.New("counter", envConfig.ToOptions()...)
+ tmpl := livetemplate.Must(livetemplate.New("counter", envConfig.ToOptions()...))
// Mount handler - auto-handles initial page, WebSocket, and HTTP actions
// All actions and WebSocket events are now logged and metered!
diff --git a/production/single-host/go.mod b/production/single-host/go.mod
index b1660c2..be593f9 100644
--- a/production/single-host/go.mod
+++ b/production/single-host/go.mod
@@ -3,7 +3,7 @@ module single-host
go 1.25
require (
- github.com/livetemplate/livetemplate v0.1.1
+ github.com/livetemplate/livetemplate v0.3.0
github.com/livetemplate/lvt v0.0.0-20251103070549-7ffea37f50da
)
@@ -31,6 +31,7 @@ require (
golang.org/x/net v0.44.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.29.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
)
// TODO: Add github.com/livetemplate/lvt v0.1.0 after it's tagged
diff --git a/production/single-host/go.sum b/production/single-host/go.sum
index 1ad4ca6..8fbd5b2 100644
--- a/production/single-host/go.sum
+++ b/production/single-host/go.sum
@@ -80,8 +80,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/livetemplate/livetemplate v0.1.1 h1:DS8VXLOvdHqtSbk+Zr6+znCHgRvU9qD6os3ABY9DOlA=
-github.com/livetemplate/livetemplate v0.1.1/go.mod h1:SobBok7X09b1oxEIHEAvABTRhGqRjCfMpUAY7E7XeHg=
+github.com/livetemplate/livetemplate v0.3.0 h1:k3cpsiOmWcjS+S/e5rvydbi6nY86ipnWd801B5hgL5M=
+github.com/livetemplate/livetemplate v0.3.0/go.mod h1:PYS1hH2a6o7d9LID96780l/HHSGJIJS70kBnVO1mIUA=
github.com/livetemplate/lvt v0.0.0-20251103070549-7ffea37f50da h1:ZONdEpB9vxj4xyJlQ1t3I/sIxkllrKu5fWadFL60nsA=
github.com/livetemplate/lvt v0.0.0-20251103070549-7ffea37f50da/go.mod h1:1/HRPggC3loru3AB6GYQdMWP1bJhuCGZERD36GlLEw0=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
@@ -161,5 +161,7 @@ golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/production/single-host/main.go b/production/single-host/main.go
index af8c910..e0210d4 100644
--- a/production/single-host/main.go
+++ b/production/single-host/main.go
@@ -93,7 +93,7 @@ func main() {
}
// Create template
- tmpl := livetemplate.New("app", envConfig.ToOptions()...)
+ tmpl := livetemplate.Must(livetemplate.New("app", envConfig.ToOptions()...))
liveHandler := tmpl.Handle(state)
// Setup HTTP routes with trace middleware
diff --git a/testing/01_basic/go.mod b/testing/01_basic/go.mod
index 6c0d761..2ce2d1b 100644
--- a/testing/01_basic/go.mod
+++ b/testing/01_basic/go.mod
@@ -3,7 +3,7 @@ module basic
go 1.25
require (
- github.com/livetemplate/livetemplate v0.1.1
+ github.com/livetemplate/livetemplate v0.3.0
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0
)
@@ -31,6 +31,7 @@ require (
golang.org/x/net v0.44.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.29.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
)
// TODO: Add github.com/livetemplate/lvt v0.1.0 after it's tagged
diff --git a/testing/01_basic/go.sum b/testing/01_basic/go.sum
index d0f43c1..090c207 100644
--- a/testing/01_basic/go.sum
+++ b/testing/01_basic/go.sum
@@ -80,8 +80,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/livetemplate/livetemplate v0.1.1 h1:DS8VXLOvdHqtSbk+Zr6+znCHgRvU9qD6os3ABY9DOlA=
-github.com/livetemplate/livetemplate v0.1.1/go.mod h1:SobBok7X09b1oxEIHEAvABTRhGqRjCfMpUAY7E7XeHg=
+github.com/livetemplate/livetemplate v0.3.0 h1:k3cpsiOmWcjS+S/e5rvydbi6nY86ipnWd801B5hgL5M=
+github.com/livetemplate/livetemplate v0.3.0/go.mod h1:PYS1hH2a6o7d9LID96780l/HHSGJIJS70kBnVO1mIUA=
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0 h1:WQcir+LsmAlaihnnRdLUiGefy2J+cnpoRMrzJgNoF4k=
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0/go.mod h1:+MkJVOR/rgGWe6xEVnjRSRCKhjM1KkpeaheqS9UHjM8=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
@@ -161,5 +161,7 @@ golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/testing/01_basic/main.go b/testing/01_basic/main.go
index 25cdc05..7f3280c 100644
--- a/testing/01_basic/main.go
+++ b/testing/01_basic/main.go
@@ -22,26 +22,8 @@ func (s *PageState) Change(ctx *livetemplate.ActionContext) error {
}
func main() {
- // Create template
- tmpl := livetemplate.New("welcome")
-
- // Parse template inline
- if _, err := tmpl.Parse(`
-
-
-
- {{.Title}}
-
-
- {{.Title}}
- {{.Message}}
- Count: {{.Count}}
-
-
-
- `); err != nil {
- log.Fatal(err)
- }
+ // Create template (will auto-discover welcome.tmpl)
+ tmpl := livetemplate.Must(livetemplate.New("welcome"))
// Create state
state := &PageState{
diff --git a/testing/01_basic/welcome.tmpl b/testing/01_basic/welcome.tmpl
new file mode 100644
index 0000000..b2e8003
--- /dev/null
+++ b/testing/01_basic/welcome.tmpl
@@ -0,0 +1,12 @@
+
+
+
+ {{.Title}}
+
+
+ {{.Title}}
+ {{.Message}}
+ Count: {{.Count}}
+
+
+
diff --git a/todos/go.mod b/todos/go.mod
index e1bd64a..0d42914 100644
--- a/todos/go.mod
+++ b/todos/go.mod
@@ -6,7 +6,7 @@ require (
github.com/chromedp/chromedp v0.14.2
github.com/go-playground/validator/v10 v10.28.0
github.com/gorilla/websocket v1.5.3
- github.com/livetemplate/livetemplate v0.1.1
+ github.com/livetemplate/livetemplate v0.3.0
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0
modernc.org/sqlite v1.39.1
)
@@ -37,6 +37,7 @@ require (
golang.org/x/net v0.46.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.30.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
modernc.org/libc v1.66.10 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
diff --git a/todos/go.sum b/todos/go.sum
index 4f9f7c0..49e92b3 100644
--- a/todos/go.sum
+++ b/todos/go.sum
@@ -84,8 +84,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/livetemplate/livetemplate v0.1.1 h1:DS8VXLOvdHqtSbk+Zr6+znCHgRvU9qD6os3ABY9DOlA=
-github.com/livetemplate/livetemplate v0.1.1/go.mod h1:SobBok7X09b1oxEIHEAvABTRhGqRjCfMpUAY7E7XeHg=
+github.com/livetemplate/livetemplate v0.3.0 h1:k3cpsiOmWcjS+S/e5rvydbi6nY86ipnWd801B5hgL5M=
+github.com/livetemplate/livetemplate v0.3.0/go.mod h1:PYS1hH2a6o7d9LID96780l/HHSGJIJS70kBnVO1mIUA=
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0 h1:WQcir+LsmAlaihnnRdLUiGefy2J+cnpoRMrzJgNoF4k=
github.com/livetemplate/lvt v0.0.0-20251103195948-fbcd6dfae2d0/go.mod h1:+MkJVOR/rgGWe6xEVnjRSRCKhjM1KkpeaheqS9UHjM8=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
@@ -177,6 +177,8 @@ golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/todos/main.go b/todos/main.go
index 7571b2d..7526262 100644
--- a/todos/main.go
+++ b/todos/main.go
@@ -374,7 +374,7 @@ func main() {
// Create template with environment-based configuration
// Configuration is loaded from LVT_* environment variables
- tmpl := livetemplate.New("todos", envConfig.ToOptions()...)
+ tmpl := livetemplate.Must(livetemplate.New("todos", envConfig.ToOptions()...))
// Mount handler - auto-handles initial page, WebSocket, and HTTP actions
http.Handle("/", tmpl.Handle(state))
diff --git a/trace-correlation/go.mod b/trace-correlation/go.mod
index 0f0d7c2..da58973 100644
--- a/trace-correlation/go.mod
+++ b/trace-correlation/go.mod
@@ -3,7 +3,7 @@ module trace-correlation
go 1.25
require (
- github.com/livetemplate/livetemplate v0.1.1
+ github.com/livetemplate/livetemplate v0.3.0
github.com/livetemplate/lvt v0.0.0-20251103070549-7ffea37f50da
)
@@ -31,6 +31,7 @@ require (
golang.org/x/net v0.44.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.29.0 // indirect
+ golang.org/x/time v0.14.0 // indirect
)
// TODO: Add github.com/livetemplate/lvt v0.1.0 after it's tagged
diff --git a/trace-correlation/go.sum b/trace-correlation/go.sum
index 1ad4ca6..8fbd5b2 100644
--- a/trace-correlation/go.sum
+++ b/trace-correlation/go.sum
@@ -80,8 +80,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/livetemplate/livetemplate v0.1.1 h1:DS8VXLOvdHqtSbk+Zr6+znCHgRvU9qD6os3ABY9DOlA=
-github.com/livetemplate/livetemplate v0.1.1/go.mod h1:SobBok7X09b1oxEIHEAvABTRhGqRjCfMpUAY7E7XeHg=
+github.com/livetemplate/livetemplate v0.3.0 h1:k3cpsiOmWcjS+S/e5rvydbi6nY86ipnWd801B5hgL5M=
+github.com/livetemplate/livetemplate v0.3.0/go.mod h1:PYS1hH2a6o7d9LID96780l/HHSGJIJS70kBnVO1mIUA=
github.com/livetemplate/lvt v0.0.0-20251103070549-7ffea37f50da h1:ZONdEpB9vxj4xyJlQ1t3I/sIxkllrKu5fWadFL60nsA=
github.com/livetemplate/lvt v0.0.0-20251103070549-7ffea37f50da/go.mod h1:1/HRPggC3loru3AB6GYQdMWP1bJhuCGZERD36GlLEw0=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
@@ -161,5 +161,7 @@ golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/trace-correlation/main.go b/trace-correlation/main.go
index d681be2..7000748 100644
--- a/trace-correlation/main.go
+++ b/trace-correlation/main.go
@@ -97,7 +97,7 @@ func main() {
}
// Create template
- tmpl := livetemplate.New("counter", envConfig.ToOptions()...)
+ tmpl := livetemplate.Must(livetemplate.New("counter", envConfig.ToOptions()...))
liveHandler := tmpl.Handle(state)
// Setup HTTP routes with trace middleware