LiveTemplate CLI (lvt) - Complete Guide

The lvt CLI is a Phoenix-inspired code generator for building LiveTemplate applications with CRUD functionality, authentication, and real-time features.

Table of Contents


Installation

go install github.com/livetemplate/lvt/cmd/lvt@latest

Or build from source:

git clone https://github.com/livetemplate/lvt
cd lvt
go build -o lvt ./cmd/lvt

Verify installation:

lvt --help

Quick Start

# 1. Create a new application
lvt new myblog
cd myblog

# 2. Generate a CRUD resource
lvt gen posts title content published:bool

# 3. Run migrations (auto-generates database code)
lvt migration up

# 4. Run the app
go run cmd/myblog/main.go

# 5. Visit http://localhost:8080/posts

That's it! You have a fully functional CRUD application with:


Command Reference

Creating Applications

lvt new <name>

Creates a new LiveTemplate application.

Usage:

# Interactive mode (recommended for beginners)
lvt new

# Direct mode
lvt new myapp

# Specify kit (CSS framework)
lvt new myapp --kit multi     # Tailwind CSS (default)
lvt new myapp --kit simple    # Pico CSS

What it generates:

myapp/
├── cmd/myapp/main.go         # Application entry point
├── go.mod                    # Go module with tools directive
├── internal/
│   ├── app/                  # Handlers and templates
│   ├── database/
│   │   ├── db.go            # Database connection
│   │   ├── schema.sql       # Database schema
│   │   ├── queries.sql      # SQL queries (for sqlc)
│   │   ├── sqlc.yaml        # sqlc configuration
│   │   └── models/          # Generated code
│   └── shared/              # Shared utilities
├── web/assets/              # Static assets
└── README.md

Kit Options:


Generating Resources

lvt gen <resource> <field:type>...

Generates a full CRUD resource with database integration.

Usage:

# Interactive mode
lvt gen

# With explicit types
lvt gen users name:string email:string age:int

# With type inference (smart defaults)
lvt gen products name price quantity enabled created_at
# → Infers: name:string price:float quantity:int enabled:bool created_at:time

What it generates:

Features:

Type Mappings:

CLI Type Go Type SQL Type
string string TEXT
int int64 INTEGER
bool bool BOOLEAN
float float64 REAL
time time.Time DATETIME

Relationships:

# Basic foreign key (ON DELETE CASCADE)
lvt gen comments post_id:references:posts author text

# Custom ON DELETE behavior
lvt gen audit_logs user_id:references:users:set_null action

# Multiple references
lvt gen likes user_id:references:users post_id:references:posts

# Restrict deletion
lvt gen invoices customer_id:references:customers:restrict amount:float

Generating Views

lvt gen view <name>

Generates a view-only handler without database integration.

Usage:

# Interactive mode
lvt gen view

# Direct mode
lvt gen view dashboard

What it generates:

Use cases:


Generating Auth

lvt gen auth

Generates a complete authentication system similar to Phoenix's mix phx.gen.auth.

Usage:

# Default: User struct, users table
lvt gen auth

# Custom struct name (table name auto-pluralized)
lvt gen auth Account              # Creates Account struct, accounts table

# Custom struct and table names
lvt gen auth Admin admin_users    # Creates Admin struct, admin_users table

# With feature flags
lvt gen auth --no-magic-link                    # Password only
lvt gen auth Account --no-email-confirm         # Custom names + no confirmation
lvt gen auth Admin admin_users --no-password    # Custom names + magic-link only

Flags:

Note: At least one authentication method (password or magic-link) must be enabled.

What it generates:

Database Tables:

Default names (can be customized):

Features:

Next Steps:

# 1. Run migrations
lvt migration up

# 2. Generate sqlc code
sqlc generate

# 3. Wire routes in main.go (see internal/app/auth/auth.go for examples)

# 4. Configure email sender (see internal/shared/email/email.go)

Example main.go setup:

import (
	"yourapp/internal/app/auth"
	"yourapp/internal/shared/email"
	"github.com/livetemplate/livetemplate"
)

// Create auth handler
emailSender := email.NewConsoleEmailSender()
authHandler := auth.NewUserHandler(db, emailSender, "http://localhost:8080")

