opencastle 0.10.0 → 0.10.2
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/README.md +11 -77
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +13 -7
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +7 -2
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/init.test.d.ts +17 -0
- package/dist/cli/init.test.d.ts.map +1 -0
- package/dist/cli/init.test.js +881 -0
- package/dist/cli/init.test.js.map +1 -0
- package/dist/cli/mcp.d.ts +9 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +56 -0
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/stack-config-update.test.d.ts +2 -0
- package/dist/cli/stack-config-update.test.d.ts.map +1 -0
- package/dist/cli/stack-config-update.test.js +185 -0
- package/dist/cli/stack-config-update.test.js.map +1 -0
- package/dist/cli/stack-config.d.ts +27 -0
- package/dist/cli/stack-config.d.ts.map +1 -1
- package/dist/cli/stack-config.js +80 -27
- package/dist/cli/stack-config.js.map +1 -1
- package/dist/cli/types.d.ts +1 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +184 -17
- package/dist/cli/update.js.map +1 -1
- package/dist/orchestrator/plugins/astro/config.d.ts +3 -0
- package/dist/orchestrator/plugins/astro/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/astro/config.js +27 -0
- package/dist/orchestrator/plugins/astro/config.js.map +1 -0
- package/dist/orchestrator/plugins/chrome-devtools/config.js +2 -2
- package/dist/orchestrator/plugins/chrome-devtools/config.js.map +1 -1
- package/dist/orchestrator/plugins/contentful/config.js +1 -1
- package/dist/orchestrator/plugins/contentful/config.js.map +1 -1
- package/dist/orchestrator/plugins/convex/config.js +1 -1
- package/dist/orchestrator/plugins/convex/config.js.map +1 -1
- package/dist/orchestrator/plugins/cypress/config.d.ts +3 -0
- package/dist/orchestrator/plugins/cypress/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/cypress/config.js +15 -0
- package/dist/orchestrator/plugins/cypress/config.js.map +1 -0
- package/dist/orchestrator/plugins/figma/config.d.ts +3 -0
- package/dist/orchestrator/plugins/figma/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/figma/config.js +31 -0
- package/dist/orchestrator/plugins/figma/config.js.map +1 -0
- package/dist/orchestrator/plugins/index.d.ts.map +1 -1
- package/dist/orchestrator/plugins/index.js +20 -0
- package/dist/orchestrator/plugins/index.js.map +1 -1
- package/dist/orchestrator/plugins/jira/config.d.ts.map +1 -1
- package/dist/orchestrator/plugins/jira/config.js +2 -3
- package/dist/orchestrator/plugins/jira/config.js.map +1 -1
- package/dist/orchestrator/plugins/linear/config.js +2 -2
- package/dist/orchestrator/plugins/linear/config.js.map +1 -1
- package/dist/orchestrator/plugins/netlify/config.d.ts +3 -0
- package/dist/orchestrator/plugins/netlify/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/netlify/config.js +30 -0
- package/dist/orchestrator/plugins/netlify/config.js.map +1 -0
- package/dist/orchestrator/plugins/nextjs/config.d.ts +3 -0
- package/dist/orchestrator/plugins/nextjs/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/nextjs/config.js +35 -0
- package/dist/orchestrator/plugins/nextjs/config.js.map +1 -0
- package/dist/orchestrator/plugins/nx/config.d.ts.map +1 -1
- package/dist/orchestrator/plugins/nx/config.js +2 -3
- package/dist/orchestrator/plugins/nx/config.js.map +1 -1
- package/dist/orchestrator/plugins/playwright/config.d.ts +3 -0
- package/dist/orchestrator/plugins/playwright/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/playwright/config.js +25 -0
- package/dist/orchestrator/plugins/playwright/config.js.map +1 -0
- package/dist/orchestrator/plugins/prisma/config.d.ts +3 -0
- package/dist/orchestrator/plugins/prisma/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/prisma/config.js +25 -0
- package/dist/orchestrator/plugins/prisma/config.js.map +1 -0
- package/dist/orchestrator/plugins/resend/config.d.ts +3 -0
- package/dist/orchestrator/plugins/resend/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/resend/config.js +46 -0
- package/dist/orchestrator/plugins/resend/config.js.map +1 -0
- package/dist/orchestrator/plugins/sanity/config.d.ts.map +1 -1
- package/dist/orchestrator/plugins/sanity/config.js +1 -2
- package/dist/orchestrator/plugins/sanity/config.js.map +1 -1
- package/dist/orchestrator/plugins/slack/config.js +1 -1
- package/dist/orchestrator/plugins/slack/config.js.map +1 -1
- package/dist/orchestrator/plugins/strapi/config.js +1 -1
- package/dist/orchestrator/plugins/strapi/config.js.map +1 -1
- package/dist/orchestrator/plugins/supabase/config.d.ts.map +1 -1
- package/dist/orchestrator/plugins/supabase/config.js +1 -2
- package/dist/orchestrator/plugins/supabase/config.js.map +1 -1
- package/dist/orchestrator/plugins/teams/config.d.ts.map +1 -1
- package/dist/orchestrator/plugins/teams/config.js +1 -2
- package/dist/orchestrator/plugins/teams/config.js.map +1 -1
- package/dist/orchestrator/plugins/turborepo/config.d.ts +3 -0
- package/dist/orchestrator/plugins/turborepo/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/turborepo/config.js +15 -0
- package/dist/orchestrator/plugins/turborepo/config.js.map +1 -0
- package/dist/orchestrator/plugins/types.d.ts +7 -7
- package/dist/orchestrator/plugins/types.d.ts.map +1 -1
- package/dist/orchestrator/plugins/vercel/config.d.ts.map +1 -1
- package/dist/orchestrator/plugins/vercel/config.js +2 -3
- package/dist/orchestrator/plugins/vercel/config.js.map +1 -1
- package/dist/orchestrator/plugins/vitest/config.d.ts +3 -0
- package/dist/orchestrator/plugins/vitest/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/vitest/config.js +15 -0
- package/dist/orchestrator/plugins/vitest/config.js.map +1 -0
- package/package.json +1 -1
- package/src/cli/doctor.ts +14 -7
- package/src/cli/init.test.ts +1141 -0
- package/src/cli/init.ts +8 -2
- package/src/cli/mcp.ts +77 -1
- package/src/cli/stack-config-update.test.ts +210 -0
- package/src/cli/stack-config.ts +110 -37
- package/src/cli/types.ts +1 -1
- package/src/cli/update.ts +230 -23
- package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
- package/src/orchestrator/agents/api-designer.agent.md +1 -11
- package/src/orchestrator/agents/architect.agent.md +1 -9
- package/src/orchestrator/agents/content-engineer.agent.md +1 -5
- package/src/orchestrator/agents/copywriter.agent.md +1 -9
- package/src/orchestrator/agents/data-expert.agent.md +2 -6
- package/src/orchestrator/agents/database-engineer.agent.md +1 -6
- package/src/orchestrator/agents/developer.agent.md +2 -12
- package/src/orchestrator/agents/devops-expert.agent.md +1 -5
- package/src/orchestrator/agents/documentation-writer.agent.md +1 -4
- package/src/orchestrator/agents/performance-expert.agent.md +1 -5
- package/src/orchestrator/agents/release-manager.agent.md +1 -11
- package/src/orchestrator/agents/researcher.agent.md +1 -4
- package/src/orchestrator/agents/security-expert.agent.md +2 -7
- package/src/orchestrator/agents/seo-specialist.agent.md +1 -10
- package/src/orchestrator/agents/testing-expert.agent.md +2 -11
- package/src/orchestrator/agents/ui-ux-expert.agent.md +3 -10
- package/src/orchestrator/customizations/README.md +2 -1
- package/src/orchestrator/customizations/agents/skill-matrix.json +106 -0
- package/src/orchestrator/customizations/agents/skill-matrix.md +58 -121
- package/src/orchestrator/instructions/general.instructions.md +1 -1
- package/src/orchestrator/plugins/astro/SKILL.md +288 -0
- package/src/orchestrator/plugins/astro/config.ts +28 -0
- package/src/orchestrator/plugins/chrome-devtools/config.ts +2 -2
- package/src/orchestrator/plugins/contentful/config.ts +1 -1
- package/src/orchestrator/plugins/convex/config.ts +1 -1
- package/src/orchestrator/plugins/cypress/SKILL.md +145 -0
- package/src/orchestrator/plugins/cypress/config.ts +16 -0
- package/src/orchestrator/plugins/figma/SKILL.md +85 -0
- package/src/orchestrator/plugins/figma/config.ts +32 -0
- package/src/orchestrator/plugins/index.ts +20 -0
- package/src/orchestrator/plugins/jira/config.ts +2 -3
- package/src/orchestrator/plugins/linear/config.ts +2 -2
- package/src/orchestrator/plugins/netlify/SKILL.md +134 -0
- package/src/orchestrator/plugins/netlify/config.ts +31 -0
- package/src/orchestrator/plugins/nextjs/SKILL.md +376 -0
- package/src/orchestrator/plugins/nextjs/config.ts +36 -0
- package/src/orchestrator/plugins/nx/config.ts +2 -3
- package/src/orchestrator/plugins/playwright/SKILL.md +191 -0
- package/src/orchestrator/plugins/playwright/config.ts +26 -0
- package/src/orchestrator/plugins/prisma/SKILL.md +137 -0
- package/src/orchestrator/plugins/prisma/config.ts +26 -0
- package/src/orchestrator/plugins/resend/SKILL.md +187 -0
- package/src/orchestrator/plugins/resend/config.ts +47 -0
- package/src/orchestrator/plugins/sanity/config.ts +1 -2
- package/src/orchestrator/plugins/slack/config.ts +1 -1
- package/src/orchestrator/plugins/strapi/config.ts +1 -1
- package/src/orchestrator/plugins/supabase/config.ts +1 -2
- package/src/orchestrator/plugins/teams/config.ts +1 -2
- package/src/orchestrator/plugins/turborepo/SKILL.md +121 -0
- package/src/orchestrator/plugins/turborepo/config.ts +16 -0
- package/src/orchestrator/plugins/types.ts +7 -7
- package/src/orchestrator/plugins/vercel/SKILL.md +99 -0
- package/src/orchestrator/plugins/vercel/config.ts +2 -3
- package/src/orchestrator/plugins/vitest/SKILL.md +166 -0
- package/src/orchestrator/plugins/vitest/config.ts +16 -0
- package/src/orchestrator/prompts/bootstrap-customizations.prompt.md +6 -4
- package/src/orchestrator/prompts/create-skill.prompt.md +6 -7
- package/src/orchestrator/skills/agent-hooks/SKILL.md +2 -2
- package/src/orchestrator/skills/memory-merger/SKILL.md +1 -1
- package/src/orchestrator/skills/nextjs-patterns/SKILL.md +0 -200
|
@@ -27,7 +27,7 @@ export const config: PluginConfig = {
|
|
|
27
27
|
'convex/envList', 'convex/envGet', 'convex/logs', 'convex/insights',
|
|
28
28
|
],
|
|
29
29
|
},
|
|
30
|
-
docsUrl:
|
|
30
|
+
docsUrl: 'https://www.opencastle.dev/docs/plugins#convex',
|
|
31
31
|
officialDocs: 'https://docs.convex.dev/',
|
|
32
32
|
mcpPackage: 'convex',
|
|
33
33
|
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cypress-testing
|
|
3
|
+
description: "Cypress E2E and component testing patterns, commands, selectors, and CI configuration. Use when writing E2E tests, component tests, or configuring Cypress in CI pipelines."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- ⚠️ This file is managed by OpenCastle. Edits will be overwritten on update. Customize in the .github/customizations/ directory instead. -->
|
|
7
|
+
|
|
8
|
+
# Cypress Testing
|
|
9
|
+
|
|
10
|
+
Cypress-specific E2E and component testing patterns. For project-specific test configuration and breakpoints, see [testing-config.md](../../customizations/stack/testing-config.md).
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx cypress open # Open interactive test runner
|
|
16
|
+
npx cypress run # Run tests headlessly (CI)
|
|
17
|
+
npx cypress run --spec "cypress/e2e/auth/**" # Run specific specs
|
|
18
|
+
npx cypress run --browser chrome # Specify browser
|
|
19
|
+
npx cypress run --headed # Run with visible browser
|
|
20
|
+
npx cypress run --component # Run component tests only
|
|
21
|
+
npx cypress run --record # Record to Cypress Cloud
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Test Structure
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
cypress/
|
|
28
|
+
├── e2e/ # E2E test specs
|
|
29
|
+
│ ├── auth/
|
|
30
|
+
│ │ ├── login.cy.ts
|
|
31
|
+
│ │ └── signup.cy.ts
|
|
32
|
+
│ └── dashboard/
|
|
33
|
+
│ └── overview.cy.ts
|
|
34
|
+
├── fixtures/ # Test data (JSON)
|
|
35
|
+
│ └── users.json
|
|
36
|
+
├── support/
|
|
37
|
+
│ ├── commands.ts # Custom commands
|
|
38
|
+
│ ├── e2e.ts # E2E support file
|
|
39
|
+
│ └── component.ts # Component test support
|
|
40
|
+
└── downloads/ # Downloaded files during tests
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Writing Tests
|
|
44
|
+
|
|
45
|
+
### E2E Test Pattern
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// cypress/e2e/auth/login.cy.ts
|
|
49
|
+
describe('Login', () => {
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
cy.visit('/login');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should log in with valid credentials', () => {
|
|
55
|
+
cy.get('[data-testid="email-input"]').type('user@example.com');
|
|
56
|
+
cy.get('[data-testid="password-input"]').type('password123');
|
|
57
|
+
cy.get('[data-testid="login-button"]').click();
|
|
58
|
+
|
|
59
|
+
cy.url().should('include', '/dashboard');
|
|
60
|
+
cy.get('[data-testid="user-menu"]').should('be.visible');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should show error for invalid credentials', () => {
|
|
64
|
+
cy.get('[data-testid="email-input"]').type('wrong@example.com');
|
|
65
|
+
cy.get('[data-testid="password-input"]').type('wrong');
|
|
66
|
+
cy.get('[data-testid="login-button"]').click();
|
|
67
|
+
|
|
68
|
+
cy.get('[data-testid="error-message"]').should('contain', 'Invalid credentials');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Custom Commands
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// cypress/support/commands.ts
|
|
77
|
+
Cypress.Commands.add('login', (email: string, password: string) => {
|
|
78
|
+
cy.session([email, password], () => {
|
|
79
|
+
cy.visit('/login');
|
|
80
|
+
cy.get('[data-testid="email-input"]').type(email);
|
|
81
|
+
cy.get('[data-testid="password-input"]').type(password);
|
|
82
|
+
cy.get('[data-testid="login-button"]').click();
|
|
83
|
+
cy.url().should('include', '/dashboard');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Selector Strategy
|
|
89
|
+
|
|
90
|
+
Priority order for selecting elements:
|
|
91
|
+
|
|
92
|
+
1. `data-testid` attributes — most resilient to UI changes
|
|
93
|
+
2. `aria-label` or `role` — accessible and meaningful
|
|
94
|
+
3. Dedicated CSS classes — avoid styling classes
|
|
95
|
+
4. **Never** use tag names, auto-generated classes, or fragile CSS paths
|
|
96
|
+
|
|
97
|
+
## Best Practices
|
|
98
|
+
|
|
99
|
+
- Use `cy.intercept()` to stub/spy on API calls — don't depend on backend state
|
|
100
|
+
- Use `cy.session()` for authentication — avoid logging in before every test
|
|
101
|
+
- Avoid `cy.wait(ms)` — use `cy.intercept()` with aliases instead
|
|
102
|
+
- Assert on visible elements — Cypress auto-retries, so assertions are resilient
|
|
103
|
+
- Keep tests independent — each test should set up its own state
|
|
104
|
+
- Use fixtures for test data — avoid hardcoding values in tests
|
|
105
|
+
- Add `data-testid` attributes to components during development, not retroactively
|
|
106
|
+
|
|
107
|
+
## CI Configuration
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
# GitHub Actions example
|
|
111
|
+
cypress:
|
|
112
|
+
runs-on: ubuntu-latest
|
|
113
|
+
steps:
|
|
114
|
+
- uses: actions/checkout@v4
|
|
115
|
+
- uses: cypress-io/github-action@v6
|
|
116
|
+
with:
|
|
117
|
+
build: npm run build
|
|
118
|
+
start: npm run start
|
|
119
|
+
wait-on: 'http://localhost:3000'
|
|
120
|
+
browser: chrome
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Configuration (cypress.config.ts)
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { defineConfig } from 'cypress';
|
|
127
|
+
|
|
128
|
+
export default defineConfig({
|
|
129
|
+
e2e: {
|
|
130
|
+
baseUrl: 'http://localhost:3000',
|
|
131
|
+
viewportWidth: 1280,
|
|
132
|
+
viewportHeight: 720,
|
|
133
|
+
video: false,
|
|
134
|
+
screenshotOnRunFailure: true,
|
|
135
|
+
defaultCommandTimeout: 10000,
|
|
136
|
+
retries: { runMode: 2, openMode: 0 },
|
|
137
|
+
},
|
|
138
|
+
component: {
|
|
139
|
+
devServer: {
|
|
140
|
+
framework: 'next',
|
|
141
|
+
bundler: 'webpack',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PluginConfig } from '../types.js';
|
|
2
|
+
|
|
3
|
+
export const config: PluginConfig = {
|
|
4
|
+
id: 'cypress',
|
|
5
|
+
name: 'Cypress',
|
|
6
|
+
category: 'tech',
|
|
7
|
+
subCategory: 'e2e-testing',
|
|
8
|
+
label: 'Cypress',
|
|
9
|
+
hint: 'E2E and component testing in the browser',
|
|
10
|
+
skillName: 'cypress-testing',
|
|
11
|
+
authType: 'none',
|
|
12
|
+
envVars: [],
|
|
13
|
+
agentToolMap: {},
|
|
14
|
+
docsUrl: 'https://www.opencastle.dev/docs/plugins#cypress',
|
|
15
|
+
officialDocs: 'https://docs.cypress.io',
|
|
16
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: figma-design
|
|
3
|
+
description: "Figma design-to-code workflows, design token extraction, component inspection, and asset export. Use when translating Figma designs into code, extracting design tokens, or referencing component specs."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- ⚠️ This file is managed by OpenCastle. Edits will be overwritten on update. Customize in the .github/customizations/ directory instead. -->
|
|
7
|
+
|
|
8
|
+
# Figma Design
|
|
9
|
+
|
|
10
|
+
Figma-specific design-to-code patterns and MCP tool usage. For project-specific design system details, see the **frontend-design** skill.
|
|
11
|
+
|
|
12
|
+
## MCP Tools
|
|
13
|
+
|
|
14
|
+
The Figma MCP server enables AI agents to inspect designs directly:
|
|
15
|
+
|
|
16
|
+
| Tool | Purpose | Primary Agents |
|
|
17
|
+
|------|---------|----------------|
|
|
18
|
+
| `figma/get_file` | Retrieve full Figma file structure | UI/UX Expert |
|
|
19
|
+
| `figma/get_file_nodes` | Get specific nodes/frames | UI/UX Expert, Developer |
|
|
20
|
+
| `figma/get_images` | Export nodes as images | UI/UX Expert |
|
|
21
|
+
| `figma/get_comments` | Read design review comments | UI/UX Expert |
|
|
22
|
+
| `figma/get_styles` | Extract color/text/effect styles | Developer |
|
|
23
|
+
| `figma/get_components` | List reusable components | Developer |
|
|
24
|
+
|
|
25
|
+
## Design-to-Code Workflow
|
|
26
|
+
|
|
27
|
+
1. **Identify the frame** — get the Figma file URL or node ID from the task
|
|
28
|
+
2. **Inspect the design** — use `get_file_nodes` to retrieve layout, spacing, colors, typography
|
|
29
|
+
3. **Extract tokens** — map Figma styles to CSS custom properties or design tokens
|
|
30
|
+
4. **Build components** — translate Figma components to React/framework components
|
|
31
|
+
5. **Verify** — compare the implementation against the original design visually
|
|
32
|
+
|
|
33
|
+
## Design Token Extraction
|
|
34
|
+
|
|
35
|
+
### From Figma Styles to CSS
|
|
36
|
+
|
|
37
|
+
```css
|
|
38
|
+
/* Map Figma color styles to CSS custom properties */
|
|
39
|
+
:root {
|
|
40
|
+
/* Primary */
|
|
41
|
+
--color-primary-50: #eff6ff;
|
|
42
|
+
--color-primary-500: #3b82f6;
|
|
43
|
+
--color-primary-900: #1e3a8a;
|
|
44
|
+
|
|
45
|
+
/* Typography (from Figma text styles) */
|
|
46
|
+
--font-heading: 'Inter', sans-serif;
|
|
47
|
+
--font-body: 'Inter', sans-serif;
|
|
48
|
+
--font-size-sm: 0.875rem; /* 14px */
|
|
49
|
+
--font-size-base: 1rem; /* 16px */
|
|
50
|
+
--font-size-lg: 1.125rem; /* 18px */
|
|
51
|
+
--font-size-xl: 1.25rem; /* 20px */
|
|
52
|
+
|
|
53
|
+
/* Spacing (from Figma auto-layout) */
|
|
54
|
+
--space-xs: 4px;
|
|
55
|
+
--space-sm: 8px;
|
|
56
|
+
--space-md: 16px;
|
|
57
|
+
--space-lg: 24px;
|
|
58
|
+
--space-xl: 32px;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Translation Rules
|
|
63
|
+
|
|
64
|
+
| Figma Concept | Code Equivalent |
|
|
65
|
+
|---------------|----------------|
|
|
66
|
+
| Auto Layout → horizontal | `display: flex; flex-direction: row` |
|
|
67
|
+
| Auto Layout → vertical | `display: flex; flex-direction: column` |
|
|
68
|
+
| Auto Layout gap | `gap: Npx` |
|
|
69
|
+
| Auto Layout padding | `padding: top right bottom left` |
|
|
70
|
+
| Fill → Hug contents | `width: auto` or `width: fit-content` |
|
|
71
|
+
| Fill → Fixed | `width: Npx` |
|
|
72
|
+
| Fill → Fill container | `flex: 1` or `width: 100%` |
|
|
73
|
+
| Corner radius | `border-radius: Npx` |
|
|
74
|
+
| Drop shadow | `box-shadow: x y blur spread color` |
|
|
75
|
+
| Opacity | `opacity: N` |
|
|
76
|
+
|
|
77
|
+
## Best Practices
|
|
78
|
+
|
|
79
|
+
- Always extract design tokens systematically — don't hardcode values from visual inspection
|
|
80
|
+
- Use Figma's auto-layout values directly for flex/grid properties
|
|
81
|
+
- Match Figma's responsive breakpoints to the project's breakpoint system
|
|
82
|
+
- Export SVG assets directly from Figma via `get_images` — don't recreate manually
|
|
83
|
+
- Cross-reference Figma component names with the codebase component library
|
|
84
|
+
- When in doubt about values, inspect the Figma node — don't approximate
|
|
85
|
+
- Keep a mapping document between Figma styles and CSS custom properties
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PluginConfig } from '../types.js';
|
|
2
|
+
|
|
3
|
+
export const config: PluginConfig = {
|
|
4
|
+
id: 'figma',
|
|
5
|
+
name: 'Figma',
|
|
6
|
+
category: 'tech',
|
|
7
|
+
subCategory: 'design',
|
|
8
|
+
label: 'Figma',
|
|
9
|
+
hint: 'Design tokens, component specs, asset export',
|
|
10
|
+
skillName: 'figma-design',
|
|
11
|
+
mcpServerKey: 'Figma',
|
|
12
|
+
mcpConfig: {
|
|
13
|
+
type: 'stdio',
|
|
14
|
+
command: 'npx',
|
|
15
|
+
args: ['-y', '@anthropic/figma-mcp@latest'],
|
|
16
|
+
envFile: '${workspaceFolder}/.env'
|
|
17
|
+
},
|
|
18
|
+
authType: 'env-token',
|
|
19
|
+
envVars: [
|
|
20
|
+
{
|
|
21
|
+
name: 'FIGMA_ACCESS_TOKEN',
|
|
22
|
+
hint: 'Generate at figma.com → Settings → Personal access tokens',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
agentToolMap: {
|
|
26
|
+
'ui-ux-expert': ['figma/*'],
|
|
27
|
+
'developer': ['figma/*'],
|
|
28
|
+
},
|
|
29
|
+
docsUrl: 'https://www.opencastle.dev/docs/plugins#figma',
|
|
30
|
+
officialDocs: 'https://www.figma.com/developers/api',
|
|
31
|
+
mcpPackage: '@anthropic/figma-mcp',
|
|
32
|
+
};
|
|
@@ -11,6 +11,16 @@ import { config as jira } from './jira/config.js';
|
|
|
11
11
|
import { config as slack } from './slack/config.js';
|
|
12
12
|
import { config as teams } from './teams/config.js';
|
|
13
13
|
import { config as chromeDevtools } from './chrome-devtools/config.js';
|
|
14
|
+
import { config as netlify } from './netlify/config.js';
|
|
15
|
+
import { config as turborepo } from './turborepo/config.js';
|
|
16
|
+
import { config as prisma } from './prisma/config.js';
|
|
17
|
+
import { config as cypress } from './cypress/config.js';
|
|
18
|
+
import { config as playwright } from './playwright/config.js';
|
|
19
|
+
import { config as vitest } from './vitest/config.js';
|
|
20
|
+
import { config as figma } from './figma/config.js';
|
|
21
|
+
import { config as resend } from './resend/config.js';
|
|
22
|
+
import { config as nextjs } from './nextjs/config.js';
|
|
23
|
+
import { config as astro } from './astro/config.js';
|
|
14
24
|
|
|
15
25
|
export type { PluginConfig, McpServerConfig, McpInput, EnvVarRequirement } from './types.js';
|
|
16
26
|
|
|
@@ -24,6 +34,16 @@ export const PLUGINS: Record<string, PluginConfig> = {
|
|
|
24
34
|
vercel,
|
|
25
35
|
nx,
|
|
26
36
|
'chrome-devtools': chromeDevtools,
|
|
37
|
+
netlify,
|
|
38
|
+
turborepo,
|
|
39
|
+
prisma,
|
|
40
|
+
cypress,
|
|
41
|
+
playwright,
|
|
42
|
+
vitest,
|
|
43
|
+
figma,
|
|
44
|
+
resend,
|
|
45
|
+
nextjs,
|
|
46
|
+
astro,
|
|
27
47
|
linear,
|
|
28
48
|
jira,
|
|
29
49
|
slack,
|
|
@@ -4,7 +4,7 @@ export const config: PluginConfig = {
|
|
|
4
4
|
id: 'jira',
|
|
5
5
|
name: 'Jira',
|
|
6
6
|
category: 'team',
|
|
7
|
-
subCategory: '
|
|
7
|
+
subCategory: 'task-management',
|
|
8
8
|
label: 'Jira',
|
|
9
9
|
hint: 'Atlassian issue tracking via Rovo MCP',
|
|
10
10
|
skillName: 'jira-management',
|
|
@@ -24,7 +24,6 @@ export const config: PluginConfig = {
|
|
|
24
24
|
'Jira/getAccessibleAtlassianResources',
|
|
25
25
|
],
|
|
26
26
|
},
|
|
27
|
-
docsUrl:
|
|
27
|
+
docsUrl: 'https://www.opencastle.dev/docs/plugins#jira',
|
|
28
28
|
officialDocs: 'https://developer.atlassian.com/cloud/jira/platform/',
|
|
29
|
-
mcpPackage: null,
|
|
30
29
|
};
|
|
@@ -4,7 +4,7 @@ export const config: PluginConfig = {
|
|
|
4
4
|
id: 'linear',
|
|
5
5
|
name: 'Linear',
|
|
6
6
|
category: 'team',
|
|
7
|
-
subCategory: '
|
|
7
|
+
subCategory: 'task-management',
|
|
8
8
|
label: 'Linear',
|
|
9
9
|
hint: 'Issue tracking with MCP integration',
|
|
10
10
|
skillName: 'linear-task-management',
|
|
@@ -28,7 +28,7 @@ export const config: PluginConfig = {
|
|
|
28
28
|
'linear/list_teams', 'linear/list_projects', 'linear/get_issue', 'linear/search_issues',
|
|
29
29
|
],
|
|
30
30
|
},
|
|
31
|
-
docsUrl: '/guides/linear-setup',
|
|
31
|
+
docsUrl: 'https://www.opencastle.dev/guides/linear-setup',
|
|
32
32
|
officialDocs: 'https://linear.app/docs',
|
|
33
33
|
mcpPackage: '@mseep/linear-mcp',
|
|
34
34
|
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: netlify-deployment
|
|
3
|
+
description: "Netlify deployment workflows, serverless functions, edge functions, environment management, and build configuration. Use when deploying to Netlify, writing serverless/edge functions, or troubleshooting builds."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- ⚠️ This file is managed by OpenCastle. Edits will be overwritten on update. Customize in the .github/customizations/ directory instead. -->
|
|
7
|
+
|
|
8
|
+
# Netlify Deployment
|
|
9
|
+
|
|
10
|
+
Netlify-specific deployment patterns and conventions. For project-specific deployment architecture, environment variables, and key files, see [deployment-config.md](../../customizations/stack/deployment-config.md).
|
|
11
|
+
|
|
12
|
+
## Deployment Model
|
|
13
|
+
|
|
14
|
+
Netlify uses Git-based continuous deployment:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
main branch → Production deployment (auto)
|
|
18
|
+
feature/* → Deploy preview (auto, unique URL)
|
|
19
|
+
fix/* → Deploy preview (auto, unique URL)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
- Every push triggers a build — no manual deploys needed
|
|
23
|
+
- Deploy previews get unique URLs for PR-based testing
|
|
24
|
+
- Instant rollback to any previous deploy from the dashboard
|
|
25
|
+
- Branch deploys can be configured for specific branches beyond `main`
|
|
26
|
+
|
|
27
|
+
## Build Configuration (netlify.toml)
|
|
28
|
+
|
|
29
|
+
```toml
|
|
30
|
+
[build]
|
|
31
|
+
command = "npm run build"
|
|
32
|
+
publish = "dist" # or ".next", "out", "build"
|
|
33
|
+
|
|
34
|
+
[build.environment]
|
|
35
|
+
NODE_VERSION = "20"
|
|
36
|
+
|
|
37
|
+
[[redirects]]
|
|
38
|
+
from = "/*"
|
|
39
|
+
to = "/index.html"
|
|
40
|
+
status = 200
|
|
41
|
+
conditions = {Role = ["admin"]}
|
|
42
|
+
|
|
43
|
+
[[headers]]
|
|
44
|
+
for = "/*"
|
|
45
|
+
[headers.values]
|
|
46
|
+
X-Frame-Options = "DENY"
|
|
47
|
+
X-Content-Type-Options = "nosniff"
|
|
48
|
+
Referrer-Policy = "strict-origin-when-cross-origin"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Serverless Functions
|
|
52
|
+
|
|
53
|
+
Place functions in `netlify/functions/`:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// netlify/functions/hello.ts
|
|
57
|
+
import type { Handler } from '@netlify/functions';
|
|
58
|
+
|
|
59
|
+
export const handler: Handler = async (event) => {
|
|
60
|
+
return {
|
|
61
|
+
statusCode: 200,
|
|
62
|
+
body: JSON.stringify({ message: 'Hello from Netlify Functions' }),
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- Functions are available at `/.netlify/functions/<name>`
|
|
68
|
+
- Supports TypeScript out of the box
|
|
69
|
+
- Default timeout: 10s (extendable to 26s on Pro)
|
|
70
|
+
- Use background functions for long-running tasks (up to 15 min)
|
|
71
|
+
|
|
72
|
+
## Edge Functions
|
|
73
|
+
|
|
74
|
+
Place edge functions in `netlify/edge-functions/`:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// netlify/edge-functions/geolocation.ts
|
|
78
|
+
import type { Context } from '@netlify/edge-functions';
|
|
79
|
+
|
|
80
|
+
export default async (request: Request, context: Context) => {
|
|
81
|
+
const { country } = context.geo;
|
|
82
|
+
return new Response(`You're visiting from ${country}`);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const config = { path: '/geo' };
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- Run at the CDN edge, sub-millisecond cold starts
|
|
89
|
+
- Use for personalization, A/B testing, geo-routing
|
|
90
|
+
- Deno runtime (not Node.js)
|
|
91
|
+
|
|
92
|
+
## Environment Variables
|
|
93
|
+
|
|
94
|
+
### Scoping
|
|
95
|
+
|
|
96
|
+
| Scope | When Applied | Use For |
|
|
97
|
+
|-------|-------------|---------|
|
|
98
|
+
| **Production** | `main` deploys | Live secrets, production API keys |
|
|
99
|
+
| **Deploy previews** | All PR/branch builds | Staging/test API keys |
|
|
100
|
+
| **Branch deploy** | Specific branch deploys | Branch-specific overrides |
|
|
101
|
+
| **Local** | `netlify dev` | Local development |
|
|
102
|
+
|
|
103
|
+
### Best Practices
|
|
104
|
+
|
|
105
|
+
- Set secrets via Netlify UI or CLI (`netlify env:set`) — never commit them
|
|
106
|
+
- Use `netlify dev` to run locally with injected env vars
|
|
107
|
+
- Validate required vars at build time in `netlify.toml`
|
|
108
|
+
|
|
109
|
+
## Scheduled Functions (Cron)
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// netlify/functions/daily-task.ts
|
|
113
|
+
import type { Handler } from '@netlify/functions';
|
|
114
|
+
|
|
115
|
+
export const handler: Handler = async () => {
|
|
116
|
+
// Run daily task
|
|
117
|
+
return { statusCode: 200, body: 'OK' };
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export const config = {
|
|
121
|
+
schedule: '0 0 * * *', // Daily at midnight UTC
|
|
122
|
+
};
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Build Troubleshooting
|
|
126
|
+
|
|
127
|
+
1. **Check build logs** — Netlify UI → Deploys → click failed deploy
|
|
128
|
+
2. **Common causes:**
|
|
129
|
+
- Missing environment variables
|
|
130
|
+
- Node.js version mismatch (set in `netlify.toml` or `.node-version`)
|
|
131
|
+
- Build command or publish directory mismatch
|
|
132
|
+
- Dependency install failures (check lockfile)
|
|
133
|
+
3. **Local debugging** — run `netlify build` locally to reproduce
|
|
134
|
+
4. **Clear cache** — Netlify UI → Deploys → Trigger deploy → Clear cache and deploy
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { PluginConfig } from '../types.js';
|
|
2
|
+
|
|
3
|
+
export const config: PluginConfig = {
|
|
4
|
+
id: 'netlify',
|
|
5
|
+
name: 'Netlify',
|
|
6
|
+
category: 'tech',
|
|
7
|
+
subCategory: 'deployment',
|
|
8
|
+
label: 'Netlify',
|
|
9
|
+
hint: 'Deployment, serverless functions, edge config',
|
|
10
|
+
skillName: 'netlify-deployment',
|
|
11
|
+
mcpServerKey: 'Netlify',
|
|
12
|
+
mcpConfig: {
|
|
13
|
+
type: 'stdio',
|
|
14
|
+
command: 'npx',
|
|
15
|
+
args: ['-y', 'netlify-mcp@latest'],
|
|
16
|
+
},
|
|
17
|
+
authType: 'env-token',
|
|
18
|
+
envVars: [
|
|
19
|
+
{
|
|
20
|
+
name: 'NETLIFY_AUTH_TOKEN',
|
|
21
|
+
hint: 'Generate at app.netlify.com → User Settings → Applications → Personal access tokens',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
agentToolMap: {
|
|
25
|
+
'devops-expert': ['netlify/*'],
|
|
26
|
+
'release-manager': ['netlify/*'],
|
|
27
|
+
},
|
|
28
|
+
docsUrl: 'https://www.opencastle.dev/docs/plugins#netlify',
|
|
29
|
+
officialDocs: 'https://docs.netlify.com',
|
|
30
|
+
mcpPackage: 'netlify-mcp',
|
|
31
|
+
};
|