/quick start

Quick Start Guide

Get your first NitroStack v3.0 server running in 5 minutes!

Prerequisites

  • Node.js 18+ installed
  • npm or yarn
  • TypeScript knowledge recommended
  • Code editor (VS Code recommended)

Step 1: Create Your Project

npx nitrostack init my-awesome-server --template typescript-auth
cd my-awesome-server
npm install

This creates a fully-featured e-commerce template with:

  • โœ… Multiple modules (auth, products, cart, orders, addresses)
  • โœ… JWT authentication
  • โœ… Beautiful Next.js widgets
  • โœ… Database integration (SQLite)
  • โœ… Complete CRUD operations

Step 2: Understand the Structure

my-awesome-server/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ app.module.ts          # Root application module
โ”‚   โ”œโ”€โ”€ index.ts                # Bootstrap entry point
โ”‚   โ”œโ”€โ”€ modules/                # Feature modules
โ”‚   โ”‚   โ”œโ”€โ”€ auth/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ auth.module.ts
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ auth.tools.ts      # @Tool definitions
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ auth.resources.ts  # @Resource definitions
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ auth.prompts.ts    # @Prompt definitions
โ”‚   โ”‚   โ”œโ”€โ”€ products/
โ”‚   โ”‚   โ”œโ”€โ”€ cart/
โ”‚   โ”‚   โ”œโ”€โ”€ orders/
โ”‚   โ”‚   โ””โ”€โ”€ addresses/
โ”‚   โ”œโ”€โ”€ guards/                 # Authentication guards
โ”‚   โ”‚   โ””โ”€โ”€ jwt.guard.ts
โ”‚   โ”œโ”€โ”€ services/               # Business logic
โ”‚   โ”‚   โ””โ”€โ”€ database.service.ts
โ”‚   โ”œโ”€โ”€ widgets/                # Next.js UI components
โ”‚   โ”‚   โ””โ”€โ”€ app/
โ”‚   โ”‚       โ”œโ”€โ”€ product-card/
โ”‚   โ”‚       โ”œโ”€โ”€ shopping-cart/
โ”‚   โ”‚       โ””โ”€โ”€ ...
โ”‚   โ””โ”€โ”€ db/                     # Database setup
โ”œโ”€โ”€ .env                        # Environment variables
โ””โ”€โ”€ package.json

Step 3: Explore a Module

Let's look at the Products module:

// src/modules/products/products.module.ts
import { Module } from 'nitrostack';
import { ProductsTools } from './products.tools.js';
import { ProductsResources } from './products.resources.js';
import { ProductsPrompts } from './products.prompts.js';

@Module({
  name: 'products',
  description: 'Product catalog management',
  controllers: [ProductsTools, ProductsResources, ProductsPrompts]
})
export class ProductsModule {}

Step 4: Create Your First Tool

// src/modules/products/products.tools.ts
import { ToolDecorator as Tool, z, ExecutionContext } from 'nitrostack';

export class ProductsTools {
  @Tool({
    name: 'get_product',
    description: 'Get product details by ID',
    inputSchema: z.object({
      product_id: z.string().describe('Product ID')
    }),
    examples: {
      request: { product_id: 'prod-1' },
      response: {
        id: 'prod-1',
        name: 'Awesome Product',
        price: 99.99,
        stock: 42
      }
    }
  })
  @Widget('product-card')  // Attach UI component
  async getProduct(input: any, context: ExecutionContext) {
    const db = getDatabase();
    const product = db.prepare('SELECT * FROM products WHERE id = ?').get(input.product_id);
    
    if (!product) {
      throw new Error('Product not found');
    }
    
    return product;
  }
}

Step 5: Start Development

npm run dev

This starts:

  1. MCP Server - Your backend (stdio transport)
  2. Widget Dev Server - Next.js at http://localhost:3001
  3. Studio - Testing environment at http://localhost:3000

Studio opens automatically in your browser! ๐ŸŽ‰

Step 6: Test in Studio

Chat with AI

  1. Go to Chat tab
  2. Select OpenAI or Gemini
  3. Enter your API key
  4. Try: "Show me the product categories"

The AI will call your tools automatically and render the widgets!

Manual Testing

  1. Go to Tools tab
  2. Click Execute on any tool
  3. Fill in the form
  4. See the response + widget preview

Step 7: Add Authentication

Protect your tools with guards:

// src/guards/jwt.guard.ts
import { Guard, ExecutionContext } from 'nitrostack';
import { verifyJWT } from 'nitrostack';

export class JWTGuard implements Guard {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const token = context.auth?.token;
    if (!token) return false;
    
