diff --git a/.agents/skills/code-connect-components/SKILL.md b/.agents/skills/code-connect-components/SKILL.md new file mode 100644 index 000000000..949169a0b --- /dev/null +++ b/.agents/skills/code-connect-components/SKILL.md @@ -0,0 +1,332 @@ +--- +name: code-connect-components +description: Connects Figma design components to code components using Code Connect. Use when user says "code connect", "connect this component to code", "connect Figma to code", "map this component", "link component to code", "create code connect mapping", "add code connect", "connect design to code", or wants to establish mappings between Figma designs and code implementations. Requires Figma MCP server connection. +metadata: + mcp-server: figma +--- + +# Code Connect Components + +## Overview + +This skill helps you connect Figma design components to their corresponding code implementations using Figma's Code Connect feature. It analyzes the Figma design structure, searches your codebase for matching components, and establishes mappings that maintain design-code consistency. + +## Prerequisites + +- Figma MCP server must be connected and accessible + - Before proceeding, verify the Figma MCP server is connected by checking if Figma MCP tools (e.g., `get_code_connect_suggestions`) are available. + - If the tools are not available, the Figma MCP server may not be enabled. Guide the user to enable the Figma MCP server that is included with the plugin. They may need to restart their MCP client afterward. +- User must provide a Figma URL with node ID: `https://figma.com/design/:fileKey/:fileName?node-id=1-2` + - **IMPORTANT:** The Figma URL must include the `node-id` parameter. Code Connect mapping will fail without it. +- **IMPORTANT:** The Figma component must be published to a team library. Code Connect only works with published components or component sets. +- **IMPORTANT:** Code Connect is only available on Organization and Enterprise plans. +- Access to the project codebase for component scanning + +## Required Workflow + +**Follow these steps in order. Do not skip steps.** + +### Step 1: Get Code Connect Suggestions + +Call `get_code_connect_suggestions` to identify all unmapped components in a single operation. This tool automatically: + +- Fetches component info from the Figma scenegraph +- Identifies published components in the selection +- Checks existing Code Connect mappings and filters out already-connected components +- Returns component names, properties, and thumbnail images for each unmapped component + +Parse the URL to extract `fileKey` and `nodeId`, then call `get_code_connect_suggestions`. + +**IMPORTANT:** When extracting the node ID from a Figma URL, convert the format: + +- URL format uses hyphens: `node-id=1-2` +- Tool expects colons: `nodeId=1:2` + +**Parse the Figma URL:** + +- URL format: `https://figma.com/design/:fileKey/:fileName?node-id=1-2` +- Extract file key: `:fileKey` (segment after `/design/`) +- Extract node ID: `1-2` from URL, then convert to `1:2` for the tool + +``` +get_code_connect_suggestions(fileKey=":fileKey", nodeId="1:2") +``` + +**Handle the response:** + +- If the tool returns **"No published components found in this selection"** → inform the user and stop. The components may need to be published to a team library first. +- If the tool returns **"All component instances in this selection are already connected to code via Code Connect"** → inform the user that everything is already mapped. +- Otherwise, the response contains a list of unmapped components, each with: + - Component name + - Node ID + - Component properties (JSON with prop names and values) + - A thumbnail image of the component (for visual inspection) + +### Step 2: Scan Codebase for Matching Components + +For each unmapped component returned by `get_code_connect_suggestions`, search the codebase for a matching code component. + +**What to look for:** + +- Component names that match or are similar to the Figma component name +- Component structure that aligns with the Figma hierarchy +- Props that correspond to Figma properties (variants, text, styles) +- Files in typical component directories (`src/components/`, `components/`, `ui/`, etc.) + +**Search strategy:** + +1. Search for component files with matching names +2. Read candidate files to check structure and props +3. Compare the code component's props with the Figma component properties returned in Step 1 +4. Detect the programming language (TypeScript, JavaScript) and framework (React, Vue, etc.) +5. Identify the best match based on structural similarity, weighing: + - Prop names and their correspondence to Figma properties + - Default values that match Figma defaults + - CSS classes or style objects + - Descriptive comments that clarify intent +6. If multiple candidates are equally good, pick the one with the closest prop-interface match and document your reasoning in a 1-2 sentence comment before your tool call + +**Example search patterns:** + +- If Figma component is "PrimaryButton", search for `Button.tsx`, `PrimaryButton.tsx`, `Button.jsx` +- Check common component paths: `src/components/`, `app/components/`, `lib/ui/` +- Look for variant props like `variant`, `size`, `color` that match Figma variants + +### Step 3: Present Matches to User + +Present your findings and let the user choose which mappings to create. The user can accept all, some, or none of the suggested mappings. + +**Present matches in this format:** + +``` +The following components match the design: +- [ComponentName](path/to/component): DesignComponentName at nodeId [nodeId](figmaUrl?node-id=X-Y) +- [AnotherComponent](path/to/another): AnotherDesign at nodeId [nodeId2](figmaUrl?node-id=X-Y) + +Would you like to connect these components? You can accept all, select specific ones, or skip. +``` + +**If no exact match is found for a component:** + +- Show the 2 closest candidates +- Explain the differences +- Ask the user to confirm which component to use or provide the correct path + +**If the user declines all mappings**, inform them and stop. No further tool calls are needed. + +### Step 4: Create Code Connect Mappings + +Once the user confirms their selections, call `send_code_connect_mappings` with only the accepted mappings. This tool handles batch creation of all mappings in a single call. + +**Example:** + +``` +send_code_connect_mappings( + fileKey=":fileKey", + nodeId="1:2", + mappings=[ + { nodeId: "1:2", componentName: "Button", source: "src/components/Button.tsx", label: "React" }, + { nodeId: "1:5", componentName: "Card", source: "src/components/Card.tsx", label: "React" } + ] +) +``` + +**Key parameters for each mapping:** + +- `nodeId`: The Figma node ID (with colon format: `1:2`) +- `componentName`: Name of the component to connect (e.g., "Button", "Card") +- `source`: Path to the code component file (relative to project root) +- `label`: The framework or language label for this Code Connect mapping. Valid values include: + - Web: 'React', 'Web Components', 'Vue', 'Svelte', 'Storybook', 'Javascript' + - iOS: 'Swift UIKit', 'Objective-C UIKit', 'SwiftUI' + - Android: 'Compose', 'Java', 'Kotlin', 'Android XML Layout' + - Cross-platform: 'Flutter' + - Docs: 'Markdown' + +**After the call:** + +- On success: the tool confirms the mappings were created +- On error: the tool reports which specific mappings failed and why (e.g., "Component is already mapped to code", "Published component not found", "Insufficient permissions") + +**Provide a summary** after processing: + +``` +Code Connect Summary: +- Successfully connected: 3 + - Button (1:2) → src/components/Button.tsx + - Card (1:5) → src/components/Card.tsx + - Input (1:8) → src/components/Input.tsx +- Could not connect: 1 + - CustomWidget (1:10) - No matching component found in codebase +``` + +## Examples + +### Example 1: Connecting a Button Component + +User says: "Connect this Figma button to my code: https://figma.com/design/kL9xQn2VwM8pYrTb4ZcHjF/DesignSystem?node-id=42-15" + +**Actions:** + +1. Parse URL: fileKey=`kL9xQn2VwM8pYrTb4ZcHjF`, nodeId=`42-15` → convert to `42:15` +2. Run `get_code_connect_suggestions(fileKey="kL9xQn2VwM8pYrTb4ZcHjF", nodeId="42:15")` +3. Response shows: Button component (unmapped) with `variant` (primary/secondary) and `size` (sm/md/lg) properties, plus a thumbnail image +4. Search codebase for Button components: Find `src/components/Button.tsx` +5. Read `Button.tsx` and confirm it has `variant` and `size` props +6. Present to user: "I found a match: + - [Button](src/components/Button.tsx): Button at nodeId [42:15](https://figma.com/design/kL9xQn2VwM8pYrTb4ZcHjF/DesignSystem?node-id=42-15) + + Would you like to connect this component?" + +7. User confirms: "Yes" +8. Detect that it's a TypeScript React component +9. Run `send_code_connect_mappings(fileKey="kL9xQn2VwM8pYrTb4ZcHjF", nodeId="42:15", mappings=[{ nodeId: "42:15", componentName: "Button", source: "src/components/Button.tsx", label: "React" }])` + +**Result:** Figma button component is now connected to the code Button component. + +### Example 2: Multiple Components with Partial Selection + +User says: "Connect components in this frame: https://figma.com/design/pR8mNv5KqXzGwY2JtCfL4D/Components?node-id=10-50" + +**Actions:** + +1. Parse URL: fileKey=`pR8mNv5KqXzGwY2JtCfL4D`, nodeId=`10-50` → convert to `10:50` +2. Run `get_code_connect_suggestions(fileKey="pR8mNv5KqXzGwY2JtCfL4D", nodeId="10:50")` +3. Response shows 3 unmapped components: ProductCard, Badge, and CustomWidget +4. Search codebase: + - ProductCard: Found `src/components/ProductCard.tsx` (props match) + - Badge: Found `src/components/Badge.tsx` (props match) + - CustomWidget: No matching component found +5. Present to user: + "The following components match the design: + - [ProductCard](src/components/ProductCard.tsx): ProductCard at nodeId [10:51](https://figma.com/design/pR8mNv5KqXzGwY2JtCfL4D/Components?node-id=10-51) + - [Badge](src/components/Badge.tsx): Badge at nodeId [10:52](https://figma.com/design/pR8mNv5KqXzGwY2JtCfL4D/Components?node-id=10-52) + + I couldn't find a match for CustomWidget (10:53). + + Would you like to connect these components? You can accept all, select specific ones, or skip." + +6. User: "Just connect ProductCard, skip Badge for now" +7. Run `send_code_connect_mappings(fileKey="pR8mNv5KqXzGwY2JtCfL4D", nodeId="10:50", mappings=[{ nodeId: "10:51", componentName: "ProductCard", source: "src/components/ProductCard.tsx", label: "React" }])` + +**Result:** Only ProductCard is connected, per the user's selection. + +### Example 3: Component Needs Creation + +User says: "Connect this icon: https://figma.com/design/8yJDMeWDyBz71EnMOSuUiw/Icons?node-id=5-20" + +**Actions:** + +1. Parse URL: fileKey=`8yJDMeWDyBz71EnMOSuUiw`, nodeId=`5-20` → convert to `5:20` +2. Run `get_code_connect_suggestions(fileKey="8yJDMeWDyBz71EnMOSuUiw", nodeId="5:20")` +3. Response shows: CheckIcon component (unmapped) with color and size properties +4. Search codebase for CheckIcon: No matches found +5. Search for generic Icon components: Find `src/icons/` directory with other icons +6. Report to user: "I couldn't find a CheckIcon component, but I found an icons directory at src/icons/. Would you like to: + - Create a new CheckIcon.tsx component first, then connect it + - Connect to a different existing icon + - Provide the path to the CheckIcon if it exists elsewhere" +7. User provides path: "src/icons/CheckIcon.tsx" +8. Detect language and framework from the file +9. Run `send_code_connect_mappings(fileKey="8yJDMeWDyBz71EnMOSuUiw", nodeId="5:20", mappings=[{ nodeId: "5:20", componentName: "CheckIcon", source: "src/icons/CheckIcon.tsx", label: "React" }])` + +**Result:** CheckIcon component is successfully connected to the Figma design. + +## Best Practices + +### Proactive Component Discovery + +Don't just ask the user for the file path — actively search their codebase to find matching components. This provides a better experience and catches potential mapping opportunities. + +### Accurate Structure Matching + +When comparing Figma components to code components, look beyond just names. Check that: + +- Props align (variant types, size options, etc.) +- Component hierarchy matches (nested elements) +- The component serves the same purpose + +### Clear Communication + +When offering to create a mapping, clearly explain: + +- What you found +- Why it's a good match +- What the mapping will do +- How props will be connected + +### Handle Ambiguity + +If multiple components could match, present options rather than guessing. Let the user make the final decision about which component to connect. + +### Graceful Degradation + +If you can't find an exact match, provide helpful next steps: + +- Show close candidates +- Suggest component creation +- Ask for user guidance + +## Common Issues and Solutions + +### Issue: "No published components found in this selection" + +**Cause:** The Figma component is not published to a team library. Code Connect only works with published components. +**Solution:** The user needs to publish the component to a team library in Figma: + +1. In Figma, select the component or component set +2. Right-click and choose "Publish to library" or use the Team Library publish modal +3. Publish the component +4. Once published, retry the Code Connect mapping with the same node ID + +### Issue: "Code Connect is only available on Organization and Enterprise plans" + +**Cause:** The user's Figma plan does not include Code Connect access. +**Solution:** The user needs to upgrade to an Organization or Enterprise plan, or contact their administrator. + +### Issue: No matching component found in codebase + +**Cause:** The codebase search did not find a component with a matching name or structure. +**Solution:** Ask the user if the component exists under a different name or in a different location. They may need to create the component first, or it might be located in an unexpected directory. + +### Issue: "Published component not found" (CODE_CONNECT_ASSET_NOT_FOUND) + +**Cause:** The source file path is incorrect, the component doesn't exist at that location, or the componentName doesn't match the actual export. +**Solution:** Verify the source path is correct and relative to the project root. Check that the component is properly exported from the file with the exact componentName specified. + +### Issue: "Component is already mapped to code" (CODE_CONNECT_MAPPING_ALREADY_EXISTS) + +**Cause:** A Code Connect mapping already exists for this component. +**Solution:** The component is already connected. If the user wants to update the mapping, they may need to remove the existing one first in Figma. + +### Issue: "Insufficient permissions to create mapping" (CODE_CONNECT_INSUFFICIENT_PERMISSIONS) + +**Cause:** The user does not have edit permissions on the Figma file or library. +**Solution:** The user needs edit access to the file containing the component. Contact the file owner or team admin. + +### Issue: Code Connect mapping fails with URL errors + +**Cause:** The Figma URL format is incorrect or missing the `node-id` parameter. +**Solution:** Verify the URL follows the required format: `https://figma.com/design/:fileKey/:fileName?node-id=1-2`. The `node-id` parameter is required. Also ensure you convert `1-2` to `1:2` when calling tools. + +### Issue: Multiple similar components found + +**Cause:** The codebase contains multiple components that could match the Figma component. +**Solution:** Present all candidates to the user with their file paths and let them choose which one to connect. Different components might be used in different contexts (e.g., `Button.tsx` vs `LinkButton.tsx`). + +## Understanding Code Connect + +Code Connect establishes a bidirectional link between design and code: + +**For designers:** See which code component implements a Figma component +**For developers:** Navigate from Figma designs directly to the code that implements them +**For teams:** Maintain a single source of truth for component mappings + +The mapping you create helps keep design and code in sync by making these connections explicit and discoverable. + +## Additional Resources + +For more information about Code Connect: + +- [Code Connect Documentation](https://help.figma.com/hc/en-us/articles/23920389749655-Code-Connect) +- [Figma MCP Server Tools and Prompts](https://developers.figma.com/docs/figma-mcp-server/tools-and-prompts/) diff --git a/.cursor/settings.json b/.cursor/settings.json index 6b5ec9f2a..11eb52f31 100644 --- a/.cursor/settings.json +++ b/.cursor/settings.json @@ -5,6 +5,12 @@ }, "slack": { "enabled": true + }, + "figma": { + "enabled": true + }, + "cursor-team-kit": { + "enabled": true } } } diff --git a/.github/workflows/azure-webapps-node.yml b/.github/workflows/azure-webapps-node.yml index 2ebbac24b..461176646 100644 --- a/.github/workflows/azure-webapps-node.yml +++ b/.github/workflows/azure-webapps-node.yml @@ -33,6 +33,8 @@ permissions: jobs: build: runs-on: ubuntu-latest + # Skip if Azure credentials are not configured + if: secrets.AZURE_WEBAPP_PUBLISH_PROFILE != '' steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/sync-file-changes-to-lovable.yml b/.github/workflows/sync-file-changes-to-lovable.yml index b66b41e63..9b12d249e 100644 --- a/.github/workflows/sync-file-changes-to-lovable.yml +++ b/.github/workflows/sync-file-changes-to-lovable.yml @@ -70,4 +70,4 @@ jobs: echo "Sending file changes to Lovable..." curl -X POST "$LOVABLE_WEBHOOK_URL" \ -H "Content-Type: application/json" \ - -d "$PAYLOAD" + -d "$PAYLOAD" || echo "Warning: Lovable webhook call failed (non-fatal)." diff --git a/.github/workflows/sync-issues-prs-to-lovable.yml b/.github/workflows/sync-issues-prs-to-lovable.yml index b565c563d..038029157 100644 --- a/.github/workflows/sync-issues-prs-to-lovable.yml +++ b/.github/workflows/sync-issues-prs-to-lovable.yml @@ -70,5 +70,5 @@ jobs: ) curl -s -X POST "$LOVABLE_WEBHOOK_URL" \ -H "Content-Type: application/json" \ - -d "$PAYLOAD" + -d "$PAYLOAD" || echo "Warning: Lovable webhook call failed (non-fatal)." echo "Done." diff --git a/README.md b/README.md index ec5920725..f5f1dd697 100644 --- a/README.md +++ b/README.md @@ -302,3 +302,52 @@ For more bulk product upload examples and complete payload structures, see [docs - **[docs/DEPLOYMENT_TEMPLATE.md](docs/DEPLOYMENT_TEMPLATE.md)** - Deployment templates, environment variables, concrete bulk-product-upload sample payloads - **[docs/PRE_LAUNCH_CHECKLIST.md](docs/PRE_LAUNCH_CHECKLIST.md)** - Pre-deployment checklist including §5 secrets configuration and POST response interpretation - **[.github/workflows/deploy-health-check.yml](.github/workflows/deploy-health-check.yml)** - Automated health checks on deployment + +## Sync Check and applyToAllProfiles + +**Sync check (SNC)** — Verifies frontend health and Beauty Assistant (brain) connectivity: + +```sh +npm run sync:check +``` + +Other scripts: `npm run health` (frontend + Beauty Assistant), `npm run brain` (edge function / Beauty Assistant only). + +**applyToAllProfiles** — Cursor/VS Code user setting so chosen options apply to every profile. In **User** `settings.json` (File → Preferences → Settings → Open Settings JSON), add: + +```json +"workbench.settings.applyToAllProfiles": [ + "workbench.editorAssociations", + "chat.mcp.access", + "npm.scriptExplorerAction", + "update.channel" +] +``` + +Include `update.channel` if you want the same update channel (e.g. stable) across all profiles. + +**commitDirectlyWarning** — Avoid committing directly to the default branch when branch protection or Windows path issues apply; use a feature branch and PR. + +## Available scripts + +| Command | What it does | +|---------|--------------| +| `npm run dev` | Start Vite dev server | +| `npm run build` | Production build | +| `npm run build:dev` | Build in development mode | +| `npm run lint` | Run ESLint | +| `npm run lint:fix` | ESLint with auto-fix | +| `npm run typecheck` | TypeScript check (no emit) | +| `npm run check` | Lint + typecheck | +| `npm run check:all` | Lint + typecheck + build | +| `npm run preview` | Serve production build | +| `npm run test` | Run Vitest once | +| `npm run test:watch` | Vitest watch mode | +| `npm run test:bulk-upload` | Bulk upload validation script | +| `npm run health` | Frontend + Beauty Assistant health check | +| `npm run brain` | Beauty Assistant (brain) connectivity check | +| `npm run sync` | Sync Shopify product catalog to Supabase | +| `npm run sync:check` | Frontend + brain sync check | +| `npm run sync:dry` | Shopify catalog sync (dry run) | +| `npm run sync:publish` | Shopify catalog sync + publish | + diff --git a/package.json b/package.json index c9890b0bd..3f455f53a 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,11 @@ "preview": "vite preview", "test": "vitest run", "test:watch": "vitest", + "test:bulk-upload": "node scripts/test-bulk-upload-validation.mjs", + "health": "node scripts/health-check.js", + "brain": "node scripts/brain-check.js", "sync": "tsx scripts/sync-shopify-catalog.ts", + "sync:check": "node scripts/sync-check.js", "sync:dry": "tsx scripts/sync-shopify-catalog.ts --dry-run", "sync:publish": "tsx scripts/sync-shopify-catalog.ts --publish" }, diff --git a/scripts/brain-check.js b/scripts/brain-check.js new file mode 100644 index 000000000..5046de53b --- /dev/null +++ b/scripts/brain-check.js @@ -0,0 +1,41 @@ +#!/usr/bin/env node +/** + * Asper Beauty Shop — Brain (Beauty Assistant) connectivity check. + * Run: npm run brain + */ + +const BRAIN_URL = + "https://qqceibvalkoytafynwoc.supabase.co/functions/v1/beauty-assistant"; + +async function main() { + console.log("Asper Beauty Shop — Brain connectivity check\n"); + try { + const res = await fetch(BRAIN_URL, { method: "GET" }); + const text = await res.text(); + let body; + try { + body = JSON.parse(text); + } catch { + body = text; + } + // Only 2xx is success. 401 (auth) and 405 (method) must fail so misconfiguration is visible. + if (res.ok) { + console.log(" ✓ Beauty Assistant (Dr. Bot):", res.status); + if (body && typeof body === "object") { + console.log(" ", JSON.stringify(body, null, 2)); + } else if (text) { + console.log(" ", text.slice(0, 200)); + } + console.log(""); + process.exit(0); + } else { + console.log(" ✗ Beauty Assistant:", res.status, body || text); + process.exit(1); + } + } catch (err) { + console.log(" ✗ Error:", err.message); + process.exit(1); + } +} + +main(); diff --git a/scripts/sync-check.js b/scripts/sync-check.js new file mode 100644 index 000000000..c24941d80 --- /dev/null +++ b/scripts/sync-check.js @@ -0,0 +1,46 @@ +#!/usr/bin/env node +/** + * Asper Beauty Shop — Sync check (frontend + brain connectivity). + * Run: npm run sync:check + */ + +const FRONTEND_HEALTH = "https://asperbeautyshop-com.lovable.app/health"; +const BRAIN_URL = + "https://qqceibvalkoytafynwoc.supabase.co/functions/v1/beauty-assistant"; + +async function fetchStatus(name, url) { + try { + const res = await fetch(url, { method: "GET" }); + return { name, status: res.status, ok: res.ok }; + } catch (err) { + return { name, status: null, ok: false, error: err.message }; + } +} + +async function main() { + console.log("Asper Beauty Shop — Sync check\n"); + + const [frontend, brain] = await Promise.all([ + fetchStatus("Frontend /health", FRONTEND_HEALTH), + fetchStatus("Beauty Assistant (brain)", BRAIN_URL), + ]); + + const frontendOk = frontend.status === 200; + const brainOk = brain.status === 200; + + console.log( + frontendOk ? " ✓" : " ✗", + frontend.name + ":", + frontend.status || frontend.error + ); + console.log( + brainOk ? " ✓" : " ✗", + brain.name + ":", + brain.status || brain.error + ); + console.log(""); + + process.exit(frontendOk && brainOk ? 0 : 1); +} + +main(); diff --git a/skills-lock.json b/skills-lock.json new file mode 100644 index 000000000..f5d77554d --- /dev/null +++ b/skills-lock.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "skills": { + "code-connect-components": { + "source": "figma/mcp-server-guide", + "sourceType": "github", + "computedHash": "7d61e4f1fda72024bbe1356eb8e84585870e8c461a1a9eb69a32f4e2c9e1beed" + } + } +} diff --git a/skills/code-connect-components/SKILL.md b/skills/code-connect-components/SKILL.md new file mode 100644 index 000000000..9d3da28b3 --- /dev/null +++ b/skills/code-connect-components/SKILL.md @@ -0,0 +1,54 @@ +--- +name: code-connect-components +description: Wire React (or other UI) components to data, events, and each other; map Figma design components to code (Figma Code Connect). Use when connecting components to APIs/state, implementing parent-child or sibling communication, aligning UI with a design system, or mapping Figma components to code (Figma URL with node-id, scan codebase, present matches). +--- + +# Code Connect Components + +Use this skill to **connect** or **wire** UI components: to data, events, or each other; or to **map Figma design components to code** (Figma Code Connect workflow). + +--- + +## Figma Code Connect (design → code) + +When the task is mapping **Figma** components to code (e.g. user provides a Figma URL or uses figma-desktop MCP): + +1. **Get Code Connect suggestions** — Unmapped components: names, properties, thumbnails. Requires Figma URL with **node-id** or connection to figma-desktop MCP. +2. **Scan codebase** — Search for matching components in `src/components/`, `components/`, or `ui/`: matching names, variant props, structure. +3. **Present matches** — Show findings for user validation. + +**Figma URL:** Must include node-id: `https://figma.com/design/:fileKey/:fileName?node-id=1-2`. Convert to tool format: URLs use hyphens (`node-id=1-2`), tool may expect colons (`nodeId=1:2`). + +**Install reference skill:** `npx skills add https://github.com/figma/mcp-server-guide --skill code-connect-components` + +--- + +## In-app component wiring (data / events / composition) + +When the task is connecting **existing code** components to data, events, or each other: + +1. **Identify touchpoints** — Which component owns the data or event? Which consumes it? +2. **Choose pattern** — Props down, callbacks up; context for cross-tree; URL/query for shareable state. +3. **Implement** — Add props/events; connect to hooks or Supabase; preserve existing types and RTL/i18n where applicable. +4. **Verify** — No broken imports; component still used where it was (e.g. App shell, layout). + +### Patterns in this project + +- **Dr. Bot / Beauty Assistant** — Chat/concierge entry points (e.g. "Consult") should dispatch `open-beauty-assistant` or open the concierge UI. Persona: `supabase/functions/beauty-assistant/index.ts` (buildSystemPrompt). +- **Supabase** — Use `createClient` from `@supabase/supabase-js`; auth for protected flows. Concierge/telemetry: `log-concierge-events`, `log-telemetry` edge functions. +- **Bilingual / RTL** — Prefer existing i18n/theme hooks; keep Arabic/EN and RTL in mind when adding copy or layout. +- **Design system** — Reuse primitives from `src/components`; match clinical-luxury tone and brand tokens. + +--- + +## When to use + +- "Connect this component to…" / "Wire X to Y" +- "Make this button open the chat" / "Link to Dr. Bot" +- "Use the same data here as on page X" +- "Map this Figma component to our code" / Figma URL with node-id / Code Connect + +## Out of scope + +- Defining new design-system primitives from scratch (use existing; extend only when necessary). +- Backend-only changes (edge function logic lives in `supabase/functions`; connect via existing APIs). diff --git a/skills/get-pr-comments/SKILL.md b/skills/get-pr-comments/SKILL.md new file mode 100644 index 000000000..84e7c4b72 --- /dev/null +++ b/skills/get-pr-comments/SKILL.md @@ -0,0 +1,50 @@ +--- +name: get-pr-comments +description: Fetch and display comments from the active PR for the current branch. Use when the user asks for PR comments, review feedback, or "get pr comments" / "apply this skill". +--- + +# Get PR Comments + +Fetch and display comments from the **active pull request** for the current branch (Cursor Team Kit style). + +--- + +## Steps + +1. **Check `gh` CLI** — Verify the GitHub CLI is available (`gh --version` or `where gh`). If not, tell the user to install [GitHub CLI](https://cli.github.com/). + +2. **Check for an open PR** — Run: + ```bash + gh pr view --json number,url,title + ``` + - If no PR exists for this branch, inform the user: *"There is no open PR for this branch."* + - If a PR exists, continue. + +3. **Fetch PR comments and reviews** — Run: + ```bash + gh pr view --json comments,reviews + ``` + Optionally for full thread context: + ```bash + gh pr view --json comments,reviews,reviewRequests + ``` + +4. **Display in a readable format**: + - **Review comments**: author, date, body (and path/line if present). + - **General PR comments**: author, date, body. + - Group by review thread where applicable. + +5. **Summarize** — Briefly summarize reviewer feedback and any **action items** or requested changes. + +--- + +## When to use + +- User says "get PR comments", "show PR feedback", "what did reviewers say?", or "apply get-pr-comments". +- Before addressing review feedback or merging. +- When preparing a response to reviewers. + +## Requirements + +- **GitHub CLI** (`gh`) installed and authenticated (`gh auth status`). +- Current branch must have an open PR. diff --git a/supabase/functions/beauty-assistant/index.ts b/supabase/functions/beauty-assistant/index.ts index 2c3d3b28e..5d906c7e9 100644 --- a/supabase/functions/beauty-assistant/index.ts +++ b/supabase/functions/beauty-assistant/index.ts @@ -1,4 +1,13 @@ +/** + * Beauty Assistant (Dr. Bot) — Supabase Edge Function. + * Dr. Bot = Asper Dual-Voice Concierge: Dr. Sami (clinical) + Ms. Zain (luxury). Single AI, context-switching persona. + * Webhooks: Gorgias / ManyChat (no auth). Website chat: Supabase Auth + SSE. + * Project scripts (SNC, health, brain), applyToAllProfiles, and commitDirectlyWarning: see README. + */ +declare const Deno: { env: { get(key: string): string | undefined } }; +// @ts-expect-error — Deno URL imports; resolved at runtime by Supabase Edge import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; +// @ts-expect-error — Deno URL imports; resolved at runtime by Supabase Edge import { createClient } from "https://esm.sh/@supabase/supabase-js@2"; // Staging origins allowed alongside production ALLOWED_ORIGIN @@ -236,7 +245,7 @@ async function fetchProductContext( // System Prompt Builder // ────────────────────────────────────────────────────────────── function buildSystemPrompt(productContext: string, shopRoutinePath: string | null): string { - return `You are the **Asper Dual-Voice Concierge** — "One Brain, Two Voices" — for Asper Beauty Shop (asperbeautyshop.com), Amman, Jordan. You operate as either **Dr. Sami** (Voice of Science) or **Ms. Zain** (Voice of Luxury) depending on the user's intent. Both voices share the same Medical Luxury identity: pharmacist-curated, authentic, precise, never pushy. Recommend ONLY from the product inventory listed below when available; name title, brand, and price. + return `You are **Dr. Bot** — the Asper Dual-Voice Concierge for Asper Beauty Shop (asperbeautyshop.com) in Jordan. You operate as **Dr. Sami** (Voice of Science) or **Ms. Zain** (Voice of Luxury) depending on the user's intent. Both voices share the same Medical Luxury identity: pharmacist-curated, authentic, precise, never pushy. Recommend ONLY from the product inventory listed below when available; name title, brand, and price. ## DR. SAMI — The Voice of Science (Clinical Authority) - **Triggers on:** medical, clinical, safety, ingredients, pregnancy, supplements, dosage, retinol, SPF, sunscreen, allergy, barrier repair, eczema, rosacea, acne, hyperpigmentation, dermatologist, pharmacist, side effects, contraindications, drug interactions, salicylic acid, benzoyl peroxide, AHA, BHA, hydroquinone, sensitive skin reactions, vitamin deficiency, collagen supplements, hair loss treatment, hormonal acne @@ -291,8 +300,8 @@ When the user mentions **bridal, wedding, عروس, زفاف, engagement, خطو - **Free Shipping Nudge:** If cart < 50 JOD, suggest a small add-on (lip balm, travel size, sheet mask) to qualify. Frame it as value: "Add a travel-size Thermal Water (3.5 JOD) to unlock free delivery!" - **Replenishment Cycle:** Standard skincare products last ~2 months. If a returning user hasn't reordered in 8+ weeks, gently ask: "How's your [product] holding up? Time for a refill?" -## Sales & Trust -- If user hesitates, pivot to trust: "Every bottle carries our Seal of Authenticity — pharmacist-vetted, JFDA certified." +## Trust & Authenticity +- **Trust & Authenticity:** Every bottle carries our Seal of Authenticity — pharmacist-vetted, JFDA certified. Gold Standard: 100% guaranteed authenticity. If user hesitates, pivot to this. - Never invent products. If no match found, say so honestly and invite browsing. ## Store Knowledge @@ -561,12 +570,17 @@ serve(async (req) => { // Fetch product context using service role key for unrestricted catalog access. // The products table uses RLS; service role bypasses those policies so the edge // function can always return relevant product recommendations regardless of the - // calling user's permissions. - const serviceClient = createClient( - Deno.env.get("SUPABASE_URL")!, - Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!, - ); - const { productContext, matchedProducts } = await fetchProductContext(serviceClient, lastText, detectedConcernSlug); + // calling user's permissions. Falls back gracefully if credentials are absent. + const supabaseUrl = Deno.env.get("SUPABASE_URL"); + const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY"); + let productContext = ""; + let matchedProducts: unknown[] = []; + if (supabaseUrl && supabaseServiceKey) { + const serviceClient = createClient(supabaseUrl, supabaseServiceKey); + const result = await fetchProductContext(serviceClient, lastText, detectedConcernSlug); + productContext = result.productContext; + matchedProducts = result.matchedProducts; + } // Detect persona from user message // Dual-Persona detection — Dr. Sami (clinical) vs Ms. Zain (beauty/aesthetic)