@relipa/ai-flow-kit 0.1.1-beta.0 → 0.1.1

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.
@@ -119,6 +119,39 @@ See: [Figma workflow guide](../../docs/common/workflows/figma.md)
119
119
 
120
120
  ---
121
121
 
122
+ ### Playwright (`playwright.json`)
123
+
124
+ Drive a real browser to explore selectors, verify flows, and capture evidence. Powers the `automation-testing` skill (Phase 3 — Explore).
125
+
126
+ **When to use:** Generating E2E UI tests. The skill uses MCP to read the live DOM (real selectors, not guessed) and screenshot each step, then emits durable `.spec.ts` files for CI.
127
+
128
+ **Setup:**
129
+ ```bash
130
+ aiflow init --adapter playwright
131
+ ```
132
+
133
+ **Requirements:**
134
+ - The web app under test must be running and reachable at `baseUrl`
135
+ - No API token needed
136
+ - First run downloads browsers via `npx playwright install` (one-time)
137
+
138
+ **Tools provided by `@playwright/mcp`:**
139
+ - `browser_navigate(url)` — open a page
140
+ - `browser_snapshot()` — accessibility tree (source of real selectors)
141
+ - `browser_click` / `browser_type` / `browser_fill` — interact with elements
142
+ - `browser_take_screenshot(path)` — capture evidence
143
+
144
+ **Usage:**
145
+ ```
146
+ /automation-testing baseUrl: http://localhost:3000 explore: true
147
+ ```
148
+
149
+ > **Hybrid principle:** MCP is for *exploration + evidence* only. It does not replace test files — the skill always emits committable `.spec.ts` so CI can re-run.
150
+
151
+ See: [automation-testing design](../../requirements/autotest/AutomationTestWorkflow.md)
152
+
153
+ ---
154
+
122
155
  ### Google Sheets (`google-sheets.json`)
123
156
 
124
157
  Connect to Google Sheets for loading task context.
