All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m17s
365 lines
16 KiB
Markdown
365 lines
16 KiB
Markdown
# Jimeng Clone — AI Video Generation Platform
|
|
|
|
> This file is the single source of truth for AI-assisted development on this project.
|
|
> AI agents (including Claude Code) should read this file first before making any changes.
|
|
|
|
## Quick Start
|
|
|
|
### Development Environment
|
|
- **Backend**: Python 3.12 + Django 4.2 + DRF + SimpleJWT
|
|
- **Frontend**: React 18 + Vite 6 + TypeScript 5 + Zustand
|
|
- **Database**: SQLite (dev) / Aliyun RDS MySQL (prod)
|
|
- **UI Library**: Arco Design (`@arco-design/web-react`)
|
|
- **Charts**: ECharts 6 + echarts-for-react
|
|
|
|
### Setup Commands
|
|
```bash
|
|
# Backend
|
|
cd backend
|
|
python -m venv venv && source venv/bin/activate
|
|
pip install -r requirements.txt
|
|
python manage.py migrate
|
|
python manage.py runserver 8000
|
|
|
|
# Frontend
|
|
cd web
|
|
npm install
|
|
npm run dev # Dev server at localhost:5173
|
|
npm run build # Production build: tsc -b && vite build
|
|
```
|
|
|
|
### Test Commands
|
|
```bash
|
|
# Frontend unit tests
|
|
cd web && npx vitest run
|
|
|
|
# Backend checks
|
|
cd backend && python manage.py check
|
|
```
|
|
|
|
### Admin Credentials (Dev)
|
|
- Username: `admin` / Password: `admin123`
|
|
|
|
## Project Architecture
|
|
|
|
### Directory Structure
|
|
```
|
|
jimeng-clone/
|
|
├── backend/ # Django REST Framework backend
|
|
│ ├── config/ # Django settings, urls, wsgi
|
|
│ │ ├── settings.py # Main config (DB, CORS, JWT, apps)
|
|
│ │ └── urls.py # Root URL routing
|
|
│ ├── apps/
|
|
│ │ ├── accounts/ # User auth: models, views, serializers, urls
|
|
│ │ └── generation/ # Video generation: models, views, serializers, urls
|
|
│ ├── requirements.txt # Python dependencies
|
|
│ └── Dockerfile # Python 3.12 + gunicorn
|
|
├── web/ # React 18 + Vite frontend
|
|
│ ├── src/
|
|
│ │ ├── App.tsx # Root router (all routes defined here)
|
|
│ │ ├── main.tsx # Entry point
|
|
│ │ ├── pages/ # Page-level components (one per route)
|
|
│ │ ├── components/ # Reusable UI components
|
|
│ │ ├── store/ # Zustand state stores
|
|
│ │ ├── lib/ # Utilities (API client, log center)
|
|
│ │ └── types/ # TypeScript type definitions
|
|
│ ├── nginx.conf # Production nginx config
|
|
│ └── Dockerfile # Node 18 + nginx
|
|
├── k8s/ # Kubernetes deployment configs
|
|
├── docs/ # PRD, design review documents
|
|
├── .gitea/workflows/ # CI/CD pipeline
|
|
└── .autonomous/ # Autonomous skill task tracking
|
|
```
|
|
|
|
### Key Files (Most Commonly Modified)
|
|
- `web/src/App.tsx` — Route definitions. Modify when adding new pages.
|
|
- `web/src/store/auth.ts` — Auth state (login/logout/JWT refresh)
|
|
- `web/src/store/generation.ts` — Video generation state & API calls
|
|
- `web/src/store/inputBar.ts` — Input bar state (mode, files, prompt)
|
|
- `web/src/lib/api.ts` — Axios client with JWT interceptor. API base URL configured here.
|
|
- `web/src/types/index.ts` — All TypeScript interfaces
|
|
- `backend/config/settings.py` — Django settings (DB, CORS, JWT, installed apps)
|
|
- `backend/config/urls.py` — Root URL routing
|
|
- `backend/apps/accounts/models.py` — User model (extends AbstractUser)
|
|
- `backend/apps/generation/models.py` — GenerationRecord + QuotaConfig models
|
|
- `backend/apps/generation/views.py` — All API endpoints (video, admin, profile)
|
|
- `backend/apps/generation/urls.py` — API URL patterns
|
|
|
|
## Development Conventions
|
|
|
|
### Code Style
|
|
- **Frontend**: TypeScript strict mode, functional components, named exports
|
|
- **Backend**: PEP 8, function-based views with `@api_view` decorator
|
|
- **CSS**: Inline styles + Arco Design component props (no separate CSS modules)
|
|
|
|
### Naming Conventions
|
|
- **React Components**: PascalCase files (e.g., `LoginPage.tsx`, `InputBar.tsx`)
|
|
- **Stores**: camelCase files (e.g., `auth.ts`, `generation.ts`)
|
|
- **Django Apps**: lowercase (e.g., `accounts`, `generation`)
|
|
- **API URLs**: `/api/v1/` prefix, no trailing slashes in URL patterns
|
|
- **Database**: snake_case (Django default)
|
|
|
|
### State Management Pattern
|
|
- Zustand stores in `web/src/store/`, one store per domain
|
|
- Each store exports a `use[Name]Store` hook
|
|
- API calls are defined inside stores (not in components)
|
|
- Pattern: `const doSomething = useAuthStore((s) => s.doSomething)`
|
|
|
|
### Component Pattern
|
|
- Pages in `web/src/pages/` — full-page components mounted by router
|
|
- Reusable components in `web/src/components/`
|
|
- Protected routes use `<ProtectedRoute>` wrapper, admin routes add `requireAdmin` prop
|
|
|
|
### Backend Pattern
|
|
- Function-based views with `@api_view(['GET', 'POST'])` decorator
|
|
- Auth via `@permission_classes([IsAuthenticated])`
|
|
- Admin endpoints check `request.user.is_staff`
|
|
- Singleton pattern for QuotaConfig (pk always = 1)
|
|
|
|
## API Endpoints
|
|
|
|
### Auth (`/api/v1/auth/`)
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| POST | `/api/v1/auth/register` | User registration |
|
|
| POST | `/api/v1/auth/login` | JWT login (returns access + refresh tokens) |
|
|
| POST | `/api/v1/auth/token/refresh` | Refresh JWT access token |
|
|
| GET | `/api/v1/auth/me` | Get current user info |
|
|
|
|
### Video Generation (`/api/v1/`)
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| POST | `/api/v1/media/upload` | Upload reference media files |
|
|
| POST | `/api/v1/video/generate` | Submit video generation task |
|
|
| GET | `/api/v1/video/tasks` | List user's generation tasks |
|
|
| GET | `/api/v1/video/tasks/<uuid>` | Get task status & result |
|
|
|
|
### Admin (`/api/v1/admin/`)
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/api/v1/admin/stats` | Dashboard statistics & charts data |
|
|
| GET | `/api/v1/admin/users` | List all users (search, filter, paginate) |
|
|
| POST | `/api/v1/admin/users/create` | Create new user |
|
|
| GET/PUT | `/api/v1/admin/users/<id>` | Get/update user details |
|
|
| PUT | `/api/v1/admin/users/<id>/quota` | Update user quota limits |
|
|
| PUT | `/api/v1/admin/users/<id>/status` | Toggle user active status |
|
|
| GET | `/api/v1/admin/records` | List all generation records |
|
|
| GET/PUT | `/api/v1/admin/settings` | Get/update global settings (QuotaConfig) |
|
|
|
|
### Profile (`/api/v1/profile/`)
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/api/v1/profile/overview` | User consumption summary |
|
|
| GET | `/api/v1/profile/records` | User's own generation records |
|
|
|
|
## Database Models
|
|
|
|
### User (extends AbstractUser)
|
|
- `email` (unique), `daily_seconds_limit` (default: 600), `monthly_seconds_limit` (default: 6000)
|
|
- `created_at`, `updated_at`
|
|
|
|
### GenerationRecord
|
|
- `user` (FK), `task_id` (UUID), `ark_task_id`, `prompt`, `mode` (universal|keyframe)
|
|
- `model` (seedance_2.0|seedance_2.0_fast), `aspect_ratio`, `duration`, `seconds_consumed`
|
|
- `status` (queued|processing|completed|failed), `result_url`, `error_message`, `reference_urls` (JSON)
|
|
- Index: (user, created_at)
|
|
|
|
### QuotaConfig (Singleton, pk=1)
|
|
- `default_daily_seconds_limit`, `default_monthly_seconds_limit`
|
|
- `announcement`, `announcement_enabled`, `updated_at`
|
|
|
|
## Frontend Routes
|
|
|
|
| Path | Component | Auth | Description |
|
|
|------|-----------|------|-------------|
|
|
| `/login` | LoginPage | No | Login page |
|
|
| `/` | VideoGenerationPage | Yes | Main video generation UI |
|
|
| `/profile` | ProfilePage | Yes | User consumption overview |
|
|
| `/admin/dashboard` | DashboardPage | Admin | Stats & charts |
|
|
| `/admin/users` | UsersPage | Admin | User management |
|
|
| `/admin/records` | RecordsPage | Admin | Generation records |
|
|
| `/admin/settings` | SettingsPage | Admin | Global quota & announcement |
|
|
|
|
## Incremental Development Guide
|
|
|
|
### How to Add Features to This Project
|
|
|
|
This project was generated and maintained using the **Autonomous Skill** for Claude Code.
|
|
For incremental development, you have two approaches:
|
|
|
|
#### Approach 1: Direct AI Development (Small Changes)
|
|
For small features, bug fixes, or UI tweaks — just describe what you want directly to Claude Code.
|
|
Claude Code will read this CLAUDE.md to understand the project context.
|
|
|
|
Example prompts:
|
|
- "Add a logout button to the navbar"
|
|
- "Fix the date format in the records table"
|
|
- "Add input validation to the login form"
|
|
- "Change the default daily quota from 600 to 1200 seconds"
|
|
|
|
**IMPORTANT — Update Documentation After Every Change:**
|
|
Even for the smallest change, you MUST update documentation to keep it in sync:
|
|
|
|
1. **Update `CLAUDE.md`** (this file):
|
|
- New API endpoint → add to API Endpoints table
|
|
- New page/route → add to Frontend Routes table
|
|
- New model/field → add to Database Models section
|
|
- New component → add to Directory Structure or Key Files
|
|
- Any config change → update relevant section
|
|
- Always add a row to the **Change History** table at the bottom
|
|
|
|
2. **Update Claude Code memory** (if auto-memory is available):
|
|
- Update the project's memory files under `~/.claude/projects/` to reflect the change
|
|
- This ensures future AI sessions across different conversations also know about the change
|
|
|
|
3. **Even non-architectural changes must be tracked**:
|
|
- Bug fix → add to Change History
|
|
- UI tweak → add to Change History
|
|
- Dependency update → update Quick Start / Tech Stack section
|
|
- Config value change → update relevant section
|
|
|
|
Failing to update documentation means future AI sessions will work with stale context and may introduce conflicts or duplicate work.
|
|
|
|
#### Approach 2: Autonomous Skill (Large Features)
|
|
For complex, multi-step features, use the Autonomous Skill:
|
|
|
|
```
|
|
autonomous: Add user notification system with email and in-app alerts
|
|
```
|
|
|
|
Or via CLI:
|
|
```bash
|
|
cd /path/to/jimeng-clone
|
|
~/.claude/plugins/marketplaces/claude-code-settings/plugins/autonomous-skill/skills/autonomous-skill/scripts/run-session.sh "Add user notification system"
|
|
```
|
|
|
|
The autonomous skill will:
|
|
1. Read this CLAUDE.md to understand the project
|
|
2. Break the feature into 10-100 sub-tasks in `.autonomous/<task-name>/task_list.md`
|
|
3. Execute across multiple sessions automatically
|
|
4. Auto-update this CLAUDE.md with architectural changes after each session
|
|
|
|
#### When to Use Which Approach
|
|
| Scenario | Approach |
|
|
|----------|----------|
|
|
| Bug fix / single-line change | Direct AI |
|
|
| Small UI tweak (button, color, text) | Direct AI |
|
|
| Add a single API endpoint | Direct AI |
|
|
| Modify existing component behavior | Direct AI |
|
|
| New feature module (3+ files) | Autonomous |
|
|
| Add entire admin page with CRUD | Autonomous |
|
|
| Refactor across multiple files | Autonomous |
|
|
| Add new subsystem (notifications, payments) | Autonomous |
|
|
|
|
### How to Add a New Page
|
|
|
|
1. Create page component in `web/src/pages/NewPage.tsx`
|
|
2. Add route in `web/src/App.tsx` inside `<Routes>`:
|
|
```tsx
|
|
<Route path="/new-page" element={<ProtectedRoute><NewPage /></ProtectedRoute>} />
|
|
```
|
|
3. If it needs state, create store in `web/src/store/newPage.ts`
|
|
4. Add API calls in the store using `api.get()` / `api.post()` from `web/src/lib/api.ts`
|
|
|
|
### How to Add a New API Endpoint
|
|
|
|
1. Add view function in `backend/apps/generation/views.py` (or relevant app):
|
|
```python
|
|
@api_view(['GET'])
|
|
@permission_classes([IsAuthenticated])
|
|
def new_endpoint_view(request):
|
|
return Response({'data': ...})
|
|
```
|
|
2. Add URL pattern in `backend/apps/generation/urls.py`:
|
|
```python
|
|
path('new/endpoint', views.new_endpoint_view, name='new_endpoint'),
|
|
```
|
|
3. Add TypeScript types in `web/src/types/index.ts`
|
|
4. Add API call in the relevant Zustand store
|
|
|
|
### How to Add a New Database Model
|
|
|
|
1. Define model in `backend/apps/generation/models.py` (or relevant app)
|
|
2. Run migrations:
|
|
```bash
|
|
cd backend
|
|
python manage.py makemigrations
|
|
python manage.py migrate
|
|
```
|
|
3. Register in admin: `backend/apps/generation/admin.py`
|
|
4. Create serializer if needed: `backend/apps/generation/serializers.py`
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Description | Required |
|
|
|----------|-------------|----------|
|
|
| `DATABASE_URL` | MySQL connection string (prod) | Prod only |
|
|
| `SECRET_KEY` | Django secret key | Yes |
|
|
| `TOS_ACCESS_KEY` | Volcano Engine TOS AccessKeyId | Yes (upload) |
|
|
| `TOS_SECRET_KEY` | Volcano Engine TOS SecretAccessKey | Yes (upload) |
|
|
| `TOS_BUCKET` | Volcano TOS bucket name (default: `video-huoshan`) | Yes (upload) |
|
|
| `TOS_ENDPOINT` | TOS endpoint URL (default: `https://tos-cn-guangzhou.volces.com`) | Yes (upload) |
|
|
| `TOS_REGION` | TOS region (default: `cn-guangzhou`) | Yes (upload) |
|
|
| `ARK_API_KEY` | Volcano Engine ARK API key for Seedance | Yes (video gen) |
|
|
| `ARK_BASE_URL` | ARK API base URL (default: `https://ark.cn-beijing.volces.com/api/v3`) | No |
|
|
|
|
## Deployment
|
|
|
|
- **CI/CD**: Gitea Actions (`.gitea/workflows/deploy.yaml`)
|
|
- **Registry**: Huawei Cloud SWR
|
|
- **Orchestration**: Kubernetes (`k8s/` directory)
|
|
- **Backend URL**: `video-huoshan-api.airlabs.art`
|
|
- **Frontend URL**: `video-huoshan-web.airlabs.art`
|
|
- **Database**: Aliyun RDS MySQL (`rm-7xv1uaw910558p1788o.mysql.rds.aliyuncs.com:3306`)
|
|
|
|
## Testing
|
|
|
|
- **Unit Tests**: 227 tests in `web/` via Vitest — `cd web && npx vitest run`
|
|
- **E2E Tests**: 49 tests via Playwright — `cd web && npx playwright test`
|
|
- **Backend**: Django system checks — `cd backend && python manage.py check`
|
|
- **Status**: 211 passing, 16 pre-existing path-resolution failures in phase2/phase3 tests
|
|
- **Test DB Isolation**: E2E tests use `TESTING=true` env var → backend writes to `test_db.sqlite3` (not `db.sqlite3`). Playwright auto-starts a test backend on port 8000 with this env var. Dev data is never polluted by tests.
|
|
|
|
## Design Guidelines
|
|
|
|
- **Color Palette**: `#0a0a0f` (bg), `#111118`, `#16161e`, `#2a2a38`, `#00b8e6` (accent)
|
|
- **Typography**: Noto Sans SC (Chinese) + Space Grotesk (UI) + JetBrains Mono (code)
|
|
- **Style**: Linear/Vercel dark theme aesthetic
|
|
- **Responsive**: `grid-cols-4 max-lg:grid-cols-2`
|
|
|
|
## Change History
|
|
|
|
| Date | Change | Scope |
|
|
|------|--------|-------|
|
|
| 2025-01 | Phase 1: Core video generation UI | Frontend |
|
|
| 2025-02 | Phase 2: Backend + Auth + Admin panel | Full stack |
|
|
| 2025-03 | Phase 3: Seconds-based quota, profile page, ECharts dashboard | Full stack |
|
|
| 2026-03 | Added CLAUDE.md for AI-assisted incremental development | Documentation |
|
|
| 2026-03-13 | Phase 4: TOS upload + Seedance API integration + DB persistence | Full stack |
|
|
| 2026-03-13 | Test DB isolation: TESTING=true → test_db.sqlite3, Playwright auto-starts test backend | Backend + Config |
|
|
| 2026-03-13 | Removed mock data fallback from DashboardPage — charts show real data only | Frontend |
|
|
|
|
### Phase 4 Details (2026-03-13)
|
|
|
|
**Backend new files:**
|
|
- `backend/utils/tos_client.py` — Volcano Engine TOS upload via official `tos` SDK
|
|
- `backend/utils/seedance_client.py` — Seedance/ARK API client (create_task, query_task)
|
|
|
|
**Backend changes:**
|
|
- `backend/config/settings.py` — Added TOS and ARK config
|
|
- `backend/apps/generation/models.py` — Added `ark_task_id`, `result_url`, `error_message`, `reference_urls` (JSONField)
|
|
- `backend/apps/generation/views.py` — New endpoints: `upload_media_view`, `video_tasks_list_view`, `video_task_detail_view`; Rewritten `video_generate_view` with Seedance integration
|
|
- `backend/apps/generation/urls.py` — Added 3 routes: `media/upload`, `video/tasks`, `video/tasks/<uuid>`
|
|
- `backend/apps/generation/serializers.py` — Added `references` field to VideoGenerateSerializer
|
|
- `backend/requirements.txt` — Added `tos>=2.7`, `requests>=2.31`
|
|
- Migration: `0003_generationrecord_ark_task_id_and_more.py`
|
|
|
|
**Frontend changes:**
|
|
- `web/src/types/index.ts` — Added `BackendTask` interface, `tosUrl` to `UploadedFile`, `taskId`/`errorMessage` to `GenerationTask`
|
|
- `web/src/lib/api.ts` — Added `mediaApi.upload()`, `videoApi.getTasks()`, `videoApi.getTaskStatus()`; Changed `videoApi.generate()` to JSON
|
|
- `web/src/store/generation.ts` — Complete rewrite: async TOS upload + API calls + polling + `loadTasks()` for refresh persistence
|
|
- `web/src/components/VideoGenerationPage.tsx` — Added `loadTasks()` on mount
|
|
- `web/src/components/GenerationCard.tsx` — Video player for results, error state display
|
|
|
|
**Flow:** Upload files → TOS → Generate API (Seedance) → DB record → Poll status → Display result
|