// Create template and register routes
tmpl, err := livetemplate.New("auth")
if err != nil {
	log.Fatal(err)
}
if _, err := tmpl.ParseFiles("internal/app/auth/auth.tmpl"); err != nil {
	log.Fatal(err)
}
http.Handle("/auth", tmpl.Handle(authHandler, livetemplate.AsState(&auth.State{})))
http.HandleFunc("/auth/logout", authHandler.HandleLogout)
http.HandleFunc("/auth/magic", authHandler.HandleMagicLinkVerify)      // if magic-link enabled
http.HandleFunc("/auth/reset", authHandler.HandleResetPassword)        // if password-reset enabled
http.HandleFunc("/auth/confirm", authHandler.HandleConfirmEmail)       // if email-confirm enabled

// Protected route example
protectedHandler := authHandler.RequireAuth(http.HandlerFunc(myHandler))
http.Handle("/dashboard", protectedHandler)

Customizing CSS Framework:

The generated auth templates use Tailwind CSS by default. To use a different CSS framework (Bulma, Pico, or plain HTML), see the Auth Customization Guide for complete examples and instructions.

E2E Testing:

The auth command generates comprehensive E2E tests using chromedp that test all auth flows:

To run E2E tests:

# Requires Docker to run Chrome in a container
go test ./internal/app/auth -run TestAuthE2E -v

# Skip E2E tests in short mode
go test ./internal/app/auth -short

The E2E tests include:


Managing Migrations

lvt migration <command>

Manages database migrations using Goose.

Commands:

# Apply all pending migrations (and run sqlc generate)
lvt migration up

# Rollback one migration
lvt migration down

# Show migration status
lvt migration status

# Create a new migration
lvt migration create add_user_roles

Auto-generated Migrations:

When you run lvt gen, migrations are automatically created:

lvt gen posts title content
# Creates: internal/database/migrations/20240315120000_create_posts.sql

Migration Format:

-- +goose Up
CREATE TABLE posts (
    id TEXT PRIMARY KEY,
    title TEXT NOT NULL,
    content TEXT,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- +goose Down
DROP TABLE posts;

sqlc Integration:

lvt migration up automatically runs sqlc generate after applying migrations, ensuring your Go database code stays in sync.


Kit Management

lvt kits <command>

Manages CSS framework kits.

Commands:

# List all available kits
lvt kits list

# Show kit information
lvt kits info tailwind

# Customize a kit for your project
lvt kits customize tailwind

# Customize globally (all projects)
lvt kits customize tailwind --global

# Validate kit structure
lvt kits validate .lvt/kits/tailwind

Available System Kits:

Kit Framework Description
multi Tailwind Multi-page app (default)
single Tailwind Single-page app
simple Pico CSS Minimal semantic HTML

Kits System

Kits are complete starter packages that include:

  1. CSS Framework Integration - ~60 helper methods for CSS classes
  2. Components - Pre-built UI blocks (form, table, layout, pagination, etc.)
  3. Templates - Generator templates for resources, views, and apps

Kit Cascade

Kits are loaded with this priority:

  1. Project: .lvt/kits/<name>/ (highest)
  2. User: ~/.config/lvt/kits/<name>/
  3. System: Embedded in binary (fallback)

This allows:

Customizing Kits

# 1. Copy kit to project
lvt kits customize multi

# 2. Edit templates
cd .lvt/kits/multi/templates
# Edit resource.go.tmpl, resource.tmpl, etc.

# 3. Generate with custom templates
lvt gen products name price
# Uses your customized templates

Type System

Type Inference

The CLI automatically infers types from field names:

lvt gen articles title content published_at author email price
# Infers: title=string, content=string, published_at=time,
#         author=string, email=string, price=float

Inference Rules:

String (default):

Integer:

Float:

Boolean:

Time:

Type Aliases


Testing

Each generated resource includes comprehensive tests.

WebSocket Tests (*_ws_test.go)

Fast unit tests for WebSocket protocol:

# Run WebSocket tests
go test ./internal/app/users -run WebSocket

# Features:
# - Dynamic port allocation
# - WebSocket connection testing
# - CRUD action testing
# - Server log capture
# - Fast execution (~2-5 seconds)

E2E Tests (*_test.go)

Full browser tests with Chromedp:

# Run E2E tests
go test ./internal/app/users -run E2E

# Features:
# - Real browser interactions
# - Visual verification
# - Screenshot capture
# - Console log access
# - Comprehensive (~20-60 seconds)

Skip Slow Tests

go test -short ./...

Project Structure

Generated apps follow idiomatic Go conventions:

myapp/
├── cmd/myapp/main.go          # Application entry point
├── go.mod                     # Go module
├── internal/
│   ├── app/                   # Handlers and templates (co-located!)
│   │   ├── posts/
│   │   │   ├── posts.go       # Handler
│   │   │   ├── posts.tmpl     # Template
│   │   │   ├── posts_test.go  # E2E tests
│   │   │   └── posts_ws_test.go # WebSocket tests
│   │   └── users/
│   ├── database/
│   │   ├── db.go              # Database connection
│   │   ├── migrations/        # Migration files
│   │   ├── queries.sql        # SQL queries (sqlc)
│   │   ├── sqlc.yaml          # sqlc config
│   │   └── models/            # Generated code
│   └── shared/                # Shared utilities
│       ├── password/          # Password hashing
│       └── email/             # Email sender
└── web/assets/                # Static assets

Key Design Decisions:


Development Workflow

Standard Workflow

# 1. Create app
lvt new myapp
cd myapp

# 2. Generate resources
lvt gen users name email
lvt gen posts title content user_id:references:users

# 3. Run migrations (auto-generates DB code)
lvt migration up

# 4. Run tests
go test ./...

# 5. Run app
go run cmd/myapp/main.go

Iterative Development

# Add a field to existing resource
lvt migration create add_users_bio
# Edit migration file to add bio column

# Run migration
lvt migration up

# Update queries.sql to include bio
# Update handler and template

# Test changes
go test ./internal/app/users

Best Practices

1. Start Simple

Begin with core resources, add features incrementally:

lvt new blog
cd blog
lvt gen posts title content      # Start here
lvt gen comments post_id:references:posts author text  # Add later

2. Use Type Inference

Let the CLI infer types for common fields:

# Instead of:
lvt gen users name:string email:string created_at:time

# Do this:
lvt gen users name email created_at

3. Test Continuously

Run tests after each change:

go test ./...

4. Customize Templates

Copy and modify templates for your needs:

lvt kits customize multi
cd .lvt/kits/multi/templates
# Edit templates

5. Use Migrations

Always use migrations for schema changes:

lvt migration create add_user_roles
# Edit migration file
lvt migration up

Troubleshooting

GOWORK conflicts

If creating an app inside an existing Go workspace:

GOWORK=off go run cmd/myapp/main.go

Migration errors

Check migration status:

lvt migration status

Rollback if needed:

lvt migration down

sqlc errors

Manually run sqlc:

sqlc generate

Test failures

Run with verbose output:

go test -v ./internal/app/users

Examples

Blog Application

lvt new myblog
cd myblog

lvt gen posts title content published:bool
lvt gen categories name description
lvt gen comments post_id:references:posts author text

lvt migration up
go test ./...
go run cmd/myblog/main.go

E-commerce Store

lvt new mystore
cd mystore

lvt gen products name price:float stock:int
lvt gen customers name email
lvt gen orders customer_id:references:customers total:float

lvt migration up
go test ./...
go run cmd/mystore/main.go

Social Network

lvt new mysocial
cd mysocial

# Generate auth first
lvt gen auth

lvt gen profiles user_id:references:users bio avatar_url
lvt gen posts user_id:references:users content
lvt gen likes user_id:references:users post_id:references:posts

lvt migration up
go test ./...
go run cmd/mysocial/main.go

Next Steps

  1. Add Authentication - Run lvt gen auth
  2. Add More Resources - Generate CRUD for your domain
  3. Customize Templates - Tailor to your design
  4. Add Business Logic - Extend handlers
  5. Deploy - Build and deploy your app

For more information: