--- description: Implement a full-stack feature across Django backend and Nuxt frontend --- # New Feature Workflow Implement a complete feature spanning the Django backend and Nuxt frontend. ## Planning Phase Before writing any code, create an implementation plan: ### 1. Feature Definition - **Goal**: What problem does this feature solve? - **User Stories**: Who uses it and how? - **Acceptance Criteria**: How do we know it's done? ### 2. Technical Scope - **Backend Changes**: Models, APIs, permissions - **Frontend Changes**: Pages, components, state - **Data Flow**: How data moves between layers ### 3. Implementation Order Always implement in this order: 1. **Database/Models** - Foundation first 2. **API Endpoints** - Backend logic 3. **Frontend Components** - UI building blocks 4. **Frontend Pages** - Assembled views 5. **Integration** - Wire it all together 6. **Tests** - Verify everything works ## Implementation Steps ### Step 1: Backend - Models ```python # Create or modify models # Remember: Inherit from BaseModel, add proper indexes class NewFeature(BaseModel): # Fields name = models.CharField(max_length=255) # ... other fields class Meta: ordering = ['-created_at'] ``` Run migrations: ```bash python manage.py makemigrations python manage.py migrate ``` ### Step 2: Backend - Serializers ```python # backend/apps/[app]/serializers.py class NewFeatureSerializer(serializers.ModelSerializer): class Meta: model = NewFeature fields = ['id', 'name', 'created_at', 'updated_at'] read_only_fields = ['id', 'created_at', 'updated_at'] class NewFeatureDetailSerializer(NewFeatureSerializer): # Extended fields for detail view related_data = RelatedSerializer(many=True, read_only=True) class Meta(NewFeatureSerializer.Meta): fields = NewFeatureSerializer.Meta.fields + ['related_data'] ``` ### Step 3: Backend - API Views ```python # backend/apps/[app]/views.py class NewFeatureViewSet(viewsets.ModelViewSet): queryset = NewFeature.objects.all() serializer_class = NewFeatureSerializer permission_classes = [IsAuthenticatedOrReadOnly] def get_queryset(self): return NewFeature.objects.select_related( # Add related models ).prefetch_related( # Add many-to-many or reverse relations ) def get_serializer_class(self): if self.action == 'retrieve': return NewFeatureDetailSerializer return NewFeatureSerializer ``` ### Step 4: Backend - URLs ```python # backend/apps/[app]/urls.py router.register('new-features', NewFeatureViewSet, basename='new-feature') ``` ### Step 5: Backend - Tests ```python # backend/apps/[app]/tests/test_new_feature.py class TestNewFeatureAPI(APITestCase): def test_list_features(self): response = self.client.get('/api/v1/new-features/') self.assertEqual(response.status_code, 200) def test_create_feature_authenticated(self): self.client.force_authenticate(user=self.user) response = self.client.post('/api/v1/new-features/', {'name': 'Test'}) self.assertEqual(response.status_code, 201) ``` ### Step 6: Frontend - Types ```typescript // frontend/types/newFeature.ts export interface NewFeature { id: string name: string createdAt: string updatedAt: string } export interface NewFeatureDetail extends NewFeature { relatedData: RelatedItem[] } ``` ### Step 7: Frontend - Composables ```typescript // frontend/composables/useNewFeatures.ts export function useNewFeatures() { const api = useApi() async function getFeatures(params?: Record) { return api>('/new-features/', { params }) } async function getFeature(id: string) { return api(`/new-features/${id}/`) } async function createFeature(data: Partial) { return api('/new-features/', { method: 'POST', body: data }) } return { getFeatures, getFeature, createFeature } } ``` ### Step 8: Frontend - Components Create necessary components following component patterns: ```vue ``` ### Step 9: Frontend - Pages ```vue ``` ### Step 10: Integration Testing Test the full flow: 1. **API Test**: Verify endpoints with curl or API client 2. **Component Test**: Test components in isolation 3. **E2E Test**: Test complete user journey ```typescript // frontend/tests/e2e/newFeature.spec.ts import { test, expect } from '@playwright/test' test('user can view new features', async ({ page }) => { await page.goto('/new-features') await expect(page.locator('h1')).toContainText('New Features') }) test('authenticated user can create feature', async ({ page }) => { // Login first await page.goto('/auth/login') // ... login steps await page.goto('/new-features/create') await page.fill('input[name="name"]', 'Test Feature') await page.click('button[type="submit"]') await expect(page).toHaveURL(/\/new-features\//) }) ``` ## Feature Checklist ### Backend - [ ] Models created with proper fields and indexes - [ ] Migrations created and applied - [ ] Serializers handle validation - [ ] ViewSet has proper permissions - [ ] Queries are optimized - [ ] URLs registered - [ ] Unit tests pass ### Frontend - [ ] Types defined - [ ] Composables created for API calls - [ ] Components follow design system - [ ] Pages have proper SEO meta - [ ] Loading states implemented - [ ] Error states handled - [ ] Responsive design verified - [ ] Keyboard accessible ### Integration - [ ] Data flows correctly between backend and frontend - [ ] Authentication/authorization works - [ ] Error handling covers edge cases - [ ] Performance is acceptable ## Output Summary After completing the feature: ```markdown ## Feature: [Feature Name] ### Backend - Model: `apps/[app]/models.py` - NewFeature - API: `/api/v1/new-features/` - Permissions: [describe] ### Frontend - Page: `/new-features` (list), `/new-features/[id]` (detail) - Components: NewFeatureCard, NewFeatureForm - Composable: useNewFeatures ### Tests - Backend: X tests passing - Frontend: X tests passing - E2E: X tests passing ### Notes - [Any important implementation notes] - [Known limitations] - [Future improvements] ```