diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..1017a04 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,273 @@ +# CLAUDE.md — AetherViz Master + +This file provides guidance for AI assistants working in this repository. + +--- + +## Project Overview + +**AetherViz Master** (v5.0) is a **Claude Code Skill** — a prompt specification that guides an AI to generate complete, self-contained interactive 3D educational visualization web pages from a single topic input. There is no traditional source code; the output is always a single-file HTML document delivered directly to the user. + +- **Repository type**: Claude Skill specification + documentation only +- **No build system, no package manager, no test suite** +- **License**: MIT +- **Author**: andyhuo520 + +--- + +## Repository Structure + +``` +aetherviz-master/ +├── CLAUDE.md # This file +├── README.md # User-facing documentation (Chinese) +├── SKILL.md # Authoritative skill specification (Claude reads this when invoked) +└── LICENSE # MIT License +``` + +There are intentionally **no source files, no `node_modules`, no `package.json`**, and no compiled assets. The project is a generative specification, not a traditional codebase. + +--- + +## How the Skill Works + +When a user invokes `/aetherviz-master` (or types a topic) in Claude Code, Claude: + +1. Reads `SKILL.md` as the authoritative specification +2. Auto-detects the subject domain and render mode from the topic keywords +3. Generates a **complete, runnable, single-file HTML document** — nothing else +4. Outputs the raw HTML directly (no markdown fences, no explanation) + +### Output Contract (strict) + +- Output starts with `` and ends with `` +- Zero external file dependencies (all libraries via CDN) +- Must run by saving as `.html` and opening in any modern browser +- Must support mobile touch (rotate, pinch-zoom) +- Must include the footer credit: `由 AetherViz Master 为你生成 ❤️` + +--- + +## Auto-Detection Logic + +### Subject → Color Theme + +| Subject | Color Gradient | +|---------|---------------| +| Physics | Blue `#3B82F6 → #0EA5E9` | +| Chemistry | Orange-Red `#F59E0B → #EF4444` | +| Biology | Emerald `#10B981 → #22D3EE` | +| Math | Golden `#F59E0B → #EAB308` | +| Astronomy | Deep Blue `#1E40AF → #3B82F6` | +| Programming | Green-Teal `#22C55E → #14B8A6` | + +### Topic → Render Mode + +```javascript +// Three.js 3D keywords: 运动, 粒子, 碰撞, 旋转, 天体, 分子, 机械, 力, 磁场, 电场 +// SVG 2D keywords: 函数, 图像, 曲线, 图表, 统计, 证明, 几何, 坐标 +// Hybrid keywords: 牛顿, 运动定律, 波动, 振动, 电磁, 能量 + +// Render mode resolution: +// hybrid → if hasHybrid || (hasThree && hasSVG) +// svg → if only hasSVG +// three → default (3D only) +``` + +--- + +## Required CDN Dependencies (Generated HTML) + +Every generated HTML file must load these via CDN — never from local files: + +| Library | CDN URL | +|---------|---------| +| Three.js r134 | `https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js` | +| Tailwind CSS v3.4+ | `https://cdn.tailwindcss.com` | +| KaTeX 0.16.11 CSS | `https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css` | +| KaTeX 0.16.11 JS | `https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js` | +| KaTeX auto-render | `https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js` | +| D3.js v7 (optional) | `https://d3js.org/d3.v7.min.js` | + +**OrbitControls**: Must be inlined as a simplified self-contained implementation (no CDN available for this). It must support `enableDamping`, touch input, and zoom limits. + +--- + +## Generated HTML Structure + +Every generated page must follow this layout: + +``` +┌─────────────────────────────────────────────────────────────┐ +│ NAV BAR: Title (topic name) | Reset | Random | Fullscreen | About │ +├───────────────────┬─────────────────────────────────────────┤ +│ LEFT SIDEBAR │ MAIN CANVAS (Three.js / SVG / Hybrid) │ +│ (30%, collapsible)│ (70%, gradient background) │ +│ - Learning goals │ │ +│ (checkboxes) │ │ +│ - KaTeX formulas │ │ +│ - Principles │ │ +│ - Applications │ │ +├───────────────────┴─────────────────────────────────────────┤ +│ CONTROL PANEL: Sliders + KaTeX results + Play/Pause/Step │ +├─────────────────────────────────────────────────────────────┤ +│ QUIZ PANEL (collapsible, 360px wide, right-side): │ +│ - Hide button (✕) → collapses to floating button (bottom-right) │ +│ - Smooth transition (0.3s ease) │ +└─────────────────────────────────────────────────────────────┘ +``` + +--- + +## Three.js Scene Requirements + +When using the 3D renderer, the scene must include: + +- `PerspectiveCamera(fov: 60, near: 0.1, far: 1000)` +- `WebGLRenderer({ antialias: true, shadowMap.enabled: true })` +- `HemisphereLight` (ambient) + `DirectionalLight` (castShadow: true) +- `MeshStandardMaterial` or `MeshPhongMaterial` with adjustable metalness/roughness +- `THREE.ArrowHelper` for vectors: Force=red `#EF4444`, Velocity=blue `#3B82F6`, Acceleration=green `#22C55E` +- `THREE.Points + BufferGeometry` for particle systems +- `THREE.Line + BufferAttribute` with fixed-length ring buffer for trails +- Physics via Verlet or Euler integration using `THREE.Clock.getDelta()` +- `THREE.Raycaster` for click-to-highlight interactions +- Sprite-based labels synced via `vector.project(camera)` + +--- + +## Hybrid Rendering (Three.js + SVG) + +When render mode is `hybrid`: + +```javascript +// SVG overlay sits above the Three.js canvas +const svgContainer = document.createElement('div'); +svgContainer.style.cssText = + 'position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;'; + +// 3D → 2D coordinate projection +function syncSVGto3D(x, y, z) { + const vector = new THREE.Vector3(x, y, z); + vector.project(camera); + return { + x: (vector.x * 0.5 + 0.5) * width, + y: (-(vector.y * 0.5) + 0.5) * height + }; +} +``` + +Slider changes must update both Three.js object properties and SVG path `d` attributes simultaneously. + +--- + +## Design System + +### Core Color Palette + +```css +/* Backgrounds */ +--bg-gradient: linear-gradient(180deg, #0F172A 0%, #164E63 50%, #155E75 100%); + +/* Primary brand */ +--primary-gradient: linear-gradient(135deg, #14B8A6 0%, #06B6D4 50%, #22D3EE 100%); + +/* Glassmorphism */ +--glass-bg: rgba(255, 255, 255, 0.08); +--glass-border: rgba(255, 255, 255, 0.15); +--glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); + +/* Text */ +--text-primary: #F8FAFC; +--text-secondary: #CBD5E1; +--text-muted: #94A3B8; +``` + +### Style Conventions + +- **Glassmorphism** on all panels and cards +- **Neon accent colors** on interactive elements +- **60fps animations** with spring easing +- Font: `Inter, system-ui, sans-serif` +- All UI panels use `backdrop-filter: blur(...)` and semi-transparent backgrounds + +--- + +## Language Detection + +- If the topic is Chinese → output the entire page in Chinese +- If the topic is English → output the entire page in English +- The skill supports bilingual input/output automatically + +--- + +## Development Conventions + +Since this repo is documentation-only, "development" means editing the specification files. + +### When modifying `SKILL.md` + +- Keep the YAML frontmatter (`name`, `description`) intact at the top +- The skill is invoked by Claude Code as `/aetherviz-master` +- Preserve all numbered sections and their headings — Claude parses them structurally +- CDN versions are pinned (Three.js r134, KaTeX 0.16.11) — do not upgrade without testing + +### When modifying `README.md` + +- README is primarily Chinese; maintain that convention +- Screenshots/GIFs go in `docs/` or are linked from GitHub issue uploads +- Keep the changelog section (`## 📝 更新日志`) up to date + +### Commit message conventions + +Use concise imperative messages, e.g.: +- `Add hybrid SVG+3D render mode to SKILL.md` +- `Update CDN URLs for KaTeX 0.16.12` +- `Fix quiz panel collapse animation spec` + +### Branch naming + +Feature branches follow: `feature/` or `claude/-` + +--- + +## Testing + +There is no automated test suite. Manual testing process: + +1. Invoke the skill with a topic (e.g., `牛顿第二定律`, `Sine function`, `DNA replication`) +2. Save the generated HTML output as `test.html` +3. Open in Chrome/Edge/Firefox and verify: + - 3D scene renders without errors + - Sliders update the scene in real time + - KaTeX formulas render correctly + - Quiz panel collapses/expands with animation + - Mobile touch controls work (use browser DevTools device emulation) + +--- + +## Running Generated Output Locally + +The generated HTML files are self-contained. Serve them with any static file server: + +```bash +python -m http.server 8080 +# or +npx serve . +# or +php -S localhost:8080 +``` + +Then open `http://localhost:8080/your-file.html` in a WebGL-capable browser. + +--- + +## Key Constraints for AI Assistants + +1. **Never add source code files** — this repo is spec-only +2. **Never add a build system or package manager** — not applicable +3. **Output is always raw HTML** — no markdown code fences, no preamble +4. **CDN versions are pinned** — Three.js r134, not latest +5. **OrbitControls must be inlined** — no CDN exists for this module +6. **Both Chinese and English topics are valid** — handle both gracefully +7. **Single file output only** — no multi-file projects, no imports diff --git a/web/.gitignore b/web/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/web/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/web/AGENTS.md b/web/AGENTS.md new file mode 100644 index 0000000..8bd0e39 --- /dev/null +++ b/web/AGENTS.md @@ -0,0 +1,5 @@ + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. + diff --git a/web/CLAUDE.md b/web/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/web/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/web/README.md b/web/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/web/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/web/app/api/generate/route.ts b/web/app/api/generate/route.ts new file mode 100644 index 0000000..e905cf6 --- /dev/null +++ b/web/app/api/generate/route.ts @@ -0,0 +1,44 @@ +import { getClient } from '@/lib/claude'; +import { INTERACTIVE_SYSTEM_PROMPT } from '@/lib/prompts'; + +export async function POST(request: Request) { + const { topic } = await request.json(); + + if (!topic?.trim()) { + return Response.json({ error: '请输入主题' }, { status: 400 }); + } + + const stream = await getClient().messages.create({ + model: 'claude-sonnet-4-6', + max_tokens: 16000, + system: [ + { + type: 'text', + text: INTERACTIVE_SYSTEM_PROMPT, + cache_control: { type: 'ephemeral' }, + }, + ], + messages: [{ role: 'user', content: `生成主题:${topic}` }], + stream: true, + }); + + const encoder = new TextEncoder(); + + const readable = new ReadableStream({ + async start(controller) { + for await (const event of stream) { + if ( + event.type === 'content_block_delta' && + event.delta.type === 'text_delta' + ) { + controller.enqueue(encoder.encode(event.delta.text)); + } + } + controller.close(); + }, + }); + + return new Response(readable, { + headers: { 'Content-Type': 'text/plain; charset=utf-8' }, + }); +} diff --git a/web/app/api/render/route.ts b/web/app/api/render/route.ts new file mode 100644 index 0000000..405c0a1 --- /dev/null +++ b/web/app/api/render/route.ts @@ -0,0 +1,55 @@ +import { getClient } from '@/lib/claude'; +import { VIDEO_SYSTEM_PROMPT } from '@/lib/prompts'; +import { renderToMp4 } from '@/lib/renderer'; + +export async function POST(request: Request) { + const { topic, previewHtml } = await request.json(); + + if (!topic?.trim()) { + return Response.json({ error: '缺少主题' }, { status: 400 }); + } + + // Step 1: Generate HyperFrames-compatible timeline HTML + const message = await getClient().messages.create({ + model: 'claude-sonnet-4-6', + max_tokens: 16000, + system: [ + { + type: 'text', + text: VIDEO_SYSTEM_PROMPT, + cache_control: { type: 'ephemeral' }, + }, + ], + messages: [ + { + role: 'user', + content: previewHtml + ? `基于以下交互式预览,生成适合视频渲染的 HyperFrames HTML(主题:${topic})。保留相同的视觉风格和教学内容,但改为全自动 GSAP timeline 驱动,4分钟结构。\n\n预览参考:\n${previewHtml.slice(0, 4000)}` + : `生成主题:${topic},视频版 HyperFrames HTML`, + }, + ], + }); + + const videoHtml = + message.content[0].type === 'text' ? message.content[0].text : ''; + + if (!videoHtml.includes(' + {children} + + ); +} diff --git a/web/app/page.tsx b/web/app/page.tsx new file mode 100644 index 0000000..2cf9fbd --- /dev/null +++ b/web/app/page.tsx @@ -0,0 +1,234 @@ +'use client'; + +import { useState, useRef, useCallback } from 'react'; + +type AppState = 'input' | 'generating' | 'preview' | 'rendering' | 'done'; + +const EXAMPLE_TOPICS = ['牛顿第二定律', '光合作用', '三角函数', 'DNA复制', '行星运动', 'Sorting Algorithms']; + +export default function Home() { + const [topic, setTopic] = useState(''); + const [state, setState] = useState('input'); + const [previewHtml, setPreviewHtml] = useState(''); + const [videoUrl, setVideoUrl] = useState(''); + const [error, setError] = useState(''); + const htmlAccumRef = useRef(''); + + const generate = useCallback(async (t: string) => { + if (!t.trim()) return; + setError(''); + setState('generating'); + htmlAccumRef.current = ''; + + try { + const res = await fetch('/api/generate', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ topic: t }), + }); + + if (!res.ok) throw new Error('生成失败'); + const reader = res.body!.getReader(); + const decoder = new TextDecoder(); + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + htmlAccumRef.current += decoder.decode(value, { stream: true }); + } + + setPreviewHtml(htmlAccumRef.current); + setState('preview'); + } catch (e) { + setError(String(e)); + setState('input'); + } + }, []); + + const renderVideo = useCallback(async () => { + setState('rendering'); + setError(''); + try { + const res = await fetch('/api/render', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ topic, previewHtml }), + }); + + if (!res.ok) { + const { error: msg } = await res.json(); + throw new Error(msg || '渲染失败'); + } + + const blob = await res.blob(); + setVideoUrl(URL.createObjectURL(blob)); + setState('done'); + } catch (e) { + setError(String(e)); + setState('preview'); + } + }, [topic, previewHtml]); + + const reset = () => { + setState('input'); + setPreviewHtml(''); + setVideoUrl(''); + setError(''); + setTopic(''); + }; + + return ( +
+ {/* Nav */} + + +
+ {/* INPUT STATE */} + {(state === 'input' || state === 'generating') && ( +
+
+

+ 输入主题,生成{' '} + + 3D 教学视频 + +

+

物理 · 化学 · 生物 · 数学 · 天文 · 编程

+
+ +
+ setTopic(e.target.value)} + onKeyDown={e => e.key === 'Enter' && generate(topic)} + placeholder="例:牛顿第二定律、光合作用、三角函数..." + disabled={state === 'generating'} + className="w-full bg-white/5 border border-white/15 rounded-xl px-5 py-4 text-lg text-white placeholder-slate-500 outline-none focus:border-cyan-500/50 transition-colors disabled:opacity-50" + /> + + +
+ {EXAMPLE_TOPICS.map(t => ( + + ))} +
+
+ + {error &&

{error}

} +
+ )} + + {/* PREVIEW STATE */} + {(state === 'preview' || state === 'rendering') && ( +
+ {/* Toolbar */} +
+
+ + {topic} + 交互预览 +
+
+ 满意后渲染为 3-4 分钟视频(约需 8-12 分钟) + +
+
+ + {/* Preview iframe */} +
+