@convertex/skill 1.0.0
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/cli.mjs +103 -0
- package/package.json +29 -0
- package/skills/convertex/SKILL.md +330 -0
- package/skills/convertex/client-first/css/rules.md +102 -0
- package/skills/convertex/client-first/naming/conventions.md +92 -0
- package/skills/convertex/client-first/structure/page-skeleton.md +154 -0
- package/skills/convertex/client-first/utilities/buttons.md +170 -0
- package/skills/convertex/client-first/utilities/layout.md +89 -0
- package/skills/convertex/client-first/utilities/spacing.md +81 -0
- package/skills/convertex/client-first/utilities/typography.md +86 -0
- package/skills/convertex/css/best-practices.md +190 -0
- package/skills/convertex/elements/background-video.md +62 -0
- package/skills/convertex/elements/dropdown.md +49 -0
- package/skills/convertex/elements/forms.md +170 -0
- package/skills/convertex/elements/images.md +90 -0
- package/skills/convertex/elements/lightbox.md +61 -0
- package/skills/convertex/elements/links-buttons.md +96 -0
- package/skills/convertex/elements/navbar.md +100 -0
- package/skills/convertex/elements/slider.md +81 -0
- package/skills/convertex/elements/tabs.md +63 -0
- package/skills/convertex/patterns/ghost-blocks.md +94 -0
package/cli.mjs
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { cpSync, existsSync, rmSync, readdirSync } from 'fs';
|
|
4
|
+
import { resolve, dirname, join } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
|
|
9
|
+
// ANSI colors
|
|
10
|
+
const green = (s) => `\x1b[32m${s}\x1b[0m`;
|
|
11
|
+
const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
|
|
12
|
+
const red = (s) => `\x1b[31m${s}\x1b[0m`;
|
|
13
|
+
const dim = (s) => `\x1b[2m${s}\x1b[0m`;
|
|
14
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
15
|
+
|
|
16
|
+
const SKILL_NAME = 'convertex';
|
|
17
|
+
const SOURCE = resolve(__dirname, 'skills', SKILL_NAME);
|
|
18
|
+
const TARGET_DIR = resolve(process.cwd(), '.claude', 'skills');
|
|
19
|
+
const TARGET = resolve(TARGET_DIR, SKILL_NAME);
|
|
20
|
+
|
|
21
|
+
const command = process.argv[2] || 'install';
|
|
22
|
+
|
|
23
|
+
function countFiles(dir) {
|
|
24
|
+
let count = 0;
|
|
25
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
26
|
+
if (entry.name.startsWith('.')) continue;
|
|
27
|
+
if (entry.isDirectory()) count += countFiles(join(dir, entry.name));
|
|
28
|
+
else count++;
|
|
29
|
+
}
|
|
30
|
+
return count;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function install() {
|
|
34
|
+
const isUpdate = existsSync(TARGET);
|
|
35
|
+
|
|
36
|
+
cpSync(SOURCE, TARGET, { recursive: true });
|
|
37
|
+
|
|
38
|
+
const fileCount = countFiles(TARGET);
|
|
39
|
+
const action = isUpdate ? 'updated' : 'installed';
|
|
40
|
+
|
|
41
|
+
console.log('');
|
|
42
|
+
console.log(` ${green('✓')} Convertex skill ${bold(action)} successfully`);
|
|
43
|
+
console.log(` ${dim(`${fileCount} files → .claude/skills/${SKILL_NAME}/`)}`);
|
|
44
|
+
console.log('');
|
|
45
|
+
|
|
46
|
+
if (!isUpdate) {
|
|
47
|
+
console.log(` ${cyan('→')} Run ${bold('claude')} in your terminal to start using the skill.`);
|
|
48
|
+
console.log(` Claude will automatically detect and use it for Webflow code generation.`);
|
|
49
|
+
console.log('');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function uninstall() {
|
|
54
|
+
if (!existsSync(TARGET)) {
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log(` ${dim('Convertex skill is not installed.')}`);
|
|
57
|
+
console.log('');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
rmSync(TARGET, { recursive: true });
|
|
62
|
+
|
|
63
|
+
console.log('');
|
|
64
|
+
console.log(` ${green('✓')} Convertex skill ${bold('uninstalled')} successfully`);
|
|
65
|
+
console.log(` ${dim(`Removed .claude/skills/${SKILL_NAME}/`)}`);
|
|
66
|
+
console.log('');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function help() {
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log(` ${bold('@convertex/skill')} — Install Convertex skills for Claude Code`);
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log(` ${bold('Usage:')}`);
|
|
74
|
+
console.log(` npx @convertex/skill install Install the skill ${dim('(default)')}`);
|
|
75
|
+
console.log(` npx @convertex/skill update Update to the latest version`);
|
|
76
|
+
console.log(` npx @convertex/skill uninstall Remove the skill`);
|
|
77
|
+
console.log(` npx @convertex/skill help Show this help`);
|
|
78
|
+
console.log('');
|
|
79
|
+
console.log(` ${dim('Skills are installed into .claude/skills/convertex/ in your project root.')}`);
|
|
80
|
+
console.log(` ${dim('Learn more at https://convertex.ai')}`);
|
|
81
|
+
console.log('');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
switch (command) {
|
|
85
|
+
case 'install':
|
|
86
|
+
case 'update':
|
|
87
|
+
install();
|
|
88
|
+
break;
|
|
89
|
+
case 'uninstall':
|
|
90
|
+
case 'remove':
|
|
91
|
+
uninstall();
|
|
92
|
+
break;
|
|
93
|
+
case 'help':
|
|
94
|
+
case '--help':
|
|
95
|
+
case '-h':
|
|
96
|
+
help();
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
console.log('');
|
|
100
|
+
console.log(` ${red('✗')} Unknown command: ${bold(command)}`);
|
|
101
|
+
help();
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@convertex/skill",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Install Convertex skills for Claude Code — Webflow-compatible HTML/CSS generation with Client-First methodology",
|
|
5
|
+
"bin": {
|
|
6
|
+
"convertex-skill": "./cli.mjs"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"cli.mjs",
|
|
10
|
+
"skills/"
|
|
11
|
+
],
|
|
12
|
+
"keywords": [
|
|
13
|
+
"claude",
|
|
14
|
+
"claude-code",
|
|
15
|
+
"webflow",
|
|
16
|
+
"convertex",
|
|
17
|
+
"skill",
|
|
18
|
+
"mcp",
|
|
19
|
+
"client-first",
|
|
20
|
+
"html-to-webflow"
|
|
21
|
+
],
|
|
22
|
+
"author": "Convertex",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/convertex/skill"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://convertex.ai"
|
|
29
|
+
}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: convertex
|
|
3
|
+
description: "Generate Webflow-compatible HTML and CSS for Convertex. Triggers on: Convertex Capture, Webflow conversion, HTML to Webflow, recreate section, reproduce page, Client-First, Finsweet, w- classes."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Convertex — Webflow HTML & CSS Generation
|
|
7
|
+
|
|
8
|
+
Generate HTML and CSS compatible with Webflow's native element system. Output two separate blocks: one for HTML (body only), one for CSS.
|
|
9
|
+
|
|
10
|
+
## Pre-Flight — Ask Before Generating
|
|
11
|
+
|
|
12
|
+
Ask these 3 questions in ONE message, then WAIT for the answer:
|
|
13
|
+
|
|
14
|
+
1. **Client-First or free naming?** — Client-First = apply the [Client-First rules](#client-first) below.
|
|
15
|
+
2. **rem or px?** — rem: `1rem = 16px`. px: pixel values.
|
|
16
|
+
3. **Content language?** — Adapt placeholder text, ARIA labels, and field names.
|
|
17
|
+
|
|
18
|
+
Skip ONLY if the user already answered all 3 in their current message.
|
|
19
|
+
|
|
20
|
+
## Output Format
|
|
21
|
+
|
|
22
|
+
- **HTML block**: Body content only. No `<html>`, `<head>`, `<body>`, or `<style>` tags. Start with the first element.
|
|
23
|
+
- **CSS block**: Separate from HTML. Flat selectors, concrete values, desktop-first with responsive overrides.
|
|
24
|
+
- **JS block**: Separate from HTML. Never place `<script>` tags or inline JavaScript inside the HTML. All JavaScript must be pushed as a separate JS block via the `js` field of `create_page` / `update_page` / `patch_page`. Do NOT wrap JS in `<div class="w-embed">` or any HTML embed — the Convertex editor has a dedicated JS panel.
|
|
25
|
+
- **Push, don't display**: If the Convertex MCP is connected, push code via `notify_sync_start()` then `create_page` / `update_page` / `patch_page`. Do NOT paste large code blocks in chat.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 10 Golden Rules
|
|
30
|
+
|
|
31
|
+
### 1. Flat CSS selectors only
|
|
32
|
+
|
|
33
|
+
`.class` or `.class1.class2` (combo). **NEVER** use:
|
|
34
|
+
- Descendant: `.parent .child` — use `.parent_child` instead
|
|
35
|
+
- Child: `.parent > .child` — use `.parent_child` instead
|
|
36
|
+
- Sibling: `.a + .b` — use separate classes
|
|
37
|
+
- Tag-qualified: `div.container` — use `.container`
|
|
38
|
+
|
|
39
|
+
### 2. Concrete values only — no CSS variables
|
|
40
|
+
|
|
41
|
+
Write actual values: `color: #2563eb`, never `color: var(--primary)`. Webflow does not support CSS custom properties natively.
|
|
42
|
+
|
|
43
|
+
### 3. Combo class pattern
|
|
44
|
+
|
|
45
|
+
First class = base, additional classes = combos. `class="button is-primary"` means `.button` is the base, `.is-primary` is a combo. In CSS: `.button.is-primary { ... }`.
|
|
46
|
+
|
|
47
|
+
### 4. Semantic HTML tags
|
|
48
|
+
|
|
49
|
+
Use `<section>`, `<header>`, `<footer>`, `<nav>`, `<main>`, `<article>`, `<aside>` for their semantic purpose. These render as Block elements in Webflow with their HTML tag preserved.
|
|
50
|
+
|
|
51
|
+
### 5. No hidden states in CSS
|
|
52
|
+
|
|
53
|
+
**NEVER** set `display: none`, `opacity: 0`, `visibility: hidden`, or `height: 0` in base CSS. Elements must be visible in Webflow Designer for editing. Set initial hidden states via JavaScript on `DOMContentLoaded`. CSS only defines the active/visible state via combo classes: `.modal.is-open { opacity: 1; }`.
|
|
54
|
+
|
|
55
|
+
### 6. CSS transitions for simple animations
|
|
56
|
+
|
|
57
|
+
Use `transition` for hover effects and state changes. Only use JavaScript animation libraries (GSAP) for scroll-triggered, staggered, or complex timeline animations.
|
|
58
|
+
|
|
59
|
+
### 7. Inline SVGs must be wrapped
|
|
60
|
+
|
|
61
|
+
Raw `<svg>` elements **must** be inside `<div class="w-embed">`. Without the wrapper, SVGs render incorrectly in Webflow.
|
|
62
|
+
|
|
63
|
+
### 8. Never use `<em>`
|
|
64
|
+
|
|
65
|
+
`<em>` becomes a block-level element in Webflow. Use `<span>` with a class that sets `font-style: italic` instead.
|
|
66
|
+
|
|
67
|
+
### 9. Never use inline `style` attributes
|
|
68
|
+
|
|
69
|
+
All styling must go through CSS classes. The `style` attribute is not supported.
|
|
70
|
+
|
|
71
|
+
### 10. Webflow components need exact `w-` structures
|
|
72
|
+
|
|
73
|
+
Navbars, forms, sliders, tabs, dropdowns, lightboxes, and background videos require specific HTML structures with `w-` classes and data attributes. **Read the pattern file** before generating any of these. See [Component Patterns](#component-patterns).
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Responsive Breakpoints
|
|
78
|
+
|
|
79
|
+
| Breakpoint | Media Query | Direction |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| XXL | `min-width: 1920px` | Upward override |
|
|
82
|
+
| XL | `min-width: 1440px` | Upward override |
|
|
83
|
+
| Large | `min-width: 1280px` | Upward override |
|
|
84
|
+
| **Desktop** | _(no media query)_ | **Base styles** |
|
|
85
|
+
| Tablet | `max-width: 991px` | Downward override |
|
|
86
|
+
| Mobile Landscape | `max-width: 767px` | Downward override |
|
|
87
|
+
| Mobile Portrait | `max-width: 479px` | Downward override |
|
|
88
|
+
|
|
89
|
+
**Rules:**
|
|
90
|
+
- Desktop-first: base styles have no media query
|
|
91
|
+
- Override downward with `max-width`, upward (rare) with `min-width`
|
|
92
|
+
- Only include properties that actually change — never repeat base values
|
|
93
|
+
- Use **only** these exact breakpoint values
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Selector Reference
|
|
98
|
+
|
|
99
|
+
### Allowed
|
|
100
|
+
```css
|
|
101
|
+
.hero_heading { } /* Single class */
|
|
102
|
+
.button.is-secondary { } /* Combo class */
|
|
103
|
+
.button:hover { } /* Pseudo on class */
|
|
104
|
+
.nav_link.is-active:hover { } /* Combo + pseudo */
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Forbidden — will break conversion
|
|
108
|
+
```css
|
|
109
|
+
.hero .heading { } /* Descendant → use .hero_heading */
|
|
110
|
+
.card > .title { } /* Child → use .card_title */
|
|
111
|
+
.input + .error { } /* Sibling → use .input_error */
|
|
112
|
+
div.container { } /* Tag-qualified → use .container */
|
|
113
|
+
a.nav-link { } /* Tag-qualified → use .nav-link */
|
|
114
|
+
.list_item:nth-child(odd) { } /* Complex pseudo → needs ghost block */
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Pseudo-Classes
|
|
120
|
+
|
|
121
|
+
**Supported natively** (write in CSS): `:hover`, `:active`, `:focus`, `:visited`, `:focus-visible`, `:focus-within`, `::placeholder`
|
|
122
|
+
|
|
123
|
+
**FORBIDDEN — never use, even in ghost blocks:**
|
|
124
|
+
`::before`, `::after` — poorly supported by Webflow, not manageable in the Designer. Always use a real HTML element instead (e.g. a `<div>` with a class for decorative elements, icons, or separators).
|
|
125
|
+
|
|
126
|
+
**Not supported natively** (may use a [ghost block](patterns/ghost-blocks.md) if necessary):
|
|
127
|
+
`:nth-child()`, `:first-child`, `:last-child`, `:not()`, `@keyframes`
|
|
128
|
+
|
|
129
|
+
```html
|
|
130
|
+
<div class="w-embed"><style>
|
|
131
|
+
.card:first-child { border-top: none; }
|
|
132
|
+
</style></div>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Contextual Styling
|
|
138
|
+
|
|
139
|
+
Webflow has no descendant selectors. When a parent state must affect children, **propagate the combo class** to every affected child:
|
|
140
|
+
|
|
141
|
+
```html
|
|
142
|
+
<div class="pricing_card is-featured">
|
|
143
|
+
<h3 class="pricing_title is-featured">Pro</h3>
|
|
144
|
+
<p class="pricing_price is-featured">$99/mo</p>
|
|
145
|
+
</div>
|
|
146
|
+
```
|
|
147
|
+
```css
|
|
148
|
+
.pricing_card.is-featured { background-color: #0f172a; }
|
|
149
|
+
.pricing_title.is-featured { color: #ffffff; }
|
|
150
|
+
.pricing_price.is-featured { color: #60a5fa; }
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Element Rules
|
|
156
|
+
|
|
157
|
+
### Spans
|
|
158
|
+
`<span>` is valid only inside text elements (`<p>`, `<h1>`–`<h6>`) or alongside text siblings. In all other cases, use `<div>`.
|
|
159
|
+
|
|
160
|
+
### Links & Buttons
|
|
161
|
+
**`<button>` is atomic in Webflow — it CANNOT have children.** It only holds plain text. If you need an icon or nested elements, use `<a>` (Link Block) instead.
|
|
162
|
+
|
|
163
|
+
Inside `<a>` Link Blocks, **always use `<div>`** for child elements (text wrappers, icon containers). Never use `<span>` — it creates Text Spans in Webflow instead of Block elements, breaking layout control.
|
|
164
|
+
|
|
165
|
+
**Link with icon — correct structure:**
|
|
166
|
+
```html
|
|
167
|
+
<a href="/page" class="button is-primary">
|
|
168
|
+
<div class="button_text">Get started</div>
|
|
169
|
+
<div class="w-embed">
|
|
170
|
+
<svg class="button_icon" width="10" height="10" viewBox="0 0 10 10" fill="none" aria-hidden="true">
|
|
171
|
+
<path d="M1 5h8M5 1l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
172
|
+
</svg>
|
|
173
|
+
</div>
|
|
174
|
+
</a>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Simple button — text only:**
|
|
178
|
+
```html
|
|
179
|
+
<button class="button">Get started</button>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**NEVER do this:**
|
|
183
|
+
```html
|
|
184
|
+
<!-- WRONG: children inside <button> -->
|
|
185
|
+
<button class="button">
|
|
186
|
+
<div class="button_text">Get started</div>
|
|
187
|
+
<div class="w-embed"><svg>...</svg></div>
|
|
188
|
+
</button>
|
|
189
|
+
|
|
190
|
+
<!-- WRONG: text directly alongside w-embed -->
|
|
191
|
+
<a href="/page" class="button">
|
|
192
|
+
Get started
|
|
193
|
+
<div class="w-embed"><svg>...</svg></div>
|
|
194
|
+
</a>
|
|
195
|
+
|
|
196
|
+
<!-- WRONG: span inside a link -->
|
|
197
|
+
<a href="/page" class="button">
|
|
198
|
+
<span class="button_text">Get started</span>
|
|
199
|
+
</a>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Lists
|
|
203
|
+
```html
|
|
204
|
+
<ul class="features_list">
|
|
205
|
+
<li class="features_list-item">First feature</li>
|
|
206
|
+
<li class="features_list-item">Second feature</li>
|
|
207
|
+
</ul>
|
|
208
|
+
```
|
|
209
|
+
Both `<ul>` and `<ol>` are supported. Style via classes on the list and list items.
|
|
210
|
+
|
|
211
|
+
### Blockquote
|
|
212
|
+
```html
|
|
213
|
+
<blockquote class="testimonial_quote">Customer feedback here.</blockquote>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Horizontal Rule
|
|
217
|
+
```html
|
|
218
|
+
<hr class="divider" />
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Inline Components
|
|
224
|
+
|
|
225
|
+
| Component | HTML | Notes |
|
|
226
|
+
|---|---|---|
|
|
227
|
+
| **Grid** | `<div class="w-layout-grid my-grid">` | Must have `display: grid` in CSS |
|
|
228
|
+
| **Container** | `<div class="w-layout-blockcontainer my-container">` | Centered max-width block |
|
|
229
|
+
| **Rich Text** | `<div class="w-richtext">` | CMS-style formatted content |
|
|
230
|
+
| **HTML Embed** | `<div class="w-embed">` | Raw HTML, SVG, or `<style>` blocks |
|
|
231
|
+
|
|
232
|
+
**Note:** `w-container` (used inside navbars) is different from `w-layout-blockcontainer` (general layout container). Don't mix them.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Custom Attributes
|
|
237
|
+
|
|
238
|
+
- **Standard**: `id`, `href`, `src`, `alt`, `loading`, `target` — set directly on the element
|
|
239
|
+
- **Custom**: `data-*`, `aria-*`, `role`, `tabindex` — supported as custom attributes
|
|
240
|
+
- **`style`** — **never use**
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Component Patterns
|
|
245
|
+
|
|
246
|
+
These components require specific `w-` HTML structures. **Read the pattern file before generating any of them:**
|
|
247
|
+
|
|
248
|
+
- [Navbar](elements/navbar.md) — `w-nav` with brand, menu, burger button
|
|
249
|
+
- [Forms](elements/forms.md) — `w-form` wrapper with `w-form-done` / `w-form-fail` states
|
|
250
|
+
- [Dropdown](elements/dropdown.md) — `w-dropdown` with toggle and list
|
|
251
|
+
- [Slider](elements/slider.md) — `w-slider` with mask, slides, arrows, dot nav
|
|
252
|
+
- [Tabs](elements/tabs.md) — `w-tabs` with `data-w-tab` matching between links and panes
|
|
253
|
+
- [Lightbox](elements/lightbox.md) — `w-lightbox` with `w-json` config
|
|
254
|
+
- [Background Video](elements/background-video.md) — `w-background-video` with data attributes
|
|
255
|
+
- [Images](elements/images.md) — `<img>`, responsive `srcset`, SVG handling, `object-fit`
|
|
256
|
+
- [Links & Buttons](elements/links-buttons.md) — `<button>` vs `<a>` detection, Link Block vs Text Link
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Advanced Reference
|
|
261
|
+
|
|
262
|
+
- [Ghost Blocks & Dynamic States](patterns/ghost-blocks.md) — hidden states with JS, `::before`/`::after`, `@keyframes`, unsupported CSS via embed blocks
|
|
263
|
+
- [CSS Property Reference](css/best-practices.md) — detailed writing guide for spacing, borders, gradients, transitions, grid, flexbox, typography, filters, effects
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Accessibility Checklist
|
|
268
|
+
|
|
269
|
+
- Every `<img>` must have `alt` (empty `alt=""` for decorative images)
|
|
270
|
+
- Form inputs must have `<label>` with matching `for`/`id`
|
|
271
|
+
- Interactive elements must be keyboard-focusable with visible focus styles
|
|
272
|
+
- Icon-only buttons/links need `aria-label`
|
|
273
|
+
- Color contrast: WCAG AA minimum (4.5:1 normal text, 3:1 large text)
|
|
274
|
+
- Don't rely on color alone to convey information
|
|
275
|
+
- Use semantic tags (`<nav>`, `<main>`, `<section>`, `<article>`)
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Client-First
|
|
280
|
+
|
|
281
|
+
**Only apply this section if the user chose Client-First.** Otherwise skip entirely.
|
|
282
|
+
|
|
283
|
+
### 5 Rules
|
|
284
|
+
|
|
285
|
+
1. **Page skeleton is mandatory** — `page-wrapper > main-wrapper > section_[id] > padding-global padding-section-[size] > container-[size] > content`
|
|
286
|
+
2. **Underscore = custom, hyphen = utility** — `hero_heading` (custom), `text-size-large` (utility), `is-primary` (combo)
|
|
287
|
+
3. **All units in rem** — Never px. Only exception: `border-width` can use px.
|
|
288
|
+
4. **Max 2 utility classes per element** — 3+ utilities = create a custom class instead. Exception: `padding-global padding-section-large`.
|
|
289
|
+
5. **Flat CSS selectors only** — Same as Webflow Rule #1.
|
|
290
|
+
|
|
291
|
+
### 3 Class Types
|
|
292
|
+
|
|
293
|
+
**Custom** — `[folder]_[element]`: specific to one component.
|
|
294
|
+
`hero_heading`, `footer_link`, `pricing_card`
|
|
295
|
+
|
|
296
|
+
**Utility** — `[category]-[property]-[value]`: reusable site-wide.
|
|
297
|
+
`text-size-large`, `margin-bottom margin-medium`, `hide-tablet`
|
|
298
|
+
|
|
299
|
+
**Combo** — `is-[variant]`: modifier on a base class. Never used alone.
|
|
300
|
+
`is-secondary`, `is-featured`, `is-active`
|
|
301
|
+
|
|
302
|
+
### Page Skeleton
|
|
303
|
+
|
|
304
|
+
```html
|
|
305
|
+
<div class="page-wrapper">
|
|
306
|
+
<main class="main-wrapper">
|
|
307
|
+
<section class="section_hero">
|
|
308
|
+
<div class="padding-global padding-section-large">
|
|
309
|
+
<div class="container-large">
|
|
310
|
+
<!-- content -->
|
|
311
|
+
</div>
|
|
312
|
+
</div>
|
|
313
|
+
</section>
|
|
314
|
+
</main>
|
|
315
|
+
</div>
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Nav and footer go **outside** `main-wrapper`, **inside** `page-wrapper`. `padding-global` and `padding-section-[size]` go on the **SAME div**.
|
|
319
|
+
|
|
320
|
+
### Detailed Client-First Reference
|
|
321
|
+
|
|
322
|
+
Read these files for complete patterns and values:
|
|
323
|
+
|
|
324
|
+
- [Naming Conventions](client-first/naming/conventions.md) — full rules for custom, utility, and combo classes
|
|
325
|
+
- [Page Skeleton](client-first/structure/page-skeleton.md) — 5-layer structure, container sizes, padding values, complete page example
|
|
326
|
+
- [CSS Rules](client-first/css/rules.md) — rem values, core structure CSS, mandatory responsive overrides, typography base styles
|
|
327
|
+
- [Typography Utilities](client-first/utilities/typography.md) — `heading-style-*`, `text-size-*`, `text-weight-*`, `text-color-*`, `text-align-*`
|
|
328
|
+
- [Spacing Utilities](client-first/utilities/spacing.md) — margin/padding two-class system, spacer blocks, all size values
|
|
329
|
+
- [Layout Utilities](client-first/utilities/layout.md) — `max-width-*`, `hide-*`, `background-color-*`, icons, positioning, aspect ratios
|
|
330
|
+
- [Button Utilities](client-first/utilities/buttons.md) — `.button` base, `is-secondary`/`is-text`/`is-small`/`is-large` variants
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# CSS Rules for Client-First
|
|
2
|
+
|
|
3
|
+
## Units: rem Only
|
|
4
|
+
|
|
5
|
+
All sizes in rem (`1rem = 16px`). Use these standard values:
|
|
6
|
+
|
|
7
|
+
| rem | px | | rem | px |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| `0.25` | 4 | | `2.5` | 40 |
|
|
10
|
+
| `0.5` | 8 | | `3` | 48 |
|
|
11
|
+
| `0.75` | 12 | | `4` | 64 |
|
|
12
|
+
| `1` | 16 | | `5` | 80 |
|
|
13
|
+
| `1.25` | 20 | | `6` | 96 |
|
|
14
|
+
| `1.5` | 24 | | `8` | 128 |
|
|
15
|
+
| `2` | 32 | | `12` | 192 |
|
|
16
|
+
|
|
17
|
+
**Exception:** `border-width` values can use `px` (e.g., `border-width: 1px`).
|
|
18
|
+
|
|
19
|
+
## Core Structure CSS
|
|
20
|
+
|
|
21
|
+
Only include classes that appear in the HTML:
|
|
22
|
+
|
|
23
|
+
```css
|
|
24
|
+
/* Horizontal padding */
|
|
25
|
+
.padding-global { padding-left: 2.5rem; padding-right: 2.5rem; }
|
|
26
|
+
|
|
27
|
+
/* Containers */
|
|
28
|
+
.container-large { max-width: 80rem; margin-left: auto; margin-right: auto; width: 100%; }
|
|
29
|
+
.container-medium { max-width: 64rem; margin-left: auto; margin-right: auto; width: 100%; }
|
|
30
|
+
.container-small { max-width: 48rem; margin-left: auto; margin-right: auto; width: 100%; }
|
|
31
|
+
|
|
32
|
+
/* Section padding */
|
|
33
|
+
.padding-section-large { padding-top: 8rem; padding-bottom: 8rem; }
|
|
34
|
+
.padding-section-medium { padding-top: 5rem; padding-bottom: 5rem; }
|
|
35
|
+
.padding-section-small { padding-top: 3rem; padding-bottom: 3rem; }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Mandatory Responsive Overrides
|
|
39
|
+
|
|
40
|
+
These must always be included when using the corresponding structure classes:
|
|
41
|
+
|
|
42
|
+
```css
|
|
43
|
+
@media (max-width: 991px) {
|
|
44
|
+
.padding-global { padding-left: 1.5rem; padding-right: 1.5rem; }
|
|
45
|
+
.padding-section-large { padding-top: 6rem; padding-bottom: 6rem; }
|
|
46
|
+
.padding-section-medium { padding-top: 4rem; padding-bottom: 4rem; }
|
|
47
|
+
.padding-section-small { padding-top: 2rem; padding-bottom: 2rem; }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@media (max-width: 479px) {
|
|
51
|
+
.padding-global { padding-left: 1.25rem; padding-right: 1.25rem; }
|
|
52
|
+
.padding-section-large { padding-top: 4rem; padding-bottom: 4rem; }
|
|
53
|
+
.padding-section-medium { padding-top: 3rem; padding-bottom: 3rem; }
|
|
54
|
+
.padding-section-small { padding-top: 1.5rem; padding-bottom: 1.5rem; }
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## CSS Organization Order
|
|
59
|
+
|
|
60
|
+
Structure your CSS in this order for consistency:
|
|
61
|
+
|
|
62
|
+
1. **Core structure** — `padding-global`, containers, `padding-section-*`
|
|
63
|
+
2. **Typography utilities** — `text-size-*`, `text-weight-*`, `heading-style-*`
|
|
64
|
+
3. **Button utilities** — `button`, `.button.is-*` variants
|
|
65
|
+
4. **Spacing utilities** — `margin-*`, `padding-*`, `spacer-*`
|
|
66
|
+
5. **Layout utilities** — `max-width-*`, `hide-*`, `overflow-*`
|
|
67
|
+
6. **Custom classes** — grouped by section (`hero_*`, `features_*`, `footer_*`)
|
|
68
|
+
7. **Responsive overrides** — tablet (991px) → mobile landscape (767px) → mobile portrait (479px)
|
|
69
|
+
|
|
70
|
+
## Typography Base Styles
|
|
71
|
+
|
|
72
|
+
Define tag-level styles for consistent typography across the site:
|
|
73
|
+
|
|
74
|
+
```css
|
|
75
|
+
/* Heading tag styles */
|
|
76
|
+
h1 { font-size: 3.5rem; font-weight: 700; line-height: 1.1; letter-spacing: -0.02em; }
|
|
77
|
+
h2 { font-size: 2.5rem; font-weight: 700; line-height: 1.2; letter-spacing: -0.02em; }
|
|
78
|
+
h3 { font-size: 2rem; font-weight: 600; line-height: 1.3; }
|
|
79
|
+
h4 { font-size: 1.5rem; font-weight: 600; line-height: 1.4; }
|
|
80
|
+
h5 { font-size: 1.25rem; font-weight: 600; line-height: 1.4; }
|
|
81
|
+
h6 { font-size: 1rem; font-weight: 600; line-height: 1.5; }
|
|
82
|
+
|
|
83
|
+
/* Body text */
|
|
84
|
+
p { font-size: 1rem; line-height: 1.6; color: #374151; }
|
|
85
|
+
a { color: #2563eb; text-decoration: none; }
|
|
86
|
+
a:hover { text-decoration: underline; }
|
|
87
|
+
|
|
88
|
+
/* Responsive typography */
|
|
89
|
+
@media (max-width: 991px) {
|
|
90
|
+
h1 { font-size: 2.75rem; }
|
|
91
|
+
h2 { font-size: 2rem; }
|
|
92
|
+
h3 { font-size: 1.75rem; }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@media (max-width: 479px) {
|
|
96
|
+
h1 { font-size: 2.25rem; }
|
|
97
|
+
h2 { font-size: 1.75rem; }
|
|
98
|
+
h3 { font-size: 1.5rem; }
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Note:** These are starting values. Adapt sizes, weights, and colors to the project's design system.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Client-First Naming Conventions
|
|
2
|
+
|
|
3
|
+
## 3 Class Types
|
|
4
|
+
|
|
5
|
+
### 1. Custom Classes — `[folder]_[element-name]`
|
|
6
|
+
|
|
7
|
+
Underscore separates the component (folder) from the element: `hero_heading`, `footer_link`, `team-list_headshot-image`.
|
|
8
|
+
|
|
9
|
+
Rules:
|
|
10
|
+
- **One underscore only** — folder + element
|
|
11
|
+
- **Hyphens for multi-word names** — `team-list_headshot-wrapper`
|
|
12
|
+
- **Descriptive, not abbreviated** — `hero_description` not `hero_desc`
|
|
13
|
+
- **Lowercase always** — never camelCase
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<section class="section_hero">
|
|
17
|
+
<div class="hero_content">
|
|
18
|
+
<h1 class="hero_heading">Welcome</h1>
|
|
19
|
+
<p class="hero_description">Build something great</p>
|
|
20
|
+
<div class="hero_button-wrapper">
|
|
21
|
+
<a href="/start" class="button">Get started</a>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="hero_image-wrapper">
|
|
25
|
+
<img src="hero.jpg" alt="Hero" class="hero_image" />
|
|
26
|
+
</div>
|
|
27
|
+
</section>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Utility Classes — `[category]-[property]-[value]`
|
|
31
|
+
|
|
32
|
+
No underscore, hyphens only. Reusable across the entire site.
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<p class="text-size-large">Large text paragraph</p>
|
|
36
|
+
<div class="margin-bottom margin-medium">Spaced element</div>
|
|
37
|
+
<div class="hide-mobile-portrait">Hidden on small screens</div>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
General → specific reading order: `text-size-large` reads as "text → size → large".
|
|
41
|
+
|
|
42
|
+
### 3. Combo Classes — `is-[variant]`
|
|
43
|
+
|
|
44
|
+
Applied ON TOP of a base class to create variants. **Never used alone.**
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<a class="button is-secondary">Learn more</a>
|
|
48
|
+
<div class="card is-featured">Featured card</div>
|
|
49
|
+
<a class="nav_link is-active">Current page</a>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```css
|
|
53
|
+
.button.is-secondary { background-color: transparent; border-width: 1px; border-style: solid; }
|
|
54
|
+
.card.is-featured { border-color: #2563eb; }
|
|
55
|
+
.nav_link.is-active { color: #2563eb; font-weight: 700; }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Decision Guide
|
|
59
|
+
|
|
60
|
+
| Situation | Use | Example |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| Specific to one component | Custom | `hero_heading` |
|
|
63
|
+
| Reused across multiple components | Utility | `text-size-large` |
|
|
64
|
+
| Variant of a base style | Combo | `is-highlighted` |
|
|
65
|
+
| 3+ utilities would stack | Custom class instead | `hero_stats` (not `text-size-large text-weight-bold text-color-primary`) |
|
|
66
|
+
|
|
67
|
+
## No Deep Stacking
|
|
68
|
+
|
|
69
|
+
Max 2 utility classes per element.
|
|
70
|
+
|
|
71
|
+
**Exception:** `padding-global padding-section-large` (Layer 4 structure) — this specific combo is always allowed.
|
|
72
|
+
|
|
73
|
+
**Wrong:**
|
|
74
|
+
```html
|
|
75
|
+
<p class="text-size-large text-weight-bold text-color-primary">Too many utilities</p>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Right:**
|
|
79
|
+
```html
|
|
80
|
+
<p class="hero_stat-value">Clean custom class</p>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Common Naming Patterns
|
|
84
|
+
|
|
85
|
+
| Component | Custom classes |
|
|
86
|
+
|---|---|
|
|
87
|
+
| Hero section | `hero_content`, `hero_heading`, `hero_description`, `hero_button-wrapper`, `hero_image` |
|
|
88
|
+
| Feature card | `feature_card`, `feature_icon`, `feature_title`, `feature_description` |
|
|
89
|
+
| Testimonial | `testimonial_card`, `testimonial_quote`, `testimonial_author`, `testimonial_avatar` |
|
|
90
|
+
| Pricing | `pricing_card`, `pricing_title`, `pricing_price`, `pricing_features`, `pricing_cta` |
|
|
91
|
+
| Footer | `footer_component`, `footer_top`, `footer_bottom`, `footer_link`, `footer_social` |
|
|
92
|
+
| CTA section | `cta_content`, `cta_heading`, `cta_description`, `cta_button-wrapper` |
|