# TankStopp Templ Integration Guide

## Overview

This guide walks you through the process of migrating from traditional HTML templates to the new `a-h/templ` system in TankStopp. The migration provides better performance, type safety, and developer experience.

## Prerequisites

Before starting the migration, ensure you have:

- Go 1.21 or later installed
- Access to the TankStopp codebase
- Basic understanding of Go templates and HTML
- Familiarity with the existing codebase structure

## Step 1: Install Required Tools

### Install templ CLI

```bash
go install github.com/a-h/templ/cmd/templ@latest
```

### Install development tools (optional but recommended)

```bash
# Hot reload tool
go install github.com/cosmtrek/air@latest

# File watcher (for manual watch scripts)
# macOS
brew install entr

# Linux
sudo apt-get install entr
```

## Step 2: Update Dependencies

The templ dependency should already be in your `go.mod` file:

```go
require (
    github.com/a-h/templ v0.3.906
    // ... other dependencies
)
```

If not, add it:

```bash
go get github.com/a-h/templ@latest
go mod tidy
```

## Step 3: Generate Templ Templates

Generate the Go code from the templ templates:

```bash
# Using the build script
./scripts/build.sh generate

# Or using templ directly
templ generate ./internal/views/

# Or using the Makefile
make generate
```

## Step 4: Update Your Handlers

### Before (Old HTML Template System)

```go
// Old handler using html/template
func DashboardHandler(w http.ResponseWriter, r *http.Request) {
    data := struct {
        Title string
        User  *models.User
        Stops []models.FuelStop
    }{
        Title: "Dashboard",
        User:  user,
        Stops: stops,
    }
    
    tmpl := template.Must(template.ParseFiles("templates/dashboard.html"))
    tmpl.Execute(w, data)
}
```

### After (New Templ System)

```go
// New handler using templ
func DashboardHandler(w http.ResponseWriter, r *http.Request) {
    // Get data...
    user := getUserFromContext(r.Context())
    stops, _ := h.db.GetFuelStops(user.ID, "", "", "", "")
    vehicles, _ := h.db.GetVehicles(user.ID)
    
    // Render templ component
    component := pages.DashboardPage(user, user.Username, stops, vehicles, len(stops), 0.0, 0.0, nil)
    
    w.Header().Set("Content-Type", "text/html")
    if err := component.Render(r.Context(), w); err != nil {
        http.Error(w, "Failed to render dashboard", http.StatusInternalServerError)
        return
    }
}
```

## Step 5: Update Route Registration

### Replace Old Template Handlers

Update your main router to use the new templ handlers:

```go
// main.go or router setup
func setupRoutes() *mux.Router {
    r := mux.NewRouter()
    
    // Create templ handlers
    templHandlers := handlers.NewTemplHandlers(db, auth, currency)
    
    // Authentication routes
    r.HandleFunc("/login", templHandlers.LoginHandler).Methods("GET", "POST")
    r.HandleFunc("/register", templHandlers.RegisterHandler).Methods("GET", "POST")
    r.HandleFunc("/logout", templHandlers.LogoutHandler).Methods("POST")
    
    // Protected routes (add auth middleware)
    protected := r.PathPrefix("/").Subrouter()
    protected.Use(authMiddleware)
    
    protected.HandleFunc("/dashboard", templHandlers.DashboardHandler).Methods("GET")
    protected.HandleFunc("/add", templHandlers.AddFuelStopHandler).Methods("GET", "POST")
    protected.HandleFunc("/edit/{id}", templHandlers.EditFuelStopHandler).Methods("GET", "POST")
    protected.HandleFunc("/vehicles", templHandlers.VehiclesHandler).Methods("GET")
    protected.HandleFunc("/add-vehicle", templHandlers.AddVehicleHandler).Methods("GET", "POST")
    protected.HandleFunc("/settings", templHandlers.SettingsHandler).Methods("GET")
    
    // Static files
    r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static/"))))
    
    return r
}
```

## Step 6: Update Authentication Middleware

Ensure your auth middleware sets the user in the request context:

```go
func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Get session from cookie
        cookie, err := r.Cookie("session")
        if err != nil {
            http.Redirect(w, r, "/login", http.StatusSeeOther)
            return
        }
        
        // Validate session and get user
        user, err := auth.ValidateSession(cookie.Value)
        if err != nil {
            http.Redirect(w, r, "/login", http.StatusSeeOther)
            return
        }
        
        // Add user to request context
        ctx := context.WithValue(r.Context(), "user", user)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}
```

## Step 7: Update Main Application

Update your main application file to use the new routing:

```go
// main.go
func main() {
    // Initialize database, auth, currency services
    db := database.New("fuel_stops.db")
    authService := auth.New(db)
    currencyService := currency.New()
    
    // Setup routes with new handlers
    router := setupRoutes(db, authService, currencyService)
    
    // Start server
    log.Println("Server starting on :8080")
    log.Fatal(http.ListenAndServe(":8080", router))
}
```

## Step 8: Build and Test

### Build the application

```bash
# Using the build script
./scripts/build.sh dev

# Or using the Makefile
make dev

# Or manual build
make generate
go build -o tankstopp ./cmd/main.go
```

### Run the application

```bash
# Direct run
./tankstopp

# Or with hot reload
make run-dev

# Or using air
air
```

