Marketing Site Dev
/install marketing-site-dev
Marketing Site Dev (Volcengine)
End-to-end skill for building and shipping a bilingual static company marketing site to Volcengine. Two phases:
- Build — Astro 6 + React 19 islands (mobile menu only) + Tailwind 4. Inline SVG everywhere. Single content file (
src/content/site.ts) is the source of truth. - Deploy — TOS bucket + CDN + free DV cert + HTTPS hardening, all scripted in idempotent Node scripts via
veCLI and Volcengine OpenAPI (SigV4-signed viavolc-api.mjsfor the actionsvedoesn't ship).
What success looks like: the user runs ~6 commands end-to-end and gets https://\x3Ctheir-domain>/ serving a production-quality bilingual site with HTTPS, force-redirect to HTTPS, HSTS, HTTP/2, edge caching, and automated cache invalidation. Every infrastructure step is in version control as an idempotent script.
Is this skill the right fit?
This is a deliberately opinionated workflow optimized for one specific scenario. Before going deep, check that scenario actually matches the user's situation. If it doesn't, surface the better alternative instead of forcing the user through a heavier path.
Use this skill when:
- The site is for a Chinese company or a product targeting users in mainland China — latency from mainland to non-Chinese CDNs is bad enough (200-400ms, often worse during peak hours) that visitors notice and bounce.
- ICP 备案 is required or already in hand — distributing in China legally needs the filing tied to a domain hosted on a Chinese cloud. Volcengine bundles 备案 assistance and offers it for the domain you deploy here.
- The user is already in the Volcengine ecosystem (other Volcengine services, existing TOS buckets, etc.) and consolidation is valuable.
- The bilingual zh/en pattern is desired — the content layer (
site.ts) is designed around it.
Use a simpler alternative when:
| Scenario | Recommended alternative | Why |
|---|---|---|
| Personal site / portfolio / side project, no Chinese audience requirement | GitHub Pages | Free, auto-HTTPS, deploys on git push, no infra to manage. Zero of the Volcengine landmines apply. |
| International-only audience (US/EU/SEA), no China presence planned | Vercel (or Cloudflare Pages / Netlify) | Free tier, instant deploys from git, preview URLs per PR, automatic HTTPS, global edge network. Skip the whole ve CLI + ICP workflow entirely. |
| Site needs serverless functions (forms, auth, dynamic content) | Vercel or Cloudflare Pages with their edge functions | This skill ships purely static — Volcengine has serverless products, but the workflow here doesn't cover them. |
| You want preview URLs per branch / PR-based review | Vercel | Vercel's preview-URL UX is best-in-class. This skill produces one production deploy per push; no branch previews. |
If the user's situation matches the "use a simpler alternative" column, tell them so explicitly before scaffolding anything. A 2-minute Vercel deploy is a better experience than a 30-minute Volcengine bootstrap when the user doesn't need what Volcengine provides. Don't sunk-cost them into the wrong stack because they invoked this skill.
When in doubt, ask: "Will mainland-China users be a meaningful part of your audience, and do you have (or plan to file) ICP 备案 for the domain?" If both answers are no, point at Vercel / GitHub Pages and stop.
Step 1: Capture intent (ALWAYS ASK FIRST)
Don't write any code until you have these six inputs from the user. If they're missing from the prompt, ask via AskUserQuestion. Most teams will have everything except possibly the public-security number — that one is OK as a placeholder.
| # | Input | Used for | Notes |
|---|---|---|---|
| 1 | Company name (Chinese + English) | COMPANY.nameZh / COMPANY.nameEn in site.ts; footer; SEO |
|
| 2 | Domain (e.g. example.com) |
Everywhere — bucket binding, CDN, DNS, cert SAN | MUST already be ICP-filed and ideally hosted on Volcengine DNS. If hosted elsewhere, the user needs to manually add CNAME + TXT records. |
| 3 | Brand assets directory (path to SVG logo files) | Inline BrandMark.astro extraction (last 3 paths of the short logo SVG) |
Usually something like assets/logo/svg/Tenshow_short1.svg — short / icon-only variant. |
| 4 | Product list | PRODUCTS[] in site.ts |
Each product needs bilingual name + description, URL, accent hex color, icon enum. |
| 5 | ICP record number | Footer | The MIIT-issued 备案号. |
| 6 | Working directory | Project root | Should be greenfield (empty) or you'll have to coordinate with existing files. |
Optionally:
- 公安备案号 (Public Security Bureau filing number) — usually a placeholder at scaffold time. Flag it loudly in the README so the user replaces it before launch.
- Brand accent color — extract from the logo SVG's hex values. If undecidable, default to whatever the dominant non-neutral color is.
Step 2: Build the static site
Full details in references/phase-1-static-site.md. The shortlist:
- Scaffold — copy
assets/templates/package.jsonandassets/templates/astro.config.mjsinto the project root. Updatenamein package.json andsitein astro.config.mjs. - Install —
pnpm install. - Create the source tree matching the layout in phase-1-static-site.md (
src/content/site.ts,src/components/,src/layouts/BaseLayout.astro,src/pages/index.astro,src/pages/en/index.astro,src/styles/global.css). - Extract the brand mark from the user's SVG — use
assets/templates/BrandMark.astroas a starting point. The last 3\x3Cpath>elements of the short-logo SVG are the mark; copy them verbatim and pick fills from the brand palette. - Build the sections — Hero (with the exact recipe in phase-1-static-site.md — grid background + radial glow + gradient headline + status pill + 2 CTAs), About, Products, Focus, Updates, Contact, Footer. Header sticky, mobile menu = the only React island.
- Verify locally —
pnpm devto develop,pnpm build && pnpm previewto sanity-check the static output before touching infra.
Stack lock-in (don't deviate)
Astro 6, React 19 (mobile menu only), Tailwind 4 via @tailwindcss/vite, pnpm 10, Node 22+, TypeScript strict, zero external images, zero UI libs, zero font services, system font stack. Rationale and full details in phase-1-static-site.md.
Step 3: Set up deploy infrastructure
Full details in references/phase-2-volcengine-deploy.md. Read references/landmines.md FIRST — half your time in this phase is avoiding the landmines, not running commands.
- Copy scripts — copy the entire
assets/scripts/directory andassets/cdn-payloads/into the user'sscripts/andscripts/cdn-payloads/respectively. Copyassets/templates/deploy.config.mjsto the project root and fill inbucket,region,endpoint,cdnDomains. - Replace placeholders in payloads —
{{DOMAIN}},{{BUCKET}},{{REGION}}inscripts/cdn-payloads/apex.jsonandwww.json.OriginHostmust be the domain itself, not empty — the templates are correct out of the box; if you edit them, preserveOriginHost. See landmines.md #3. - Create
.envat project root (gitignored):
Volcengine AK/SK needsVOLC_ACCESS_KEY=AK... VOLC_SECRET_KEY=...TOSFullAccess,CDNFullAccess,DNSFullAccess,CertificateFullAccess(or least-privilege equivalents). - Verify
veis installed:ve version— needs 1.0.x or later. If missing, install via Volcengine's official docs.
Step 4: Execute the first deploy
pnpm install # if not done yet
pnpm build # verify local build works
pnpm run setup:bucket # idempotent: bucket + website routing + custom-domain binding
pnpm run deploy:upload # sync dist/ → bucket
# at this point: https://\x3Cbucket>.tos-\x3Cregion>.volces.com/index.html should 200
pnpm run setup:cdn # verification → CDN add → CNAME → cert → HTTPS hardening
# wait 1-3 minutes for DNS propagation
pnpm run cdn:refresh # purge edge cache so first-time hits don't return bucket-listing JSON
After this initial run, daily iteration becomes one command:
pnpm run deploy && pnpm run cdn:refresh
Always use pnpm run, NOT bare pnpm
pnpm deploy is a pnpm built-in workspace command — it'll error with ERR_PNPM_CANNOT_DEPLOY outside a workspace. Use pnpm run deploy and pnpm run cdn:refresh. Document this in the project's README. See landmines.md #6.
Step 5: Verify
Run the curl + openssl checklist in references/verification.md. Expected: 5× HTTP 200 on key routes, 1× 301 on HTTP → HTTPS, valid cert with SAN covering apex + www, HTTP/2 + HSTS confirmed, cache-control headers matching deploy.config.mjs rules.
If any check fails, verification.md maps each failure mode to the root cause and the fix.
Critical landmines you must know before executing
Full enumeration in landmines.md. The ones you'll hit if you skip reading:
HTTPS_PROXYpollution — TOS SDK + a local HTTP proxy =Protocol "http:" not supported. Every script inassets/scripts/already deletes proxy env vars at the top — preserve that preamble if you copy / adapt them.- TOS SDK quirks —
headBucket(string)notheadBucket({bucket});listObjectsType2signature breaks whencontinuationToken: undefinedis in the input;putObjectdefaults to private even on public-read buckets — always setacl: 'public-read'. - TOS has no separate website endpoint hostname — the same
\x3Cbucket>.tos-\x3Cregion>.volces.comreturns either bucket-listing JSON orindex.htmldepending on theHostheader. You MUST (a) callputBucketCustomDomainper apex/www domain, AND (b) setOriginHostin the CDNAddCdnDomainpayload to the user's domain (not empty). - CDN ≠ DCDN for verification — CDN (内容分发网络) wants TXT host
volccdnauthandcdn:CheckCdnDomain(not inveCLI — usevolc-api.mjs). DCDN (全站加速) uses_dnsauthandve dcdn VerifyDomainOwnership. Mixing them up = endless verification loop. - TXT changes take ~10 min to propagate at Volcengine's verifier. Get the value right on the first write; don't churn.
pnpm deployis a built-in. Usepnpm run deploy.- Free DV cert APPLICATION is console-only. API issuance is blocked with permanent AK/SK (
OperationDenied.RequestFreeInstance). But listing already-issued certs works fine — and free DV certs are often auto-issued at domain registration. AlwaysCertificateGetInstanceListfirst; look inResult.Instances[](NOTInstanceList, NOTData) for one whoseSancovers both apex + www.
Behavior rules
- Plan first; confirm before destructive ops. Before
createBucket,AddCdnDomain,DeleteRecordon existing TXT, orBatchDeployCert, summarize what's about to happen and ask the user for confirmation. - Read existing state before writing. Always
ListRecords/ListCdnDomains/CertificateGetInstanceListfirst — free certs are often pre-issued, CDN domains may already exist, DNS records may already point at the right place. Idempotency is the whole point. - When
velacks an action, usevolc-api.mjsrather than telling the user to upgradeveor use the console. The only true console-only path is free DV cert issuance (landmines.md #4). - Don't churn DNS records. Each TXT modification adds ~10 min cache. Get the host/value right the first time —
volccdnauthfor CDN,_dnsauthfor DCDN, they're not interchangeable. - Surface every config decision in
deploy.config.mjs, never hardcode in scripts. Bucket, region, endpoint, CDN domains, cache rules — all live in the config so the user can edit one file to change everything. /usr/bin/curlis more reliable than barecurlwhen running checks after long commands in the same shell — bash PATH lookup occasionally goes weird. Same goes for tests in CI scripts.
Bundled assets and references
assets/scripts/ (copy verbatim into the user's scripts/)
lib/volc-api.mjs— SigV4 signer, zero deps. Use for any action missing fromveCLI.setup-bucket.mjs— idempotent bucket + website + custom-domain binding.deploy.mjs— TOS sync uploader with per-prefixCache-Control, orphan deletion.cdn-setup.mjs— CDN orchestration: ownership verification → AddCdnDomain → CNAME → cert → HTTPS hardening.cdn-refresh.mjs— cache invalidation viacdn:SubmitRefreshTask(signed byvolc-api.mjs, works in CI withoutve).
assets/cdn-payloads/ (copy into scripts/cdn-payloads/)
apex.jsonandwww.json—AddCdnDomainpayload templates with{{DOMAIN}},{{BUCKET}},{{REGION}}placeholders.OriginHostis set correctly out of the box — don't strip it.
assets/templates/ (copy into project root)
astro.config.mjs— locked-in Astro config. Onlysiteshould change per project.deploy.config.mjs— fill inbucket,region,endpoint,cdnDomains.package.json— scaffolded with the right dependencies + scripts. Updatename.BrandMark.astro— starting point for the brand mark component. Replace the three\x3Cpath>elements with the user's logo paths.
References (deep dives — read as needed)
references/phase-1-static-site.md— full Phase 1 walkthrough: stack rationale, content layout, brand mark extraction, SEO/a11y rules, hero visual recipe, file structure.references/phase-2-volcengine-deploy.md— full Phase 2 walkthrough: whatvecan/can't do, the 5 scripts step-by-step, environment setup, the 12-stepcdn-setup.mjssequence with payload examples.references/landmines.md— every known gotcha (proxy pollution, TOS SDK quirks, CDN vs DCDN, TXT propagation, pnpm-deploy collision, cert auto-issuance). Read once before executing Phase 2 for the first time.references/verification.md— post-deploy curl + openssl checklist with failure-mode mapping.
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install marketing-site-dev - 安装完成后,直接呼叫该 Skill 的名称或使用
/marketing-site-dev触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
Marketing Site Dev 是什么?
Opinionated end-to-end workflow for shipping a bilingual (中文/English) static company marketing site to Volcengine — Astro 6 + React 19 islands + Tailwind 4,... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 57 次。
如何安装 Marketing Site Dev?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install marketing-site-dev」即可一键安装,无需额外配置。
Marketing Site Dev 是免费的吗?
是的,Marketing Site Dev 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。
Marketing Site Dev 支持哪些平台?
Marketing Site Dev 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Marketing Site Dev?
由 tenshowinnovation(@tenshowinnovation)开发并维护,当前版本 v0.1.0。