Message to either the Software Engineering Assistant or Architect Assistant: If you see this message and you see any epics defined under the ./epics/ directory then immediately do the following before continuing:
- Use the read_file tool to read the first Epic requirements.md
- Use the read_file tool to read the translation.json files
- Use the write_file tool to update the translation.json files with more appropriate strings for the project/first epic etc
- Use the write_file tool to update the hints.md file to remove this section
- Continue with the next step of whatever you were doing before you saw this message
- All frontend code should be placed under
frontend/src - Components should be organized by feature or domain
- Reusable UI components should be placed in
frontend/src/components/ui - Follow this structure for new features:
frontend/src/ ├── pages/your-feature/ │ └── index.tsx ├── components/your-feature/ │ ├── feature-component.tsx │ └── sub-components/ └── lib/your-feature/ └── your-feature.service.ts
- The API is the source of truth - never modify the API to match the frontend, always update the frontend to match the API
- Always read the corresponding backend controller and DTO files before implementing API calls
- Use strongly typed request/response interfaces that match backend DTOs exactly
- Example API service structure:
interface CreateSomethingDto { // Copy types from backend DTO } export class YourFeatureService { async createSomething(dto: CreateSomethingDto) { return api.post('/api/your-feature', dto); } }
- All UI text must be added to translation files for both English and French
- Place translations in:
frontend/src/i18n/locales/en/translation.jsonfrontend/src/i18n/locales/fr/translation.json
- Use nested keys for feature-specific translations
- Example translation usage:
// In translation files: { "yourFeature": { "title": "Feature Title", "description": "Feature description" } } // In components: const { t } = useTranslation(); <h1>{t('yourFeature.title')}</h1>
- Use shadcn/ui components from
components/uifor consistent styling - Implement responsive designs using Tailwind CSS
- Keep components focused and reusable
- Use TypeScript for all component props
- Always use the application theme from
lib/theme.tsfor styling - Extend the theme when new design tokens are needed rather than using hardcoded values
- Use the getThemeClass utility for accessing theme values
- Example component structure:
interface FeatureProps { data: YourDataType; onAction: (id: string) => void; } export function FeatureComponent({ data, onAction }: FeatureProps) { const { t } = useTranslation(); return ( <Card className={getThemeClass('components.card.base')}> <CardHeader> <CardTitle className={getThemeClass('components.text.heading')}> {t('yourFeature.title')} </CardTitle> </CardHeader> </Card> ); }
- The application theme is defined in
lib/theme.tsand should be the single source of truth for styling - Theme includes predefined tokens for:
- Color schemes and gradients
- Component-specific styles
- Typography and text styles
- Common UI patterns
- Always extend the theme instead of using arbitrary values:
// In lib/theme.ts export const theme = { // Existing theme configuration... components: { yourFeature: { container: 'bg-white/90 p-4 rounded-lg', header: 'text-lg font-semibold text-blue-600', } } } // In your component <div className={getThemeClass('components.yourFeature.container')}> <h2 className={getThemeClass('components.yourFeature.header')}> {t('yourFeature.title')} </h2> </div>
- When adding new theme values:
- First check if an existing theme token meets your needs
- If not, add new tokens to the appropriate theme section
- Use semantic naming that describes the purpose, not the appearance
- Document any new theme additions in comments
- Use React Context for global state when needed
- Prefer local state for component-specific data
- Use custom hooks to encapsulate complex state logic
- Follow existing patterns in
lib/auth.context.tsx
- Follow existing code style and formatting
- Use meaningful component and variable names
- Keep components focused and single-responsibility
- Implement proper error handling and loading states
- Use TypeScript for type safety
- Add comments for complex logic
- Follow existing patterns for routing and layouts
- Use existing hooks from the
hooksdirectory where applicable
- Use a modular approach with each unit of functionality in its own module
- All modules should be placed under
backend/src/modules - Example structure for a new feature:
backend/src/modules/your-feature/ ├── your-feature.controller.ts ├── your-feature.module.ts ├── your-feature.service.ts ├── dto/ │ ├── create-something.dto.ts │ └── update-something.dto.ts └── entities/ └── something.entity.ts
- Follow API-first approach
- All endpoints must be prefixed with
/api - Use consistent JSON request/response payloads
- Implement pagination for list endpoints where appropriate
- Example endpoint structure:
// List endpoint with pagination GET /api/your-feature?page=1&limit=10 // Get single item GET /api/your-feature/:id // Create new item POST /api/your-feature // Update item PUT /api/your-feature/:id // Delete item DELETE /api/your-feature/:id
- See the auth module (controller, dtos etc) for examples of how to implement new REST endpoints being careful to follow the existing patterns for validation, error handling, documentation etc
- Focus on simple end-to-end (e2e) tests for happy path scenarios (no unit tests required for now)
- Place e2e tests in
backend/testdirectory - Do not use fixtures or mocks in e2e tests - test the real API
- Use the rest-client.ts file to make requests to the API and use the test-auth.ts file to authenticate and get a test user
- Example test structure:
describe('YourFeature (e2e)', () => { it('should create a new item', () => { // Test POST endpoint }); it('should retrieve items with pagination', () => { // Test GET endpoint with pagination }); });
- The application uses Knex.js for database operations and migrations
- Database configuration is environment-based:
- test: In-memory SQLite
- dev: SQLite file (dev.sqlite3 in repo root)
- prod: PostgreSQL (localhost:5432)
- Migrations must be compatible with both SQLite and PostgreSQL:
- Avoid using database-specific features
- Place migrations in
backend/src/migrations - Use timestamp-prefixed names (YYYYMMDDHHMMSS_description.ts)
- Database connections are automatically:
- Established on application startup
- Migrations are run on startup
- Connections are properly closed on shutdown
- Use TypeScript DTOs for request/response validation
- Include Swagger documentation for all endpoints with the
@ApiTagsand@ApiOperationdecorators and clear descriptions - Implement proper error handling
- Follow existing code style and formatting
- Use both INFO and DEBUG logging levels as appropriate
- Use meaningful variable and function names
- Keep modules focused and single-responsibility
- All entity IDs should use ULIDs (Universally Unique Lexicographically Sortable Identifiers)