### Test the migration

1. **Login/Registration**: Test user authentication flows
2. **Dashboard**: Verify fuel stops display correctly
3. **Add Fuel Stop**: Test form submission and validation
4. **Vehicle Management**: Test vehicle CRUD operations
5. **Settings**: Test user preference updates
6. **Responsive Design**: Test on different screen sizes

## Step 9: Clean Up Old Templates

Once everything is working, remove the old HTML templates:

```bash
# Backup old templates (optional)
mkdir -p backup
mv templates backup/

# Or remove directly
rm -rf templates/
```

## Step 10: Update Build Process

### Update CI/CD Pipeline

If you have a CI/CD pipeline, update it to include templ generation:

```yaml
# .github/workflows/build.yml
- name: Generate templ templates
  run: |
    go install github.com/a-h/templ/cmd/templ@latest
    templ generate ./internal/views/

- name: Build application
  run: go build -o tankstopp ./cmd/main.go
```

### Update Docker Build

If using Docker, update your Dockerfile:

```dockerfile
# Dockerfile
FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

# Install templ
RUN go install github.com/a-h/templ/cmd/templ@latest

COPY . .

# Generate templates and build
RUN templ generate ./internal/views/
RUN go build -o tankstopp ./cmd/main.go

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/tankstopp .
COPY --from=builder /app/static ./static
CMD ["./tankstopp"]
```

## Development Workflow

### Daily Development

1. **Start development server**:
   ```bash
   make run-dev
   # or
   air
   ```

2. **Make changes to templ files**:
   - Edit `.templ` files in `internal/views/`
   - Templates are automatically regenerated in watch mode

3. **Format code regularly**:
   ```bash
   make format
   ```

### Adding New Pages

1. **Create templ template**:
   ```bash
   # Create new template file
   touch internal/views/pages/my_new_page.templ
   ```

2. **Define the template**:
   ```go
   package pages
   
   import (
       "tankstopp/internal/views/components"
       "tankstopp/internal/models"
   )
   
   templ MyNewPage(user *models.User, data MyData) {
       @components.BaseLayout("My New Page", user, user.Username) {
           @components.PageHeader("Subtitle", "My New Page")
           
           <div class="page-body">
               <div class="container-xl">
                   // Your content here
               </div>
           </div>
       }
   }
   ```

3. **Generate and create handler**:
   ```bash
   make generate
   ```

4. **Add handler method**:
   ```go
   func (h *TemplHandlers) MyNewPageHandler(w http.ResponseWriter, r *http.Request) {
       user := getUserFromContext(r.Context())
       // Get data...
       
       component := pages.MyNewPage(user, data)
       
       w.Header().Set("Content-Type", "text/html")
       component.Render(r.Context(), w)
   }
   ```

5. **Add route**:
   ```go
   r.HandleFunc("/my-new-page", templHandlers.MyNewPageHandler).Methods("GET")
   ```

## Troubleshooting

### Common Issues

1. **Templates not updating**:
   - Make sure you're running `make generate` after changing `.templ` files
   - Check that generated `*_templ.go` files are being updated

2. **Import errors**:
   - Ensure all imports in templ files are valid Go imports
   - Check that models and services are properly imported

3. **Context issues**:
   - Make sure user is properly set in request context
   - Verify auth middleware is working correctly

4. **Static files not loading**:
   - Check that static file serving is properly configured
   - Verify file paths in templates are correct

### Performance Optimization

1. **Enable compression**:
   ```go
   // Add gzip middleware
   import "github.com/gorilla/handlers"
   
   router := setupRoutes()
   handler := handlers.CompressHandler(router)
   ```

2. **Add caching headers**:
   ```go
   // For static files
   r.PathPrefix("/static/").Handler(
       http.StripPrefix("/static/", 
           addCacheHeaders(http.FileServer(http.Dir("./static/")))))
   ```

3. **Monitor memory usage**:
   ```bash
   # Check memory usage
   go tool pprof http://localhost:8080/debug/pprof/heap
   ```

## Best Practices

1. **Component Reusability**: Break down complex pages into smaller, reusable components
2. **Type Safety**: Always use strongly-typed parameters in templ functions
3. **Error Handling**: Properly handle rendering errors in handlers
4. **Performance**: Use templ's compile-time optimization features
5. **Testing**: Write tests for your handlers and components
6. **Documentation**: Document complex templ components and their usage

## Next Steps

After successful migration:

1. **Add Tests**: Create tests for your new handlers and components
2. **Performance Monitoring**: Set up monitoring for template rendering performance
3. **Accessibility**: Ensure templates meet accessibility standards
4. **SEO**: Add proper meta tags and structured data
5. **Internationalization**: Consider adding i18n support

## Support

For issues or questions:

1. Check the [templ documentation](https://templ.guide/)
2. Review the example handlers in `internal/handlers/templ_handlers.go`
3. Look at the component examples in `internal/views/components/`
4. Check the build scripts and Makefile for automation examples

## Conclusion

The migration to templ provides significant benefits:
- **Type Safety**: Compile-time checking prevents runtime errors
- **Performance**: No runtime template parsing
- **Developer Experience**: Better IDE support and refactoring
- **Maintainability**: Component-based architecture

The new system is more robust and provides a better foundation for future development.