Building Your First AYW Bot: A Step-by-Step Guide
A complete tutorial for building your first human-guided AI chatbot with AYW. From setup to deployment in 15 minutes.
Published: May 16, 2026 | 8 min read | Part 1 of AYW Dev.to Series
What is AYW?
AYW (As You Wish) is a modern, interactive chatbot platform that puts human guidance at the center of AI conversations. Unlike traditional chatbots that follow rigid scripts or fully autonomous AI that can go off-track, AYW bots learn from human guidance and adapt to each unique customer journey.
Prerequisites
- Node.js 18+ installed
- PostgreSQL database (we use Prisma ORM)
- OpenAI API key (for AI responses)
- Basic knowledge of TypeScript and React
Architecture Overview
AYW uses a monorepo architecture with three main apps:
ayw-monorepo/
├── apps/
│ ├── backend/ # Express + TypeScript API
│ ├── frontend/ # React + Vite web app
│ └── chatbot/ # Chatbot logic (in development)
├── packages/ # Shared utilities
└── prisma/ # Database schema
The backend handles API routes, WebSocket connections, and AI integration. The frontend provides the user interface including a chat widget, dashboard, and landing page.
Step 1: Clone and Install
git clone https://github.com/ayw-ai/ayw-monorepo.git
cd ayw-monorepo
npm install
This uses npm workspaces to install dependencies across all apps.
Step 2: Set Up Environment Variables
Create .env files in both apps/backend and apps/frontend:
apps/backend/.env:
DATABASE_URL="postgresql://user:password@localhost:5432/ayw_db"
OPENAI_API_KEY="your-openai-api-key"
JWT_SECRET="your-jwt-secret"
FRONTEND_URL="http://localhost:3000"
PORT=4000
apps/frontend/.env:
VITE_API_URL="http://localhost:4000"
Step 3: Set Up the Database
cd apps/backend
npx prisma migrate dev --name init
npx prisma generate
This creates your database schema with tables for users, conversations, and messages.
Step 4: Start the Development Servers
In the root directory, run:
npm run dev
This concurrently starts:
- Backend server on
http://localhost:4000 - Frontend on
http://localhost:3000 - Chatbot service (when ready)
Step 5: Create Your First Bot Configuration
Now let's configure your first bot. Create a bot config in apps/backend/src/services/botConfig.ts:
export interface BotConfig {
name: string;
type: 'welcome' | 'support' | 'sales' | 'feedback';
systemPrompt: string;
temperature: number;
maxTokens: number;
}
export const welcomeBot: BotConfig = {
name: 'Welcome Bot',
type: 'welcome',
systemPrompt: `You are the AYW Welcome Bot. Your job is to:
1. Greet visitors warmly
2. Understand their intent (support, sales, feedback)
3. Route them to the appropriate specialist bot
4. Maintain a helpful, human-guided tone
Always be polite, concise, and guide users to the right destination.`,
temperature: 0.7,
maxTokens: 500
};
Step 6: Build the Chat Service with OpenAI
Create apps/backend/src/services/chatbotService.ts:
import OpenAI from 'openai';
import { PrismaClient } from '@prisma/client';
import { BotConfig, welcomeBot, supportBot, salesBot, feedbackBot } from './botConfig';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const prisma = new PrismaClient();
const botConfigs: Record<string, BotConfig> = {
welcome: welcomeBot,
support: supportBot,
sales: salesBot,
feedback: feedbackBot
};
export class ChatbotService {
async processMessage({ message, conversationId, botType, userId }: {
message: string;
conversationId?: string;
botType: string;
userId?: string;
}) {
const config = botConfigs[botType] || welcomeBot;
// Create or get conversation
let conversation;
if (conversationId) {
conversation = await prisma.conversation.findUnique({
where: { id: conversationId }
});
} else {
conversation = await prisma.conversation.create({
data: {
botType,
userId,
status: 'active'
}
});
}
// Save user message
await prisma.message.create({
data: {
conversationId: conversation.id,
role: 'user',
content: message
}
});
// Get conversation history
const history = await prisma.message.findMany({
where: { conversationId: conversation.id },
orderBy: { createdAt: 'asc' },
take: 10
});
// Call OpenAI with human-guided system prompt
const completion = await openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{ role: 'system', content: config.systemPrompt },
...history.map(msg => ({
role: msg.role as 'user' | 'assistant',
content: msg.content
}))
],
temperature: config.temperature,
max_tokens: config.maxTokens
});
const botResponse = completion.choices[0].message.content;
// Save bot response
await prisma.message.create({
data: {
conversationId: conversation.id,
role: 'assistant',
content: botResponse,
botType
}
});
return {
message: botResponse,
conversationId: conversation.id,
botType: config.type
};
}
}
Step 7: Build the Frontend Chat Interface
Create apps/frontend/src/pages/ChatPage.tsx:
import { useState, useRef, useEffect } from 'react';
import { Send, Bot, User } from 'lucide-react';
import { chatbotService } from '../services/chatbotService';
interface Message {
id: string;
role: 'user' | 'assistant';
content: string;
timestamp: Date;
}
export default function ChatPage() {
const [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState('');
const [isLoading, setIsLoading] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
const sendMessage = async () => {
if (!input.trim()) return;
const userMessage: Message = {
id: Date.now().toString(),
role: 'user',
content: input,
timestamp: new Date()
};
setMessages(prev => [...prev, userMessage]);
setInput('');
setIsLoading(true);
try {
const response = await chatbotService.sendMessage({
message: input,
botType: 'welcome'
});
const botMessage: Message = {
id: (Date.now() + 1).toString(),
role: 'assistant',
content: response.message,
timestamp: new Date()
};
setMessages(prev => [...prev, botMessage]);
} catch (error) {
console.error('Failed to send message:', error);
} finally {
setIsLoading(false);
}
};
return (
<div className="flex flex-col h-screen max-w-4xl mx-auto p-4">
<header className="mb-4">
<h1 className="text-2xl font-bold">AYW Chatbot Demo</h1>
<p className="text-gray-600">Powered by human-guided AI</p>
</header>
<div className="flex-1 overflow-y-auto border rounded-lg p-4 space-y-4">
{messages.map(msg => (
<div
key={msg.id}
className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
>
<div className={`flex items-start gap-2 max-w-[80%] ${msg.role === 'user' ? 'flex-row-reverse' : ''}`}>
<div className="w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center">
{msg.role === 'user' ? <User size={18} /> : <Bot size={18} />}
</div>
<div className={`rounded-lg p-3 ${msg.role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-100'}`}>
<p>{msg.content}</p>
<span className="text-xs opacity-70 mt-1 block">
{msg.timestamp.toLocaleTimeString()}
</span>
</div>
</div>
</div>
))}
{isLoading && (
<div className="flex justify-start">
<div className="bg-gray-100 rounded-lg p-3">
<p className="animate-pulse">Thinking...</p>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
<div className="mt-4 flex gap-2">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
placeholder="Type your message..."
className="flex-1 border rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
onClick={sendMessage}
disabled={isLoading}
className="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600 disabled:opacity-50"
>
<Send size={18} />
</button>
</div>
</div>
);
}
Step 8: Test Your Bot
- Navigate to
http://localhost:3000/chat - Type: "Hello, I need help with my account"
- The Welcome Bot should greet you and route your intent
- Check the backend logs to see the OpenAI API calls
Why Human-Guided AI Matters
Traditional chatbots fail because they either:
- Follow rigid scripts (frustrating for complex queries)
- Use fully autonomous AI (unpredictable, hard to trust)
AYW's human-guided approach means:
- AI handles routine queries instantly
- Human experts guide complex conversations
- The system learns from every interaction
- Customers get fast, accurate, trustworthy support
Next Steps
Now that you've built your first AYW bot, you can:
- Add more bot types - Create specialist bots for support, sales, etc.
- Implement WebSocket - Add real-time streaming responses
- Add human escalation - Allow bots to hand off to human agents
- Integrate analytics - Track conversation success rates
- Deploy to production - Use Vercel for frontend, Railway or Render for backend
Resources
- GitHub Repo: https://github.com/ayw-ai/ayw-monorepo
- Documentation: https://docs.ayw.ai (coming soon)
- Live Demo: https://ayw-demo.example.com (coming soon)
- Discord Community: Join us! (coming soon)
Building something cool with AYW? Tag your project with #AYWChatbot and share it in the comments below! 👇
Tags: #AI #Chatbots #TypeScript #React #NodeJS #OpenAI #Tutorial #HumanGuidedAI
Series: AYW Developer Tutorials (Part 1 of 6)
Top comments (0)