prototyping

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ART+COM Prototyping

ART+COM 原型开发指南

Take one understandable step at a time. Explain outcomes, not implementation details. Run commands and make technical decisions for the user. Proceed automatically through the standard workflow; ask questions only when the answer changes the prototype, an interactive login needs the user, permissions are missing, or an existing project could be overwritten.
每次只执行一个易懂的步骤。解释最终结果,而非实现细节。为用户运行命令并做出技术决策。自动执行标准工作流;仅当答案会改变原型、需要用户进行交互式登录、缺少权限或可能覆盖现有项目时,才向用户提问。

1. Make the computer ready first

1. 先准备好电脑环境

Run
bash scripts/check-prerequisites.sh
from this skill directory first. Give a short plain-language summary: what is ready, what is missing, and what happens next. Never print login tokens or environment-variable values.
Require:
  • Homebrew
  • Node.js 22 or later and its bundled npm
  • GitLab CLI (
    glab
    ) authenticated to
    gitlab.artcom.de
  • Netlify CLI (
    netlify
    ) authenticated to the intended ART+COM Netlify team
If anything is missing or outdated, briefly say which tools will be installed or updated, then repair the prerequisites automatically in this order:
  1. If Homebrew is missing, use its official installer and respect any macOS administrator or password prompt.
  2. If Node.js is missing or older than 22, run
    brew install node
    or
    brew upgrade node
    .
  3. If
    glab
    is missing, run
    brew install glab
    .
  4. If
    netlify
    is missing, run
    npm install --global netlify-cli
    after Node/npm are ready.
  5. Re-run the preflight script.
