A production-ready, SOLID-principles-based AI chatbot system with React frontend, NestJS backend, and AWS Bedrock integration.
This monorepo contains three main packages:
React component library wrapping @assistant-ui/react with event-driven architecture.
Key Features:
- Event-Driven Architecture: Decoupled communication using Observer pattern
- Tool Registry: Dynamic tool registration using Registry and Strategy patterns
- Type-Safe: Full TypeScript support with strict typing
- Framework Agnostic: Core logic separated from React specifics
Design Patterns Used:
- Facade Pattern (Chatbot component)
- Strategy Pattern (Tool handlers)
- Observer Pattern (Event bus)
- Registry Pattern (Tool registry)
- Dependency Injection (Context API)
NestJS backend with AWS Bedrock integration.
Key Features:
- AWS Bedrock Integration: Uses Anthropic Claude via Bedrock
- Conversation History: Repository pattern for data persistence
- AI Tools: Web scraping, search, and form interaction
- SOLID Architecture: Clean separation of concerns
Architecture Layers:
- Domain Layer: Entities and repository interfaces
- Application Layer: Services and use cases
- Infrastructure Layer: Repository implementations
- Presentation Layer: HTTP controllers
Tools Provided:
- Web Scraper: Extract content from web pages
- Search: DuckDuckGo-based web search
- Form Interaction: Event-driven form manipulation
React demo application showcasing chatbot integration.
Features:
- Contact form with AI-powered auto-fill
- Real-time chatbot interaction
- Clean, responsive UI
- Demonstrates loose coupling via refs and events
- Bun installed
- AWS account with Bedrock access
- AWS credentials with Bedrock permissions
- Install dependencies:
bun install- Set up environment variables:
Backend (apps/backend/.env):
cp apps/backend/.env.example apps/backend/.env
# Edit apps/backend/.env with your AWS credentialsDemo (apps/demo/.env):
cp apps/demo/.env.example apps/demo/.env
# Edit if your backend runs on a different port- Build the component library:
bun run build:uiTerminal 1 - Backend:
bun run dev:backendTerminal 2 - Demo App:
bun run dev:demoThe demo app will be available at http://localhost:5173 The backend API will be available at http://localhost:3000
In the chatbot, try:
-
Form Auto-Fill:
- "Fill the form with my name as John Doe and email john@example.com"
- "Set the priority to high and subject to 'Technical Support'"
- "Submit the form"
-
Web Scraping:
- "Scrape the content from https://example.com"
- "Get the title from https://github.com"
-
Web Search:
- "Search for 'NestJS best practices'"
- "Find information about AWS Bedrock"
chatbot/
βββ packages/
β βββ chatbot-ui/ # React component library
β βββ src/
β β βββ components/ # React components
β β βββ context/ # React context
β β βββ core/ # Core business logic
β β βββ hooks/ # React hooks
β β βββ types/ # TypeScript types
β βββ package.json
βββ apps/
β βββ backend/ # NestJS backend
β β βββ src/
β β β βββ domain/ # Domain entities & interfaces
β β β βββ application/ # Services & use cases
β β β βββ infrastructure/ # Data access implementations
β β β βββ presentation/ # HTTP controllers
β β β βββ config/ # Configuration
β β βββ package.json
β βββ demo/ # React demo app
β βββ src/
β β βββ components/ # React components
β β βββ types.ts # TypeScript types
β βββ package.json
βββ package.json # Root package.json
- Each class/module has one reason to change
- Tools are separated (WebScraperTool, SearchTool, FormInteractionTool)
- Services handle specific domains (AIService, ConversationService)
- Tool system is open for extension (new tools) but closed for modification
- Event bus allows new event types without changing core code
- Repository interface can be replaced with different implementations
- Tool interface allows different tool implementations
- Small, focused interfaces (ITool, IConversationRepository)
- Clients only depend on methods they use
- High-level modules depend on abstractions (interfaces)
- Repository pattern: Services depend on IConversationRepository, not concrete implementations
- Tool system: AIService depends on ITool interface
- Repository Pattern: Data access abstraction
- Strategy Pattern: Interchangeable algorithms (tools)
- Observer Pattern: Event-driven communication
- Facade Pattern: Simplified interface to complex subsystems
- Registry Pattern: Dynamic object registration
- Dependency Injection: Loose coupling via DI
- Command Pattern: Form interaction instructions
- Factory Pattern: Tool creation and registration
- Frontend: React 18, TypeScript, Vite
- Backend: NestJS, TypeScript, Bun
- AI: AWS Bedrock (Anthropic Claude), AI SDK
- UI Framework: @assistant-ui/react
- Build Tool: Bun, Vite
- Type Safety: TypeScript, Zod
# Build all packages
bun run build
# Build specific package
bun run build:ui
bun run build:demo
bun run build:backend- Create tool class implementing
IToolinterface inapps/backend/src/application/tools/ - Register in
apps/backend/src/app.module.ts - Tool automatically becomes available to AI
Example:
@Injectable()
export class MyCustomTool implements ITool<MyParams, MyResult> {
readonly name = 'my_tool';
readonly description = 'Description of what my tool does';
readonly parametersSchema = z.object({ /* ... */ });
async execute(params: MyParams): Promise<MyResult> {
// Implementation
}
}Register custom tool handlers in your app:
import { useToolRegistry } from '@chatbot-monorepo/ui';
function MyComponent() {
useToolRegistry('my_custom_tool', async (params) => {
// Handle tool execution
return { success: true, data: 'result' };
});
}- Never commit
.envfiles - Rotate AWS credentials regularly
- Use IAM roles with least privilege
- Validate all tool inputs
- Sanitize web scraping results
MIT
Contributions are welcome! Please follow the SOLID principles and existing code patterns.