From webflow-code-component-skills
Validates Webflow Code Components pre-deployment: checks project structure, dependencies, prop configs, SSR compatibility, styling setup, bundle size, and common issues before webflow library share.
npx claudepluginhub webflow/webflow-skills --plugin webflow-code-component-skillsThis skill uses the workspace's default tool permissions.
Validate code components before deployment to catch issues early.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Validate code components before deployment to catch issues early.
Use when:
webflow library shareDo NOT use when:
Verify webflow.json exists:
library.name, library.components)"./src/**/*.webflow.@(js|jsx|mjs|ts|tsx)" covering all supported extensionsglobals path if specified — file must exist and be importablebundleConfig path if specified — file must existCheck dependencies:
@webflow/webflow-cli installed@webflow/data-types installed@webflow/react installedVerify component files:
.webflow.tsx / .webflow.ts files matching the glob patternValidate imports in .webflow.tsx files:
declareComponent from @webflow/reactprops from @webflow/data-types (if props are defined)For each component, check:
declareComponent is called with the component and a config objectname is provided in the configname properties and appropriate defaultValue where applicable{ href, target, preload } object)options array)Validate component options:
options object is present, validate:
applyTagSelectors is a boolean (default: false) — enables site tag selectors in Shadow DOMssr is a boolean (default: true) — controls server-side renderingCheck for SSR issues:
useEffect or guarded blocks:
window, document, localStorage, sessionStorage, navigatorssr: false in options if component is purely interactive or browser-dependentCheck styling:
.webflow.tsx or via globals filevar(--variable-name, fallback)font-family: inheritapplyTagSelectors: true is set in component optionsCheck for Shadow DOM + React Context issues:
props.Slot) AND imports/uses useContext or a Context Provider:
Run TypeScript/build check:
Check bundle size:
Run local bundle test (optional, suggest to user):
npx webflow library bundle --public-path http://localhost:4000/ to test bundling before sharing--debug-bundler flag to inspect the final webpack configCSS-in-JS library detection:
@webflow/styled-components-utils is installed and styledComponentsShadowDomDecorator is exported from globals decorators array@emotion/styled, @emotion/react, @mui/material): verify @webflow/emotion-utils is installed and emotionShadowDomDecorator is exported from globals decorators arrayTailwind CSS detection:
tailwindcss in dependencies):
@tailwindcss/postcss is installedpostcss.config.mjs exists with @tailwindcss/postcss plugin@import "tailwindcss" in globals.css)Sass/Less preprocessor detection:
.scss files or sass in dependencies): verify sass and sass-loader are installed, and a webpack config adds the .scss rule.less files or less in dependencies): verify less and less-loader are installed, and a webpack config adds the .less rulebundleConfig is set in webflow.json pointing to the webpack configWebpack custom config validation (if bundleConfig is specified):
module.exports)entry, output, target (these are silently filtered out)module.rules uses function syntax (currentRules) => { ... }, not an array| Check | Severity | Description |
|---|---|---|
| webflow.json exists | Error | Required for CLI |
| Dependencies installed | Error | @webflow/webflow-cli, @webflow/data-types, @webflow/react |
| Component files exist | Error | React + definition files present |
| declareComponent called | Error | Required in .webflow.tsx with correct imports |
| Valid prop types | Error | Only the 11 supported types (Text/String, RichText, TextNode, Link, Image, Number, Boolean, Variant, Visibility, Slot, ID) |
| Build succeeds | Error | No compilation errors |
| Bundle size < 50MB | Error | Maximum bundle limit enforced by Webflow |
| Check | Severity | Description |
|---|---|---|
| Props have defaults | Warning | Better designer experience |
| SSR compatibility | Warning | Browser APIs, dynamic content, heavy UI, non-deterministic output |
| Styles imported | Warning | Styles may not appear in Shadow DOM |
| Site class usage | Warning | Site classes don't work in Shadow DOM — use component-specific classes |
| Shadow DOM + Context | Warning | Slots prevent React Context sharing between parent/child |
| CSS-in-JS decorator | Warning | styled-components/Emotion need Shadow DOM decorators |
| Tailwind setup | Warning | Missing postcss config or globals import |
| Sass/Less setup | Warning | Missing loaders or webpack config |
| Webpack blocked props | Warning | entry, output, target overrides are silently ignored |
| Webpack rules format | Warning | Must use function syntax, not array |
| Component options | Warning | applyTagSelectors and ssr must be booleans |
| Glob pattern coverage | Warning | Pattern should cover all supported extensions (.js, .jsx, .mjs, .ts, .tsx) |
| bundleConfig file | Warning | File must exist if specified in webflow.json |
| Check | Severity | Description |
|---|---|---|
| Component count | Info | Number of components |
| Prop count | Info | Props per component |
| Bundle size | Info | Current bundle size vs 50MB limit |
| Frameworks detected | Info | CSS-in-JS, Tailwind, Sass/Less usage |
User prompt:
Check if my components are ready to deploy
Response:
🔍 Build Validation: My Component Library
Running pre-deployment checks...
---
## Project Structure
✅ webflow.json found
✅ library.name: "My Component Library"
✅ library.components: "./src/**/*.webflow.@(js|jsx|mjs|ts|tsx)"
✅ globals: "./src/globals.ts"
✅ bundleConfig: not specified (using defaults)
---
## Dependencies
✅ @webflow/webflow-cli: installed
✅ @webflow/data-types: installed
✅ @webflow/react: installed
✅ react: installed
✅ typescript: installed
---
## Frameworks Detected
✅ Tailwind CSS detected
✅ @tailwindcss/postcss installed
✅ postcss.config.mjs found
✅ globals.css imports Tailwind
---
## Components Found (4)
### 1. Button ✅
- File: src/components/Button/Button.webflow.tsx
- Imports: ✅ declareComponent, ✅ props, ✅ Button component
- Props: label (Text), variant (Variant), disabled (Boolean)
- All props have defaults ✅
- SSR compatible ✅
- Options: applyTagSelectors: true ✅
- Styles imported ✅
### 2. Card ✅
- File: src/components/Card/Card.webflow.tsx
- Imports: ✅ declareComponent, ✅ props, ✅ Card component
- Props: title (Text), image (Image), content (RichText), link (Link)
- All props have defaults ✅
- SSR compatible ✅
- Styles imported ✅
### 3. Modal ⚠️
- File: src/components/Modal/Modal.webflow.tsx
- Imports: ✅ declareComponent, ✅ props, ✅ Modal component
- Props: title (Text), isOpen (Boolean), content (Slot)
- All props have defaults ✅
- ⚠️ SSR Issue: Uses `document.body` in render
→ Suggestion: Add `ssr: false` to options or wrap in useEffect
- Styles imported ✅
### 4. CartIcon ⚠️
- File: src/components/CartIcon/CartIcon.webflow.tsx
- Imports: ✅ declareComponent, ✅ CartIcon component
- Props: none
- ⚠️ Missing props - component has no editable properties
→ Suggestion: Consider adding props for designer customization
- ⚠️ Uses localStorage without SSR guard
→ Suggestion: Wrap in useEffect or useState initializer
- Styles imported ✅
---
## Build Test
✅ Build completed successfully
✅ No TypeScript errors
✅ No webpack errors
✅ Bundle size: 2.3MB / 50MB limit
---
## Summary
| Category | Status |
|----------|--------|
| Project Structure | ✅ Pass |
| Dependencies | ✅ Pass |
| Frameworks | ✅ Pass |
| Components | ⚠️ 2 warnings |
| Build | ✅ Pass |
---
## Ready to Deploy: ⚠️ WITH WARNINGS
You can deploy, but consider fixing these issues:
1. **Modal SSR Issue**
Add to Modal.webflow.tsx:
```typescript
options: {
ssr: false
}
const [count, setCount] = useState(() => {
if (typeof window === "undefined") return 0;
return parseInt(localStorage.getItem("cartCount") || "0");
});
💡 To deploy: npx webflow library share
💡 To test locally first: npx webflow library bundle --public-path http://localhost:4000/
---
**Example: Build Failure**
🔍 Build Validation: My Component Library
Running pre-deployment checks...
✅ webflow.json found ⚠️ library.components uses narrow glob: "./src//*.webflow.tsx" → Recommendation: Use "./src//*.webflow.@(js|jsx|mjs|ts|tsx)" to cover all supported extensions
❌ Missing: @webflow/react Fix: npm install --save-dev @webflow/react
❌ Build Failed
Error in src/components/Button/Button.webflow.tsx:
Module not found: Error: Can't resolve '@webflow/react'
| Category | Status |
|---|---|
| Dependencies | ❌ 1 error |
| Build | ❌ Failed |
Fix the following before deployment:
Install missing dependency
npm install --save-dev @webflow/react
Re-run validation After installing, run this check again.
---
**Example: CSS-in-JS Missing Decorator**
🔍 Build Validation: My Component Library
⚠️ styled-components detected but Shadow DOM decorator not configured
→ Install: npm install @webflow/styled-components-utils
→ Add to globals.ts:
typescript import { styledComponentsShadowDomDecorator } from "@webflow/styled-components-utils"; export const decorators = [styledComponentsShadowDomDecorator];
→ Reference globals in webflow.json:
json { "library": { "globals": "./src/globals.ts" } }
Without this, styled-components styles will be injected into document.head instead of the Shadow DOM, and your components will appear unstyled.
---
**Example: Webpack Config Issues**
🔍 Build Validation: My Component Library
⚠️ webpack.webflow.js: module.rules uses array syntax
→ Must use function syntax: rules: (currentRules) => { return [...]; }
→ Array syntax will not work — the function receives current rules to extend
⚠️ webpack.webflow.js: overrides output property
→ The output property is blocked and will be silently ignored
→ Blocked properties: entry, output, target
💡 Use --debug-bundler flag to inspect the final merged webpack config:
npx webflow library bundle --debug-bundler
---
**Example: Shadow DOM Context Warning**
File: src/components/ThemeProvider/ThemeProvider.webflow.tsx
Props: theme (Variant), children (Slot)
⚠️ Shadow DOM + React Context Issue: Component uses Slot prop AND React Context (ThemeContext). Children placed in slots render in separate Shadow DOM containers with their own React roots — they cannot access this Context.
Alternatives for cross-component state:
---
## Guidelines
### Validation Order
Run checks in this order for efficiency:
1. Project structure (fast, catches obvious issues)
2. Dependencies (medium, required for build)
3. Component analysis (medium, catches code issues)
4. Framework detection (medium, validates CSS-in-JS/Tailwind/Sass setup)
5. Build test (slow, but required)
### SSR Detection Patterns
Look for these patterns that indicate SSR issues:
```typescript
// Direct browser API usage (will break SSR)
window.innerWidth
document.getElementById
localStorage.getItem
navigator.userAgent
sessionStorage.getItem
// Dynamic/personalized content (may cause hydration mismatch)
// User-specific dashboards, authenticated views
// Heavy/interactive UI (SSR adds no value, re-renders anyway)
// Charts, 3D scenes, maps, animation-driven elements
// Non-deterministic output (differs server vs client)
Math.random()
new Date().toLocaleString()
// Safe patterns (in useEffect or state initializer)
useEffect(() => {
// Browser APIs here are fine
}, []);
useState(() => {
if (typeof window === "undefined") return default;
return window.innerWidth;
});
When SSR issues are found, prominently suggest the ssr: false option:
export default declareComponent(MyComponent, {
name: "My Component",
options: {
ssr: false // Disables server-side rendering
},
});
Check project dependencies and files to detect styling frameworks:
styled-components:
styled-components in package.json dependencies@webflow/styled-components-utils installedstyledComponentsShadowDomDecorator in globals decorators arrayEmotion / Material UI:
@emotion/styled, @emotion/react, or @mui/material in dependencies@webflow/emotion-utils installedemotionShadowDomDecorator in globals decorators arrayTailwind CSS:
tailwindcss in dependencies@tailwindcss/postcss installedpostcss.config.mjs with @tailwindcss/postcss plugin@import "tailwindcss")Sass:
.scss files in src or sass in dependenciessass and sass-loader installed as dev dependencies.scss rule using function syntax for module.rulesbundleConfig set in webflow.jsonLess:
.less files in src or less in dependenciesless and less-loader installed as dev dependencies.less rule using function syntax for module.rulesbundleConfig set in webflow.jsonWhen bundleConfig is specified in webflow.json:
module.exports = { ... }entry, output, targetmodule.rules must be a function, not an array: rules: (currentRules) => { ... }ModuleFederationPlugin and MiniCssExtractPlugin are auto-deduplicated| Error | Cause | Fix |
|---|---|---|
| "Can't resolve '@webflow/react'" | Missing dependency | npm i -D @webflow/react |
| "Cannot find module './Component'" | Wrong import path | Check relative paths |
| "Type 'X' is not assignable" | TypeScript error | Fix type mismatch |
| "Unexpected token" | Syntax error | Check JSX/TS syntax |
| "Maximum call stack" | Circular import | Break dependency cycle |
| Bundle exceeds 50MB | Too many/large dependencies | Tree-shake, lazy load, replace heavy libs |
| Styles not appearing | Missing Shadow DOM decorator | Add CSS-in-JS decorator or import styles in .webflow.tsx |
Quick wins for reducing bundle size: