document.addEventListener("DOMContentLoaded", function () { const sourceMap = captureSourceMap(); let currentLocale = getInitialLocale(); let heroRotationTimer = null; const copyMessages = { zh: { copy: "复制", copied: "已复制", failed: "复制失败" }, en: { copy: "Copy", copied: "Copied", failed: "Copy failed" } }; const enTranslations = { "common.nav.home": "Home", "common.nav.docs": "Docs", "common.nav.skills": "Skills", "common.nav.console": "Console", "common.nav.pricing": "Pricing", "common.login": "Sign in", "common.logout": "Sign out", "index.meta.title": "Popi.art SkillHub", "index.meta.description": "Static bilingual prototype for Popi.art SkillHub, written from popiartcli and Popiart_skillhub.", "index.hero.catalogCard": `
OFFICIAL SKILLHUB

Official skill catalog

The public registry comes from Popiart_skillhub. It currently exposes 59 skills across image, video, and audio.

`, "index.hero.baselineCard": `
RUNTIME BASELINE

3 official runtime baselines

text2image / img2img / image2video

`, "index.hero.mcpCard": `
MCP

discoverable tool surface

list_skills / run_skill / get_job / pull_artifact

`, "index.hero.showcaseCard": `
SHOWCASE

PopiStudio Alice

The character-consistency showcase skill is already visible in the public catalog.

`, "index.hero.copy": `
POP I . ART

Creator skill entry for Coding Agents

popiartcli owns the unified CLI entrypoint, auth, skill discovery, run, jobs, artifacts, and MCP discoverability; Popiart_skillhub owns the public catalog and skill descriptions.

Quick start Browse skills
59 public skills Image / Video / Audio text2image · img2img
`, "index.surfaces.heading": `
PRODUCT SURFACES

Today’s product surface is grounded in CLI + SkillHub

The homepage is organized around real command surfaces, catalog facts, and execution boundaries instead of vague product copy.

`, "index.surfaces.metricTotal": "public skills", "index.surfaces.metricAudio": "audio skills", "index.surfaces.metricImage": "image skills", "index.surfaces.metricVideo": "video skills", "index.scenarios.heading": `
SCENARIOS

High-value scenarios extracted from the catalog

These names stay close to the real skill ids, categories, and capabilities in Popiart_skillhub.

`, "index.scenarios.card1": `
IMAGE

Text2Image

Built around popiskill-image-text2image-* for prompt-driven image generation, character sheets, three-view, and stylized artwork.

View image skills `, "index.scenarios.card2": `
IMAGE

Img2Img

Includes baseline image editing, localized retouching, and the PopiStudio Alice consistency showcase workflow.

View img2img `, "index.scenarios.card3": `
VIDEO

Image2Video

One of the official runtime baselines, ideal for turning still frames into short teasers and motion clips.

View video skills `, "index.scenarios.card4": `
VIDEO

Text2Video

The catalog already includes text2video definitions across kling, sora2pro, and studio-oriented variants.

View text2video `, "index.scenarios.card5": `
AUDIO

TTS / Voice

Covers doubao, ima-studio, multimodel, and voice-engineer style speech output workflows.

View audio skills `, "index.scenarios.card6": `
AUDIO

STT / Dubbing

The catalog already includes local speech recognition, video transcription, translation, and localization-related skills.

View STT & dubbing `, "index.scenarios.card7": `
MCP

Agent Discoverability

popiart mcp serve / print-config / doctor already forms a practical tool surface for agent integration.

Read MCP docs `, "index.scenarios.card8": `
BOOTSTRAP

Bootstrap & Seed Skills

The CLI generates discoverability assets and merges bundled seed skills into the query path.

View bootstrap `, "index.flow.heading": `
INTEGRATION FLOW

Real integration flow

No invented commands. The first-screen product story follows the commands already implemented in popiartcli.

`, "index.flow.step1": `
01

Install the CLI

Supports Homebrew, install.sh, PowerShell, and source build. The main distribution path is the Go CLI.

`, "index.flow.step2": `
02

Bootstrap the agent

Use bootstrap --discoverable to generate shell completion, MCP config snippets, and seed skill profile assets.

`, "index.flow.step3": `
03

Auth & discover

Sign in with the product-layer key, then use skills list/get/schema to discover merged remote and local skills.

`, "index.flow.step4": `
04

Run / Jobs / Artifacts

Tasks always return a job_id, long jobs are polled, and outputs are recovered through artifacts pull.

`, "index.cta.text": `
NEXT STEP
Continue to docs, skills, and the console prototype `, "index.footer.title": "Popi.art SkillHub Static Prototype", "index.footer.subtitle": "Content is rewritten from popiartcli and Popiart_skillhub, with layout references from open-claw.", "docs.meta.title": "Popi.art Docs", "docs.meta.description": "Bilingual static documentation prototype for Popi.art CLI and SkillHub.", "docs.heading": `
DOCUMENTATION

Documentation written from the real CLI surface

This page is sourced from the popiartcli README, current status notes, and command tree. It does not invent future commands.

`, "docs.toc": `
ON THIS PAGE
`, "docs.install": `
INSTALL

Installation methods

The current popiartcli README explicitly lists Homebrew, curl/install.sh, PowerShell, and source build as supported install paths.

Homebrew
brew tap wtgoku-create/popi
brew install wtgoku-create/popi/popiart
popiart bootstrap --agent codex --discoverable
Source Build
git clone https://github.com/wtgoku-create/popiartcli.git
cd popiartcli
go install ./cmd/popiart
popiart --help
`, "docs.quickstart": `
QUICK START

Quick start

The smallest closed loop is: install the CLI, sign in, discover a skill, run a task, poll jobs, and pull artifacts.

Quick Start
popiart auth login --key pk-...
popiart skills list --tag image
popiart run popiskill-image-text2image-basic-v1 --input @params.json --wait
popiart jobs get job_xxx
popiart artifacts pull art_xxx
`, "docs.coreCommands": `
COMMAND GROUP

Core commands

`, "docs.platformCommands": `
COMMAND GROUP

Platform commands

`, "docs.mcp": `
MCP

Implemented MCP discoverability

The repo already implements popiart mcp serve / print-config / doctor and exposes a practical agent-facing tool surface.

MCP
popiart mcp serve --describe
popiart mcp print-config
popiart mcp doctor
popiart bootstrap --agent codex --discoverable
`, "docs.baseline": `
RUNTIME BASELINE

Current official runtime baseline

The current status notes for popiartcli explicitly treat only three skills as the official runtime baseline. They are the best candidates for homepage and console defaults.

`, "docs.footer.title": "Popi.art Docs Prototype", "docs.footer.subtitle": "Documentation is rewritten from the popiartcli README, command tree, and current-status notes.", "login.meta.title": "Popi.art Login", "login.meta.description": "Static bilingual login prototype for Popi.art.", "login.form": `
SIGN IN

Sign in with the product-layer key

The real auth model in popiartcli is a PopiArt product-layer key, not a raw OpenAI, Gemini, Sora, or other provider key pasted into the client.

The real CLI command is popiart auth login --key pk-....
Read CLI docs
`, "login.why": `
WHY THIS MODEL

Unified gateway boundary

popiartcli is the local entrypoint, popiartServer is the product backend, and PopiNewAPI is the model gateway. Provider keys do not enter the CLI.

`, "login.after": `
AFTER LOGIN

What you can do after sign-in

`, "login.store": `
STORE

How local credentials are stored

Saved keys go into ~/.popiart/config.json, and can be overridden by POPIART_KEY or POPIART_TOKEN.

`, "login.footer.title": "Popi.art Login Prototype", "login.footer.subtitle": "The login model follows popiart auth login --key instead of inventing a separate account system.", "pricing.meta.title": "Popi.art Pricing", "pricing.meta.description": "Static bilingual pricing prototype for Popi.art credits and usage.", "pricing.heading": `
PRICING

Buy more Credits

The static pricing page follows the credits structure of open-claw, while capability names come from popiartcli and Popiart_skillhub.

`, "pricing.packs": `
CREDIT PACKS

Choose a credit pack after login

This static prototype only demonstrates the information architecture. Real pricing, recharge, balance, and billing should come from popiartServer.

Starter Pack 200 Credits / for quick starts and single demos
¥29
Creator Pack 1000 Credits / for day-to-day run, jobs, and artifacts workflows
¥99
Studio Pack 5000 Credits / for multi-project or higher-frequency agent usage
¥399
Buy after login Read docs
`, "pricing.usage": `
CREDIT USAGE

Static usage examples by capability

Capability names and categories follow the current catalog. Credit numbers are placeholders for the static prototype and should later come from the real billing table.

Image tools

popiskill-image-text2image-basic-v1 Generate images from text prompts
4 Credits/image
popiskill-image-img2img-basic-v1 Edit an existing image
2 Credits/image
popiskill-image-img2img-edit-v1 Local editing with multi-image references
3 Credits/image
popiskill-image-text2image-character-sheet-v1 Character sheets and multi-view generation
6 Credits/image

Video & audio tools

popiskill-video-image2video-basic-v1 Generate video from a starting image
20 Credits / 5s
popiskill-video-text2video-studio-v1 Generate video clips from text
25 Credits / 5s
popiskill-video-avatar-talking-head-v1 Talking-head and avatar-driven video
18 Credits / 5s
popiskill-audio-tts-multimodel-v1 Multi-model speech generation
3 Credits / run
`, "pricing.faqHeading": `
FAQ

Frequently asked questions

`, "pricing.faq1": `

Can credit packs stack?

The static prototype assumes packs can stack into the same product-layer account. Real validity and stacking rules should come from the billing service.

`, "pricing.faq2": `

Can all 59 skills in SkillHub run immediately?

No. The current CLI status notes explicitly treat only 3 skills as the official runtime baseline. Everything else still depends on server-side registration and routing.

`, "pricing.faq3": `

Can usage continue after credits run out?

The static prototype currently assumes you need to purchase another credits pack. If monthly plans or bundled quotas are added later, the billing layer should define the rule.

`, "pricing.faq4": `

Why use a product-layer key instead of a provider key?

popiartcli should not hold raw upstream provider keys. Those keys belong behind the gateway and product backend boundary.

`, "pricing.footer.title": "Popi.art Pricing Prototype", "pricing.footer.subtitle": "Pricing copy is organized around product-layer value and avoids exposing provider details directly.", "skills.meta.title": "Popi.art Skills", "skills.meta.description": "Static bilingual skill catalog prototype for Popi.art SkillHub.", "skills.heading": `
SKILL CATALOG

Turn Popiart_skillhub directly into a product catalog

The directory structure comes from index.json, and detail structure comes from each skills/*/SKILL.md instead of a separate hand-written layer.

`, "skills.metrics.origin": "popiart origin skills", "skills.metrics.upstream": "upstream reference skill", "skills.metrics.showcase": "showcase skills", "skills.metrics.baseline": "runtime baseline", "skills.pills.naming": "Naming: popiskill----v", "skills.pills.categories": "Categories: image / video / audio / meta", "skills.pills.source": "Source: index.json + SKILL.md", "skills.featuredHeading": `
FEATURED

Featured skills

`, "skills.card1": `
IMAGE BASELINE

popiskill-image-text2image-basic-v1

One of the official runtime baselines and the most natural default capability to highlight on the homepage and in the console.

  • Capability: text2image
  • Origin: popiart
  • Display: text-to-image
`, "skills.card2": `
IMAGE BASELINE

popiskill-image-img2img-basic-v1

The baseline image-editing path and a key entrypoint from the static catalog into actual editable workflows.

  • Capability: img2img
  • Origin: popiart
  • Display: image editing
`, "skills.card3": `
VIDEO BASELINE

popiskill-video-image2video-basic-v1

The strongest public example skill on the current video path for a runnable product showcase.

  • Capability: image2video
  • Origin: popiart
  • Display: image-to-video
`, "skills.card4": `
IMAGE SHOWCASE

popiskill-image-img2img-popistudio-alice-showcase-v1

A fixed-reference Alice consistency showcase workflow, suitable for demos and proof frames.

  • Capability: img2img
  • Showcase: true
  • Display: PopiStudio Alice
`, "skills.card5": `
VIDEO SHOWCASE

popiskill-video-image2video-popistudio-alice-showcase-v1

Extends the Alice showcase from a single frame into a teaser-style motion clip, which makes it ideal for homepage marketing.

  • Capability: image2video
  • Showcase: true
  • Display: Alice teaser
`, "skills.card6": `
AUDIO CATALOG

popiskill-audio-tts-multimodel-v1

The presence of many audio skills makes it clear the site cannot be designed only around images and video.

  • Capability: tts
  • Category: audio
  • Display: multi-model TTS
`, "skills.detail": `
DETAIL EXAMPLE

What a skill detail page should look like

From SKILL.md you can reliably extract frontmatter descriptions, recommended usage, discouraged usage, required inputs, workflow, command patterns, payload templates, and artifact handling.

  • Use when: demo frame / proof frame / character consistency
  • Do not use: text-only / batch / long-form video
  • Required input: scene_prompt
  • Optional: shot_type / camera / mood / aspect_ratio
`, "skills.command": `
REAL COMMAND

Alice showcase command pattern

Skill Run
popiart run popiskill-image-img2img-popistudio-alice-showcase-v1 \
  --input @params.json \
  --wait
`, "skills.footer.title": "Popi.art Skill Catalog Prototype", "skills.footer.subtitle": "Skill-page fields are designed from index.json and SKILL.md, and can later connect directly to the remote registry.", "console.meta.title": "Popi.art Console", "console.meta.description": "Static bilingual console prototype for Popi.art.", "console.heading": `

Console

Manage product-layer keys, inspect credit usage, and install the CLI quickly.

`, "console.stat1": `
Remaining credits
0 Total 0 credits `, "console.stat2": `
Used
0 Accumulated this month `, "console.stat3": `
Calls
0 CLI / API calls this month `, "console.apiHeading": "

API keys

", "console.secrets": `
POPIART_KEY
pk_559196••••••••••••••••••••••••
POPIART_TOKEN
pk_559196••••••••••••••••••••••••
`, "console.installHeading": "

Quick install command

", "console.installCard": `
Quick Install
brew tap wtgoku-create/popi
brew install wtgoku-create/popi/popiart
export POPIART_KEY="pk_559196_demo"
export POPIART_ENDPOINT="https://api.creatoragentos.io/v1"
popiart bootstrap --agent codex --discoverable
`, "console.footer.title": "Popi.art Console Prototype", "console.footer.subtitle": "The console layout is heavily inspired by open-claw, while config fields and install commands are rewritten from popiartcli." }; bindLocaleToggles(); applyLocale(currentLocale); function captureSourceMap() { const map = {}; document.querySelectorAll("[data-i18n]").forEach(function (node) { map[node.getAttribute("data-i18n")] = node.textContent; }); document.querySelectorAll("[data-i18n-html]").forEach(function (node) { map[node.getAttribute("data-i18n-html")] = node.innerHTML.trim(); }); document.querySelectorAll("[data-i18n-content]").forEach(function (node) { map[node.getAttribute("data-i18n-content")] = node.getAttribute("content") || ""; }); return map; } function getInitialLocale() { try { const url = new URL(window.location.href); const param = url.searchParams.get("lang"); if (param === "en" || param === "zh") { return param; } } catch (error) { // Ignore URL parsing failures for unusual environments. } try { const stored = window.localStorage.getItem("popiart_locale"); if (stored === "en" || stored === "zh") { return stored; } } catch (error) { // Ignore storage failures. } return "zh"; } function resolveTranslation(key, locale) { if (locale === "en" && Object.prototype.hasOwnProperty.call(enTranslations, key)) { return enTranslations[key]; } return sourceMap[key]; } function applyLocale(locale) { currentLocale = locale; document.documentElement.lang = locale === "en" ? "en" : "zh-CN"; try { window.localStorage.setItem("popiart_locale", locale); } catch (error) { // Ignore storage failures. } try { const url = new URL(window.location.href); url.searchParams.set("lang", locale); window.history.replaceState({}, "", url.toString()); } catch (error) { // Ignore history update failures. } document.querySelectorAll("[data-i18n]").forEach(function (node) { const value = resolveTranslation(node.getAttribute("data-i18n"), locale); if (typeof value === "string") { node.textContent = value; } }); document.querySelectorAll("[data-i18n-html]").forEach(function (node) { const value = resolveTranslation(node.getAttribute("data-i18n-html"), locale); if (typeof value === "string") { node.innerHTML = value; } }); document.querySelectorAll("[data-i18n-content]").forEach(function (node) { const value = resolveTranslation(node.getAttribute("data-i18n-content"), locale); if (typeof value === "string") { node.setAttribute("content", value); } }); document.querySelectorAll("[data-locale-toggle]").forEach(function (node) { node.textContent = locale === "zh" ? "EN" : "中文"; node.setAttribute("aria-label", locale === "zh" ? "Switch to English" : "切换到中文"); }); bindCopyButtons(); initRotatingHero(); } function bindLocaleToggles() { document.querySelectorAll("[data-locale-toggle]").forEach(function (node) { node.onclick = function (event) { event.preventDefault(); applyLocale(currentLocale === "zh" ? "en" : "zh"); }; }); } function bindCopyButtons() { const messages = copyMessages[currentLocale] || copyMessages.zh; document.querySelectorAll("[data-copy-target]").forEach(function (button) { button.onclick = async function () { const targetId = button.getAttribute("data-copy-target"); const target = targetId ? document.getElementById(targetId) : null; if (!target) { return; } const original = button.textContent || messages.copy; try { await navigator.clipboard.writeText(target.textContent || ""); button.textContent = messages.copied; } catch (error) { button.textContent = messages.failed; } window.setTimeout(function () { button.textContent = original; }, 1400); }; }); } function initRotatingHero() { if (heroRotationTimer) { window.clearInterval(heroRotationTimer); heroRotationTimer = null; } const rotating = document.querySelector("[data-hero-phrases]"); if (!rotating) { return; } let phrases = []; try { phrases = JSON.parse(rotating.getAttribute("data-hero-phrases") || "[]"); } catch (error) { phrases = []; } if (phrases.length > 1) { let index = 0; heroRotationTimer = window.setInterval(function () { index = (index + 1) % phrases.length; rotating.textContent = phrases[index]; }, 2400); } } });