If GitLab login is missing, ask the user for a personal access token: tell them to open
https://gitlab.artcom.de/-/user_settings/personal_access_tokens
, create a token with the
api
scope, and paste it into the chat. Then log in by piping the token to
glab auth login --hostname gitlab.artcom.de --stdin
. Never echo the token back, store it in a file, or include it in any output. If Netlify login is missing, tell the user a browser window will open and run
netlify login
. Re-run the preflight until every required item is ready.
Then confirm the Netlify login is the company account, not a personal one:
bash
netlify status
The listed team must be
ART+COM
. If it is a personal team, tell the user in plain language that they are signed in with a private Netlify account, then run
netlify logout
and
netlify login
again so they can pick their ART+COM account. Do not continue with a personal account: it cannot password-protect a prototype and has none of the shared broker variables.
首先从本技能目录运行
bash scripts/check-prerequisites.sh
。用简洁的通俗语言总结:哪些环境已就绪、哪些缺失,以及下一步操作。切勿打印登录令牌或环境变量值。
所需工具:
  • Homebrew
  • Node.js 22或更高版本及其附带的npm
  • 已通过
    gitlab.artcom.de
    认证的GitLab CLI(
    glab
  • 已通过目标ART+COM Netlify团队认证的Netlify CLI(
    netlify
若有工具缺失或版本过时,简要说明将安装或更新哪些工具,然后按以下顺序自动修复前置依赖:
  1. 若缺少Homebrew,使用其官方安装程序,并遵循macOS管理员或密码提示。
  2. 若缺少Node.js或版本低于22,运行
    brew install node
    brew upgrade node
  3. 若缺少
    glab
    ,运行
    brew install glab
  4. 若缺少
    netlify
    ,在Node/npm就绪后运行
    npm install --global netlify-cli
  5. 重新运行预检脚本。
若未完成GitLab登录,向用户索要个人访问令牌:告知用户打开
https://gitlab.artcom.de/-/user_settings/personal_access_tokens
,创建一个拥有
api
权限范围的令牌,并粘贴到聊天框中。然后通过将令牌传入
glab auth login --hostname gitlab.artcom.de --stdin
完成登录。切勿回显令牌、将其存储到文件或包含在任何输出中。若未完成Netlify登录,告知用户将打开一个浏览器窗口,并运行
netlify login
。重复运行预检脚本,直到所有必需项均就绪。
随后确认Netlify登录的是公司账户,而非个人账户:
bash
netlify status
列出的团队必须为
ART+COM
。若显示为个人团队,用通俗语言告知用户当前登录的是私人Netlify账户,然后运行
netlify logout
netlify login
,让用户选择ART+COM账户。切勿使用个人账户继续操作:它无法为原型设置密码保护,也不具备任何共享代理变量。

2. Gather a short prototype brief

2. 收集简短的原型需求说明

Ask one question at a time, in this order:
  1. “Are we starting a new prototype, or improving an existing folder?” If existing, ask them to choose the folder.
  2. “In one or two sentences, what should people be able to see or do?”
  3. “Which ART+COM project is this prototype for?” Derive a lowercase, hyphenated
    project-slug
    from the answer.
  4. “Should the app be portrait or landscape?”
  5. “Will people use touch input? Answer yes or no.”
  6. “Will it contain a 3D scene or object that people can explore?”
  7. If not 3D: “Is it mainly a content website with pages, text, images, and simple animations?”
  8. “Does it need to show or control live data from an MQTT broker?” Explain that “I’m not sure” is a valid answer; treat it as no MQTT for now.
  9. For a new prototype, ask for a simple prototype name. Derive a lowercase, hyphenated
    prototype-name
    for its local folder. Use
    <project-slug>-<prototype-name>
    as its
    repository-name
    .
  10. “Is this prototype covered by a strict client NDA, so it needs its own password instead of the shared ART+COM preview password?” Say that either way nobody reaches it without a password; the only difference is which one. Treat “I’m not sure” as no.
For a new prototype, use
~/Documents/prototypes/<prototype-name>
unless the user already supplied a destination. Create the
prototypes
folder if needed. If that prototype folder already exists, do not overwrite it; ask the user whether to use that folder or a different name.
Do not ask non-technical users to choose a framework, GitLab group, build command, publish directory, or Netlify team. Use the defaults below and explain the choice in one sentence.
What the user needsUseExplain it as
3D scene, spatial interaction, WebGLReact + TypeScript + Three.js via React Three Fiber“A solid base for a real-time 3D experience.”
Content-led site, story, portfolio, information pagesAstro + TypeScript“Fast pages that are simple to update.”
Interactive controls, visual UI, data display, or an app-like toolReact + TypeScript + Vite“A flexible base for interactive experiences.”
UnclearReact + TypeScript + Vite“A safe general-purpose starting point; we can change direction later.”
Use MQTT only when the user explicitly selects it in the plain-language question.
依次逐个提问:
  1. “我们是要创建新原型,还是改进现有文件夹中的原型?”若为现有原型,让用户选择对应的文件夹。
  2. “用一两句话描述,人们应该能看到或做什么?”
  3. “这个原型属于ART+COM的哪个项目?”根据回答生成小写、连字符分隔的
    project-slug
  4. “应用应该是竖屏还是横屏?”
  5. “人们会使用触摸输入吗?请回答是或否。”
  6. “它是否包含可浏览的3D场景或对象?”
  7. 若不涉及3D:“它主要是包含页面、文本、图片和简单动画的内容网站吗?”
  8. “它是否需要显示或控制来自MQTT代理的实时数据?”说明“不确定”是有效答案;暂时视为不需要MQTT。
  9. 对于新原型,询问一个简单的原型名称。为其本地文件夹生成小写、连字符分隔的
    prototype-name
    。使用
    <project-slug>-<prototype-name>
    作为
    repository-name
  10. “这个原型是否受严格的客户保密协议约束,因此需要使用独立密码而非ART+COM共享预览密码?”说明无论哪种情况,无密码均无法访问;唯一区别是使用的密码不同。将“不确定”视为不需要独立密码。
对于新原型,默认使用
~/Documents/prototypes/<prototype-name>
作为存储路径,除非用户已指定目标位置。若
prototypes
文件夹不存在则创建。若该原型文件夹已存在,切勿覆盖;询问用户是使用该文件夹还是更换名称。
切勿让非技术用户选择框架、GitLab群组、构建命令、发布目录或Netlify团队。使用以下默认选项,并用一句话解释选择理由。
用户需求使用方案通俗解释
3D场景、空间交互、WebGLReact + TypeScript + Three.js(基于React Three Fiber)“实时3D体验的可靠基础。”
内容导向型网站、故事展示、作品集、信息页面Astro + TypeScript“更新简便的快速页面。”
交互式控件、可视化UI、数据展示或类应用工具React + TypeScript + Vite“交互式体验的灵活基础。”
需求不明确React + TypeScript + Vite“安全通用的起点;后续可调整方向。”
仅当用户在通俗语言提问中明确选择时,才添加MQTT功能。

3. Create the project

3. 创建项目

For a new project, create it only after all readiness checks succeed. Explain the selected stack in one sentence, then scaffold it:
bash
undefined
对于新项目,仅在所有就绪检查通过后再创建。用一句话解释所选技术栈,然后搭建项目:
bash
undefined

Content site

内容网站

npm create astro@latest <prototype-name>
npm create astro@latest <prototype-name>

Interactive or 3D experience

交互式或3D体验

npm create vite@latest <prototype-name> -- --template react-ts cd <prototype-name> npm install
npm create vite@latest <prototype-name> -- --template react-ts cd <prototype-name> npm install

Add this only for 3D

仅针对3D项目添加

npm install three @react-three/fiber @react-three/drei

Immediately after scaffolding a new project, create `AGENTS.md` with these project constraints:

```md
npm install three @react-three/fiber @react-three/drei

搭建新项目后立即创建`AGENTS.md`,包含以下项目约束:

```md

ART+COM internal prototype

ART+COM 内部原型

This is an ART+COM internal prototype. Do not add accessibility features or responsive layouts. Build only for the agreed orientation and touch-input mode.
This prototype is private. It is password protected on Netlify and its pages carry
noindex
headers. Never remove the password, the
X-Robots-Tag
headers, or
robots.txt
.
Commit changes regularly while working. After each commit, update the Netlify deployment by running
netlify deploy --prod --build
once the site is connected to Netlify.
Regularly update the installed ART+COM skills so the newest version is always used:
npx skills add artcom/agent-skills --skill prototyping

Also create `CLAUDE.md` containing only the line `@AGENTS.md`, so Claude Code imports the same constraints.

For an existing project, inspect `package.json`, identify its current framework and commands, and extend it without replacing its configuration, lockfile, or deployment setup.

Create a minimal working first screen that reflects the user’s description and the agreed orientation and touch-input mode. Do not add responsive layouts or accessibility features. For a 3D project, include a visible, interactive Three.js scene; do not merely install the packages. For a content site, include the requested page structure and sample content. For an interactive app, include the main interaction or data-state shape. Keep the first version small and runnable.

Create `.env.example` with names and safe placeholders only. Ensure real `.env*` files are ignored by Git. Never put real broker URLs, credentials, or Netlify secrets in source code, `netlify.toml`, commits, or output.

Create a `netlify.toml` with the actual build command, `dist` as the publish directory for Astro and Vite, and headers that keep the prototype out of search results:

```toml
[[headers]]
  for = "/*"
  [headers.values]
    X-Robots-Tag = "noindex, nofollow, noarchive"
Netlify adds this header to deploy previews on its own, but never to the production URL the user will share, so set it explicitly. Also create
public/robots.txt
with:
text
User-agent: *
Disallow: /
Run
npm run build
; a successful build is sufficient verification.
这是ART+COM的内部原型。请勿添加无障碍功能或响应式布局。仅针对约定的方向和触摸输入模式进行构建。
本原型为私有内容。在Netlify上设置了密码保护,其页面带有
noindex
标头。切勿移除密码、
X-Robots-Tag
标头或
robots.txt
文件。
工作期间定期提交更改。每次提交后,若站点已连接到Netlify,运行
netlify deploy --prod --build
更新Netlify部署。
定期更新已安装的ART+COM技能,确保始终使用最新版本:
npx skills add artcom/agent-skills --skill prototyping

同时创建`CLAUDE.md`,仅包含一行`@AGENTS.md`,以便Claude Code导入相同的约束条件。

对于现有项目,检查`package.json`,识别其当前框架和命令,在不替换配置、锁文件或部署设置的前提下进行扩展。

创建一个符合用户描述、约定方向和触摸输入模式的最小可运行初始页面。请勿添加响应式布局或无障碍功能。对于3D项目,包含一个可见的交互式Three.js场景;切勿仅安装依赖包。对于内容网站,包含请求的页面结构和示例内容。对于交互式应用,包含主要交互逻辑或数据状态结构。保持初始版本简洁且可运行。

创建仅包含变量名和安全占位符的`.env.example`。确保真实的`.env*`文件被Git忽略。切勿将真实的代理URL、凭据或Netlify密钥放入源代码、`netlify.toml`、提交记录或输出中。

创建`netlify.toml`,包含实际构建命令、将`dist`设为Astro和Vite的发布目录,以及防止原型被搜索引擎收录的标头:

```toml
[[headers]]
  for = "/*"
  [headers.values]
    X-Robots-Tag = "noindex, nofollow, noarchive"
Netlify会自动为部署预览添加此标头,但不会为用户将共享的生产URL添加,因此需显式设置。同时创建
public/robots.txt
,内容如下:
text
User-agent: *
Disallow: /
运行
npm run build
;构建成功即为验证通过。

4. Add live MQTT data only when wanted

4. 仅在需要时添加实时MQTT数据

If MQTT is selected, fetch the current ART+COM MQTT skill from:
text
https://raw.githubusercontent.com/artcom/agent-skills/main/skills/mqtt-topping/SKILL.md
Run
npm install mqtt-topping
. It requires Node.js 22 or later.
Use
PUBLIC_BROKER
only for browser-safe, non-secret connection information. Keep
INTERNAL_BROKER
server-side; do not expose it through a
VITE_*
variable or browser code. Follow the MQTT skill's parse-error, background-error, QoS, and retained-message guidance. Explicitly use
retain: false
for transient commands and events.
若选择了MQTT,从以下地址获取当前ART+COM的MQTT技能:
text
https://raw.githubusercontent.com/artcom/agent-skills/main/skills/mqtt-topping/SKILL.md
运行
npm install mqtt-topping
。它需要Node.js 22或更高版本。
仅将
PUBLIC_BROKER
用于浏览器安全的非保密连接信息。将
INTERNAL_BROKER
保留在服务器端;切勿通过
VITE_*
变量或浏览器代码暴露它。遵循MQTT技能中的解析错误、后台错误、QoS和保留消息指南。对于临时命令和事件,显式使用
retain: false

5. Give every new prototype its shared home

5. 为每个新原型分配共享存储位置

New ART+COM prototypes belong in the
prototypes
group on
https://gitlab.artcom.de
. Do not ask the user to choose a namespace or confirm this standard setup. Once the local prototype builds successfully, automatically create its private project at
https://gitlab.artcom.de/prototypes/<repository-name>
and connect the folder to it. Always prefix
repository-name
with
project-slug
.
Initialise Git if necessary. Check whether the GitLab project already exists before creating it; if it does, connect only when it is the intended
prototypes/<repository-name>
project. Otherwise create it with the ART+COM host explicitly selected:
bash
GITLAB_HOST=gitlab.artcom.de glab repo create prototypes/<repository-name> --private --defaultBranch main
Verify the
origin
remote points to
gitlab.artcom.de/prototypes/<repository-name>
. Never replace a different existing remote. Before the first commit, verify that
.env
,
.env.*
except
.env.example
,
node_modules
, and build output are not staged. Automatically make the initial commit and push the new prototype once the project is connected. Report the GitLab URL and commit after the push completes.
For an existing project, retain its current remote unless the user explicitly asks to create or replace it with a project under
prototypes
.
新的ART+COM原型应存放在
https://gitlab.artcom.de
prototypes
群组中。切勿让用户选择命名空间或确认此标准设置。本地原型构建成功后,自动在
https://gitlab.artcom.de/prototypes/<repository-name>
创建私有项目,并将文件夹与其连接。始终用
project-slug
作为
repository-name
的前缀。
必要时初始化Git。创建前检查GitLab项目是否已存在;若已存在,仅当它是目标
prototypes/<repository-name>
项目时才进行连接。否则,显式选择ART+COM主机创建项目:
bash
GITLAB_HOST=gitlab.artcom.de glab repo create prototypes/<repository-name> --private --defaultBranch main
验证
origin
远程仓库指向
gitlab.artcom.de/prototypes/<repository-name>
。切勿替换已存在的其他远程仓库。首次提交前,验证
.env
.env.*
.env.example
除外)、
node_modules
和构建输出未被暂存。项目连接后自动完成初始提交并推送新原型。推送完成后报告GitLab URL和提交记录。
对于现有项目,保留其当前远程仓库,除非用户明确要求在
prototypes
下创建或替换项目。

6. Connect Netlify and broker configuration

6. 连接Netlify和代理配置

From the project root, state that the prototype is being connected to Netlify. Do not use
netlify init
: it configures continuous deployment and introduces interactive Git-provider setup. List accessible Netlify teams, select the one clearly named ART+COM, and create a directly deployable site with:
bash
netlify sites:create --name <repository-name> --account-slug <artcom-team-slug>
Use the same
<project-slug>-<prototype-name>
value as the GitLab repository. A Netlify site name is a globally unique public subdomain, so an unprefixed name like
kiosk
both collides with other Netlify customers and makes the prototype easy to guess.
This creates and links an empty project to the current folder. If a site of that name already exists, link it only when it belongs to the intended ART+COM team; otherwise create
<repository-name>-<yyyymmdd>
. Keep
.netlify/state.json
local only. Do not configure GitLab continuous deployment in this initial flow.
Make the site private as described in section 7 before the first production deploy. Then run the local build and deploy with
netlify deploy --prod --build
.
After linking, check whether
PUBLIC_BROKER
and
INTERNAL_BROKER
exist as shared team variables with appropriate scopes and deploy contexts. Do not use
netlify env:list
: it prints values, including the shared preview password. List names and scopes only:
bash
netlify api getEnvVars --data '{"account_id":"<account-id>"}' \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{for(const v of JSON.parse(s)) console.log(v.key, "|", (v.scopes||[]).join(","), "|", (v.values||[]).map(x=>x.context).join(","))})'
INTERNAL_BROKER
needs the Functions scope when it is used by a Netlify Function.
Netlify CLI can create site variables, but ART+COM broker variables must remain shared team variables. If either name is missing, do not create a site-specific replacement. If the authenticated account has Team Owner access, create the missing shared variable through the Netlify API; otherwise, state which name is missing and that a Netlify Team Owner must add it in Team settings → Environment variables. Re-check once configured.
从项目根目录告知用户正在将原型连接到Netlify。请勿使用
netlify init
:它会配置持续部署并引入交互式Git提供商设置。列出可访问的Netlify团队,选择明确命名为ART+COM的团队,然后创建可直接部署的站点:
bash
netlify sites:create --name <repository-name> --account-slug <artcom-team-slug>
使用与GitLab仓库相同的
<project-slug>-<prototype-name>
值。Netlify站点名称是全局唯一的公共子域名,因此像
kiosk
这样无前缀的名称既会与其他Netlify客户冲突,也会让原型容易被猜测到。
此命令会创建一个空项目并链接到当前文件夹。若该名称的站点已存在,仅当它属于目标ART+COM团队时才进行链接;否则创建
<repository-name>-<yyyymmdd>
。仅在本地保留
.netlify/state.json
。在此初始流程中请勿配置GitLab持续部署。
在首次生产部署之前,按照第7节的说明将站点设为私有。然后运行本地构建并部署:
netlify deploy --prod --build
链接后,检查
PUBLIC_BROKER
INTERNAL_BROKER
是否作为共享团队变量存在,并具备适当的权限范围和部署上下文。请勿使用
netlify env:list
:它会打印变量值,包括共享预览密码。仅列出变量名和权限范围:
bash
netlify api getEnvVars --data '{"account_id":"<account-id>"}' \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{for(const v of JSON.parse(s)) console.log(v.key, "|", (v.scopes||[]).join(","), "|", (v.values||[]).map(x=>x.context).join(","))})'
INTERNAL_BROKER
被Netlify Function使用时,需要Functions权限范围。
Netlify CLI可以创建站点变量,但ART+COM的代理变量必须保持为共享团队变量。若任一变量名缺失,请勿创建站点特定的替代变量。若已认证账户拥有团队所有者权限,通过Netlify API创建缺失的共享变量;否则,说明缺失的变量名,并告知用户Netlify团队所有者必须在团队设置→环境变量中添加该变量。配置完成后重新检查。

7. Keep every prototype private

7. 确保所有原型的私有性

A Netlify site is public and searchable the moment it is deployed. Every ART+COM prototype must be password protected before its first production deploy. Do not ask the user whether they want this; it is the standard setup.
ART+COM uses one shared preview password for all prototypes. Netlify's team-wide default Password Protection is an Enterprise feature, so on the ART+COM Pro plan every site must be set individually. Do not look for a team setting that applies it automatically; there is none.
Which password depends on the NDA answer from the brief.
For a normal prototype, the shared password is stored as the team environment variable
ARTCOM_PREVIEW_PASSWORD
, so do not ask the user for it. Read the ART+COM
account_id
once from
netlify api listAccountsForUser
, then fetch and apply the password in a way that keeps it out of the chat:
bash
PREVIEW_PW=$(netlify api getEnvVar --data "{\"account_id\":\"<account-id>\",\"key\":\"ARTCOM_PREVIEW_PASSWORD\"}" \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const o=JSON.parse(s);const v=(o.values||[]).find(x=>x.context==="all")||(o.values||[])[0];process.stdout.write(v&&v.value?v.value:"")})')

netlify api updateSite --data "$(PW="$PREVIEW_PW" SID="<site-id>" node -e 'process.stdout.write(JSON.stringify({site_id:process.env.SID,body:{password:process.env.PW}}))')" > /dev/null
The value stays in a shell variable and is never printed. If
PREVIEW_PW
comes back empty the variable is missing: ask the user for the shared password, pass it to the same
updateSite
call, and offer to store it for next time so nobody is asked again:
bash
netlify api createEnvVars --data "$(PW="<shared-password>" node -e 'process.stdout.write(JSON.stringify({account_id:"<account-id>",body:[{key:"ARTCOM_PREVIEW_PASSWORD",scopes:["functions"],values:[{context:"all",value:process.env.PW}]}]}))')"
Keep that variable non-secret, because a Netlify secret variable cannot be read back. The
functions
scope keeps it out of every build environment while leaving it readable through the API.
Never write the shared password into this skill, a prototype repository, or any other file: this skill is published in a public repository.
For a prototype under a strict client NDA, do not use the shared password. Offer to generate one instead:
bash
node -e 'console.log(require("crypto").randomBytes(9).toString("base64url"))'
Report that generated password once in the chat and tell the user to store it in their password manager, because Netlify will never show it again. Accept a password of the user's own choosing just as readily.
Either way, set it on the new site:
bash
netlify api updateSite --data '{"site_id":"<site-id>","body":{"password":"<password>"}}'
Never echo the shared password back, write any password to a file, commit one, or include one in later output. Netlify does not return it either, so confirm the result with:
bash
netlify api getSite --data '{"site_id":"<site-id>"}' \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>console.log(JSON.parse(s).has_password))'
This is the only check available and it is safe to run. Deploy only once it prints
true
. If the user does not know the password, stop before deploying and say plainly that the prototype would otherwise be readable by anyone on the internet.
This protects the production URL and every deploy URL together. Visitors get a neutral password page and stay signed in for that browser session.
Never remove a password on your own. If the user explicitly asks for a link that needs no password, tell them plainly that the prototype then becomes visible to anyone who has the URL, and only then run:
bash
netlify api updateSite --data '{"site_id":"<site-id>","body":{"password":""}}'
For a prototype that runs unattended on a display in the office, offer firewall traffic rules instead: a Team Owner allows the office IP range under Project configuration → Access & security → Firewall traffic rules, so nobody has to type a password after a reboot.
Netlify站点一经部署即为公开且可被搜索引擎收录。每个ART+COM原型必须在首次生产部署前设置密码保护。请勿询问用户是否需要此设置;这是标准流程。
ART+COM为所有原型使用一个共享预览密码。Netlify的团队级默认密码保护是企业版功能,因此在ART+COM专业版计划中,每个站点必须单独设置。请勿寻找可自动应用此设置的团队配置;不存在这样的配置。
使用哪种密码取决于需求说明中的保密协议回答。
对于普通原型,共享密码存储为团队环境变量
ARTCOM_PREVIEW_PASSWORD
,因此无需向用户索要。从
netlify api listAccountsForUser
中读取一次ART+COM的
account_id
,然后通过不泄露密码的方式获取并应用密码:
bash
PREVIEW_PW=$(netlify api getEnvVar --data "{\"account_id\":\"<account-id>\",\"key\":\"ARTCOM_PREVIEW_PASSWORD\"}" \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const o=JSON.parse(s);const v=(o.values||[]).find(x=>x.context==="all")||(o.values||[])[0];process.stdout.write(v&&v.value?v.value:"")})')

