| name | lvt-add-migration |
| description | Use when adding database migrations to LiveTemplate apps - guides both auto-generated migrations (from lvt gen resource) and custom migrations (indexes, constraints, data transformations) |
| keywords | ["lvt","livetemplate","lt"] |
| category | core |
| version | 1.0.0 |
lvt-add-migration
Add and manage database migrations in LiveTemplate applications using goose + sqlc.
🎯 ACTIVATION RULES
Context Detection
This skill typically runs in existing LiveTemplate projects (.lvtrc exists).
✅ Context Established By:
- Project context -
.lvtrc exists (most common scenario)
- Agent context - User is working with
lvt-assistant agent
- Keyword context - User mentions "lvt", "livetemplate", or "lt"
Keyword matching (case-insensitive): lvt, livetemplate, lt
Trigger Patterns
With Context:
✅ "create a migration"
✅ "add an index to posts"
✅ "run migrations"
Without Context (needs keywords):
✅ "create a migration in my lvt app"
✅ "use livetemplate to add database migration"
❌ "create a migration" (no context, no keywords)
Overview
LiveTemplate uses goose for migration version control and sqlc for type-safe code generation. Migrations come from two sources:
- Auto-generated:
lvt gen resource creates migrations automatically
- Custom migrations: Manual SQL for indexes, constraints, data fixes, etc.
Migration Workflow
Auto-Generated Migrations (Resources)
When you generate a resource, lvt creates:
database/schema.sql - Updated with new table
database/queries.sql - CRUD operations
- Migration file - Timestamped in
migrations/
lvt gen resource products name price:float
lvt migration up
lvt migration status
Note: lvt migration up automatically runs sqlc generate - no need to run it manually.
Custom Migrations
For indexes, constraints, or data transformations:
lvt migration create add_products_price_index
-- +goose Up
CREATE INDEX idx_products_price ON products(price);
-- +goose Down
DROP INDEX idx_products_price;
lvt migration up
Commands Reference
| Command | Purpose | Auto-runs sqlc? |
|---|
lvt migration create <name> | Create empty migration file | No |
lvt migration up | Apply pending migrations | Yes ✓ |
lvt migration down | Rollback last migration | Yes ✓ |
lvt migration status | Show migration state | No |
Common Scenarios
Adding an Index
lvt migration create add_user_email_index
-- +goose Up
CREATE INDEX idx_users_email ON users(email);
-- +goose Down
DROP INDEX idx_users_email;
lvt migration up
Adding a Constraint
lvt migration create add_price_check
-- +goose Up
-- +goose StatementBegin
ALTER TABLE products
ADD CONSTRAINT price_positive CHECK (price > 0);
-- +goose StatementEnd
-- +goose Down
ALTER TABLE products DROP CONSTRAINT price_positive;
lvt migration up
Data Transformation
lvt migration create normalize_user_emails
-- +goose Up
UPDATE users SET email = LOWER(TRIM(email));
-- +goose Down
-- Data transformations usually can't be reversed
-- Document this in comment
lvt migration up
Migration File Format
Goose uses special comments to mark sections:
CREATE TABLE users (id INTEGER PRIMARY KEY);
DROP TABLE users;
For multi-statement migrations:
CREATE TABLE users (id INTEGER PRIMARY KEY);
CREATE INDEX idx_users_id ON users(id);
DROP INDEX idx_users_id;
DROP TABLE users;
When to Use Custom Migrations
Use custom migrations for:
- Indexes for query performance
- Foreign key constraints
- Unique constraints
- Check constraints
- Data fixes or transformations
- Complex schema changes
DON'T use for:
- Adding new tables → Use
lvt gen resource
- Adding columns to existing tables → Edit schema.sql + create migration manually
Common Mistakes
❌ Editing schema.sql Without Migration
vim database/schema.sql
lvt migration up
Why wrong: Schema changes need migrations for version control and team coordination.
❌ Running sqlc Manually
lvt migration up
cd database && sqlc generate
Why wrong: lvt migration up auto-runs sqlc generate.
❌ Wrong Goose Format
CREATE INDEX idx_products_price ON products(price);
Why wrong: Goose won't recognize this as a migration.
❌ Forgetting Down Migration
CREATE INDEX idx_products_price ON products(price);
Why wrong: Can't rollback if needed. Always write reversible migrations when possible.
Rollback Strategy
Check status before rolling back:
lvt migration status
lvt migration down
lvt migration status
Note: Rolling back drops the last migration. If you need to roll back multiple migrations, run lvt migration down multiple times.
Troubleshooting
Migration Fails
lvt migration up
lvt migration up
Out of Sync State
lvt migration status
Integration with Development Workflow
Typical flow:
lvt gen resource products name price:float
lvt migration create add_products_price_index
lvt migration up
vim app/products/products.go
File Locations
project/
├── database/
│ ├── migrations/ ← Migration files here
│ │ ├── 20240101120000_create_products.sql
│ │ └── 20240101120100_add_products_price_index.sql
│ ├── schema.sql ← Current schema (updated by gen resource)
│ ├── queries.sql ← SQL queries (updated by gen resource)
│ └── models/ ← Generated Go code (auto-generated)
└── app.db ← SQLite database
Quick Reference
| I need to... | Command |
|---|
| Add a new table | lvt gen resource <name> <fields> |
| Add an index | lvt migration create add_<table>_<col>_index |
| Add a constraint | lvt migration create add_<name>_constraint |
| Apply migrations | lvt migration up |
| Rollback last | lvt migration down |
| Check status | lvt migration status |
| Fix data | lvt migration create fix_<description> |
Remember
✓ lvt gen resource creates migrations automatically
✓ lvt migration up auto-runs sqlc generate
✓ Always write Down migrations when possible
✓ Use goose format (-- +goose Up/Down)
✓ Custom migrations go in database/migrations/
✗ Don't edit schema.sql directly without creating migration
✗ Don't manually run sqlc after migration up
✗ Don't skip Down migration section