One of the most tedious parts of building a web application is writing CRUD boilerplate. With Stacks, your models automatically generate fully typed API endpoints, database migrations, factories, and seeders.
Define a Model, Get an API
Here's what a typical Stacks model looks like:
// app/Models/Post.ts
export default defineModel({
name: 'Post',
table: 'posts',
traits: {
useTimestamps: true,
useApi: {
uri: 'posts',
routes: ['index', 'store', 'show', 'update', 'destroy'],
},
},
attributes: {
title: {
validation: { rule: schema.string().min(3).max(255) },
factory: faker => faker.lorem.sentence(),
},
slug: {
unique: true,
validation: { rule: schema.string().min(3).max(255) },
},
body: {
validation: { rule: schema.string() },
},
},
})
From this single file, Stacks generates:
- API routes:
GET /api/posts,POST /api/posts,GET /api/posts/:id,PATCH /api/posts/:id,DELETE /api/posts/:id - Database migration: Creates the
poststable with all columns - Factory: Generates realistic test data using Faker
- Seeder: Populates your database with sample data
- TypeScript types: Full type inference for queries and responses
Type-Safe Queries
The Stacks ORM is built on Kysely, giving you fully type-safe database queries:
const posts = await db
.selectFrom('posts')
.where('status', '=', 'published')
.orderBy('published_at', 'desc')
.selectAll()
.execute()
Every column name, operator, and value is type-checked at compile time. Typos become compile errors, not runtime bugs.
Relationships
Stacks supports all common relationship types with a clean, declarative syntax:
export default defineModel({
name: 'Post',
belongsTo: ['Author'],
traits: { taggable: true, categorizable: true, commentables: true },
})
What's Next
We are working on even more ORM features — real-time subscriptions, full-text search integration, and automatic OpenAPI documentation generation. Stay tuned.