aem-eds-kit 0.4.25 → 0.4.30
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/CHANGELOG.md +39 -0
- package/README.md +113 -23
- package/dist/bin/eds.js +276 -145
- package/package.json +6 -2
- package/samples/hero.svg +35 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,17 +7,56 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
9
|
### Changed
|
|
10
|
+
- **`block from-design` now fetches the design once into a cached snapshot,
|
|
11
|
+
then generates from it** (fetch → cache → generate). The CLI resolves the
|
|
12
|
+
design via the cheapest adapter - local SVG/PNG export, a cached snapshot
|
|
13
|
+
(`tmp/eds-cli/design-cache/`), the **Figma REST** API (with a token), or a
|
|
14
|
+
**single** Figma MCP call the agent caches - so retries and refine passes
|
|
15
|
+
never re-fetch. Replaces the old flow where the agent made several MCP calls
|
|
16
|
+
mid-generation. New `src/lib/figma/rest.ts` and `design-source.ts`.
|
|
17
|
+
- **MCP usage cut to one call per block.** The prompt now uses only
|
|
18
|
+
`get_design_context` (dropped `get_variable_defs`; `get_screenshot` is opt-in
|
|
19
|
+
via `--screenshot`) - the Figma Dev Mode MCP server meters tool calls per plan
|
|
20
|
+
(Starter/View/Collab: ~6-20/month). Set a Figma token to skip MCP via REST.
|
|
21
|
+
- **Block generation defaults to the fastest model (Haiku)**, overridable with
|
|
22
|
+
`model` in config - block codegen is structured, bounded work.
|
|
23
|
+
- **`eds block preview` no longer auto-launches.** After `from-design` you get a
|
|
24
|
+
menu to refine the block or open the preview on demand; `--no-serve` became
|
|
25
|
+
`--serve` (opt-in, non-interactive runs only).
|
|
26
|
+
- **Shorter interactive-menu labels** (details moved to each choice's
|
|
27
|
+
description).
|
|
10
28
|
- **Smaller published package (~206 kB → ~73 kB packed; 808 kB → ~220 kB
|
|
11
29
|
unpacked).** The build no longer ships a source map (it was ~60% of the
|
|
12
30
|
package; re-enable ad hoc with `tsup --sourcemap`) and now minifies the single
|
|
13
31
|
bundled binary (`dist/bin/eds.js` 265 kB → ~170 kB).
|
|
14
32
|
|
|
15
33
|
### Fixed
|
|
34
|
+
- **Block preview blank-screen cases.** The harness now (a) reduces a full-HTML
|
|
35
|
+
`_<name>.preview.html` mock to its `<body>` contents, (b) reveals the body past
|
|
36
|
+
the EDS `body.appear` visibility gate (which `scripts.js` would normally flip),
|
|
37
|
+
and (c) loads the block script via a defensive dynamic `import()` so a bad
|
|
38
|
+
import (e.g. a missing `scripts/*.js`) shows the authored markup instead of a
|
|
39
|
+
blank frame. The prompt now requires a bare preview fragment and self-contained
|
|
40
|
+
block JS.
|
|
41
|
+
- **`eds block preview header|footer`** now warns that these are page chrome and
|
|
42
|
+
can't render standalone (they fetch the nav/footer fragment and need the full
|
|
43
|
+
page runtime).
|
|
16
44
|
- Removed the dangling `main`/`types` fields that pointed at a never-built
|
|
17
45
|
`dist/index.js` (a bare `import "aem-eds-kit"` would have failed) - the package
|
|
18
46
|
is a CLI, exposed via its `bin`.
|
|
19
47
|
|
|
20
48
|
### Added
|
|
49
|
+
- **`eds block preview` with no name → a live gallery of every content block**,
|
|
50
|
+
each in its own width-honest iframe. Routes are computed per request, so a
|
|
51
|
+
block generated while the gallery is open appears on the next reload
|
|
52
|
+
(header/footer are skipped - page chrome can't render standalone). New
|
|
53
|
+
`buildGallery` + a dynamic request handler on the preview server.
|
|
54
|
+
- **`block from-design` accepts a local SVG/PNG export** (`eds block from-design
|
|
55
|
+
./hero.svg`) - reads the design straight from disk, no network and no MCP.
|
|
56
|
+
- **Figma REST path** via a Personal Access Token (`FIGMA_TOKEN` env or
|
|
57
|
+
`figma.token` config, scope `file_content:read`) - a quota separate from the
|
|
58
|
+
MCP tool-call limit. New flags `--mcp` (force MCP) and `--refresh` (ignore the
|
|
59
|
+
cache).
|
|
21
60
|
- **`block from-design` records the design's frame widths** in the block's
|
|
22
61
|
`.eds-meta.json` (`breakpoints`), so `eds block preview` is width-honest at the
|
|
23
62
|
**real design widths**, not a fixed device set. The agent writes the widths it
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
**Turn a design into an EDS block** - JS, CSS and a Universal Editor model - without leaving your terminal.
|
|
12
12
|
|
|
13
|
-
`aem-eds-kit` gives you the `eds` command. Paste a design link - Figma,
|
|
13
|
+
`aem-eds-kit` gives you the `eds` command. Paste a design link - a Figma URL, or a Framer / Google Stitch page - and it hands the design to the AI agent you already use (Claude Code, Cursor or Codex), which writes production-ready code straight into your repo. Figma is read through MCP or the REST API; Framer and Stitch render real HTML, so they're **scraped with headless Chromium** (no token needed). It also scaffolds blocks, previews them in your browser, and keeps your project healthy with a few quick audits.
|
|
14
14
|
|
|
15
15
|
It lives next to `@adobe/aem-cli` (your local dev server) and handles everything around it.
|
|
16
16
|
|
|
@@ -56,6 +56,26 @@ eds block from-design "<figma-url>" --name hero
|
|
|
56
56
|
|
|
57
57
|
`eds` runs on your machine, not on your site - it never adds a single byte to what your visitors download.
|
|
58
58
|
|
|
59
|
+
## Try it in 30 seconds (no Figma account, no token)
|
|
60
|
+
|
|
61
|
+
From inside an EDS project (or spin a throwaway one up with `eds sandbox new demo`):
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
eds block from-design --sample --name hero --dry-run # see the prompt - zero setup
|
|
65
|
+
eds block from-design --sample --name hero # generate it with your AI agent
|
|
66
|
+
eds block preview hero # see it live in the browser
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`--sample` uses a **bundled "Kiri Bloom" hero design**, read straight from disk - **no Figma token, no MCP call, no network**. (`--dry-run` needs no AI agent either - it just prints the prompt.)
|
|
70
|
+
|
|
71
|
+
Ready for the real thing? Point it at the official **Kiri Bloom AEM EDS Kit** training file in Figma:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
eds block from-design \
|
|
75
|
+
"https://www.figma.com/design/vwlEKTFhcrlwuA8dRgN5SD/Kiri-Bloom-AEM-EDS-Kit-Example?node-id=0-1" \
|
|
76
|
+
--name hero
|
|
77
|
+
```
|
|
78
|
+
|
|
59
79
|
## Interactive mode
|
|
60
80
|
|
|
61
81
|
Run `eds` with no command and it opens an **interactive menu** that walks you through every feature (set up the project, generate a block from a design, migrate a classic AEM component, scaffold, create a block, add an integration, preview, Admin API, audits, Figma setup). Most commands are also interactive on their own when you omit arguments - e.g. `eds init`, `eds block from-design` (wizard), `eds migrate component`, `eds scaffold`, `eds integrate`, `eds preview`. Flags and subcommands still work for CI / power users.
|
|
@@ -83,6 +103,10 @@ eds scaffold blocks
|
|
|
83
103
|
# Add a third-party service (GTM, GA4, chat…)
|
|
84
104
|
eds integrate
|
|
85
105
|
|
|
106
|
+
# QA a block before you ship it (visual regression + content/a11y)
|
|
107
|
+
eds block test hero
|
|
108
|
+
eds block check hero
|
|
109
|
+
|
|
86
110
|
# Audit your project
|
|
87
111
|
eds doctor
|
|
88
112
|
```
|
|
@@ -103,7 +127,7 @@ eds scaffold ue
|
|
|
103
127
|
eds scaffold helpers
|
|
104
128
|
|
|
105
129
|
# 4. Build blocks - from a design, from scratch, or migrated from classic AEM
|
|
106
|
-
eds block from-design # paste a Figma/Stitch
|
|
130
|
+
eds block from-design # paste a Figma URL, a Framer/Stitch page, or a local SVG
|
|
107
131
|
# eds block create hero
|
|
108
132
|
# eds migrate component ./components/hero
|
|
109
133
|
|
|
@@ -266,28 +290,49 @@ The generated `_<name>.json` uses the EDS block-plugin (xwalk) format (`definiti
|
|
|
266
290
|
|
|
267
291
|
### `eds block from-design [design-url]`
|
|
268
292
|
|
|
269
|
-
Translates a design - **Figma, Google Stitch
|
|
293
|
+
Translates a design - **a Figma URL, a Framer / Google Stitch page, or a local SVG/PNG export** - into an EDS block. Run with **no URL** for a step-by-step wizard (design source, name, link, content source, UE model, screenshot, run mode). It builds a prompt with EDS conventions + your project's design tokens and hands it to your AI agent (Claude Code, Cursor, or Codex). *(This was `from-figma` before it went design-agnostic; Figma is the most battle-tested source and stays pixel-perfect.)*
|
|
294
|
+
|
|
295
|
+
**Figma vs. web sources.** Figma paints to a WebGL canvas, so it's read through the **REST API** (with a token) or **MCP**. Framer and Google Stitch render **real HTML**, so `eds` **scrapes** them with headless Chromium — reading computed layout, typography, colours and geometry straight off the page (no token, no MCP). Canva and Sketch are canvas/image-based and aren't scrapeable — export a frame and pass it as a local SVG/PNG. The provider is detected from the URL host, or set with `--provider`.
|
|
296
|
+
|
|
297
|
+
**Fetch → cache → generate.** `eds` resolves the design **once** into a snapshot, then the agent generates from it — so retries and refine passes never re-fetch. It picks the cheapest adapter automatically:
|
|
270
298
|
|
|
271
|
-
|
|
299
|
+
1. **Local file** — pass a path to an SVG/PNG export (`eds block from-design ./hero.svg`) → read from disk, no network.
|
|
300
|
+
2. **Cache** — a snapshot already fetched for this design (`tmp/eds-cli/design-cache/`) is reused.
|
|
301
|
+
3. **Web scrape (Framer / Stitch)** — the live page is rendered in headless Chromium and its computed layout/styles are extracted. Needs Playwright + a browser: `npx playwright install chromium`.
|
|
302
|
+
4. **Figma REST** — if a Figma token is set, `eds` fetches the node itself and embeds a compact design spec. Separate, generous quota; **does not touch the MCP limit**.
|
|
303
|
+
5. **Figma MCP** — fallback: the agent makes **one** `get_design_context` call and caches it.
|
|
304
|
+
|
|
305
|
+
The agent then generates pixel-perfect code (JS + CSS) **and its Universal Editor model** by default, with lightweight **placeholders** for not-yet-authored content. You see a **live, colour-coded log** with per-phase timings. On success you get a **menu** — refine the block with another pass, open the live preview, or finish (preview is **opt-in**, never auto-launched).
|
|
306
|
+
|
|
307
|
+
> **Figma MCP limits:** the Dev Mode MCP server is metered per plan (Starter / View / Collab seats: ~6–20 **tool calls a month**). `eds` uses **one** MCP call per block and caches it; set a Figma token to skip MCP entirely via REST. See [How Figma integration works](#how-figma-integration-works).
|
|
272
308
|
|
|
273
309
|
```bash
|
|
274
310
|
eds block from-design # interactive wizard
|
|
275
|
-
eds block from-design "<figma-url>" --name hero # non-interactive
|
|
311
|
+
eds block from-design "<figma-url>" --name hero # non-interactive (REST if a token is set, else MCP)
|
|
312
|
+
eds block from-design "<framer-url>" --name hero # Framer/Stitch → scraped with headless Chromium
|
|
313
|
+
eds block from-design ./hero.svg --name hero # from a local export (no network)
|
|
314
|
+
eds block from-design --sample --name hero # bundled Kiri Bloom sample (no token, no MCP)
|
|
276
315
|
eds block from-design "<figma-url>" --dry-run # just build the prompt
|
|
277
316
|
```
|
|
278
317
|
|
|
279
318
|
| Flag | Description |
|
|
280
319
|
|---|---|
|
|
281
320
|
| `--name <name>` | Override the inferred block name |
|
|
321
|
+
| `--provider <type>` | Design source: `figma` \| `framer` \| `stitch` (else detected from the URL) |
|
|
282
322
|
| `--source <type>` | Content source: `document` \| `ue` \| `cf` \| `mixed` |
|
|
283
323
|
| `--widths <list>` | Design frame widths for preview breakpoints (e.g. `390,768,1440`) |
|
|
284
324
|
| `--agent <type>` | Force `claude` \| `cursor` \| `codex` \| `none` |
|
|
285
325
|
| `--dry-run` | Build the prompt only |
|
|
286
326
|
| `--no-ue-model` | Skip the Universal Editor model |
|
|
287
|
-
| `--
|
|
288
|
-
| `--
|
|
327
|
+
| `--screenshot` | Add a screenshot MCP call for a pixel check (opt-in — costs a call) |
|
|
328
|
+
| `--mcp` | Force the Figma MCP adapter even when a REST token is set |
|
|
329
|
+
| `--refresh` | Ignore the cached snapshot and re-fetch |
|
|
330
|
+
| `--sample` | Use the bundled Kiri Bloom sample design (no URL, token or MCP) |
|
|
331
|
+
| `--serve` | Auto-start the live preview (non-interactive runs only) |
|
|
289
332
|
| `--yes` | Skip confirmation prompts |
|
|
290
333
|
|
|
334
|
+
Set a **Figma Personal Access Token** (scope `file_content:read`) to use the REST path — via `FIGMA_TOKEN` env or `figma.token` in config. The block generation model defaults to the fastest (Haiku); override with `model` in config.
|
|
335
|
+
|
|
291
336
|
The generated block records the **design's frame widths** in its `.eds-meta.json` (`breakpoints`), so `eds block preview` shows it at the real design widths rather than a fixed device set. The agent writes the widths it reads from the design; `--widths` overrides them, and 375/768/1280 is only the fallback.
|
|
292
337
|
|
|
293
338
|
**Supported Figma URL formats:**
|
|
@@ -313,16 +358,55 @@ eds block list
|
|
|
313
358
|
eds block list --json # machine-readable output
|
|
314
359
|
```
|
|
315
360
|
|
|
316
|
-
### `eds block preview
|
|
361
|
+
### `eds block preview [name]`
|
|
362
|
+
|
|
363
|
+
Serves a **live, breakpoint-switchable preview** in your browser - no build, no files written to your project (the harness is served from memory). A dropdown switches widths inside a width-honest iframe, and **edits live-reload** the browser (the server watches the block folder).
|
|
317
364
|
|
|
318
|
-
|
|
365
|
+
Run it **with no name** for a **gallery** of every content block, each in its own iframe. Routes are computed per request, so a block generated while the gallery is open **appears on the next reload** (header/footer are skipped — they're page chrome and can't render standalone).
|
|
319
366
|
|
|
320
367
|
```bash
|
|
321
|
-
eds block preview
|
|
368
|
+
eds block preview # gallery of all blocks
|
|
369
|
+
eds block preview hero # a single block
|
|
322
370
|
eds block preview hero --widths 375,768,1280 # custom breakpoints
|
|
323
371
|
eds block preview hero --port 9000 --no-open
|
|
324
372
|
```
|
|
325
373
|
|
|
374
|
+
### `eds block test [name]` · `eds block check [name]`
|
|
375
|
+
|
|
376
|
+
Two deterministic QA passes over a block's **rendered** DOM (no agent) - one block, or **all** of them when you omit the name. Both render the block in headless Chromium (Playwright), so install the browser once: `npx playwright install chromium`. Wire them into CI next to the audits - both exit non-zero on failure.
|
|
377
|
+
|
|
378
|
+
**`eds block test`** - **visual regression.** Screenshots each block at every breakpoint and diffs it (pixelmatch) against a committed baseline in `blocks/<name>/__snapshots__/`; it fails when the changed-pixel ratio crosses the threshold (default 1%) and writes the diff image to `tmp/eds-cli/visual-diff/`. `--update` (re)writes the baselines after an intended change. `--design` does a **design↔render** diff instead - the rendered block against its Figma design image (needs a Figma token and a Figma source in the block's `.eds-meta.json`).
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
eds block test # all blocks vs committed baselines
|
|
382
|
+
eds block test hero # one block
|
|
383
|
+
eds block test hero --update # (re)write baselines after an intended change
|
|
384
|
+
eds block test hero --design # rendered block vs its Figma design image
|
|
385
|
+
eds block test --threshold 0.02 # allow 2% changed pixels
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
| Flag | Description |
|
|
389
|
+
|---|---|
|
|
390
|
+
| `--update` | (Re)write baseline screenshots instead of comparing |
|
|
391
|
+
| `--threshold <ratio>` | Max changed-pixel ratio before failing (default `0.01` = 1%) |
|
|
392
|
+
| `--design` | Compare the rendered block against its Figma design image (needs a token) |
|
|
393
|
+
| `--widths <list>` | Breakpoint widths (e.g. `375,768,1280`) |
|
|
394
|
+
| `--port <port>` | Port for the internal preview server (default `8788`) |
|
|
395
|
+
|
|
396
|
+
**`eds block check`** - **content, link & a11y.** Renders each block (after `decorate()`) and flags missing image `alt`, missing image dimensions (CLS risk), links/buttons with no accessible name, empty `href`s and inline event handlers. Checks run at the widest breakpoint; it exits non-zero on any error, or on any warning with `--strict`.
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
eds block check # all blocks
|
|
400
|
+
eds block check hero # one block
|
|
401
|
+
eds block check --strict # fail on warnings too
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
| Flag | Description |
|
|
405
|
+
|---|---|
|
|
406
|
+
| `--strict` | Fail on warnings too, not just errors |
|
|
407
|
+
| `--widths <list>` | Breakpoint widths (the widest is used) |
|
|
408
|
+
| `--port <port>` | Port for the internal preview server (default `8789`) |
|
|
409
|
+
|
|
326
410
|
### `eds scaffold ue` · `eds scaffold blocks`
|
|
327
411
|
|
|
328
412
|
Scaffold Universal Editor components deterministically (no agent). `eds scaffold ue` writes/merges the three UE config files with the default-content components and a **`field-reference` block showing all 17 field types** + a multifield. `eds scaffold blocks` scaffolds standard Block Collection blocks (hero, cards, columns, accordion, embed) with UE models. Run `eds scaffold` for an interactive picker.
|
|
@@ -449,23 +533,26 @@ The vendored framework (`scripts/aem.js` / `lib-franklin.js`) is never flagged.
|
|
|
449
533
|
|
|
450
534
|
## How Figma integration works
|
|
451
535
|
|
|
452
|
-
|
|
536
|
+
The design is fetched **once** into a cached snapshot, then the agent generates from it. Separating the fetch from the generation means retries and refine passes never re-fetch, and the snapshot is inspectable (`tmp/eds-cli/design-cache/`). `eds` picks the cheapest adapter available:
|
|
453
537
|
|
|
454
538
|
```
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
└──────────┘
|
|
539
|
+
┌─ local SVG/PNG ─┐
|
|
540
|
+
├─ cache hit ──────┤ design.json ┌─────────────┐ block files
|
|
541
|
+
design reference ──┼─ Figma REST ─────┼───→ (cached) ───────→│ Claude Code │ ───────────────→ repo
|
|
542
|
+
(url / file) └─ Figma MCP ──────┘ snapshot │ /Cursor/Codex│
|
|
543
|
+
(1 call, agent dumps to cache) └─────────────┘
|
|
461
544
|
```
|
|
462
545
|
|
|
546
|
+
- **No token needed** for the MCP path — the agent uses its own Figma MCP connection and makes **one** `get_design_context` call per block (then caches it).
|
|
547
|
+
- **Set a Figma token** (`FIGMA_TOKEN` or `figma.token`) to use the **REST** path instead: `eds` fetches the node over HTTPS and embeds a compact spec — a **separate, far larger quota** than the MCP limit, so it works comfortably on Starter / Collab seats.
|
|
548
|
+
- **Local export** (`./file.svg|png`) reads straight from disk — zero network, best for vector/text-heavy frames.
|
|
549
|
+
|
|
463
550
|
The prompt includes:
|
|
464
|
-
-
|
|
465
|
-
- EDS block conventions (`decorate(block)`, vanilla JS, semantic HTML, full-width/mobile-first)
|
|
551
|
+
- The design data (embedded spec, local file, or a single-call MCP fetch) for the target node
|
|
552
|
+
- EDS block conventions (`decorate(block)`, vanilla JS, semantic HTML, full-width/mobile-first, self-contained JS)
|
|
466
553
|
- CSS custom properties from your `styles/styles.css`
|
|
467
|
-
- Universal Editor model generation (fields mapped from
|
|
468
|
-
- Lighthouse performance requirements +
|
|
554
|
+
- Universal Editor model generation (fields mapped from design layers/variants) - on by default
|
|
555
|
+
- Lighthouse performance requirements + a single structural self-verification pass
|
|
469
556
|
- Output file structure
|
|
470
557
|
|
|
471
558
|
## Configuration
|
|
@@ -475,9 +562,12 @@ Priority: CLI flags → env vars → `.edsrc.json` (project) → `~/.eds/config.
|
|
|
475
562
|
**`~/.eds/config.json`** (created by `eds figma setup`):
|
|
476
563
|
```json
|
|
477
564
|
{
|
|
478
|
-
"agent": "claude"
|
|
565
|
+
"agent": "claude",
|
|
566
|
+
"model": "haiku",
|
|
567
|
+
"figma": { "token": "figd_…" }
|
|
479
568
|
}
|
|
480
569
|
```
|
|
570
|
+
`model` sets the block-generation model (default: fastest / Haiku). `figma.token` (or the `FIGMA_TOKEN` env var) enables the REST fetch path — a Personal Access Token with scope `file_content:read`. Tokens are secrets; keep them out of the repo.
|
|
481
571
|
|
|
482
572
|
**`.edsrc.json`** (project root, optional):
|
|
483
573
|
```json
|
|
@@ -574,7 +664,7 @@ Tests use fixtures in `tests/fixtures/` - a sample EDS project and recorded Figm
|
|
|
574
664
|
|
|
575
665
|
## Roadmap
|
|
576
666
|
|
|
577
|
-
- **Design sources** -
|
|
667
|
+
- **Design sources** - Figma (REST/MCP), Framer and Google Stitch (headless-Chromium scrape) are wired; next is deepening the scrape extractor (multi-breakpoint capture, component/variant detection) and a generic `eds setup` in place of `eds figma setup`. Canva/Sketch stay on the local-export path (canvas/image — not scrapeable).
|
|
578
668
|
- **Screenshot-to-block** - build a block from a plain image (harder: no structured layout/measurements, so pixel-perfect is tougher).
|
|
579
669
|
- **Tokens & sync** - design variables → CSS custom properties, and incremental re-sync of an existing block (`--update`).
|
|
580
670
|
- **Headless & CI** - a direct MCP client (no agent needed) for CI/CD, plus `eds lighthouse`, `eds rum` and `eds migrate page`.
|