@payloadcms/figma 0.1.0-alpha.3 → 0.1.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/check-project-subdomain-availability.d.ts +12 -0
- package/dist/api/check-project-subdomain-availability.js +32 -0
- package/dist/api/control-plane-error.d.ts +6 -0
- package/dist/api/control-plane-error.js +8 -0
- package/dist/api/control-plane-fetch.d.ts +7 -0
- package/dist/api/control-plane-fetch.js +37 -0
- package/dist/api/control-plane.d.ts +0 -8
- package/dist/api/control-plane.js +1 -47
- package/dist/api/create-project.d.ts +18 -0
- package/dist/api/create-project.js +37 -0
- package/dist/api/list-project-workspaces.d.ts +8 -0
- package/dist/api/list-project-workspaces.js +28 -0
- package/dist/api/project-resource-type.d.ts +1 -0
- package/dist/api/project-resource-type.js +1 -0
- package/dist/auth/headless-oauth-flow.d.ts +23 -0
- package/dist/auth/headless-oauth-flow.js +69 -0
- package/dist/auth/oauth-flow.d.ts +2 -0
- package/dist/auth/oauth-flow.js +13 -8
- package/dist/auth/token-store.d.ts +4 -1
- package/dist/auth/token-store.js +14 -0
- package/dist/auth/types.d.ts +12 -0
- package/dist/cli.d.ts +10 -1
- package/dist/cli.js +39 -4
- package/dist/commands/bootstrap.js +2 -1
- package/dist/commands/deploy.d.ts +10 -0
- package/dist/commands/deploy.js +39 -11
- package/dist/commands/detect-project-resource-type.d.ts +3 -0
- package/dist/commands/detect-project-resource-type.js +28 -0
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.js +163 -78
- package/dist/commands/login.d.ts +11 -1
- package/dist/commands/login.js +66 -4
- package/dist/commands/prompt-to-create-project/format-project-subdomain.d.ts +1 -0
- package/dist/commands/prompt-to-create-project/format-project-subdomain.js +3 -0
- package/dist/commands/prompt-to-create-project/format-unavailable-subdomain-reason.d.ts +1 -0
- package/dist/commands/prompt-to-create-project/format-unavailable-subdomain-reason.js +7 -0
- package/dist/commands/prompt-to-create-project/get-default-project-name.d.ts +1 -0
- package/dist/commands/prompt-to-create-project/get-default-project-name.js +13 -0
- package/dist/commands/prompt-to-create-project/prompt-for-available-subdomain.d.ts +7 -0
- package/dist/commands/prompt-to-create-project/prompt-for-available-subdomain.js +32 -0
- package/dist/commands/prompt-to-create-project/resolve-project-region.d.ts +8 -0
- package/dist/commands/prompt-to-create-project/resolve-project-region.js +27 -0
- package/dist/commands/prompt-to-create-project/resolve-project-subdomain.d.ts +9 -0
- package/dist/commands/prompt-to-create-project/resolve-project-subdomain.js +54 -0
- package/dist/commands/prompt-to-create-project/resolve-text-input.d.ts +9 -0
- package/dist/commands/prompt-to-create-project/resolve-text-input.js +23 -0
- package/dist/commands/prompt-to-create-project/resolve-workspace-plan-key.d.ts +12 -0
- package/dist/commands/prompt-to-create-project/resolve-workspace-plan-key.js +36 -0
- package/dist/commands/prompt-to-create-project/validate-subdomain.d.ts +1 -0
- package/dist/commands/prompt-to-create-project/validate-subdomain.js +9 -0
- package/dist/commands/prompt-to-create-project.d.ts +24 -0
- package/dist/commands/prompt-to-create-project.js +69 -0
- package/dist/commands/setup-agent.d.ts +12 -0
- package/dist/commands/setup-agent.js +123 -0
- package/dist/commands/write-project-configuration.d.ts +12 -0
- package/dist/commands/write-project-configuration.js +16 -0
- package/dist/db-content-api/index.js +52 -33
- package/dist/db-content-api/utilities/data/injectGlobalType.d.ts +6 -0
- package/dist/db-content-api/utilities/data/injectGlobalType.js +11 -0
- package/dist/db-content-api/utilities/isRecord.d.ts +9 -0
- package/dist/db-content-api/utilities/isRecord.js +19 -0
- package/dist/db-content-api/utilities/joins.js +5 -1
- package/dist/db-content-api/utilities/meta/resolvesToRelationshipValue.d.ts +10 -0
- package/dist/db-content-api/utilities/meta/resolvesToRelationshipValue.js +95 -0
- package/dist/db-content-api/utilities/meta/stringifyIdsInWhere.d.ts +9 -0
- package/dist/db-content-api/utilities/meta/stringifyIdsInWhere.js +112 -0
- package/dist/db-content-api/utilities/where.d.ts +2 -6
- package/dist/db-content-api/utilities/where.js +20 -9
- package/dist/exports/views.d.ts +1 -0
- package/dist/exports/views.js +1 -0
- package/dist/imageSizeOptions.d.ts +23 -0
- package/dist/imageSizeOptions.js +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/lib/write-agent-config.d.ts +12 -0
- package/dist/lib/write-agent-config.js +52 -0
- package/dist/oauth/defaults.d.ts +1 -0
- package/dist/oauth/defaults.js +1 -0
- package/dist/oauth/endpoints/getLoginEndpoint.js +7 -2
- package/dist/oauth/index.js +24 -9
- package/dist/oauth/utilities/getAdminCollectionSlug.d.ts +1 -1
- package/dist/oauth/utilities/getAuthorizeURL.d.ts +3 -0
- package/dist/oauth/utilities/getAuthorizeURL.js +8 -2
- package/dist/plugin/build-config.js +22 -9
- package/dist/plugin/cloud-limits/CloudLimitModal/index.d.ts +2 -3
- package/dist/plugin/cloud-limits/CloudLimitModal/index.js +4 -16
- package/dist/plugin/cloud-limits/CloudLimitModal/index.scss +5 -0
- package/dist/plugin/cloud-limits/CloudLimitProvider/index.d.ts +0 -3
- package/dist/plugin/cloud-limits/CloudLimitProvider/index.js +65 -124
- package/dist/plugin/cloud-limits/LimitReachedView/index.css +14 -0
- package/dist/plugin/cloud-limits/LimitReachedView/index.d.ts +4 -0
- package/dist/plugin/cloud-limits/LimitReachedView/index.js +52 -0
- package/dist/plugin/cloud-limits/SlugRegistryContext/index.d.ts +7 -2
- package/dist/plugin/cloud-limits/SlugTracker/index.d.ts +0 -8
- package/dist/plugin/cloud-limits/SlugTracker/index.js +14 -10
- package/dist/plugin/cloud-limits/routes.d.ts +2 -0
- package/dist/plugin/cloud-limits/routes.js +4 -0
- package/dist/plugin/cloud-limits/server/redirectInitialAutosaveCreate.d.ts +9 -0
- package/dist/plugin/cloud-limits/server/redirectInitialAutosaveCreate.js +28 -0
- package/dist/plugin/cloud-limits/shared.d.ts +1 -1
- package/dist/plugin/cloud-limits/shared.js +25 -0
- package/dist/plugin/cloud-limits/utilities/cloudLimitInterceptor.d.ts +2 -0
- package/dist/plugin/cloud-limits/utilities/cloudLimitInterceptor.js +134 -0
- package/dist/plugin/cloud-limits/utilities/toasts.d.ts +4 -0
- package/dist/plugin/cloud-limits/utilities/toasts.js +19 -0
- package/dist/skills/deploy-to-figma/SKILL.md +234 -0
- package/dist/skills/deploy-to-figma/references/cli-reference.md +146 -0
- package/dist/types.d.ts +9 -0
- package/dist/utils/lambda-config.js +4 -14
- package/dist/utils/messages.js +22 -3
- package/dist/utils/payload-generate.d.ts +10 -0
- package/dist/utils/payload-generate.js +59 -0
- package/dist/utils/pnpm-builds.d.ts +14 -0
- package/dist/utils/pnpm-builds.js +125 -0
- package/package.json +9 -1
- package/dist/lib/download-skill.d.ts +0 -12
- package/dist/lib/download-skill.js +0 -77
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deploy-to-figma
|
|
3
|
+
description: This skill should be used when the user asks to "deploy to Figma", "publish to Figma", "ship to Figma", "deploy my app to Figma Cloud", "put this Payload site on Figma", or otherwise wants to deploy the current project to Figma Cloud. You (the agent) inspect, classify, and build the target project; the @payloadcms/figma CLI only authenticates and deploys the verified artifact you hand it.
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
allowed-tools: Read, Bash, AskUserQuestion
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Deploy to Figma Cloud
|
|
9
|
+
|
|
10
|
+
Deploy a project to Figma Cloud with the `@payloadcms/figma` CLI. **You** (the
|
|
11
|
+
agent) determine the deploy shape — you inspect the project, run the build, and
|
|
12
|
+
verify the real build artifacts, then hand the CLI an explicit adapter and
|
|
13
|
+
output root you have confirmed on disk. The CLI no longer inspects the project;
|
|
14
|
+
it only authenticates and ships the artifact you point it at.
|
|
15
|
+
|
|
16
|
+
**Golden rule:** detection is your job. Read files and inspect real artifacts —
|
|
17
|
+
do not ask `@payloadcms/figma` what framework this is, and do not guess. When the
|
|
18
|
+
evidence conflicts or the shape isn't one Figma Cloud supports, **stop** before
|
|
19
|
+
touching auth or deploy.
|
|
20
|
+
|
|
21
|
+
Run the CLI with `npx @payloadcms/figma@alpha <...>` **from the target folder**.
|
|
22
|
+
If a different invocation is already established in the repo (e.g.
|
|
23
|
+
`pnpm start --`), use that instead — but `npx @payloadcms/figma@alpha` is the
|
|
24
|
+
default.
|
|
25
|
+
|
|
26
|
+
If the user's request contains **“Figma staging”** (case-insensitive), append
|
|
27
|
+
`--infra-env staging` to every CLI invocation in this flow, including login,
|
|
28
|
+
login completion, deploy, and deploy retries. Otherwise omit the flag.
|
|
29
|
+
|
|
30
|
+
## Flow overview
|
|
31
|
+
|
|
32
|
+
1. **Resolve** the target project directory.
|
|
33
|
+
2. **Inspect & classify** the deploy shape from evidence — or stop if unsupported/ambiguous.
|
|
34
|
+
3. **Build & verify** the real artifact (buildable projects); static folders skip the build.
|
|
35
|
+
4. **Detect initialization** from `target/.env`; gather creation inputs if uninitialized.
|
|
36
|
+
5. **Preflight auth** with the resumable headless flow.
|
|
37
|
+
6. **Deploy** the verified artifact with an explicit `--adapter` and `--output`.
|
|
38
|
+
7. **Report** the deployed URL.
|
|
39
|
+
|
|
40
|
+
Exact CLI contracts (flags, JSON shapes, artifact signatures) live in
|
|
41
|
+
`references/cli-reference.md` — consult it when a flag or field is unclear.
|
|
42
|
+
|
|
43
|
+
## Step 1 — Resolve the target directory
|
|
44
|
+
|
|
45
|
+
- If the prompt names a directory, that is the target.
|
|
46
|
+
- Otherwise use the current folder.
|
|
47
|
+
- In a **monorepo**, operate from the target **package** folder — not the repo
|
|
48
|
+
root. If several plausible apps exist and none is clearly the target, **ask**
|
|
49
|
+
via `AskUserQuestion` rather than guessing.
|
|
50
|
+
|
|
51
|
+
Every command and the build run **from the target folder**.
|
|
52
|
+
|
|
53
|
+
## Step 2 — Inspect and classify the deploy shape
|
|
54
|
+
|
|
55
|
+
Gather evidence yourself with `Read`/`Bash`. Do **not** rely on
|
|
56
|
+
`@payloadcms/figma` for detection. Look at:
|
|
57
|
+
|
|
58
|
+
- `package.json` — `dependencies`/`devDependencies`, `scripts.build`, and
|
|
59
|
+
`packageManager`.
|
|
60
|
+
- Lockfiles — `pnpm-lock.yaml`, `package-lock.json`, `yarn.lock`, `bun.lockb`.
|
|
61
|
+
- Framework config — `next.config.*`, `vite.config.*`, `nitro.config.*`,
|
|
62
|
+
`nuxt.config.*`, `app.config.*`.
|
|
63
|
+
- Source layout and any build artifacts already on disk.
|
|
64
|
+
|
|
65
|
+
Map the evidence to one **supported deploy shape**:
|
|
66
|
+
|
|
67
|
+
| Evidence | Shape | `--adapter` |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `next` dependency / `next.config.*` / a `next build` script | Next.js | `nextjs` |
|
|
70
|
+
| Nitro, Nuxt, TanStack Start, or any other evidenced Nitro output | Nitro | `nitro` |
|
|
71
|
+
| A built (or buildable) Vite single-page app | Vite | `vite` |
|
|
72
|
+
| A simple static folder — `index.html` plus CSS/JS/assets, no build needed (even with **no** `package.json`) | Static | `vite`, output = that folder |
|
|
73
|
+
|
|
74
|
+
If the evidence fits **none** of these, or points at **more than one** framework
|
|
75
|
+
with no clear winner, or you otherwise can't land confidently on one supported
|
|
76
|
+
shape → **go to Step 8 and stop**. Do not build, authenticate, or deploy.
|
|
77
|
+
|
|
78
|
+
## Step 3 — Build and verify the artifact
|
|
79
|
+
|
|
80
|
+
**Buildable projects** (Next.js / Nitro / Vite): run the build **from the target
|
|
81
|
+
folder, before** any auth or project creation, with `FIGMA_EXTRACT_SCHEDULES=true`.
|
|
82
|
+
|
|
83
|
+
Pick the package manager by searching the **target folder and its ancestors**
|
|
84
|
+
(up to the repo/monorepo root) — in a monorepo the `packageManager` field and
|
|
85
|
+
the lockfile usually live at the workspace root, not in the target package.
|
|
86
|
+
Precedence: nearest `packageManager` field → nearest lockfile
|
|
87
|
+
(`pnpm-lock.yaml`→pnpm, `package-lock.json`→npm, `yarn.lock`→yarn,
|
|
88
|
+
`bun.lockb`→bun) → available tooling. Run the build itself **from the target
|
|
89
|
+
package folder** with whichever manager you resolved, e.g.:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
FIGMA_EXTRACT_SCHEDULES=true npm run build
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Then **inspect the actual artifacts** to confirm the adapter and the output
|
|
96
|
+
**root**:
|
|
97
|
+
|
|
98
|
+
- **Next.js** — the root contains `BUILD_ID` and standalone server output. Pass
|
|
99
|
+
the root (e.g. `.next`) — **never** `.next/standalone`.
|
|
100
|
+
- **Nitro** — the root contains `server/index.mjs` (typically `.output`).
|
|
101
|
+
- **Vite** — the root contains `index.html` (typically `dist`).
|
|
102
|
+
|
|
103
|
+
**Static folders** skip the build entirely. The output is the exact folder that
|
|
104
|
+
contains `index.html` (often `.`).
|
|
105
|
+
|
|
106
|
+
If the build fails, or the artifacts don't match the shape you classified (the
|
|
107
|
+
evidence now conflicts), **stop** — go to Step 8. Never pass an `--output` root
|
|
108
|
+
you have not confirmed exists on disk.
|
|
109
|
+
|
|
110
|
+
## Step 4 — Detect initialization; gather creation inputs
|
|
111
|
+
|
|
112
|
+
Detect initialization **only** by testing whether `target/.env` contains a
|
|
113
|
+
nonempty `FIGMA_PROJECT_ID`, e.g.:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
test -f .env && grep -Eq '^FIGMA_PROJECT_ID=.+' .env && echo initialized || echo uninitialized
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Do **not** print the value or dump `.env`.
|
|
120
|
+
|
|
121
|
+
**Initialized** (`FIGMA_PROJECT_ID` present) → skip this step; pass no creation flags.
|
|
122
|
+
|
|
123
|
+
**Uninitialized** → gather the five project-creation fields across **two** grouped
|
|
124
|
+
`AskUserQuestion` interactions (a single call accepts at most four questions),
|
|
125
|
+
each field offering the CLI default so the user can accept as-is:
|
|
126
|
+
|
|
127
|
+
**Interaction 1 — naming** (three questions):
|
|
128
|
+
|
|
129
|
+
| Field | CLI default | Deploy flag |
|
|
130
|
+
| --- | --- | --- |
|
|
131
|
+
| Project name | derived from the directory name | `--name` |
|
|
132
|
+
| Description | `"<name> project"` | `--description` |
|
|
133
|
+
| Subdomain | slugified from the project name | `--subdomain` |
|
|
134
|
+
|
|
135
|
+
**Interaction 2 — placement** (two questions):
|
|
136
|
+
|
|
137
|
+
| Field | CLI default | Deploy flag |
|
|
138
|
+
| --- | --- | --- |
|
|
139
|
+
| Workspace | the account's default Figma workspace | `--workspace` |
|
|
140
|
+
| Region | `us-east-1` | `--region` |
|
|
141
|
+
|
|
142
|
+
Present the defaults as the recommended option. For any field left at its
|
|
143
|
+
default, **omit** the corresponding flag and let the CLI apply the default — only
|
|
144
|
+
pass a flag when the user supplied a non-default value.
|
|
145
|
+
|
|
146
|
+
## Step 5 — Preflight authentication
|
|
147
|
+
|
|
148
|
+
The deploy command needs a valid credential and cannot open a browser in a
|
|
149
|
+
headless/agent context, so authenticate first with the resumable headless flow.
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npx @payloadcms/figma@alpha login --headless --json
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Parse `status`:
|
|
156
|
+
|
|
157
|
+
- `authenticated` — already logged in. Proceed to deploy.
|
|
158
|
+
- `authorization_required` — the JSON includes `authorizationUrl` and
|
|
159
|
+
`sessionId`. Give the user the `authorizationUrl`, ask them to open it,
|
|
160
|
+
approve, and paste back **the full redirected URL** (the
|
|
161
|
+
`http://localhost:.../callback?...` address the browser lands on). Then:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npx @payloadcms/figma@alpha login --complete <sessionId> --callback-url '<redirect-url>' --json
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Quote the callback URL in single quotes. Expect `{"status":"authenticated",...}`.
|
|
168
|
+
|
|
169
|
+
**Handle the callback URL as a one-time secret:** pass it directly to the
|
|
170
|
+
`--complete` command and nothing else. Do not echo it back, summarize it, store
|
|
171
|
+
it in a file, or repeat it in later messages.
|
|
172
|
+
|
|
173
|
+
If completion fails, report the CLI's error and let the user retry the login
|
|
174
|
+
step; do not loop silently.
|
|
175
|
+
|
|
176
|
+
## Step 6 — Deploy
|
|
177
|
+
|
|
178
|
+
Run **from the target folder**, non-interactively with `-y`. Always pass
|
|
179
|
+
`--skip-build` (you already built, or a static folder needs no build) and the
|
|
180
|
+
explicit `--adapter` / `--output` you verified in Steps 2–3:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npx @payloadcms/figma@alpha deploy -y --skip-build --adapter <nextjs|nitro|vite> --output <verified-root>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Add the project-creation flags from Step 4 only for an uninitialized project.
|
|
187
|
+
|
|
188
|
+
Examples:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Next.js app in a monorepo package (already initialized), built to .next
|
|
192
|
+
npx @payloadcms/figma@alpha deploy -y --skip-build --adapter nextjs --output .next
|
|
193
|
+
|
|
194
|
+
# Vite single-page app, built to dist
|
|
195
|
+
npx @payloadcms/figma@alpha deploy -y --skip-build --adapter vite --output dist
|
|
196
|
+
|
|
197
|
+
# Simple static folder (index.html at the folder root), no build
|
|
198
|
+
npx @payloadcms/figma@alpha deploy -y --skip-build --adapter vite --output .
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Deterministic retry — workspace selection
|
|
202
|
+
|
|
203
|
+
If deploy fails with a message like:
|
|
204
|
+
|
|
205
|
+
> Multiple eligible Figma workspaces. Pass --workspace `<plan-key>`. Available: Acme (plan_abc), Beta (plan_xyz)
|
|
206
|
+
|
|
207
|
+
re-run the exact same command with `--workspace <plan-key>` added, choosing the
|
|
208
|
+
plan key the user selected (ask via `AskUserQuestion` if not already known,
|
|
209
|
+
listing the workspaces from the error's `Available:` list). This is the only
|
|
210
|
+
retry to perform automatically. For other errors, surface the CLI message and stop.
|
|
211
|
+
|
|
212
|
+
## Step 7 — Report the result
|
|
213
|
+
|
|
214
|
+
On success the CLI prints a line like `URL: https://<subdomain>.<domain>`.
|
|
215
|
+
Extract that URL and report it to the user as the deployed address, noting the
|
|
216
|
+
CLI's own message that a deploy usually takes 2–3 minutes to finish.
|
|
217
|
+
|
|
218
|
+
## Step 8 — Unsupported or ambiguous → stop
|
|
219
|
+
|
|
220
|
+
If Steps 2–3 can't land confidently on one supported shape, **stop before auth
|
|
221
|
+
or deploy**. Tell the user what you found and quote the supported set:
|
|
222
|
+
|
|
223
|
+
> Figma Cloud supports Next.js, Vite single-page apps, and any Nitro-based app
|
|
224
|
+
> (including Nuxt and TanStack Start).
|
|
225
|
+
|
|
226
|
+
Never run `login` or `deploy` for an unsupported or ambiguous project. Decide
|
|
227
|
+
this **before** asking an uninitialized project's creation questions — never make
|
|
228
|
+
the user answer prompts only to fail on an unsupported framework.
|
|
229
|
+
|
|
230
|
+
## Additional resources
|
|
231
|
+
|
|
232
|
+
- **`references/cli-reference.md`** — the deploy/login flags this skill uses, the
|
|
233
|
+
`login ... --json` JSON shapes, and the on-disk artifact signatures that
|
|
234
|
+
confirm each adapter and output root.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# @payloadcms/figma CLI reference (deploy-to-figma)
|
|
2
|
+
|
|
3
|
+
Exact contracts the orchestration depends on. Source of truth is the CLI itself
|
|
4
|
+
(`payload/payload-plugin` in figma/figma); this file mirrors the flags and shapes
|
|
5
|
+
the skill reads. If something is unclear, run the command and inspect the raw
|
|
6
|
+
output rather than guessing.
|
|
7
|
+
|
|
8
|
+
The CLI does **not** inspect the project — there is no `deploy --inspect` and no
|
|
9
|
+
project-inspection JSON API. The agent classifies the deploy shape from evidence
|
|
10
|
+
(see `SKILL.md` Steps 2–3) and hands the CLI an explicit `--adapter` and
|
|
11
|
+
`--output`.
|
|
12
|
+
|
|
13
|
+
## Classifying the deploy shape (agent-driven)
|
|
14
|
+
|
|
15
|
+
Detect the shape yourself from files on disk. Do **not** call `@payloadcms/figma`
|
|
16
|
+
to detect it.
|
|
17
|
+
|
|
18
|
+
| Evidence | adapter | typical output root |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| Next.js — `next` dep, `next.config.*`, or a `next build` script | `nextjs` | `.next` |
|
|
21
|
+
| Nitro / Nuxt / TanStack Start / other evidenced Nitro output | `nitro` | `.output` |
|
|
22
|
+
| Built Vite single-page app | `vite` | `dist` |
|
|
23
|
+
| Simple static folder — `index.html` + CSS/JS/assets, no build (no `package.json` OK) | `vite` | the folder itself (often `.`) |
|
|
24
|
+
|
|
25
|
+
Framework config hints: Next.js `distDir` (`next.config.*`), Vite `build.outDir`
|
|
26
|
+
(`vite.config.*`), Nitro/Nuxt `output.dir` (`nitro.config.*` / `nuxt.config.*`).
|
|
27
|
+
Custom output dirs mean you must confirm the real root against artifacts below.
|
|
28
|
+
|
|
29
|
+
### On-disk artifact signatures (confirm before deploy)
|
|
30
|
+
|
|
31
|
+
After building (or for a static folder, as-is), confirm the output **root** by
|
|
32
|
+
what it contains:
|
|
33
|
+
|
|
34
|
+
- **Next.js** — root contains `BUILD_ID` **and** standalone server output. Pass
|
|
35
|
+
the root such as `.next`; **never** `.next/standalone`.
|
|
36
|
+
- **Nitro** — root contains `server/index.mjs` (typically `.output`).
|
|
37
|
+
- **Vite / static** — root contains `index.html` (typically `dist`; a static
|
|
38
|
+
folder may be `.`).
|
|
39
|
+
|
|
40
|
+
If the build fails or the artifacts don't match the classified shape, **stop** —
|
|
41
|
+
do not pass an unverified `--output`.
|
|
42
|
+
|
|
43
|
+
## Building
|
|
44
|
+
|
|
45
|
+
Run the target package's build **from the target folder**, before auth, with
|
|
46
|
+
`FIGMA_EXTRACT_SCHEDULES=true`. Choose the package manager by searching the
|
|
47
|
+
target folder **and its ancestors** (up to the repo/monorepo root) — the
|
|
48
|
+
`packageManager` field and the lockfile often live at the workspace root, not
|
|
49
|
+
the target package. Precedence: nearest `packageManager` field → nearest
|
|
50
|
+
lockfile (`pnpm-lock.yaml`→pnpm, `package-lock.json`→npm, `yarn.lock`→yarn,
|
|
51
|
+
`bun.lockb`→bun) → available tooling. Even so, run the build itself from the
|
|
52
|
+
target package folder. Static folders skip the build.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
FIGMA_EXTRACT_SCHEDULES=true npm run build
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## `login --headless --json`
|
|
59
|
+
|
|
60
|
+
Starts (or short-circuits) a resumable login without a live terminal.
|
|
61
|
+
|
|
62
|
+
Already authenticated:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{ "status": "authenticated", "userId": "..." }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Authorization required:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"status": "authorization_required",
|
|
73
|
+
"authorizationUrl": "https://www.figma.com/oauth?...",
|
|
74
|
+
"sessionId": "sess_...",
|
|
75
|
+
"expiresAt": 1730000000000
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## `login --complete <sessionId> --callback-url '<url>' --json`
|
|
80
|
+
|
|
81
|
+
Completes a pending headless login using the full redirect URL the browser
|
|
82
|
+
landed on (`http://localhost:<port>/callback?code=...&state=...`). Returns:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{ "status": "authenticated", "userId": "..." }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Treat the callback URL as a one-time secret: pass it once, never echo or persist it.
|
|
89
|
+
|
|
90
|
+
## Infrastructure environment
|
|
91
|
+
|
|
92
|
+
When the user's request contains “Figma staging” (case-insensitive), append
|
|
93
|
+
`--infra-env staging` to every CLI command, including login, login completion,
|
|
94
|
+
deploy, and deploy retries. Otherwise omit the flag.
|
|
95
|
+
|
|
96
|
+
## `deploy` flags used by this skill
|
|
97
|
+
|
|
98
|
+
The deploy command is always explicit — the agent supplies the verified adapter
|
|
99
|
+
and output root and skips the build (it already ran, or the folder is static):
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx @payloadcms/figma@alpha deploy -y --skip-build --adapter <nextjs|nitro|vite> --output <root>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
| Flag | Purpose |
|
|
106
|
+
| --- | --- |
|
|
107
|
+
| `-y`, `--yes` | Non-interactive; safe project-creation defaults |
|
|
108
|
+
| `--infra-env staging` | Target Figma staging when explicitly requested |
|
|
109
|
+
| `--skip-build` | Always passed — deploy the artifact as-is, never rebuild |
|
|
110
|
+
| `--adapter <name>` | `nextjs` \| `vite` \| `nitro` — the shape you classified |
|
|
111
|
+
| `--output <path>` | The exact, verified build output root |
|
|
112
|
+
| `--name <name>` | Project name (uninitialized project creation) |
|
|
113
|
+
| `--description <text>` | Project description (uninitialized) |
|
|
114
|
+
| `--subdomain <sub>` | Requested subdomain (uninitialized) |
|
|
115
|
+
| `--workspace <planKey>` | Workspace plan key (uninitialized; also the retry flag) |
|
|
116
|
+
| `--region <region>` | Region, e.g. `us-east-1` (uninitialized) |
|
|
117
|
+
|
|
118
|
+
Initialization is detected only by a nonempty `FIGMA_PROJECT_ID` in `target/.env`
|
|
119
|
+
(never printed). Initialized projects pass no creation flags.
|
|
120
|
+
|
|
121
|
+
## Deterministic deploy retry
|
|
122
|
+
|
|
123
|
+
When multiple eligible workspaces exist and none is a default, non-interactive
|
|
124
|
+
deploy fails with:
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
Multiple eligible Figma workspaces. Pass --workspace <plan-key>. Available: <Name> (<plan-key>), ...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Re-run the identical command with `--workspace <plan-key>` for the chosen
|
|
131
|
+
workspace. An invalid `--workspace` value fails with:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
Workspace plan key "<key>" is not eligible. Available: <Name> (<plan-key>), ...
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Success output
|
|
138
|
+
|
|
139
|
+
On success the CLI prints:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
URL: https://<subdomain>.<domain>
|
|
143
|
+
This usually takes 2-3 minutes to complete.
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Extract the `URL:` line as the deployed address.
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type arg from 'arg';
|
|
2
2
|
export interface Args extends arg.Spec {
|
|
3
3
|
'--adapter': StringConstructor;
|
|
4
|
+
'--callback-url': StringConstructor;
|
|
5
|
+
'--complete': StringConstructor;
|
|
4
6
|
'--debug': BooleanConstructor;
|
|
7
|
+
'--description': StringConstructor;
|
|
5
8
|
'--dry-run': BooleanConstructor;
|
|
6
9
|
'--env': StringConstructor;
|
|
7
10
|
'--environment': string;
|
|
8
11
|
'--force': BooleanConstructor;
|
|
12
|
+
'--global': BooleanConstructor;
|
|
13
|
+
'--headless': BooleanConstructor;
|
|
9
14
|
'--help': BooleanConstructor;
|
|
10
15
|
'--id': StringConstructor;
|
|
11
16
|
'--infra-env': StringConstructor;
|
|
@@ -13,7 +18,11 @@ export interface Args extends arg.Spec {
|
|
|
13
18
|
'--logout': BooleanConstructor;
|
|
14
19
|
'--name': StringConstructor;
|
|
15
20
|
'--output': StringConstructor;
|
|
21
|
+
'--project': BooleanConstructor;
|
|
22
|
+
'--region': StringConstructor;
|
|
23
|
+
'--subdomain': StringConstructor;
|
|
16
24
|
'--template': StringConstructor;
|
|
25
|
+
'--workspace': StringConstructor;
|
|
17
26
|
'--yes': BooleanConstructor;
|
|
18
27
|
'-e': string;
|
|
19
28
|
'-f': string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { IndentationText, Node, Project, SyntaxKind } from 'ts-morph';
|
|
4
|
+
import { ensurePnpmWorkspace } from './pnpm-builds.js';
|
|
4
5
|
const RUN_SH_CONTENT = `#!/bin/bash -x
|
|
5
6
|
|
|
6
7
|
[ ! -d '/tmp/cache' ] && mkdir -p /tmp/cache
|
|
@@ -19,21 +20,10 @@ NODE_ENV=production exec node server.js
|
|
|
19
20
|
await fs.chmod(runShPath, 0o755);
|
|
20
21
|
// 2. Modify next config to add standalone output
|
|
21
22
|
await addNextConfigProperties(projectPath);
|
|
22
|
-
// 3.
|
|
23
|
-
const npmrcPath = path.join(projectPath, '.npmrc');
|
|
24
|
-
let npmrcContent = '';
|
|
25
|
-
try {
|
|
26
|
-
npmrcContent = await fs.readFile(npmrcPath, 'utf-8');
|
|
27
|
-
} catch {
|
|
28
|
-
// File doesn't exist, start fresh
|
|
29
|
-
}
|
|
30
|
-
if (!npmrcContent.includes('node-linker=hoisted')) {
|
|
31
|
-
npmrcContent += npmrcContent && !npmrcContent.endsWith('\n') ? '\n' : '';
|
|
32
|
-
npmrcContent += 'node-linker=hoisted\n';
|
|
33
|
-
await fs.writeFile(npmrcPath, npmrcContent, 'utf-8');
|
|
34
|
-
}
|
|
35
|
-
// 4. Add lambda:buildzip script to package.json
|
|
23
|
+
// 3. Add lambda:buildzip script to package.json
|
|
36
24
|
await addLambdaBuildScript(projectPath, packageManager);
|
|
25
|
+
// 4. Write pnpm-workspace.yaml (hoisted linker + build approvals)
|
|
26
|
+
await ensurePnpmWorkspace(projectPath);
|
|
37
27
|
}
|
|
38
28
|
/**
|
|
39
29
|
* Find the Next.js config file, checking TS extensions first
|
package/dist/utils/messages.js
CHANGED
|
@@ -14,6 +14,7 @@ export function helpMessage() {
|
|
|
14
14
|
${pc.cyan('logout')} Clear all stored tokens
|
|
15
15
|
${pc.cyan('list-tokens')} Show stored token information
|
|
16
16
|
${pc.cyan('init')} Initialize a Figma CMS project
|
|
17
|
+
${pc.cyan('setup-agent')} Install or update the Figma deploy skill
|
|
17
18
|
${pc.cyan('bootstrap')} Print bootstrap info (tenant IDs, OAuth creds) for a project
|
|
18
19
|
${pc.cyan('debug')} Show debug info for troubleshooting
|
|
19
20
|
${pc.cyan('env')} Switch active environment
|
|
@@ -31,16 +32,20 @@ export function helpMessage() {
|
|
|
31
32
|
${pc.bold('AUTHENTICATION')}
|
|
32
33
|
|
|
33
34
|
${pc.cyan('@payloadcms/figma login')} Authenticate with Figma
|
|
35
|
+
${pc.cyan('@payloadcms/figma login --headless --json')} Start resumable login for agents
|
|
36
|
+
${pc.cyan('@payloadcms/figma login --complete <id> --callback-url <url>')} Complete resumable login
|
|
37
|
+
${pc.dim('--json')} Emit machine-readable login status
|
|
34
38
|
${pc.cyan('@payloadcms/figma logout')} Clear tokens for current environment
|
|
35
39
|
${pc.cyan('@payloadcms/figma list-tokens')} Display stored OAuth and project tokens
|
|
36
40
|
|
|
37
41
|
${pc.bold('INIT COMMAND')}
|
|
38
42
|
|
|
39
|
-
${pc.cyan('@payloadcms/figma init
|
|
43
|
+
${pc.cyan('@payloadcms/figma init')} Create and initialize project
|
|
44
|
+
${pc.cyan('@payloadcms/figma init --id <cms-resource-id>')} Connect existing project
|
|
40
45
|
${pc.cyan('@payloadcms/figma init --id <id> --env staging')} Initialize for specific environment
|
|
41
46
|
${pc.dim('--name, -n <name>')} Set project directory name (skips prompt)
|
|
42
47
|
${pc.dim('--force')} Force reconfiguration of existing project
|
|
43
|
-
${pc.dim('--no-
|
|
48
|
+
${pc.dim('--no-agent')} Skip writing AI agent config files (AGENTS.md, CLAUDE.md)
|
|
44
49
|
${pc.dim('--template, -t <spec>')} Override scaffold template (e.g. main:website, owner/repo#ref:path)
|
|
45
50
|
${pc.dim('--payload-version <tag|version>')} Core Payload npm dist-tag or version (default canary; e.g. latest, 4.0.0-canary.16)
|
|
46
51
|
|
|
@@ -58,14 +63,28 @@ export function helpMessage() {
|
|
|
58
63
|
${pc.bold('DEPLOY COMMAND')}
|
|
59
64
|
|
|
60
65
|
${pc.cyan('@payloadcms/figma deploy')} Deploy your project to Figma
|
|
66
|
+
${pc.dim(' Creates a project when not initialized')}
|
|
61
67
|
${pc.dim('--id <project-id>')} Override FIGMA_PROJECT_ID
|
|
62
68
|
${pc.dim('--env <environment>')} Override FIGMA_ENVIRONMENT_NAME
|
|
63
|
-
${pc.dim('--yes, -y')} Skip
|
|
69
|
+
${pc.dim('--yes, -y')} Skip prompts; use safe defaults for project creation
|
|
70
|
+
${pc.dim('--name <name>')} New project name (default: package/directory name)
|
|
71
|
+
${pc.dim('--description <description>')} New project description (default: <name> project)
|
|
72
|
+
${pc.dim('--subdomain <subdomain>')} New project subdomain (default: generated from name)
|
|
73
|
+
${pc.dim('--workspace <plan-key>')} Workspace plan key (default workspace if omitted)
|
|
74
|
+
${pc.dim('--region <region>')} New project region (default: us-east-1 non-interactively)
|
|
64
75
|
${pc.dim('--skip-build')} Skip building and use existing build
|
|
65
76
|
${pc.dim('--skip-size-check')} Skip the client-side bundle size check
|
|
66
77
|
${pc.dim('--adapter <nextjs|nitro|vite>')} Override framework detection
|
|
67
78
|
${pc.dim('--output <path>')} Exact framework build output root
|
|
68
79
|
|
|
80
|
+
${pc.bold('SETUP AGENT COMMAND')}
|
|
81
|
+
|
|
82
|
+
${pc.cyan('@payloadcms/figma setup-agent')} Prompt for global or project installation
|
|
83
|
+
${pc.cyan('@payloadcms/figma setup-agent --global')} Install/update globally
|
|
84
|
+
${pc.cyan('@payloadcms/figma setup-agent --project')} Install/update in the current project
|
|
85
|
+
${pc.dim('--yes, -y')} Skip skills installer prompts
|
|
86
|
+
${pc.dim('Non-interactive use requires --global or --project.')}
|
|
87
|
+
|
|
69
88
|
${pc.bold('UPGRADE COMMAND')}
|
|
70
89
|
|
|
71
90
|
${pc.cyan('@payloadcms/figma upgrade')} Run all upgrade migrations
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type PayloadGenerateResult = {
|
|
2
|
+
error: string;
|
|
3
|
+
ok: false;
|
|
4
|
+
} | {
|
|
5
|
+
ok: true;
|
|
6
|
+
};
|
|
7
|
+
/** Never throws. */
|
|
8
|
+
export declare function generateImportMap(projectPath: string): Promise<PayloadGenerateResult>;
|
|
9
|
+
/** Never throws. */
|
|
10
|
+
export declare function generateTypes(projectPath: string): Promise<PayloadGenerateResult>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import spawn from 'cross-spawn';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
// buildFigmaConfig throws without a resolvable environmentId/contentSystemId,
|
|
4
|
+
// which an unauthenticated init lacks. It reads these env vars before the
|
|
5
|
+
// bootstrap cache, so injecting them avoids the throw. Always inject the
|
|
6
|
+
// placeholder (not the real env) for deterministic behavior; the generated
|
|
7
|
+
// artifacts are ID-independent, so the value never affects output.
|
|
8
|
+
const GENERATE_PLACEHOLDER = 'figma-generate-placeholder';
|
|
9
|
+
/** Runs `payload <subcommand>` via the project's local binary. Never throws. */ function runPayloadGenerate(projectPath, subcommand) {
|
|
10
|
+
const bin = path.join(projectPath, 'node_modules', '.bin', 'payload');
|
|
11
|
+
return new Promise((resolve)=>{
|
|
12
|
+
const child = spawn(bin, [
|
|
13
|
+
subcommand
|
|
14
|
+
], {
|
|
15
|
+
cwd: projectPath,
|
|
16
|
+
env: {
|
|
17
|
+
...process.env,
|
|
18
|
+
FIGMA_CONTENT_API_CONTENT_SYSTEM_ID: GENERATE_PLACEHOLDER,
|
|
19
|
+
FIGMA_EID: GENERATE_PLACEHOLDER
|
|
20
|
+
},
|
|
21
|
+
stdio: 'pipe'
|
|
22
|
+
});
|
|
23
|
+
// Drain both pipes. An unread stdout buffer fills and blocks the child,
|
|
24
|
+
// hanging init; stdout also carries diagnostics on some failures.
|
|
25
|
+
let stderr = '';
|
|
26
|
+
let stdout = '';
|
|
27
|
+
child.stderr?.on('data', (data)=>{
|
|
28
|
+
stderr += data.toString();
|
|
29
|
+
});
|
|
30
|
+
child.stdout?.on('data', (data)=>{
|
|
31
|
+
stdout += data.toString();
|
|
32
|
+
});
|
|
33
|
+
child.on('close', (code)=>{
|
|
34
|
+
if (code === 0) {
|
|
35
|
+
resolve({
|
|
36
|
+
ok: true
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
const output = stderr.trim() || stdout.trim();
|
|
40
|
+
resolve({
|
|
41
|
+
error: output || `payload ${subcommand} exited with code ${code}`,
|
|
42
|
+
ok: false
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
child.on('error', (error)=>{
|
|
47
|
+
resolve({
|
|
48
|
+
error: error.message,
|
|
49
|
+
ok: false
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** Never throws. */ export function generateImportMap(projectPath) {
|
|
55
|
+
return runPayloadGenerate(projectPath, 'generate:importmap');
|
|
56
|
+
}
|
|
57
|
+
/** Never throws. */ export function generateTypes(projectPath) {
|
|
58
|
+
return runPayloadGenerate(projectPath, 'generate:types');
|
|
59
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write init's pnpm-workspace.yaml: hoisted node linker (the Lambda runtime needs a
|
|
3
|
+
* flat node_modules) plus build approvals, migrating off the now-ignored package.json
|
|
4
|
+
* `pnpm.onlyBuiltDependencies`. Written for every project so an npx/npm scaffold still
|
|
5
|
+
* installs cleanly when the user later switches to pnpm.
|
|
6
|
+
*/
|
|
7
|
+
export declare function ensurePnpmWorkspace(projectPath: string): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Set each build `true` under `allowBuilds` and drop it from any `ignoredBuiltDependencies`
|
|
10
|
+
* denylist. Pure and idempotent. pnpm v11 reads approvals only from pnpm-workspace.yaml.
|
|
11
|
+
*/
|
|
12
|
+
export declare function upsertBuildApprovals(content: string, builds: string[]): string;
|
|
13
|
+
/** Set a top-level `key: value` scalar, replacing any existing one. Pure and idempotent. */
|
|
14
|
+
export declare function upsertTopLevelScalar(content: string, key: string, value: string): string;
|