    try {
      const payload = verifyJWT({
        token,
        secret: process.env.JWT_SECRET!
      });
      context.auth = { subject: payload.sub };
      return true;
    } catch {
      return false;
    }
  }
}

Use it on your tools:

@Tool({ name: 'create_order' })
@UseGuards(JWTGuard)  // โ† Auth required!
async createOrder(input: any, ctx: ExecutionContext) {
  const userId = ctx.auth?.subject;  // Authenticated user ID
  // ...
}

Step 8: Create a Widget

// src/widgets/app/product-card/page.tsx
'use client';
import { withToolData } from 'nitrostack/widgets';

function ProductCard({ data }) {
  return (
    <div style={{
      padding: '24px',
      background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
      borderRadius: '16px',
      color: 'white'
    }}>
      <h2>{data.name}</h2>
      <p className="price">${data.price}</p>
      <p className="stock">In stock: {data.stock}</p>
    </div>
  );
}

export default withToolData(ProductCard);

Step 9: Add Dependency Injection

Create a service:

// src/services/product.service.ts
import { Injectable } from 'nitrostack';
import { DatabaseService } from './database.service.js';

@Injectable()
export class ProductService {
  constructor(private db: DatabaseService) {}
  
  async findById(id: string) {
    return this.db.queryOne('SELECT * FROM products WHERE id = ?', [id]);
  }
  
  async findByCategory(category: string) {
    return this.db.query('SELECT * FROM products WHERE category = ?', [category]);
  }
}

Use it in your tools:

export class ProductsTools {
  constructor(private productService: ProductService) {}  // Auto-injected!
  
  @Tool({ name: 'get_product' })
  async getProduct(input: any) {
    return this.productService.findById(input.product_id);
  }
}

Register in module:

@Module({
  name: 'products',
  controllers: [ProductsTools],
  providers: [ProductService, DatabaseService]  // โ† Add services
})
export class ProductsModule {}

Step 10: Add Caching

@Tool({ name: 'get_product' })
@Cache({ ttl: 300, key: (input) => `product:${input.product_id}` })
async getProduct(input: any) {
  // Cached for 5 minutes!
  return this.productService.findById(input.product_id);
}

Step 11: Add Rate Limiting

@Tool({ name: 'send_email' })
@RateLimit({ requests: 10, window: '1m', key: (ctx) => ctx.auth?.subject })
async sendEmail(input: any) {
  // Max 10 emails per minute per user
}

Step 12: Generate Types

Auto-generate TypeScript types from your tools:

npx nitrostack generate types

This creates src/types/generated-tools.ts:

export type GetProductInput = {
  product_id: string;
};

export type GetProductOutput = {
  id: string;
  name: string;
  price: number;
  stock: number;
};

Use in widgets:

import { GetProductOutput } from '../../types/generated-tools';

function ProductCard({ data }: { data: GetProductOutput }) {
  // Fully typed! โœ…
  return <div>{data.name}</div>;
}

Common Commands

# Development
npm run dev                    # Start dev server + Studio (all services)
nitrostack dev                   # Alternative: use CLI directly

# Building
npm run build                  # Build MCP server + widgets
nitrostack build                 # Alternative: use CLI directly

# Production
npm start                      # Run production server
node dist/index.js             # Alternative: run directly

# Widget-Specific Commands
npm run widget <command>       # Run any npm command in widgets directory
npm run widget add <package>   # Install widget dependency
npm run widget remove <package> # Remove widget dependency

# Code Generation
nitrostack generate types        # Generate types
nitrostack generate module users # Generate module
nitrostack generate tool get-user # Generate tool

Next Steps

Now that you have a working server:

  1. ๐Ÿ“– Core Concepts - Deep dive into modules, tools, etc.
  2. ๐ŸŽจ Widgets Guide - Build beautiful UIs
  3. ๐Ÿ” Authentication - Secure your server
  4. ๐Ÿงช Testing Guide - Write tests
  5. ๐Ÿšข Deployment - Go to production

Troubleshooting

Port Already in Use

# Change ports
nitrostack dev --port 3002  # Studio on 3002, widgets on 3003

TypeScript Errors

# Ensure dependencies are installed
npm install

# Rebuild
npm run build

Database Issues

# Re-seed database
npm run db:seed

Widget Not Loading

  • Check http://localhost:3001 is running
  • Verify widget route matches tool name
  • Check browser console for errors

Getting Help


๐ŸŽ‰ Congratulations! You've built your first NitroStack v3.0 server!

Next: Core Concepts โ†’