This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
IMPORTANT: Use English for all code, comments, documentation, commit messages, variable names, function names, and any technical communication. This is a strict requirement for the entire codebase.
- Functional Programming: Use functional programming patterns exclusively
- Never use classes: All code must use functions, pure functions, and functional composition
- No OOP: Avoid object-oriented programming patterns (classes, inheritance, this keyword)
- Use functional patterns: pure functions, immutability, composition, higher-order functions
- YAGNI (You Aren't Gonna Need It): Only implement functionality that is currently needed. Do not create functions, features, or abstractions for future use. If a function is not used in the current implementation, do not write it.
- No default parameters: Never use default values in function arguments. All parameters must be explicitly provided by the caller. This makes function calls explicit and prevents hidden behavior.
- No fallback values: Never use fallback or default values in configuration, environment variables, or other critical values (e.g.,
const url = process.env.URL || 'http://localhost:3000'). All required values must be explicitly provided or throw clear errors when missing. This prevents hidden behavior and makes missing configuration immediately visible.
- No comments: Do not add comments or inline documentation
- No JSDoc: Do not use JSDoc annotations
- Code should be self-documenting through clear naming and structure
- Prefer named exports: Use
export const ComponentNameinstead ofexport defaultwhen possible - Exception: Next.js requires
export defaultfor pages, layouts, and route handlers - Named exports improve code discoverability and refactoring capabilities
- Interfaces: All TypeScript interfaces must start with capital "I" (e.g.,
IUser,IProduct,IOrder) - This convention clearly distinguishes interfaces from types, classes, and other constructs
- Optional properties: Use
?for optional properties instead of| undefined(e.g.,email?: stringinstead ofemail: string | undefined) - Nullable types: Use
| nullwhen a value can be explicitly null (e.g.,email: string | null) - Return types: Do not explicitly declare return types for functions - let TypeScript infer them automatically (e.g.,
const add = (a: number, b: number) => a + binstead ofconst add = (a: number, b: number): number => a + b) - Always use braces: Always use curly braces
{}for if statements, even for single-line blocks (e.g.,if (condition) { return value; }instead ofif (condition) return value;) - No magic numbers: Extract numeric constants to named constants at the top of the file to make the code self-documenting (e.g.,
const DEFAULT_PAGE_SIZE = 10;instead of using10directly in code) - User-facing strings must be translated: All strings visible to users must be internationalized. This includes:
- UI text in components
- Error messages from services and API responses
- AI agent responses (chatNode, productsNode, etc.) - all messages returned to users must use translations from
messages/files - Never hardcode user-facing strings in code - always use
getTranslationsor translation files - Services and agents must accept locale parameter and use it to fetch translated strings
- This makes optional properties more concise and follows TypeScript best practices
Comprehensive documentation is available in the docs/ directory:
- AGENTS.md - AI agents architecture and LangGraph implementation
- AUTHENTICATION.md - Complete authentication and authorization guide
- TEST_GUIDE.md - Testing guidelines and best practices
Cognito is a modern agentic e-commerce platform, similar to Magento or WooCommerce, designed with cutting-edge technology and AI-powered autonomous agents. Unlike traditional e-commerce systems, Cognito leverages AI agents to autonomously handle complex workflows, customer interactions, and business processes.
-
API Backend (Agentic)
- Built with LangGraph - framework for building stateful, multi-agent AI applications
- Autonomous AI agents handle complex e-commerce workflows
- MongoDB for application data storage
- Weaviate for vector embeddings and semantic search
- RESTful API endpoints
-
AI Chat Interface
- Conversational product search
- Natural language product discovery
- Direct purchase capability through chat
- Mobile-first responsive design with desktop support
-
CMS (Content Management System)
- Store configuration interface
- Product management
- Order and inventory management
- Settings and customization
- Mobile-first responsive design with desktop support
- Frontend: Next.js with TypeScript
- Backend: LangGraph + MongoDB
- AI/ML: LangGraph for conversational commerce
- Database:
- MongoDB - Primary database for application data
- Weaviate - Vector database for AI-powered search and recommendations
- Validation: Zod with zod-i18n-map for runtime type validation and internationalized error messages
- Authentication: Auth.js (NextAuth v5) with JWT sessions and role-based access control
The domain/ directory contains domain models and interfaces that define the core business entities and their contracts:
- Domain Interfaces: TypeScript interfaces and types representing business entities (e.g.,
domain/user.ts) - Pure Types: Domain models are pure TypeScript types with no implementation logic
- Business Contracts: Define the shape of data used throughout the application
- Technology Agnostic: Domain layer is independent of frameworks, databases, and external services
Directory Structure:
domain/
├── user.ts # User-related interfaces and types
├── product.ts # Product domain models (future)
├── order.ts # Order domain models (future)
└── ... # Other domain entities
Principles:
- Domain types represent business concepts, not database schemas
- Keep domain models simple and focused on data structure
- Use functional programming patterns (no classes)
- Domain layer should have no external dependencies
The models/ directory contains all database access logic and external data source operations:
- Database Operations: All MongoDB and Weaviate operations must be implemented in models
- Functional Pattern: Use pure functions for all model operations
- Single Responsibility: Each model handles operations for one domain entity
- Technology Abstraction: Services should never directly access databases, only through models
Directory Structure:
models/
├── users/
│ ├── usersModel.ts # User database operations
│ └── usersModel.test.ts # Model tests
├── products/
│ └── productsModel.ts # Product database operations
└── ... # Other entity models
Example:
// models/users/usersModel.ts
import { Db } from 'mongodb';
import { IUser } from '@/domain/user';
export const findUserByEmail = async (
db: Db,
email: string
): Promise<IUser | null> => {
const collection = db.collection<IUser>('users');
return collection.findOne({ email, deleted: false });
};
export const createUser = async (
db: Db,
userData: Omit<IUser, '_id'>
): Promise<IUser> => {
const collection = db.collection<IUser>('users');
const result = await collection.insertOne(userData as any);
return { ...userData, _id: result.insertedId.toString() };
};Principles:
- All MongoDB operations go through models
- All Weaviate operations go through models
- Models return domain types (interfaces from
domain/) - Models are server-side only (never imported in client components)
- Services use models, never direct database access
- Use functional programming patterns (no classes)
- Each function should be pure and testable
The repositories/ directory contains client-side API communication with internal API routes:
- API Operations: All fetch() calls to internal API routes must be implemented in repositories
- HTTP Abstraction: Repositories abstract HTTP communication from hooks and components
- Separation of Concerns: Components and hooks should never make direct fetch() calls
- Error Handling: Repositories handle HTTP-level errors and response parsing
Directory Structure:
repositories/
├── api/
│ ├── registration/
│ │ ├── registrationApiRepository.ts # API calls for registration
│ │ └── registrationApiRepository.test.ts # Repository tests
│ ├── auth/
│ │ └── authApiRepository.ts # API calls for authentication
│ └── ... # Other API repositories
└── ...
Example:
// repositories/api/registration/registrationApiRepository.ts
import { IUser } from '@/domain/user';
export interface IRegistrationRequest {
email: string;
password: string;
termsAccepted: boolean;
}
export interface IRegistrationResponse {
message: string;
user: Omit<IUser, 'password'>;
}
export const registerUser = async (
data: IRegistrationRequest
): Promise<IRegistrationResponse> => {
const response = await fetch('/api/registration', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Registration failed');
}
return response.json();
};Usage in hooks:
// components/registration/registrationForm/useRegistrationForm.ts
import { registerUser } from '@/repositories/api/registration/registrationApiRepository';
export const useRegistrationForm = () => {
const handleSubmit = async () => {
try {
const result = await registerUser({
email,
password,
termsAccepted,
});
// Handle success
} catch (error) {
// Handle error
}
};
};Principles:
- All fetch() calls to internal API routes go through repositories
- Repositories are client-side only (never imported in server code)
- Repositories handle request formatting and response parsing
- Error responses are converted to Error objects
- Use TypeScript interfaces for request/response types
- Keep HTTP-level concerns in repositories, business logic in hooks
The application uses Zod for runtime type validation and schema validation:
- Schema Definition: Define validation schemas using Zod in service layers
- Internationalization: Use
zod-i18n-mapfor translated validation error messages - Supported Languages: English (en), Polish (pl)
- Type Safety: Zod schemas provide both runtime validation and TypeScript type inference
Usage Pattern:
// services/registration/registration.service.ts
import { z } from 'zod';
import { zodI18nMap } from 'zod-i18n-map';
export const registrationSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
firstName: z.string().min(1),
});
export type RegistrationInput = z.infer<typeof registrationSchema>;
export const validateRegistrationData = (
data: unknown,
locale: string
): RegistrationInput => {
// Configure zod i18n for the locale
z.setErrorMap(zodI18nMap);
return registrationSchema.parse(data);
};Principles:
- All external input (API requests, form submissions) must be validated with Zod
- Define schemas close to where they're used (in service files)
- Use
z.infer<typeof schema>to derive TypeScript types from schemas - Always pass locale explicitly to validation functions (no default parameters)
- Validation errors are automatically translated based on locale via zod-i18n-map
CRITICAL: All error messages must be translated based on the request locale:
- Never hardcode error messages in English or any specific language
- Detect locale from request (from URL, headers, or request context)
- Zod validation errors are automatically translated via zod-i18n-map based on locale
- Business logic errors must be translated server-side using
getTranslationsfrom next-intl - API responses must return fully translated error messages, not translation keys
- Services must accept locale parameter and use
getTranslationsto translate errors
Translation namespace structure for errors:
- Feature-specific errors:
[feature].errors(e.g.,registration.errors.userExists) - Common/generic errors:
commonErrors(e.g.,commonErrors.serverError)
Custom React hooks are used to extract and reuse component logic:
- Location: Hooks specific to a component/feature should be placed in the same directory as the component
- Generic hooks: Only truly reusable, generic hooks go in
hooks/directory - Naming: Always prefix with
use(e.g.,useRegistrationForm,useAuth) - Services integration: Hooks should use service layer functions for validation and business logic
- Separation of concerns: Hooks manage component state and effects, services handle business logic
Example structure:
components/
├── registration/
│ └── registrationForm/
│ ├── RegistrationForm.tsx # Component using the hook
│ ├── useRegistrationForm.ts # Hook with form state and logic
│ └── ...
Principles:
- Hooks import and use functions from services (e.g., validation functions)
- Services contain pure business logic that can be reused across hooks, API routes, and other contexts
- Keep hooks focused on React-specific concerns (state, effects, refs)
- Business logic stays in services, not in hooks
- Forms: Shared form logic and reusable form components are located in
components/forms
The application uses next-intl for internationalization:
- Supported locales: English (en), Polish (pl)
- Default locale: English (en)
- Translation files: Located in
messages/directory (e.g.,messages/en.json,messages/pl.json) - URL structure: All routes are prefixed with locale (e.g.,
/en/cms/login,/pl/cms/login) - Configuration:
i18n/config.ts- Locale configurationi18n/request.ts- Server-side translation setupmiddleware.ts- Locale detection and routing
Usage in components:
// Server components
import { useTranslations } from 'next-intl';
const t = useTranslations('namespace');
t('key'); // Returns translated string
// Client components
'use client';
import { useTranslations } from 'next-intl';
// Same usage as server componentsThe application uses a template system that separates business logic from presentation layer, enabling complete UI customization without modifying core functionality.
Business Logic Components (components/, app/, services/):
- Component state (useState, useReducer)
- Side effects (useEffect, API calls)
- Event handlers and business logic
- Data fetching and mutations
- Routing and navigation
Template Components (template/):
- Pure presentational components
- HTML structure (JSX)
- CSS styles (SCSS modules)
- Visual design and layout
- Receive all data via props
template/
├── components/ # Presentational components
│ └── LoginForm/
│ ├── LoginFormTemplate.tsx # Pure JSX + props
│ └── LoginFormTemplate.module.scss # Component styles
├── styles/ # Global styles and design system
│ ├── globals.scss # Global CSS reset and base styles
│ ├── variables.scss # Design tokens (colors, fonts, spacing)
│ └── mixins.scss # Reusable SCSS utilities
└── README.md # Template customization guide
Logic Component (business logic):
// components/login/loginForm/LoginForm.tsx
'use client';
import { useState } from 'react';
import { LoginFormTemplate } from '@/template/components/LoginForm/LoginFormTemplate';
export const LoginForm = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e: React.FormEvent) => {
// Business logic here
};
return (
<LoginFormTemplate
email={email}
password={password}
onEmailChange={setEmail}
onPasswordChange={setPassword}
onSubmit={handleSubmit}
/>
);
};Template Component (presentation):
// template/components/LoginForm/LoginFormTemplate.tsx
import styles from './LoginFormTemplate.module.scss';
export interface LoginFormTemplateProps {
email: string;
password: string;
onEmailChange: (value: string) => void;
onPasswordChange: (value: string) => void;
onSubmit: (e: React.FormEvent) => void;
}
export const LoginFormTemplate = ({
email,
password,
onEmailChange,
onPasswordChange,
onSubmit,
}: LoginFormTemplateProps) => {
return (
<form onSubmit={onSubmit}>
<input
type="email"
value={email}
onChange={(e) => onEmailChange(e.target.value)}
/>
{/* Pure presentation - no business logic */}
</form>
);
};Design Tokens (template/styles/variables.scss):
- Colors:
$primary-color,$secondary-color,$background-color, etc. - Typography:
$font-family-base,$font-size-base,$font-size-h1, etc. - Spacing:
$spacing-xsto$spacing-2xl - Border radius:
$border-radius-smto$border-radius-xl - Breakpoints:
$breakpoint-mobile,$breakpoint-tablet,$breakpoint-desktop
SCSS Mixins (template/styles/mixins.scss):
@include flex-center; // Flexbox centered layout
@include card; // Card styling with shadow
@include button-primary; // Primary button styles
@include input-base; // Input field styles
// Responsive utilities
@include mobile { /* ... */ }
@include tablet-up { /* ... */ }
@include desktop { /* ... */ }✅ DO:
- Keep template components pure (no state, no side effects)
- Use design tokens from
variables.scss - Maintain TypeScript prop interfaces
- Import templates from
@/template/components/ - Document template customization in
template/README.md
❌ DON'T:
- Add business logic to template components
- Make API calls from templates
- Use React hooks (useState, useEffect) in templates
- Change prop interfaces without updating logic components
- Import from
components/,services/, orapp/in templates
Users can completely customize the application's appearance by:
- Replacing the entire
template/directory - Keeping the same file names and TypeScript interfaces
- Modifying HTML structure and styles as needed
See template/README.md for detailed customization guide.
This project is in the initial setup phase. The Next.js frontend structure has been initialized.
# Start infrastructure services (MongoDB, Weaviate, Redis, etc.)
docker-compose up -d
# Install dependencies
npm install
# Run development server
npm run dev
# Stop infrastructure services
docker-compose down# Start all services (app + infrastructure)
docker-compose -f docker-compose.prod.yml up -d
# View logs
docker-compose -f docker-compose.prod.yml logs -f app
# Stop services
docker-compose -f docker-compose.prod.yml down
# Rebuild after changes
docker-compose -f docker-compose.prod.yml up -d --build# Build for production
npm run build
# Start production server locally
npm start
# Lint code
npm run lintStart everything (Docker + Next.js) in one command:
make dev-fullThis is the easiest way to start the development environment. It will:
- Start all Docker services (MongoDB, Weaviate, vLLM)
- Start Next.js development server
- Show colored output for each process
Alternative commands:
# Using npm
npm run dev:full
# Using bash script
./dev.sh start# Start/Stop
make dev-full # Start everything
make dev # Start only Next.js (Docker must be running)
make dev-infra # Start only Docker services
make stop # Stop Docker services
make status # Check Docker services status
# Logs and Debugging
make logs # View Docker logs (follow mode)
# Testing (always run with TEST_LOCALE=en)
TEST_LOCALE=en make test # Run all tests
TEST_LOCALE=en make test-watch # Run tests in watch mode
TEST_LOCALE=en npm test # Alternative: run tests with npm
make lint # Run ESLint
make type-check # Run TypeScript type checking
# Build
make build # Build production bundle
# Cleanup
make clean # Stop Docker and remove volumes (DANGER: deletes data)- Application: http://localhost:2137
- Shop (AI Chat): http://localhost:2137/en/shop/chat
- CMS (Admin): http://localhost:2137/en/cms
- MongoDB: localhost:2138
- Weaviate: localhost:2139 (HTTP), localhost:2140 (gRPC)
- vLLM Qwen3-VL: localhost:2141
- vLLM Qwen3: localhost:2142
If services fail to start:
make clean # Remove all Docker data
make dev-infra # Restart Docker services
make dev # Start Next.jsFor more detailed information, see DEVELOPMENT.md.
When working on a GitHub task, try to link the PR to the task using the "Closes #[task-number]" keyword in the PR description (only when it naturally comes up in the conversation, don't force it).
When setting up this project, ensure to:
- Set up MongoDB connection
- Implement LangGraph backend API
- Build the chat interface
- Create the CMS admin panel
- Add authentication and authorization
- Implement product management
- Add payment gateway integration