Starter Template (Calculator)
Time to read: 10 minutes
The beginner-friendly NitroStack template - Learn v3.0 fundamentals with a simple calculator example. Perfect for understanding the core concepts without authentication complexity.
What You'll Learn
- v3.0 Decorators -
@Tool,@Resource,@Prompt,@Module,@McpApp - Module Organization - How to structure a feature module
- Input Validation - Using Zod schemas
- UI Widgets - Creating beautiful Next.js components
- Examples - Including request/response examples
Quick Start
# Install NitroStack CLI
npm install -g nitrostack
# Create project
nitrostack init my-calculator --template typescript-starter
cd my-calculator
# Start development
npm run dev
Opens Studio on http://localhost:3000.
Features
One Module: Calculator
A complete example showing all NitroStack features:
Tool:
calculate- Perform arithmetic (add, subtract, multiply, divide)
Resource:
calculator://operations- List all available operations
Prompt:
calculator_help- Get usage instructions
Widgets:
- Calculator Result - Beautiful result display
- Calculator Operations - Operation list viewer
No Authentication
Focus on learning the basics without auth complexity. Great for:
- First-time users
- Learning NitroStack fundamentals
- Understanding the architecture
- Building simple utilities
Project Structure
src/
āāā modules/
ā āāā calculator/
ā āāā calculator.module.ts # Module definition
ā āāā calculator.tools.ts # Tool with @Tool decorator
ā āāā calculator.resources.ts # Resource with @Resource
ā āāā calculator.prompts.ts # Prompt with @Prompt
āāā widgets/
ā āāā app/
ā āāā calculator-result/ # Result widget
ā āāā calculator-operations/ # Operations widget
āāā app.module.ts # Root module with @McpApp
āāā index.ts # Bootstrap
Code Examples
Tool with Examples
@Tool({
name: 'calculate',
description: 'Perform basic arithmetic calculations',
inputSchema: z.object({
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
a: z.number().describe('First number'),
b: z.number().describe('Second number')
}),
examples: {
request: {
operation: 'add',
a: 5,
b: 3
},
response: {
operation: 'add',
a: 5,
b: 3,
result: 8,
expression: '5 + 3 = 8'
}
}
})
@Widget('calculator-result')
async calculate(input: any, ctx: ExecutionContext) {
// Calculation logic
return { result, expression };
}
Resource Definition
@Resource({
uri: 'calculator://operations',
name: 'Calculator Operations',
description: 'List of available calculator operations',
mimeType: 'application/json',
examples: {
response: {
operations: [
{ name: 'add', symbol: '+', description: 'Addition' }
]
}
}
})
@Widget('calculator-operations')
async getOperations(uri: string, ctx: ExecutionContext) {
const operations = [...];
return {
contents: [{
uri,
mimeType: 'application/json',
text: JSON.stringify({ operations }, null, 2)
}]
};
}
Prompt Definition
@Prompt({
name: 'calculator_help',
description: 'Get help with calculator operations',
arguments: [
{
name: 'operation',
description: 'The operation to get help with (optional)',
required: false
}
]
})
async getHelp(args: any, ctx: ExecutionContext) {
return {
messages: [
{
role: 'user',
content: { type: 'text', text: 'How do I use the calculator?' }
},
{
role: 'assistant',
content: { type: 'text', text: 'Instructions here...' }
}
]
};
}
Module Definition
@Module({
name: 'calculator',
description: 'Basic arithmetic calculator',
controllers: [CalculatorTools, CalculatorResources, CalculatorPrompts]
})
export class CalculatorModule {}
Root Module
@McpApp({
server: {
name: 'calculator-server',
version: '1.0.0'
},
logging: { level: 'info' }
})
@Module({
imports: [
ConfigModule.forRoot(),
CalculatorModule
]
})
export class AppModule {}
Example Workflows
Basic Calculation
User: "What's 25 times 4?"
AI: Calls calculate(operation="multiply", a=25, b=4)
Result: Widget showing "25 Ć 4 = 100"
Get Help
User: "How do I divide numbers?"
AI: Uses calculator_help prompt with operation="divide"
Result: Instructions for division
List Operations
User: "What can this calculator do?"
AI: Fetches calculator://operations resource
Result: Widget showing all 4 operations with examples
Key Learning Points
1. Examples Are Important
The examples field in tools and resources helps:
- AI understand how to use your tools
- UI widgets get proper TypeScript types
- Developers see expected input/output
2. Widgets Enhance UX
Instead of plain JSON, users see:
- Beautiful gradients
- Color-coded operations
- Easy-to-read layouts
3. Decorators Reduce Boilerplate
Compare v3.0:
@Tool({ name: 'calculate' })
async calculate(input: any) { }
With v2.x (old):
server.tool(createTool({
name: 'calculate',
handler: async (input) => { }
}));
4. ExecutionContext is Powerful
async calculate(input: any, ctx: ExecutionContext) {
ctx.logger.info('Calculating', { operation: input.operation });
// ctx.auth - For authenticated requests
// ctx.metadata - Request metadata
}
Customization Ideas
Add More Operations
Add power, square root, percentage:
operation: z.enum(['add', 'subtract', 'multiply', 'divide', 'power', 'sqrt'])
Add History
- Create
HistoryService - Store calculations in memory or file
- Add
get_historytool - Create history widget
Add Unit Converter Module
nitrostack generate module converter
Create tools for:
- Temperature (C ā F)
- Distance (km ā miles)
- Weight (kg ā lbs)
Best Practices Demonstrated
- Clear Examples - Every tool has request/response examples
- Input Validation - Zod schemas validate all inputs
- Error Handling - Division by zero check
- Logging - ExecutionContext logger usage
- Type Safety - Full TypeScript throughout
- UI Components - Engaging widgets for all outputs
- Modular Code - Clean separation of concerns
When to Use This Template
Perfect for:
- ā Learning NitroStack v3.0
- ā Simple utilities (calculators, converters, formatters)
- ā Proof of concepts
- ā Teaching/demos
- ā Stateless operations
Not ideal for:
- ā Applications requiring authentication
- ā Database-backed applications
- ā Complex state management
- ā Production e-commerce (use typescript-auth instead)
Next Steps
After mastering this template:
- E-commerce Template - Learn authentication, database, complex modules
- Tools Guide - Advanced tool patterns
- Widgets Guide - Build sophisticated UIs
- Dependency Injection - Services and DI
Troubleshooting
Tool Not Found
npm run build
Ensure TypeScript is compiled.
Widget Not Displaying
cd src/widgets
npm run build
cd ../..
npm run dev
Rebuild widgets and restart.
Division by Zero
The tool handles this automatically:
if (input.b === 0) {
throw new Error('Cannot divide by zero');
}
Comparison with E-commerce Template
| Feature | Starter | E-commerce |
|---|---|---|
| Complexity | Simple | Advanced |
| Authentication | None | JWT + Guards |
| Database | No | SQLite |
| Modules | 1 | 5 |
| Tools | 1 | 20+ |
| Learning Curve | Easy | Moderate |
| Use Case | Learning | Production |
Summary
The Starter Template is your first step into NitroStack v3.0:
- ā Simple calculator example
- ā All core features demonstrated
- ā No authentication complexity
- ā Beautiful UI widgets
- ā Clear, commented code
- ā Perfect for learning
Start here, understand the patterns, then move to the E-commerce template for production features!
Ready to Learn? Install NitroStack and create your first server!