Skip to content

Frontend Development

The RAG Modulo frontend is built with React 18 and follows modern best practices for component-based development.

Tech Stack

  • React 18 - Modern React with hooks and concurrent features
  • TypeScript - Type-safe development
  • Tailwind CSS - Utility-first CSS framework
  • Carbon Design System - IBM's design language for consistent UI
  • React Router - Client-side routing
  • Axios - HTTP client for API communication

Project Structure

frontend/src/
โ”œโ”€โ”€ components/
โ”‚   โ”œโ”€โ”€ ui/              # Reusable UI components
โ”‚   โ”œโ”€โ”€ modals/          # Modal dialogs
โ”‚   โ”œโ”€โ”€ podcasts/        # Podcast generation features
โ”‚   โ”œโ”€โ”€ search/          # Search interface components
โ”‚   โ””โ”€โ”€ ...
โ”œโ”€โ”€ contexts/            # React contexts for state management
โ”œโ”€โ”€ services/            # API clients and services
โ”œโ”€โ”€ pages/               # Page-level components
โ”œโ”€โ”€ styles/              # Global styles and Tailwind config
โ””โ”€โ”€ utils/               # Utility functions

Getting Started

Prerequisites

Local Development

# One-time setup
make local-dev-setup

# Start infrastructure only (Postgres, Milvus, etc.)
make local-dev-infra

# Start frontend development server with hot-reload
make local-dev-frontend

The frontend will be available at http://localhost:3000

Manual Setup

cd frontend
npm install
npm run dev

Using Docker

# Build and run with Docker Compose
make build-all
make run-app

Development Guidelines

Component Development

Using Reusable UI Components

The project includes a comprehensive library of reusable UI components. Always use these instead of creating custom implementations:

import { Button, Input, Modal, Card } from '@/components/ui';

function MyComponent() {
  return (
    <Card>
      <Input
        label="Name"
        placeholder="Enter name"
        fullWidth
      />
      <Button variant="primary" onClick={handleSubmit}>
        Submit
      </Button>
    </Card>
  );
}

See the UI Components Guide for detailed documentation.

Component Best Practices

  1. Use TypeScript - Define proper interfaces for props
  2. Follow naming conventions - PascalCase for components, camelCase for functions
  3. Keep components focused - Single responsibility principle
  4. Use hooks effectively - Leverage React hooks for state and side effects
  5. Implement error boundaries - Handle errors gracefully
  6. Add accessibility - Include ARIA labels and keyboard navigation

Styling Guidelines

Tailwind CSS

Use Tailwind utility classes following the Carbon Design System color palette:

// Primary colors
<div className="bg-blue-60 text-white">Primary action</div>

// Gray scale
<div className="bg-gray-10 text-gray-100">Subtle background</div>

// Status colors
<div className="bg-green-50 text-white">Success</div>
<div className="bg-red-50 text-white">Error</div>
<div className="bg-yellow-30 text-gray-100">Warning</div>

Component Classes

Pre-defined component classes are available in tailwind.css:

<button className="btn-primary">Primary Button</button>
<input className="input-field" />
<div className="card">Card content</div>

Note: For new components, prefer using the reusable UI components over these utility classes.

State Management

Local State

Use React hooks for component-local state:

const [count, setCount] = useState(0);
const [user, setUser] = useState<User | null>(null);

Context API

Use React Context for shared state across components:

import { useNotification } from '../../contexts/NotificationContext';

function MyComponent() {
  const { addNotification } = useNotification();

  const handleSuccess = () => {
    addNotification('success', 'Operation completed!');
  };
}

API Integration

Use the centralized API client:

import apiClient from '../../services/apiClient';

// Fetch collections
const collections = await apiClient.getCollections();

// Create collection
const newCollection = await apiClient.createCollection({
  name: 'My Collection',
  is_private: true
});

Code Quality

Linting

# Run ESLint
cd frontend
npm run lint

# Auto-fix issues
npm run lint:fix

Type Checking

# Check TypeScript errors
npx tsc --noEmit

Testing

# Run tests
npm test

# Run tests with coverage
npm test -- --coverage

Building for Production

# Create optimized production build
npm run build

# The build output will be in the `build/` directory

Common Development Tasks

Adding a New Page

  1. Create component in src/pages/
  2. Add route in your routing configuration
  3. Import and use reusable UI components
  4. Add TypeScript interfaces for props and state

Creating a New Feature

  1. Plan component structure
  2. Create reusable components if needed
  3. Implement feature using existing UI components
  4. Add API integration if needed
  5. Write tests
  6. Update documentation

Debugging

React DevTools

Install React DevTools browser extension for component inspection and profiling.

Network Debugging

  1. Open browser DevTools (F12)
  2. Go to Network tab
  3. Check API requests and responses
  4. Verify request/response payloads

Console Logging

console.log('Component rendered', { props, state });
console.error('Error occurred', error);

Performance Optimization

Code Splitting

Use React.lazy for route-based code splitting:

const Dashboard = React.lazy(() => import('./pages/Dashboard'));

<Suspense fallback={<Loading />}>
  <Dashboard />
</Suspense>

Memoization

Use React.memo and useMemo to prevent unnecessary re-renders:

const ExpensiveComponent = React.memo(({ data }) => {
  return <div>{/* render */}</div>;
});

const memoizedValue = useMemo(() =>
  computeExpensiveValue(data),
  [data]
);

Troubleshooting

Common Issues

Module Resolution Errors

# Clear caches and restart
rm -rf node_modules/.cache
npm run dev

TypeScript Errors

# Clean TypeScript cache
rm -f tsconfig.tsbuildinfo
npx tsc --noEmit

Port Already in Use

# Kill process on port 3000
lsof -ti:3000 | xargs kill -9

Resources

Next Steps