mirror of
https://github.com/NanmiCoder/claude-code-haha.git
synced 2026-10-10 11:53:10 +08:00
docs: show Agent Teams and the promo film in README and on the site (#1435)
- README: add an Agent Teams loop cut from the promo film (subtitles cropped) and a cover that opens the 90-second film from the CDN. - Site: add a click-to-play film section after the hero; the video element is only created on click, and the poster ships with the site.
This commit is contained in:
@@ -33,6 +33,11 @@ cc-haha is a **desktop Claude Code workspace** for macOS, Windows, and Linux: mu
|
|||||||
<a href="https://github.com/NanmiCoder/cc-haha/releases"><img src="https://img.shields.io/badge/⬇_Download_Desktop-macOS_%7C_Windows_%7C_Linux-FF7A00?style=for-the-badge" alt="Download Desktop"></a>
|
<a href="https://github.com/NanmiCoder/cc-haha/releases"><img src="https://img.shields.io/badge/⬇_Download_Desktop-macOS_%7C_Windows_%7C_Linux-FF7A00?style=for-the-badge" alt="Download Desktop"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://cdn.zizhi1.com/cc-haha/site/cchaha-film-1080p-v1.mp4"><img src="docs/images/readme-film-cover-en.webp" width="720" alt="Watch the 90-second cc-haha film"></a>
|
||||||
|
<br><sub>A 90-second film made with Opus 5.5, narrated in Chinese with Chinese subtitles. Opens the video in your browser.</sub>
|
||||||
|
</p>
|
||||||
|
|
||||||
The top row covers **getting started and daily work**: sessions, permissions, changes, and Computer Use. The second shows **extensions**: models, skills, scheduled tasks, and IM. These screenshots show the real project in the Chinese interface. Click a thumbnail to see the full screen.
|
The top row covers **getting started and daily work**: sessions, permissions, changes, and Computer Use. The second shows **extensions**: models, skills, scheduled tasks, and IM. These screenshots show the real project in the Chinese interface. Click a thumbnail to see the full screen.
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
@@ -50,6 +55,16 @@ The top row covers **getting started and daily work**: sessions, permissions, ch
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
### Agent Teams
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="docs/images/readme-features/agent-teams.webp" width="100%" alt="Agent Teams: confirm the proposed team, then watch members work through dependency lanes until the report and page are ready">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
Describe the goal and the lead proposes a team: who does what, who waits for whom. You choose each member's model and confirm before anyone starts. Independent tasks run in parallel, dependent ones unlock in order on the lane canvas, and every hand-off shows up in the message feed. The report and page land in the same workspace for you to check.
|
||||||
|
|
||||||
|
<sub>Clip from the cc-haha promo film, in the Chinese interface. Demo data; on-screen times are staged.</sub>
|
||||||
|
|
||||||
Start here: [install the app](docs/en/start/install.md) → [connect a model](docs/en/start/models.md) → [run your first session](docs/en/start/first-session.md) → [explore settings](docs/en/desktop/settings.md) → [try real workflows](docs/en/cases/index.md). For hands-free cross-app work on macOS, follow the [Computer Use guide](docs/en/desktop/computer-use.md).
|
Start here: [install the app](docs/en/start/install.md) → [connect a model](docs/en/start/models.md) → [run your first session](docs/en/start/first-session.md) → [explore settings](docs/en/desktop/settings.md) → [try real workflows](docs/en/cases/index.md). For hands-free cross-app work on macOS, follow the [Computer Use guide](docs/en/desktop/computer-use.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ cc-haha 是一个**桌面端 Claude Code 工作台**:多会话与全局搜索
|
|||||||
<a href="https://github.com/NanmiCoder/cc-haha/releases"><img src="https://img.shields.io/badge/⬇_下载桌面端-macOS_%7C_Windows_%7C_Linux-FF7A00?style=for-the-badge" alt="下载桌面端"></a>
|
<a href="https://github.com/NanmiCoder/cc-haha/releases"><img src="https://img.shields.io/badge/⬇_下载桌面端-macOS_%7C_Windows_%7C_Linux-FF7A00?style=for-the-badge" alt="下载桌面端"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://cdn.zizhi1.com/cc-haha/site/cchaha-film-1080p-v1.mp4"><img src="docs/images/readme-film-cover-zh-CN.webp" width="720" alt="观看 90 秒 cc-haha 宣传片"></a>
|
||||||
|
<br><sub>由 Opus 5.5 制作的 90 秒宣传片,点击在浏览器中播放。</sub>
|
||||||
|
</p>
|
||||||
|
|
||||||
上排看**上手与日常工作**:新建、权限、改动与 Computer Use;下排看**扩展能力**:模型、技能、定时任务与 IM。截图来自真实项目,保留项目与会话列表。点击缩略图可查看完整界面。
|
上排看**上手与日常工作**:新建、权限、改动与 Computer Use;下排看**扩展能力**:模型、技能、定时任务与 IM。截图来自真实项目,保留项目与会话列表。点击缩略图可查看完整界面。
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
@@ -50,6 +55,16 @@ cc-haha 是一个**桌面端 Claude Code 工作台**:多会话与全局搜索
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
### Agent Teams
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="docs/images/readme-features/agent-teams.webp" width="100%" alt="Agent Teams:确认团队方案后,成员按依赖泳道推进,直到报告和页面完成">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
说出目标,lead 先给出团队方案:谁做什么、谁等谁。每个成员用哪个模型由你来挑,你确认后成员才出发。能同时做的并行推进,要接力的在泳道画布上按依赖解锁,每次交接都记在通讯流里;报告和页面放进同一个工作区,打开就能检查。
|
||||||
|
|
||||||
|
<sub>片段取自 cc-haha 宣传片,演示数据,画面中的时间为演示设定。</sub>
|
||||||
|
|
||||||
从 0 开始:[下载安装](docs/start/install.md) → [连接模型](docs/start/models.md) → [跑通第一条会话](docs/start/first-session.md) → [设置指南](docs/desktop/settings.md) → [实战案例](docs/cases/index.md)。想体验不抢鼠标的跨应用操作,接着看 [Computer Use 指南](docs/desktop/computer-use.md)。
|
从 0 开始:[下载安装](docs/start/install.md) → [连接模型](docs/start/models.md) → [跑通第一条会话](docs/start/first-session.md) → [设置指南](docs/desktop/settings.md) → [实战案例](docs/cases/index.md)。想体验不抢鼠标的跨应用操作,接着看 [Computer Use 指南](docs/desktop/computer-use.md)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 3.7 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 141 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 144 KiB |
@@ -14,9 +14,12 @@ import poster from './assets/wandor-poster.webp'
|
|||||||
import landscape from './assets/quiet-landscape.webp'
|
import landscape from './assets/quiet-landscape.webp'
|
||||||
import stillLife from './assets/quiet-moments.webp'
|
import stillLife from './assets/quiet-moments.webp'
|
||||||
import projectSession from './assets/project-session.png'
|
import projectSession from './assets/project-session.png'
|
||||||
|
import filmPoster from './assets/film-poster.webp'
|
||||||
import './home.css'
|
import './home.css'
|
||||||
|
|
||||||
const VIDEO = 'https://pollen-batch-41236914.figma.site/_components/v2/f0ee2dae7671c170c34f12e31c4cb41418976c98/769c564298c132f7919405cd9f17c1b1231f341d.769c5642.mp4'
|
const VIDEO = 'https://pollen-batch-41236914.figma.site/_components/v2/f0ee2dae7671c170c34f12e31c4cb41418976c98/769c564298c132f7919405cd9f17c1b1231f341d.769c5642.mp4'
|
||||||
|
// The film is hosted on the CDN; versioned keys keep cached copies from going stale.
|
||||||
|
const FILM = 'https://cdn.zizhi1.com/cc-haha/site/cchaha-film-1080p-v1.mp4'
|
||||||
const featureIcons = [Code2, MousePointer2, GitCompareArrows]
|
const featureIcons = [Code2, MousePointer2, GitCompareArrows]
|
||||||
const stepIcons = [Download, SlidersHorizontal, FolderOpen, ScanEye]
|
const stepIcons = [Download, SlidersHorizontal, FolderOpen, ScanEye]
|
||||||
const taskSteps = {
|
const taskSteps = {
|
||||||
@@ -139,7 +142,25 @@ function Hero({ locale, paused, setPaused, onPreview }: { locale: LandingLocale;
|
|||||||
<div className="wander-suggestions" aria-label={en ? 'Try an idea' : '试试这些想法'}>{c.taskSuggestions.map((item, index) => { const Symbol = featureIcons[index]; return <button key={item.category} aria-pressed={selected === item.category} onClick={() => { setText(item.prompt); setSelected(item.category) }}><Symbol size={14} />{item.label}</button> })}</div>
|
<div className="wander-suggestions" aria-label={en ? 'Try an idea' : '试试这些想法'}>{c.taskSuggestions.map((item, index) => { const Symbol = featureIcons[index]; return <button key={item.category} aria-pressed={selected === item.category} onClick={() => { setText(item.prompt); setSelected(item.category) }}><Symbol size={14} />{item.label}</button> })}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="wander-hero__foot"><a href="#discover"><ArrowDown size={16} />{en ? 'SCROLL TO EXPLORE' : '往下走,看看更多可能'}</a><span>macOS · Windows · Linux</span><button onClick={() => setPaused(!paused)} aria-pressed={paused}>{paused ? <Play size={14} /> : <Pause size={14} />}{paused ? (en ? 'Play scenery' : '播放风景') : (en ? 'Pause scenery' : '暂停风景')}</button></div>
|
<div className="wander-hero__foot"><a href="#film"><ArrowDown size={16} />{en ? 'SCROLL TO EXPLORE' : '往下走,看看更多可能'}</a><span>macOS · Windows · Linux</span><button onClick={() => setPaused(!paused)} aria-pressed={paused}>{paused ? <Play size={14} /> : <Pause size={14} />}{paused ? (en ? 'Play scenery' : '播放风景') : (en ? 'Pause scenery' : '暂停风景')}</button></div>
|
||||||
|
</section>
|
||||||
|
}
|
||||||
|
|
||||||
|
function Film({ locale }: { locale: LandingLocale }) {
|
||||||
|
const en = locale === 'en'
|
||||||
|
// The video element is only created after a click, so visitors who never play it download nothing.
|
||||||
|
const [started, setStarted] = useState(false)
|
||||||
|
const posterAlt = en ? 'Closing frame of the cc-haha film: the wordmark over a painted countryside' : 'cc-haha 宣传片片尾:田园风景上的 cc-haha 字标'
|
||||||
|
return <section className="wander-film wander-section" id="film" aria-labelledby="film-title">
|
||||||
|
<div className="wander-section__heading"><span className="wander-eyebrow">cc-haha / {en ? 'THE FILM · 1:30' : '90 秒短片'}</span><h2 id="film-title">{en ? <>Ninety seconds.<br />See it <em>at work.</em></> : <>90 秒,<br />看它<em>怎么做事。</em></>}</h2><p>{en ? 'A team splits the work, hands it off, runs on schedule, and picks up again on your phone.' : '组队分工、接力推进、按时执行,再到手机上接着聊。'}</p></div>
|
||||||
|
<div className="wander-showcase wander-film__frame">
|
||||||
|
<div className="wander-showcase__bar"><span className="wander-window-dots"><i /><i /><i /></span><span>cc-haha / {en ? 'FILM' : '宣传片'}</span><span>{en ? 'CHINESE NARRATION' : '有声 · 中文字幕'}</span></div>
|
||||||
|
{started
|
||||||
|
? <video className="wander-film__media" src={FILM} poster={filmPoster} controls autoPlay playsInline preload="metadata" aria-label={en ? 'cc-haha film' : 'cc-haha 宣传片'} />
|
||||||
|
: <button className="wander-film__media wander-film__start" onClick={() => setStarted(true)} aria-label={en ? 'Play the 90-second film' : '播放 90 秒宣传片'}><img src={filmPoster} alt={posterAlt} width={1600} height={900} loading="lazy" /><span className="wander-primary"><Play size={16} />{en ? 'Play the film' : '播放短片'}</span></button>}
|
||||||
|
</div>
|
||||||
|
{en && <p className="wander-film__note">Narrated in Chinese with Chinese subtitles. Demo data; on-screen times are staged.</p>}
|
||||||
|
{!en && <p className="wander-film__note">片中为演示数据,画面中的时间为演示设定。</p>}
|
||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,5 +240,5 @@ export default function HomePage({ locale = 'en' }: { locale?: LandingLocale })
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setPageMeta({ alternate: locale === 'en' ? '/' : '/en', canonical: locale === 'en' ? '/en' : '/', description: landingContent[locale].hero.description, lang: locale === 'en' ? 'en' : 'zh-CN', title: locale === 'en' ? 'cc-haha — Less busywork. More room for life.' : 'cc-haha — 把琐碎交给 AI,把时间留给生活。' })
|
setPageMeta({ alternate: locale === 'en' ? '/' : '/en', canonical: locale === 'en' ? '/en' : '/', description: landingContent[locale].hero.description, lang: locale === 'en' ? 'en' : 'zh-CN', title: locale === 'en' ? 'cc-haha — Less busywork. More room for life.' : 'cc-haha — 把琐碎交给 AI,把时间留给生活。' })
|
||||||
}, [locale])
|
}, [locale])
|
||||||
return <div className="wander-page font-sans"><a className="u-skip" href="#main">{locale === 'en' ? 'Skip to content' : '跳到正文'}</a><main id="main" tabIndex={-1}><Hero locale={locale} paused={paused} setPaused={setPaused} onPreview={setPreview} /><Discover locale={locale} onEnlarge={setEnlargedImage} /><Journey locale={locale} /><Possibilities locale={locale} onPreview={setPreview} /><Faq locale={locale} /></main><Closing locale={locale} />{preview && <TaskPreview task={preview} locale={locale} onClose={() => setPreview(null)} />}{enlargedImage && <ImageViewer image={enlargedImage} locale={locale} onClose={() => setEnlargedImage(null)} />}</div>
|
return <div className="wander-page font-sans"><a className="u-skip" href="#main">{locale === 'en' ? 'Skip to content' : '跳到正文'}</a><main id="main" tabIndex={-1}><Hero locale={locale} paused={paused} setPaused={setPaused} onPreview={setPreview} /><Film locale={locale} /><Discover locale={locale} onEnlarge={setEnlargedImage} /><Journey locale={locale} /><Possibilities locale={locale} onPreview={setPreview} /><Faq locale={locale} /></main><Closing locale={locale} />{preview && <TaskPreview task={preview} locale={locale} onClose={() => setPreview(null)} />}{enlargedImage && <ImageViewer image={enlargedImage} locale={locale} onClose={() => setEnlargedImage(null)} />}</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
Updated 2026-09-26. The user explicitly supplied the video and requested this art direction for the complete cc-haha landing page.
|
Updated 2026-09-26. The user explicitly supplied the video and requested this art direction for the complete cc-haha landing page.
|
||||||
|
|
||||||
- `wandor-poster.webp`: 1920×1080 static frame captured in Ego Lite from the supplied video. Used during loading, media failure and reduced motion. The video is loaded from the exact supplied Figma URL in HomePage.tsx; no external video is required during deterministic build/check.
|
- `wandor-poster.webp`: 1920×1080 static frame captured in Ego Lite from the supplied video. Used during loading, media failure and reduced motion. The video is loaded from the exact supplied Figma URL in HomePage.tsx; no external video is required during deterministic build/check.
|
||||||
|
- `film-poster.webp`: 1600px frame at 1:25 of the user's 90-second cc-haha promo film (2026-10-02), taken before the closing download chip appears so it does not sit behind the play button. The film itself (1080p, faststart MP4) is hosted on the user's Qiniu CDN under `cc-haha/site/`; HomePage.tsx creates the video element only after a click, so build/check never fetches it. Upload a replacement under a new `-vN` key rather than overwriting.
|
||||||
- `quiet-landscape.webp`: original image generated with the built-in imagegen tool, optimized to WebP. Used behind the feature gallery, onboarding and closing sections.
|
- `quiet-landscape.webp`: original image generated with the built-in imagegen tool, optimized to WebP. Used behind the feature gallery, onboarding and closing sections.
|
||||||
- `quiet-moments.webp`: original image generated with the built-in imagegen tool, optimized to 900px WebP. Editorial still life beside the task examples.
|
- `quiet-moments.webp`: original image generated with the built-in imagegen tool, optimized to 900px WebP. Editorial still life beside the task examples.
|
||||||
- `project-session.png`: the exact 3456×2168 PNG supplied by the user on 2026-09-26. The user explicitly requested displaying the real project and session list without masking. Copied unchanged; no cropping, redaction, or reconstruction. Used for the landing page's code tab in both locales and its full-size preview.
|
- `project-session.png`: the exact 3456×2168 PNG supplied by the user on 2026-09-26. The user explicitly requested displaying the real project and session list without masking. Copied unchanged; no cropping, redaction, or reconstruction. Used for the landing page's code tab in both locales and its full-size preview.
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 170 KiB |
@@ -117,6 +117,13 @@ html:has(.wander-page) { scroll-padding-top: 0; }
|
|||||||
.wander-showcase__caption a { margin-top: 5px; font-size: 11px; }
|
.wander-showcase__caption a { margin-top: 5px; font-size: 11px; }
|
||||||
.wander-discover__note { display: flex; justify-content: center; gap: 35px; margin-top: 27px; font-size: 10px; color: #616351; }
|
.wander-discover__note { display: flex; justify-content: center; gap: 35px; margin-top: 27px; font-size: 10px; color: #616351; }
|
||||||
.wander-discover__note span { display: flex; align-items: center; gap: 6px; }
|
.wander-discover__note span { display: flex; align-items: center; gap: 6px; }
|
||||||
|
.wander-film { background: #faf9f5; padding-bottom: 20px; }
|
||||||
|
.wander-film__frame { margin-top: 40px; }
|
||||||
|
.wander-film__media { position: relative; display: block; width: 100%; aspect-ratio: 16 / 9; padding: 0; overflow: hidden; border-radius: 18px; background: #f8f9f4; border: 1px solid #78776622; }
|
||||||
|
.wander-film__start img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .6s ease; }
|
||||||
|
.wander-film__start:hover img { transform: scale(1.015); }
|
||||||
|
.wander-film__start > span { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); box-shadow: 0 10px 30px #1e281d30; }
|
||||||
|
.wander-film__note { margin-top: 18px; text-align: center; font-size: 10px; color: #616351; }
|
||||||
.wander-journey { position: relative; min-height: 880px; background: #f1eadb; padding: 85px 30px 140px; isolation: isolate; }
|
.wander-journey { position: relative; min-height: 880px; background: #f1eadb; padding: 85px 30px 140px; isolation: isolate; }
|
||||||
.wander-landscape { position: absolute; z-index: -2; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center bottom; }
|
.wander-landscape { position: absolute; z-index: -2; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center bottom; }
|
||||||
.wander-journey::before { content: ''; position: absolute; z-index: -1; inset: 0; background: linear-gradient(#faf9f5 0%, #faf9f5b0 20%, #faf9f510 80%); }
|
.wander-journey::before { content: ''; position: absolute; z-index: -1; inset: 0; background: linear-gradient(#faf9f5 0%, #faf9f5b0 20%, #faf9f510 80%); }
|
||||||
@@ -279,6 +286,8 @@ html:has(.wander-page) { scroll-padding-top: 0; }
|
|||||||
.wander-section h2, .wander-journey h2 { font-size: 39px; line-height: 1.25; margin: 16px 0; }
|
.wander-section h2, .wander-journey h2 { font-size: 39px; line-height: 1.25; margin: 16px 0; }
|
||||||
.wander-eyebrow { font-size: 9px; }
|
.wander-eyebrow { font-size: 9px; }
|
||||||
.wander-section__heading > p { max-width: 290px; font-size: 12px; }
|
.wander-section__heading > p { max-width: 290px; font-size: 12px; }
|
||||||
|
.wander-film__frame { margin-top: 28px; }
|
||||||
|
.wander-film__start > span { top: 74%; min-height: 38px; padding: 9px 16px; gap: 8px; font-size: 12px; }
|
||||||
.wander-discover::before { background-size: auto 600px; inset: 200px 0 0; }
|
.wander-discover::before { background-size: auto 600px; inset: 200px 0 0; }
|
||||||
.wander-feature-tabs { width: 100%; justify-content: space-between; padding: 4px; margin: 26px auto 22px; }
|
.wander-feature-tabs { width: 100%; justify-content: space-between; padding: 4px; margin: 26px auto 22px; }
|
||||||
.wander-feature-tabs button { flex: 1; padding: 12px 8px; font-size: 11px; gap: 5px; min-height: 44px; }
|
.wander-feature-tabs button { flex: 1; padding: 12px 8px; font-size: 11px; gap: 5px; min-height: 44px; }
|
||||||
|
|||||||
Reference in New Issue
Block a user