Getting Started

What is SMRT?

SMRT is a full-stack TypeScript framework that generates database schemas, REST APIs, MCP tools, and CLI commands from simple object definitions. Define your data models once with the @smrt decorator, and the framework handles the rest.

Prerequisites

  • Node.js 24+ (the framework's engines require node >=24)
  • pnpm 9+ (npm also works)
  • Basic TypeScript knowledge

Installation

Option 1: Clone the SaaS starter (recommended)

The fastest way to see the whole framework in one place is the smrt-saas-starter — a reference SvelteKit app wired up with the SMRT packages, auth, and admin UI. Clone it and run the dev server:

bash
git clone https://github.com/happyvertical/smrt-saas-starter.git
cd smrt-saas-starter
pnpm install
pnpm dev

Option 2: Add SMRT to an existing SvelteKit project

Run smrt init inside an existing SvelteKit project to scaffold a smrt.config.ts and the wiring SMRT needs:

bash
npx smrt init

Option 3: Install packages by hand

Start from just the core package, then add what you need:

bash
pnpm add @happyvertical/smrt-core

Most projects also pull in the shared types and the config loader, plus any domain packages for the problem you're solving (for example agents and background jobs):

bash
pnpm add @happyvertical/smrt-types @happyvertical/smrt-config
pnpm add @happyvertical/smrt-agents @happyvertical/smrt-jobs

Your First SmrtObject

Step 1: Define Your Model

Create a file src/models/Task.ts:

typescript
import { SmrtObject, smrt } from '@happyvertical/smrt-core';

@smrt({
  api: true,    // Generate REST API
  cli: true,    // Generate CLI commands
  mcp: true     // Generate MCP tools
})
export class Task extends SmrtObject {
  title: string = '';
  description: string = '';
  status: string = 'todo';
  dueDate: string = '';

  complete() {
    this.status = 'done';
  }
}

Step 2: Create the Collection

typescript
import { SmrtCollection } from '@happyvertical/smrt-core';
import { Task } from './Task.js';

export class TaskCollection extends SmrtCollection<Task> {
  static readonly _itemClass = Task;

  async findByStatus(status: string) {
    return this.list({ where: { status } });
  }

  async findOverdue() {
    return this.list({
      where: {
        'status !=': 'done',
        'dueDate <': new Date().toISOString()
      }
    });
  }
}

Step 3: Use Your Object

typescript
import { TaskCollection } from './models/TaskCollection.js';

// Create collection via static factory
const tasks = await TaskCollection.create({
  db: 'tasks.db'
});

// Create
const task = await tasks.create({
  title: 'Learn SMRT Framework',
  description: 'Read the getting started guide',
  dueDate: '2025-01-20'
});
await task.save();

// Query
const allTasks = await tasks.list();
const todoTasks = await tasks.findByStatus('todo');
const overdue = await tasks.findOverdue();

// Update
task.status = 'in_progress';
await task.save();

// Custom method
task.complete();
await task.save();

// Delete
await task.delete();

Auto-Generated Interfaces

With the @smrt decorator, you get:

REST API Endpoints

http
GET    /api/tasks          # List tasks
GET    /api/tasks/:id      # Get task by ID
POST   /api/tasks          # Create task
PATCH  /api/tasks/:id      # Update task
DELETE /api/tasks/:id      # Delete task

CLI Commands

bash
smrt tasks list
smrt tasks get <id>
smrt tasks create --title "My Task"
smrt tasks update <id> --status done
smrt tasks delete <id>

MCP Tools

Claude Code can interact with your objects using natural language via MCP.

Configuration

Create smrt.config.ts in your project root:

typescript
import { defineConfig } from '@happyvertical/smrt-config';

export default defineConfig({
  smrt: {
    logLevel: 'info',
    environment: 'development',
    embeddings: { provider: 'local' }
  },
  modules: {
    // Module-scoped configs keyed by module name
    'my-agent': {
      cronSchedule: '0 2 * * *',
      maxRetries: 3
    }
  },
  packages: {
    // Package-scoped configs keyed by package name
    ai: { defaultModel: 'gpt-4o' }
  }
});

Note:

The config top-level keys are smrt (global options), modules (module-scoped config), packages (package-scoped config), site (site templates), and export (SSG export). Use getModuleConfig() and getPackageConfig() to retrieve them at runtime.

Common Patterns

Relationships

typescript
import { SmrtObject, smrt, foreignKey, manyToMany } from '@happyvertical/smrt-core';

@smrt()
class Project extends SmrtObject {
  name: string = '';

  @foreignKey(User)
  ownerId: string = '';

  @manyToMany(Tag, { through: 'project_tags' })
  tags: Tag[] = [];
}

Computed Properties

typescript
@smrt()
class Order extends SmrtObject {
  subtotal: number = 0.0;
  taxRate: number = 0.08;

  get total(): number {
    return this.subtotal * (1 + this.taxRate);
  }
}

AI-Powered Methods

Every SmrtObject exposes three AI methods: is() (boolean check), do() (freeform action), and describe() (generate a description).

typescript
// is() — evaluate criteria, returns boolean
const isValid = await product.is(`
  - Has a non-empty description
  - Price is greater than $10
  - Name does not contain profanity
`);

// do() — perform an action based on instructions, returns string
const summary = await product.do(`
  Write a 50-word marketing description.
  Highlight key features and target audience.
`);

// describe() — generate a concise description, returns string
const blurb = await product.describe();

Next Steps

  • Objects — SmrtObject fields, relationships, AI methods, and lifecycle hooks
  • Collections — Querying, filtering, pagination, and batch operations
  • Agents — Autonomous actors with persistent state
  • Modules — Available packages organized by purpose

Help