- 根目录加入 docker-compose、Caddyfile、文档等原本不在仓库里的文件 - 前后端两份 GitHub Actions 合并成根目录的一个 deploy workflow: 构建前端上传到 build/,再在服务器上 git pull 并重建容器 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
WebPreview is a web-based tutorial/challenge platform where users view tutorials and submit HTML/CSS/JS code for challenges. It has a Django API backend and a Vue 3 frontend, deployed via Docker Compose with Caddy as reverse proxy.
Architecture
-
api/— Django backend using django-ninja for REST APIs and Django Channels (Daphne/ASGI) for WebSocket supportapi/api/— Django project config (settings, urls, asgi)api/account/— User auth (login/logout, profiles, batch creation). Three roles:super,admin,normal— affects scoring weightsapi/task/— Tutorial and Challenge models (singleTaskbase model withtask_type), with separatetutorial.pyandchallenge.pyrouter filesapi/submission/— Code submission +Ratingmodel. Submission score is a weighted average of ratings by role: super×0.5, admin×0.3, normal×0.2.Profile.recalculate_total_score()uses best-score-per-challengeapi/prompt/— LLM chat feature: WebSocket consumer streams DeepSeek responses,Conversation/Messagemodels store history, code blocks extracted from responsesapi/utils/upload.py— Image upload endpoint- API routers are registered in
api/api/urls.pyunder/api/prefix - Uses
AUTH_USER_MODEL = "account.User"(custom user model) - Dev mode uses SQLite (
ENV != "production"); production uses PostgreSQL + Redis (sessions, caching, channel layers)
-
client/— Vue 3 + TypeScript SPA built with Rsbuild- UI framework: Naive UI (auto-imported via
unplugin-vue-components) src/api.ts— Axios-based API client with CSRF and auth interceptors; exportsAccount,Tutorial,Challenge,Submission,Prompt,Helperobjectssrc/router.ts— Vue Router with auth guards; routes under/dashboardrequire loginsrc/store/— Reactive state (plain Vue refs, not Vuex/Pinia)src/pages/— Route-level views (Home, Dashboard, ChallengeHome, TutorialEditor, ChallengeEditor, Submissions, Leaderboard, MyScores)src/components/— Shared components:Task.vue,Tutorial.vue,Challenge.vue,Editors.vue(CodeMirror),Preview.vue(live HTML preview),Toolbar.vue,PromptPanel.vue(LLM chat)
- UI framework: Naive UI (auto-imported via
-
Caddyfile— Routes/api*,/admin*,/ws*to backend; serves SPA and static/media files -
docker-compose.yaml— Services: caddy, api, postgres, redis
Development Commands
Client (from client/)
npm run start # Dev server (Rsbuild)
npm run build # Production build
npm run fmt # Format with Prettier
Frontend env vars used at build time: PUBLIC_BASE_URL, PUBLIC_ADMIN_URL, PUBLIC_WS_URL.
API (from api/)
uv run manage.py runserver # Dev server
uv run manage.py migrate # Run migrations
uv run manage.py createsuperuser # Create admin user
Uses uv for Python dependency management (pyproject.toml + uv.lock). Set ENV=dev in .env (default) for SQLite.
Docker (from project root)
docker compose up -d # Start all services
docker compose up -d --build # Rebuild and start
Key Technical Details
- Backend API pattern: each Django app has
api.py(or named router files liketask/tutorial.py,task/challenge.py) with django-ninja routers, plusschemas.pyfor Pydantic models. Routers mount under/api/<prefix>/ - WebSocket:
prompt/consumers.pyhandles LLM chat atws://<host>/ws/prompt/<task_id>/. Django Channels is configured; in dev, channel layer is in-memory (no Redis needed) - LLM config:
LLM_API_KEY,LLM_BASE_URL(default: DeepSeek),LLM_MODELset via.env - Task
displayfield: integer used as URL slug for tutorials/challenges (unique per task type), not the DBid - Submission IDs: UUIDs (not integers)
- Frontend dev server proxies
/mediatoPUBLIC_WEB_URLenv var; API calls go toBASE_URLdefined insrc/utils/const.ts - Environment config via
.envfile inapi/(referenced by docker-compose and Django'spython-dotenv) - Language/locale is Chinese (
zh-hans,Asia/Shanghaitimezone) - Client build output goes to
build/directory, served by Caddy in production