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:
- MCP Server - Your backend (stdio transport)
- Widget Dev Server - Next.js at
http://localhost:3001 - Studio - Testing environment at
http://localhost:3000
Studio opens automatically in your browser! ๐
Step 6: Test in Studio
Chat with AI
- Go to Chat tab
- Select OpenAI or Gemini
- Enter your API key
- Try: "Show me the product categories"
The AI will call your tools automatically and render the widgets!
Manual Testing
- Go to Tools tab
- Click Execute on any tool
- Fill in the form
- 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:
- ๐ Core Concepts - Deep dive into modules, tools, etc.
- ๐จ Widgets Guide - Build beautiful UIs
- ๐ Authentication - Secure your server
- ๐งช Testing Guide - Write tests
- ๐ข 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:3001is running - Verify widget route matches tool name
- Check browser console for errors
Getting Help
- ๐ Documentation
- ๐ฌ GitHub Discussions
- ๐ Report Issues
๐ Congratulations! You've built your first NitroStack v3.0 server!
Next: Core Concepts โ