Frequently Asked Questions
Common questions about the s-m-r-t framework, setup, troubleshooting, and best practices.
Getting Started
What does s-m-r-t stand for?
What is s-m-r-t?
s-m-r-t is a full-stack TypeScript framework that abstracts away implementation details for databases, REST APIs, MCP tools, and CLI commands. Define your data models once with the @smrt decorator, and get auto-generated APIs, CLI commands, and Claude integration.
Which databases does s-m-r-t support?
s-m-r-t supports multiple databases through adapters:
- SQLite (great for development and testing)
- PostgreSQL (recommended for production)
- DuckDB (analytical workloads)
Do I need to know SQL?
No! s-m-r-t abstracts database operations into TypeScript methods. However, understanding basic database concepts (tables, relationships, indexes) is helpful for building efficient applications.
Can I use s-m-r-t with an existing database?
Yes! s-m-r-t can work with existing databases. Use the scanner to generate SmrtObject classes from your existing schema, or manually define models that map to your tables.
Configuration & Setup
How do I configure database connections?
Create a smrt.config.ts file with a url connection string:
export default {
database: {
adapter: 'postgres',
url: process.env.DATABASE_URL || 'postgresql://user:password@localhost:5432/myapp'
}
};
// For SQLite:
// database: { adapter: 'sqlite', url: 'myapp.db' }How do I enable API generation?
Add api: true to your @smrt decorator:
@smrt({
api: true, // Generates all CRUD endpoints
// OR specify operations:
api: {
include: ['list', 'get', 'create']
}
})
class Product extends SmrtObject {
// ...
}How do I set up multi-tenancy?
Use the smrt-tenancy module with the @TenantScoped decorator. All queries will automatically filter by the current tenant context.
Development
How do I run migrations?
s-m-r-t can auto-generate migrations from your models. Use the CLI:
smrt db:diff --generate
smrt db:migrateHow do I test s-m-r-t applications?
Use smrt-vitest for testing with smrtVitestPlugin() in your vitest config and createIsolatedTestDb() for DB isolation:
import { createIsolatedTestDb } from '@happyvertical/smrt-vitest';
describe('Task Tests', () => {
it('should create task', async () => {
const db = await createIsolatedTestDb();
const tasks = await TaskCollection.create({ db });
const task = await tasks.create({
title: 'Test Task'
});
expect(task.title).toBe('Test Task');
});
});Can I use s-m-r-t with SvelteKit?
Yes! s-m-r-t works great with SvelteKit. Use the template-sveltekit template to get started with a pre-configured setup.
How do I integrate Claude AI?
s-m-r-t includes built-in MCP (Model Context Protocol) support. Enable it with mcp: true in your @smrt decorator, then start the MCP server with smrt-dev-mcp start.
Claude Code can then interact with your objects using natural language.
Data Modeling
How do I define relationships between models?
Use the @foreignKey() decorator for same-package references and plain string IDs for cross-package references:
import { smrt, SmrtObject, foreignKey } from '@happyvertical/smrt-core';
@smrt()
class Order extends SmrtObject {
// Same-package: use @foreignKey() decorator
@foreignKey(Customer)
customerId: string = '';
// Cross-package: plain string ID (avoids circular deps)
tenantId: string = '';
}What's the difference between CTI and STI?
CTI (Class Table Inheritance): Each class gets its own table. More
normalized but requires joins.
STI (Single Table Inheritance): All subclasses share one table with a discriminator
field. Faster queries but denormalized.
Use CTI when subclasses have many unique fields. Use STI when they're similar.
How do I add computed properties?
Use TypeScript getters with @field({ transient: true }) for non-persisted properties:
@smrt()
class Order extends SmrtObject {
subtotal: number = 0.0; // DECIMAL
taxRate: number = 0.0; // DECIMAL
@field({ transient: true })
get total(): number {
return this.subtotal * (1 + this.taxRate);
}
}Performance
How do I optimize queries?
- Use
limitandoffsetfor pagination - Use
orderByfor sorted results - Set
conflictColumnsin @smrt() for efficient upsert operations - Use
listByIds()for batch fetching (single query) - Use
getOrUpsert()for find-or-create patterns
Should I use caching?
Yes! For frequently accessed data, implement caching at the collection level or use a dedicated caching layer (Redis, Memcached). s-m-r-t collections support custom caching strategies.
How do I handle large datasets?
- Always use pagination for lists
- Implement cursor-based pagination for large tables
- Use background jobs for batch operations
- Consider data archiving strategies
- Optimize indexes for common queries
Troubleshooting
Build fails with "Cannot find module"
Ensure all s-m-r-t packages are installed and have matching versions. Run npm install and check for peer dependency warnings.
Database connection fails
Check:
- Database server is running
- Connection credentials are correct
- Firewall allows connections
- Database exists and user has permissions
API endpoints return 404
Verify:
api: trueis set in @smrt decorator- API server is running
- Manifest was generated (run build)
- Correct port and prefix in config
TypeScript errors with decorators
Enable experimental decorators in tsconfig.json:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}Deployment
How do I deploy s-m-r-t applications?
s-m-r-t applications can be deployed anywhere Node.js runs:
- Docker containers (recommended)
- Kubernetes
- Traditional VPS (DigitalOcean, Linode)
- Serverless platforms (with limitations)
- Static hosts for adapter-static builds
What environment variables do I need?
At minimum:
DATABASE_URL(connection string for PostgreSQL or path for SQLite)NODE_ENV(production, development)PORTfor the API server- Any API keys for third-party services
Should I run migrations in production?
Yes, but with caution:
- Test migrations in staging first
- Run during maintenance windows for large changes
- Keep backups before schema changes
- Use migration tools for rollback capability