@@ -0,0 +1,11 @@
1
+ {
2
+ "mcpServers": {
3
+ "playwright": {
4
+ "command": "npx",
5
+ "args": [
6
+ "-y",
7
+ "@playwright/mcp@latest"
8
+ ]
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,105 @@
1
+ # E2E Test Patterns (Playwright)
2
+
3
+ Reusable patterns the `automation-testing` skill applies when generating Page Objects and specs. Selector priority is always: **`getByRole` → `getByLabel` → `getByTestId`** → (CSS/XPath only as last resort).
4
+
5
+ ---
6
+
7
+ ## 1. Login / Authentication
8
+
9
+ **Test cases to cover:**
10
+ - Valid credentials → redirect to landing page
11
+ - Wrong password → error message visible
12
+ - Empty required field → validation message
13
+ - (optional) Locked/disabled account → blocked
14
+
15
+ ```typescript
16
+ test('TC01 - Login success', async ({ page }) => {
17
+ const login = new LoginPage(page);
18
+ await login.navigate('/login');
19
+ await login.login('user@example.com', 'Password123');
20
+ await expect(page).toHaveURL(/\/dashboard/);
21
+ });
22
+ ```
23
+
24
+ ---
25
+
26
+ ## 2. CRUD (Create / Read / Update / Delete)
27
+
28
+ **Cover:** create → appears in list → edit → reflects change → delete → removed. Always assert on the list/detail after each mutation, not just the success toast.
29
+
30
+ ```typescript
31
+ test('Create item appears in list', async ({ page }) => {
32
+ const list = new ItemListPage(page);
33
+ await list.navigate('/items');
34
+ await list.openCreate();
35
+ await list.fillForm({ name: 'Sample' });
36
+ await list.submit();
37
+ await expect(list.rowByName('Sample')).toBeVisible();
38
+ });
39
+ ```
40
+
41
+ > **Test data:** prefer a unique suffix (e.g. timestamp passed in via fixture) so reruns don't collide. Clean up created data in `afterEach` when possible.
42
+
43
+ ---
44
+
45
+ ## 3. Form validation
46
+
47
+ - Submit empty → each required field shows its message
48
+ - Invalid format (email, phone) → format message
49
+ - Boundary (min/max length) → length message
50
+ - Valid input → no error, submit succeeds
51
+
52
+ ```typescript
53
+ test('Email format validation', async ({ page }) => {
54
+ const form = new SignupPage(page);
55
+ await form.navigate('/signup');
56
+ await form.emailInput.fill('not-an-email');
57
+ await form.submit();
58
+ await expect(page.getByText(/invalid email/i)).toBeVisible();
59
+ });
60
+ ```
61
+
62
+ ---
63
+
64
+ ## 4. Modal / Dialog
65
+
66
+ - Open trigger → modal visible
67
+ - Confirm → action runs + modal closes
68
+ - Cancel / backdrop / Esc → modal closes, no action
69
+
70
+ ```typescript
71
+ await page.getByRole('button', { name: 'Delete' }).click();
72
+ const dialog = page.getByRole('dialog');
73
+ await expect(dialog).toBeVisible();
74
+ await dialog.getByRole('button', { name: 'Confirm' }).click();
75
+ await expect(dialog).toBeHidden();
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 5. Pagination / Table
81
+
82
+ - Default page loads expected count
83
+ - Next/Prev changes rows
84
+ - Page size change updates count
85
+ - Sort by column reorders rows
86
+
87
+ ```typescript
88
+ await expect(page.getByRole('row')).toHaveCount(11); // header + 10 rows
89
+ await page.getByRole('button', { name: 'Next' }).click();
90
+ await expect(page.getByText('Page 2')).toBeVisible();
91
+ ```
92
+
93
+ ---
94
+
95
+ ## 6. General assertions & waits
96
+
97
+ - Prefer **web-first assertions** (`await expect(locator).toBeVisible()`) — they auto-retry. Never `waitForTimeout` to "wait for UI".
98
+ - Assert on **user-visible outcome** (URL, text, element state), not internal state.
99
+ - For async data, assert the loaded element, not a spinner disappearing.
100
+
101
+ ---
102
+
103
+ ## 7. Evidence (MCP explore phase)
104
+
105
+ When exploring via Playwright MCP, capture a screenshot per significant step into `<evidenceDir>/[ticket-id]/TC<NN>-step<N>.png`. Name files so the reviewer can map evidence → test case at a glance.
@@ -0,0 +1,168 @@
1
+ ---
2
+ name: automation-testing
3
+ description: Generate runnable Playwright E2E tests for a web UI from requirement/business-logic docs or a tester's free-form draft. Uses Playwright MCP to explore real selectors and capture evidence on a live browser, then emits durable .spec.ts files plus an HTML report. Tester does not need to know TypeScript.
4
+ keywords: automation, testing, playwright, e2e, mcp, testcase, browser, evidence, report, qa, tester
5
+ ---
6
+
7
+ # Automation Testing (Hybrid MCP)
8
+
9
+ Generate **runnable** Playwright E2E tests for a web UI. Works in a **multi-repo workspace** (a parent folder containing backend + frontend repos).
10
+
11
+ ## Core principle — HYBRID
12
+
13
+ > Playwright MCP does **not** replace test files. It **improves** them.
14
+ > Use the live browser to *learn* the app's real selectors and capture evidence, but the deliverable is always committable `.spec.ts` so CI can re-run.
15
+
16
+ ## When to use
17
+
18
+ - Tester/Dev wants E2E UI tests but doesn't write TypeScript
19
+ - A requirement (`requirement.md`) or business-logic doc exists and test cases should be derived from it
20
+ - A finished feature needs regression coverage with evidence
21
+
22
+ ## How to invoke
23
+
24
+ ```
25
+ /automation-testing baseUrl: <url> [explore: true|false] [autoRun: true|false] [headed: true|false] [ticketId: <id>]
26
+ ---
27
+ (optional) tester's free-form test case draft
28
+ ```
29
+
30
+ **Example:**
31
+ ```
32
+ /automation-testing baseUrl: http://localhost:3000 explore: true autoRun: true
33
+ ---
34
+ 1. Vào /login, nhập đúng email/password → vào dashboard
35
+ 2. Nhập sai password → hiện thông báo lỗi
36
+ 3. Để trống email → hiện validation lỗi
37
+ ```
38
+
39
+ ## Params
40
+
41
+ | Param | Type | Default | Description |
42
+ |-------|------|---------|-------------|
43
+ | `baseUrl` | string | — | URL of the running web app **(required)** |
44
+ | `explore` | boolean | `true` | Use Playwright MCP to explore real selectors + capture evidence before generating |
45
+ | `autoRun` | boolean | `true` | Run `npx playwright test` after generating |
46
+ | `headed` | boolean | `false` | Show browser window during `autoRun` (CI should keep `false`) |
47
+ | `ticketId` | string | — | Ticket id; if omitted, read from `.aiflow/context/current.json` |
48
+
49
+ ---
50
+
51
+ ## Phase 1 — Collect
52
+
53
+ 1. **Resolve workspace.** Read `.aiflow/repos.json`.
54
+ - If it does NOT exist: copy the template at `.claude/skills/automation-testing/templates/repos.json`, ask the user to confirm the paths (`backend`, `frontend`, `e2e`, `planDir`, `evidenceDir`), then write `.aiflow/repos.json`. **Do not guess** the folder layout.
55
+ 2. **Resolve ticket.** Use `ticketId` param, else read `.aiflow/context/current.json`. If none, use a descriptive slug for `[ticket-id]`.
56
+ 3. **Read inputs** (any that exist):
57
+ - `<planDir>/[ticket-id]/requirement.md` (Gate 1)
58
+ - `<planDir>/[ticket-id]/plan.md` (Gate 2)
59
+ - business-logic doc (path provided by user or pasted)
60
+ - tester's draft (text after `---`)
61
+ - `custom/rules/test-patterns.md`
62
+ 4. **Require `baseUrl`.** If missing, ask before continuing.
63
+ 5. If NO testcase draft is provided, that's fine — derive test cases from the requirement + business-logic docs (this is the primary value).
64
+
65
+ ---
66
+
67
+ ## Phase 2 — Analyze (GATE 1)
68
+
69
+ Produce a structured test case list:
70
+
71
+ ```
72
+ ## Test Cases — [Feature Name]
73
+
74
+ | ID | Test case | Steps | Expected Result |
75
+ |------|--------------------------------|------------------------------------------------|----------------------------------|
76
+ | TC01 | Đăng nhập thành công | 1. /login 2. Nhập email+pass hợp lệ 3. Submit | Redirect /dashboard |
77
+ | TC02 | Sai mật khẩu | 1. /login 2. Sai password 3. Submit | Hiện error message |
78
+ | TC03 | Validation email trống | 1. /login 2. Submit ngay | "Email là bắt buộc" |
79
+ ```
80
+
81
+ > ⚠️ **GATE — STOP HERE.** Show the list and ask:
82
+ > "Danh sách test cases trên có đúng không? Thêm/sửa/xóa gì không? Xác nhận để tôi khám phá app và sinh code."
83
+ >
84
+ > **Wait for confirmation before Phase 3.** Do not explore or generate code until confirmed.
85
+
86
+ ---
87
+
88
+ ## Phase 3 — Explore (Playwright MCP, live browser)
89
+
90
+ Only if `explore: true` AND the Playwright MCP server is available AND the app is reachable.
91
+
92
+ For each test case, drive the real app:
93
+ 1. `browser_navigate(baseUrl + path)` — open the page
94
+ 2. `browser_snapshot()` — read the accessibility tree; **extract real selectors** (prefer `getByRole` → `getByLabel` → `getByTestId`)
95
+ 3. Walk the flow (type, click) to confirm it behaves as the test case expects
96
+ 4. `browser_take_screenshot()` → save to `<evidenceDir>/[ticket-id]/TC<NN>-step<N>.png`
97
+ 5. Record the verified selectors for Phase 4
98
+
99
+ **Output of this phase:** a selector map (element → verified locator) + evidence screenshots.
100
+
101
+ > Do NOT commit the MCP session. The committable artifact is produced in Phase 4.
102
+
103
+ ### Fallback
104
+ If `explore: false`, MCP unavailable, or the app is unreachable:
105
+ - Generate from inference (v1 behavior)
106
+ - **Warn clearly** that selectors are unverified and a developer must check them
107
+ - Skip evidence capture
108
+
109
+ ---
110
+
111
+ ## Phase 4 — Generate (durable scripts)
112
+
113
+ Write files under the `e2e` path from `repos.json`:
114
+
115
+ ```
116
+ <e2e>/
117
+ ├── pages/
118
+ │ ├── BasePage.ts ← only if missing (template below)
119
+ │ └── [Feature]Page.ts ← Page Object; selectors from Phase 3
120
+ ├── specs/[ticket-id]/[feature].spec.ts
121
+ ├── fixtures/test.ts ← only if missing
122
+ └── playwright.config.ts ← only if missing (template below)
123
+ ```
124
+
125
+ **Rules:**
126
+ - `BasePage.ts` / `playwright.config.ts` / `fixtures/test.ts` — create only if absent. Templates at `.claude/skills/automation-testing/templates/`.
127
+ - **Page Object** — declare locators using verified selectors from Phase 3 (`getByRole` > `getByLabel` > `getByTestId`; avoid CSS/XPath unless unavoidable). One async method per action.
128
+ - **Spec** — one `test()` per case; group with `test.describe`; test ids MUST match Phase 2 (TC01, TC02…); explicit `expect` assertions.
129
+ - Apply patterns from `custom/rules/test-patterns.md` where relevant.
130
+
131
+ ---
132
+
133
+ ## Phase 5 — Run & Report
134
+
135
+ ### If `autoRun: true`
136
+ 1. Determine the target repo for E2E (per §Git below) and `cd` there.
137
+ 2. Run `npx playwright test <e2e>/specs/[ticket-id]/` (add `--headed` if `headed: true`).
138
+ 3. On completion: `npx playwright show-report` (or report the HTML path).
139
+ 4. Summarize: pass/fail count, failed-test screenshots, plus the Phase 3 exploration evidence folder.
140
+
141
+ ### If `autoRun: false`
142
+ Print manual instructions:
143
+ ```
144
+ ✅ Scripts generated.
145
+ npx playwright test # all
146
+ npx playwright test <e2e>/specs/[ticket-id]/ # this ticket
147
+ npx playwright test --headed # show browser
148
+ npx playwright show-report # HTML report
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Git & Gate 5 (multi-repo)
154
+
155
+ The parent workspace is usually NOT a git repo. Commit to the **repo that owns the code under test**:
156
+
157
+ | Artifact | Commit target |
158
+ |----------|---------------|
159
+ | E2E tests for UI | the **frontend** repo (`<frontend>/e2e/`) — unless a dedicated `e2e` repo exists |
160
+ | requirement.md / plan.md | `<planDir>` at parent level (shared; not committed into a sub-repo) |
161
+
162
+ > When creating a PR (aiflow Gate 5 / `requesting-code-review`), `cd` into the correct sub-repo first — `git`/PR commands must run inside that repo, not the parent cwd.
163
+
164
+ ---
165
+
166
+ ## Two mandatory gates
167
+ 1. After Phase 2 — confirm the test case list before exploring/generating.
168
+ 2. After Phase 5 — hand off (evidence + report) and ask the developer to review before commit/PR.
@@ -0,0 +1,30 @@
1
+ import { Page, expect } from '@playwright/test';
2
+
3
+ /**
4
+ * BasePage — shared helpers for all Page Objects.
5
+ * Generated by the aiflow `automation-testing` skill. Create once; extend per feature.
6
+ */
7
+ export abstract class BasePage {
8
+ constructor(protected readonly page: Page) {}
9
+
10
+ /** Navigate to a path relative to playwright.config `baseURL`. */
11
+ async navigate(path = '/'): Promise<void> {
12
+ await this.page.goto(path);
13
+ await this.waitForLoad();
14
+ }
15
+
16
+ /** Wait until network is idle (page settled). */
17
+ async waitForLoad(): Promise<void> {
18
+ await this.page.waitForLoadState('networkidle');
19
+ }
20
+
21
+ /** Capture a full-page screenshot as evidence. */
22
+ async screenshot(name: string): Promise<void> {
23
+ await this.page.screenshot({ path: `evidence/${name}.png`, fullPage: true });
24
+ }
25
+
26
+ /** Assert the current URL matches (string or RegExp). */
27
+ async expectUrl(url: string | RegExp): Promise<void> {
28
+ await expect(this.page).toHaveURL(url);
29
+ }
30
+ }
@@ -0,0 +1,21 @@
1
+ import { defineConfig, devices } from '@playwright/test';
2
+
3
+ /**
4
+ * Playwright config generated by the aiflow `automation-testing` skill.
5
+ * Create once per target repo; edit to fit your environment.
6
+ */
7
+ export default defineConfig({
8
+ testDir: './specs',
9
+ fullyParallel: false,
10
+ retries: process.env.CI ? 1 : 0,
11
+ reporter: [['html', { open: 'never' }], ['list']],
12
+ use: {
13
+ baseURL: process.env.BASE_URL || 'http://localhost:3000',
14
+ trace: 'on-first-retry',
15
+ screenshot: 'only-on-failure',
16
+ video: 'retain-on-failure',
17
+ },
18
+ projects: [
19
+ { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
20
+ ],
21
+ });
@@ -0,0 +1,8 @@
1
+ {
2
+ "_comment": "Workspace map for the automation-testing skill. Copied to .aiflow/repos.json. Paths are relative to the parent workspace folder (aiflow cwd). Adjust to match your layout.",
3
+ "backend": "./backend",
4
+ "frontend": "./frontend",
5
+ "e2e": "./frontend/e2e",
6
+ "planDir": "./plan",
7
+ "evidenceDir": "./frontend/e2e/evidence"
8
+ }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: figma-to-component
3
- description: Read designs from Figma and generate React/Next.js/Vue components following project conventions. Supports specific frame URLs and entire pages.
4
- keywords: figma, design, component, ui, generate, react, nextjs, vue, frontend
3
+ description: Read designs from Figma and generate React/Next.js App Router/Vue/Angular components following project conventions. Supports specific frame URLs and entire pages.
4
+ keywords: figma, design, component, ui, generate, react, nextjs, nextjs-app-router, vue, angular, frontend
5
5
  ---
6
6
 
7
7
  # Figma to Component
@@ -14,6 +14,19 @@ keywords: figma, design, component, ui, generate, react, nextjs, vue, frontend
14
14
 
15
15
  ---
16
16
 
17
+ ## Step 0: Verify Figma MCP is available
18
+
19
+ Before doing anything, confirm the Figma MCP server is connected in this session:
20
+
21
+ - The tool `mcp__figma__get_figma_data` (and `mcp__figma__download_figma_images`) must be available.
22
+ - If it is **not** available, STOP and tell the developer:
23
+ > Figma MCP not connected. Run `aiflow init -a figma` (REST API token) or
24
+ > `aiflow init -a figma-desktop` (Figma Desktop), then restart the session.
25
+
26
+ Do not guess design values from the URL — without the MCP server the skill cannot read the design.
27
+
28
+ ---
29
+
17
30
  ## Process
18
31
 
19
32
  ### Step 1: Identify input
@@ -30,20 +43,24 @@ Extract `fileKey` and `nodeId` from the URL.
30
43
  Use Figma MCP tools to fetch design information:
31
44
 
32
45
  ```
33
- 1. Get node info: figma_get_file_nodes(fileKey, nodeIds=[nodeId])
34
- 2. Get styles: figma_get_file_styles(fileKey)
35
- 3. Get components: figma_get_file_components(fileKey) if needed
36
- 4. Export image if visual reference needed: figma_get_image(fileKey, nodeId)
46
+ 1. Get node info, styles, and components in one call:
47
+ get_figma_data(fileKey, nodeId, depth=2)
48
+
49
+ 2. Export image if visual reference needed:
50
+ download_figma_images(fileKey, nodes=[{ nodeId, fileName }], localPath)
37
51
  ```
38
52
 
53
+ Note: `get_figma_data` returns layout, fills, strokes, typography, and component
54
+ definitions in a single response. No separate style or component fetch is needed.
55
+
39
56
  Analyze the output to extract:
40
57
  - **Layout**: flexbox direction, gap, padding, alignment
41
58
  - **Sizing**: width/height (fixed vs fill vs hug)
42
- - **Colors**: fills, strokes → map to Tailwind colors if available
43
- - **Typography**: font-size, font-weight, line-height, letter-spacing → map to Tailwind text classes
44
- - **Spacing**: padding, margin, gap → map to Tailwind spacing scale
45
- - **Border**: radius, width, color → map to Tailwind border classes
46
- - **Shadow**: box-shadow → map to Tailwind shadow classes
59
+ - **Colors**: fills, strokes → map to project CSS tokens / Tailwind colors if available
60
+ - **Typography**: font-size, font-weight, line-height, letter-spacing
61
+ - **Spacing**: padding, margin, gap
62
+ - **Border**: radius, width, color
63
+ - **Shadow**: box-shadow
47
64
  - **States**: hover, focus, disabled, active (if variants present)
48
65
  - **Responsive**: breakpoints if multiple frames present
49
66
 
@@ -73,19 +90,12 @@ download_figma_images({
73
90
  - `localPath` defaults to `public/assets/figma/` (relative to the project root)
74
91
  - `fileName` follows the pattern: `<layer name in lowercase, spaces replaced with ->-<nodeId>.png`
75
92
  - Example: layer "Banner Top" with nodeId "123-456" → `banner-top-123-456.png`
76
- - If MCP does not support `download_figma_images`, use `get_images` to get the URL, then notify DEV to download manually and place in `public/assets/figma/`
93
+ - If MCP does not support `download_figma_images`, get the image URL via `get_figma_data`, then notify DEV to download manually and place in `public/assets/figma/`
77
94
 
78
95
  **Record the result:**
79
96
 
80
97
  After export, save the mapping for use in Step 4:
81
98
 
82
- ```
83
- imageMap = {
84
- "<nodeId>": "public/assets/figma/<fileName>.png"
85
- }
86
- ```
87
-
88
- Example:
89
99
  ```
90
100
  imageMap = {
91
101
  "123-456": "public/assets/figma/banner-top-123-456.png",
@@ -93,53 +103,50 @@ imageMap = {
93
103
  }
94
104
  ```
95
105
 
96
- ### Step 3: Map Figma tokens Tailwind / CSS
106
+ ### Step 3: Detect CSS tooling, then map Figma tokens
97
107
 
98
- **Color mapping:**
99
- ```
100
- Figma hex #3B82F6 → Tailwind blue-500
101
- Figma hex #EF4444 → Tailwind red-500
102
- Figma rgba(0,0,0,0.5) → Tailwind black/50
103
- No Tailwind match → use arbitrary value [#hexcode]
104
- ```
108
+ **Detect the project's styling approach first** (do not assume Tailwind):
105
109
 
106
- **Spacing mapping (8px grid):**
107
- ```
108
- 4px → p-1 / gap-1
109
- 8px p-2 / gap-2
110
- 12px → p-3 / gap-3
111
- 16px p-4 / gap-4
112
- 24px p-6 / gap-6
113
- 32px p-8 / gap-8
114
- No match → arbitrary value [20px]
115
- ```
110
+ 1. `tailwind.config.*` present → **Tailwind** map to utility classes; extend `tailwind.config` with design tokens when a value has no built-in match
111
+ 2. `*.module.css` / `*.module.scss` files present → **CSS Modules** — emit a co-located `.module.css` and reference `styles.x`
112
+ 3. `styled-components` / `@emotion` in `package.json` → **CSS-in-JS** — emit styled components
113
+ 4. None of the above **vanilla CSS** — emit a co-located `.css` file with CSS custom properties
114
+
115
+ **Design tokens:** prefer mapping Figma Styles/Variables to existing project tokens
116
+ (Tailwind theme keys or CSS custom properties) instead of hardcoding hex/px values.
117
+ Only fall back to an arbitrary value when no token matches.
118
+
119
+ **Tailwind reference mappings** (when Tailwind is the detected tooling):
116
120
 
117
- **Typography mapping:**
118
121
  ```
119
- text-xs: 12px
120
- text-sm: 14px
121
- text-base: 16px
122
- text-lg: 18px
123
- text-xl: 20px
124
- text-2xl: 24px
125
- text-3xl: 30px
126
- font-normal: 400
127
- font-medium: 500
128
- font-semibold: 600
129
- font-bold: 700
122
+ Color: #3B82F6 → blue-500 · #EF4444 → red-500 · rgba(0,0,0,0.5) → black/50
123
+ no match → arbitrary value [#hexcode]
124
+ Spacing: 4→p-1/gap-1 · 8→p-2 · 12→p-3 · 16→p-4 · 24→p-6 · 32→p-8 (8px grid)
125
+ no match → arbitrary value [20px]
126
+ Type: 12→text-xs · 14→text-sm · 16→text-base · 18→text-lg · 20→text-xl · 24→text-2xl · 30→text-3xl
127
+ 400→font-normal · 500→font-medium · 600→font-semibold · 700→font-bold
130
128
  ```
131
129
 
132
130
  ### Step 4: Generate component
133
131
 
134
- **Framework detection** — check the project's CLAUDE.md to determine the framework:
135
- - `reactjs` / `nextjs` → generate `.tsx` with React conventions
136
- - `vue-nuxt` generate `.vue` with Vue 3 Composition API
132
+ **Framework detection** — check in this order:
133
+
134
+ 1. Read project's `CLAUDE.md` for framework identifier:
135
+ - `nextjs-app-router` → Next.js App Router (Server/Client Components)
136
+ - `reactjs` / `nextjs` → React / Next.js Pages Router `.tsx`
137
+ - `vue-nuxt` → Vue 3 `.vue` with Composition API
138
+ - `angular` → Angular `@Component` class
139
+ 2. Scan project files if CLAUDE.md is ambiguous:
140
+ - `app/` directory present → `nextjs-app-router`
141
+ - `angular.json` present → `angular`
142
+ - `nuxt.config.*` present → `vue-nuxt`
143
+ 3. Fallback → `nextjs` (React Pages Router)
137
144
 
138
145
  **Image node rendering rule:**
139
146
 
140
147
  Before rendering each node, check `imageMap` from Step 2.5:
141
148
  - If `nodeId` is in `imageMap` → render using `<img>` (React/Vue) or `<Image>` (Next.js), do NOT use CSS `background-image`
142
- - If not in `imageMap` → render normally using div + Tailwind classes
149
+ - If not in `imageMap` → render normally using div + styling classes
143
150
 
144
151
  React/Next.js template for image node:
145
152
  ```tsx
@@ -197,6 +204,57 @@ export const [ComponentName] = ({ className }: [ComponentName]Props) => {
197
204
  };
198
205
  ```
199
206
 
207
+ #### Next.js App Router component template:
208
+
209
+ Default to **Server Component**. Add `'use client'` only when the design has
210
+ interactive states (hover effects, click handlers, form inputs, modals).
211
+
212
+ ```tsx
213
+ // Server Component — no interactivity (default)
214
+ interface [ComponentName]Props {
215
+ className?: string;
216
+ }
217
+
218
+ export default async function [ComponentName]({ className }: [ComponentName]Props) {
219
+ return (
220
+ <div className={cn(
221
+ // Layout classes
222
+ // Sizing classes
223
+ // Color classes
224
+ className
225
+ )}>
226
+ {/* Child nodes */}
227
+ </div>
228
+ );
229
+ }
230
+ ```
231
+
232
+ ```tsx
233
+ // Client Component — has onClick / useState / useEffect
234
+ 'use client'
235
+
236
+ import { useState } from 'react'
237
+
238
+ interface [ComponentName]Props {
239
+ className?: string;
240
+ }
241
+
242
+ export function [ComponentName]({ className }: [ComponentName]Props) {
243
+ return (
244
+ <div className={cn(
245
+ // Layout classes
246
+ // Sizing classes
247
+ // Color classes
248
+ className
249
+ )}>
250
+ {/* Child nodes */}
251
+ </div>
252
+ );
253
+ }
254
+ ```
255
+
256
+ File path: `app/components/[ComponentName].tsx` or `components/[ComponentName].tsx`
257
+
200
258
  #### Vue 3 component template:
201
259
 
202
260
  ```vue
@@ -221,6 +279,40 @@ const props = withDefaults(defineProps<Props>(), {});
221
279
  </template>
222
280
  ```
223
281
 
282
+ #### Angular component template:
283
+
284
+ Use Tailwind classes if `tailwind.config.*` exists in the project root.
285
+ Otherwise use `styles` array with CSS-in-component.
286
+
287
+ ```typescript
288
+ import { Component, Input } from '@angular/core';
289
+ import { CommonModule } from '@angular/common';
290
+
291
+ @Component({
292
+ selector: 'app-[component-name]',
293
+ standalone: true,
294
+ imports: [CommonModule],
295
+ template: `
296
+ <div [class]="hostClasses">
297
+ <!-- Child nodes -->
298
+ </div>
299
+ `,
300
+ styles: []
301
+ })
302
+ export class [ComponentName]Component {
303
+ @Input() className = '';
304
+
305
+ get hostClasses(): string {
306
+ return [
307
+ // Layout classes
308
+ // Sizing classes
309
+ // Color classes
310
+ this.className
311
+ ].filter(Boolean).join(' ');
312
+ }
313
+ }
314
+ ```
315
+
224
316
  ### Step 5: Handle interactive states
225
317
 
226
318
  If Figma has variants (Default, Hover, Disabled, Active):
@@ -245,14 +337,14 @@ const variantClasses = {
245
337
  After generation, verify:
246
338
 
247
339
  - [ ] Layout matches Figma (flex direction, alignment, gap)
248
- - [ ] Colors mapping correct (or use arbitrary values if no Tailwind match)
340
+ - [ ] Colors mapping correct (project tokens, or arbitrary values if no match)
249
341
  - [ ] Typography correct (size, weight, line-height)
250
342
  - [ ] Spacing correct (padding, margin, gap)
251
343
  - [ ] Component has `className` prop for external overrides
252
- - [ ] Use `cn()` helper for conditional/mergeable classes
344
+ - [ ] Conditional/mergeable classes use the project's helper (`cn()` for Tailwind)
253
345
  - [ ] Responsive if Figma has mobile frames
254
346
  - [ ] Props typed with TypeScript interface
255
- - [ ] Image nodes use `<img>` tag (do not use CSS `background-image`)
347
+ - [ ] Image nodes use `<img>` / `<Image>` (do not use CSS `background-image`)
256
348
  - [ ] Image files exist in `public/assets/figma/` before submitting code
257
349
 
258
350
  ---
@@ -273,9 +365,9 @@ Always output in order:
273
365
 
274
366
  ## Rules
275
367
 
276
- - **Do not hardcode** hex colors directly into className if a Tailwind equivalent exists
277
- - **Always use** `cn()` (clsx + twMerge) to merge classes
278
- - **No new CSS imports** use Tailwind utilities only
368
+ - **Detect styling tooling first** do not assume Tailwind; honour CSS Modules / styled-components / vanilla CSS when detected
369
+ - **Prefer design tokens** map Figma Styles/Variables to project tokens; only hardcode a value when no token matches
370
+ - **Always use** the project's class-merge helper (`cn()` = clsx + twMerge for Tailwind)
279
371
  - **Responsive** — if Figma only has 1 breakpoint, default to mobile-first design
280
372
  - **Accessibility** — add `aria-label`, `role`, `alt` for interactive and image elements
281
373
  - **Image** — detect image fills in Figma node data, export via `download_figma_images` MCP, save to `public/assets/figma/`. Use `<Image>` (Next.js) or `<img>` (React/Vue) with `src` pointing to the exported file. Do NOT use CSS `background-image` for image nodes.
@@ -283,6 +375,19 @@ Always output in order:
283
375
 
284
376
  ---
285
377
 
378
+ ## Troubleshooting
379
+
380
+ | Symptom | Cause | Fix |
381
+ |---------|-------|-----|
382
+ | `mcp__figma__get_figma_data` not available | Figma MCP server not connected | Run `aiflow init -a figma` or `-a figma-desktop`, restart session |
383
+ | `403 Forbidden` / token rejected | PAT invalid or wrong header | Re-issue a `figd_...` token; `init` sends `X-Figma-Token` (not `Bearer`) |
384
+ | Tool call hangs / times out | Large node tree (`depth` too high) | Lower `depth` (e.g. `depth=1`), target a specific `nodeId` not the whole file |
385
+ | `404` on node | Wrong `fileKey`/`nodeId` | Re-copy the frame URL; node-id uses `-` in URL but `:` in API |
386
+ | Empty fills / no styles | Node is a component instance | Fetch the main component, or increase `depth` |
387
+ | `download_figma_images` unsupported | Older MCP preset | Get image URL via `get_figma_data`, download manually to `public/assets/figma/` |
388
+
389
+ ---
390
+
286
391
  ## Trigger Example Commands
287
392
 
288
393
  ```
@@ -7,6 +7,22 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.1.1] - 2026-06-08
11
+
12
+ ### Added
13
+
14
+ - **Ubuntu / Linux clipboard support in `ak prompt`** — `ak prompt` now copies to the clipboard on native Linux. It auto-detects the display server (Wayland → `wl-copy`, X11 → `xclip` → `xsel`) and the package manager (`apt-get` / `dnf` / `pacman` / `zypper`). When no clipboard tool is installed it prints a clear warning (`⚠ Clipboard tool not found (need: xclip)`), shows the exact install command, and offers to install it via `sudo` then retries the copy. If the user declines or no package manager is found, it falls back to printing the full prompt for manual copy. Previously the command silently failed on Ubuntu when neither `xclip` nor `xsel` was present.
15
+ - **`figma-to-component`: image detection & export** — The skill now scans the Figma node tree for image nodes (`fills[].type === "IMAGE"`, `VECTOR`/`BOOLEAN_OPERATION`, complex non-CSS groups), exports them via `download_figma_images` into `public/assets/figma/`, and records an `imageMap`. Generated components render those nodes with `<Image>` (Next.js) / `<img>` (React/Vue) instead of CSS `background-image`.
16
+ - **`figma-to-component`: MCP availability pre-check (Step 0)** — The skill now verifies `mcp__figma__get_figma_data` / `mcp__figma__download_figma_images` are connected before running, and stops with setup instructions (`aiflow init -a figma` / `-a figma-desktop`) instead of guessing design values from the URL.
17
+ - **`figma-to-component`: CSS tooling detection + design tokens** — Detection now branches on the project's styling approach (Tailwind / CSS Modules / styled-components / vanilla CSS) instead of hardcoding Tailwind, and prefers mapping Figma Styles/Variables to existing project tokens (Tailwind theme keys or CSS custom properties), falling back to arbitrary values only when no token matches.
18
+ - **`figma-to-component`: troubleshooting table** — Added a troubleshooting section covering MCP-not-connected, `403`/token rejected, request timeout (lower `depth`), `404` node-id, empty fills, and unsupported `download_figma_images`.
19
+
20
+ ### Fixed
21
+
22
+ - **Critical: `figma-to-component` source/installed divergence** — The source skill (`custom/skills/figma-to-component/SKILL.md`) still referenced the non-existent tool names `figma_get_file_nodes` / `figma_get_file_styles` / `figma_get_image` and only had 2-tier framework detection, while the installed `.claude/` copy had been fixed in 0.0.9. The next `aiflow init` / `sync-skills` would have overwritten the working copy with the broken source — re-introducing the 0.0.9 bug. Both copies are now synced to a single canonical version: correct tool names (`get_figma_data` / `download_figma_images`), 4-tier framework detection (App Router / React / Vue / Angular), and the image-export step.
23
+
24
+ ---
25
+
10
26
  ## [0.1.0] - 2026-05-28
11
27
 
12
28
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relipa/ai-flow-kit",
3
- "version": "0.1.1-beta.0",
3
+ "version": "0.1.1",
4
4
  "description": "All-in-one AI Flow Kit for team development with Claude AI - skills, templates, and MCP adapters",
5
5
  "author": "Example Team",
6
6
  "publishConfig": {
@@ -65,4 +65,4 @@
65
65
  "<rootDir>/tests/**/*.test.js"
66
66
  ]
67
67
  }
68
- }
68
+ }