netlify api updateSite --data "$(PW="$PREVIEW_PW" SID="<site-id>" node -e 'process.stdout.write(JSON.stringify({site_id:process.env.SID,body:{password:process.env.PW}}))')" > /dev/null
密码值仅保留在shell变量中,绝不会被打印。若
PREVIEW_PW
为空,说明变量缺失:向用户索要共享密码,将其传入相同的
updateSite
调用,并提议将其存储以便下次无需再询问:
bash
netlify api createEnvVars --data "$(PW="<shared-password>" node -e 'process.stdout.write(JSON.stringify({account_id:"<account-id>",body:[{key:"ARTCOM_PREVIEW_PASSWORD",scopes:["functions"],values:[{context:"all",value:process.env.PW}]}]}))')"
将该变量设为非保密变量,因为Netlify的保密变量无法被读取。
functions
权限范围可使其脱离所有构建环境,同时仍可通过API读取。
切勿将共享密码写入本技能、原型仓库或任何其他文件:本技能发布在公共仓库中。
对于受严格客户保密协议约束的原型,请勿使用共享密码。提议生成一个独立密码:
bash
node -e 'console.log(require("crypto").randomBytes(9).toString("base64url"))'
在聊天框中报告一次生成的密码,并告知用户将其存储在密码管理器中,因为Netlify不会再次显示该密码。同样接受用户自行选择的密码。
无论哪种情况,将密码设置到新站点:
bash
netlify api updateSite --data '{"site_id":"<site-id>","body":{"password":"<password>"}}'
切勿回显共享密码、将任何密码写入文件、提交密码或在后续输出中包含密码。Netlify也不会返回密码,因此通过以下命令确认结果:
bash
netlify api getSite --data '{"site_id":"<site-id>"}' \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>console.log(JSON.parse(s).has_password))'
这是唯一可用的安全检查命令。仅当输出为
true
时才进行部署。若用户不知道密码,在部署前停止操作,并用通俗语言说明否则原型会被互联网上的任何人访问。
此设置会同时保护生产URL和所有部署URL。访问者会看到一个中性的密码页面,且在该浏览器会话中保持登录状态。
切勿自行移除密码。若用户明确要求无需密码的链接,用通俗语言说明此时原型会对任何拥有URL的人可见,仅在确认后运行:
bash
netlify api updateSite --data '{"site_id":"<site-id>","body":{"password":""}}'
对于在办公室显示器上无人值守运行的原型,提议使用防火墙流量规则替代:团队所有者在项目配置→访问与安全→防火墙流量规则中允许办公室IP范围,这样重启后无需输入密码即可访问。

8. Finish in plain language

8. 用通俗语言总结收尾

Summarize the prototype folder, chosen approach and reason, GitLab URL, Netlify URL, build/deploy result, and whether live MQTT was added. State that the prototype is password protected and say which password opens it: the shared ART+COM preview password, or this prototype's own password for an NDA prototype. Never print the shared password. State any blocked step in ordinary language and give the one action the user needs to take next.
总结原型文件夹位置、所选方案及理由、GitLab URL、Netlify URL、构建/部署结果,以及是否添加了实时MQTT功能。说明原型已设置密码保护,并告知使用哪种密码:ART+COM共享预览密码,或保密协议原型的独立密码。切勿打印共享密码。用通俗语言说明任何被阻塞的步骤,并告知用户下一步需执行的操作。