@pen.dev/cli 0.3.3 → 0.3.5
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 +13 -6
- package/dist/anthropic-messages-xcJLXjiT.mjs +40 -0
- package/dist/azure-openai-responses-CoA9_5_J.mjs +2 -0
- package/dist/dist-Dmu1Pp1Y.mjs +1580 -0
- package/dist/{dist-BY6vOcMF.mjs → dist-L3CkgNK3.mjs} +2 -2
- package/dist/{error-body-D2Mrqb4g.mjs → error-body-BBlqjbe7.mjs} +1 -1
- package/dist/google-generative-ai-CFHCNDEQ.mjs +2 -0
- package/dist/google-shared-DolBdAGX.mjs +318 -0
- package/dist/google-vertex-tT_ymu8S.mjs +2 -0
- package/dist/index.mjs +2 -2
- package/dist/lib-EA7A-_Pc.mjs +9 -0
- package/dist/mistral-conversations-CsN5eF3B.mjs +5 -0
- package/dist/models-BBd5zwn6.mjs +2 -0
- package/dist/node_modules/@highagency/pencil-wasm/package.json +1 -1
- package/dist/node_modules/@highagency/pencil-wasm/pencil.d.ts +3 -0
- package/dist/node_modules/@highagency/pencil-wasm/pencil.js +1 -1
- package/dist/node_modules/@highagency/pencil-wasm/pencil.wasm +0 -0
- package/dist/openai-CbFQ5q5I.mjs +18 -0
- package/dist/openai-codex-responses-BIh-ZL5a.mjs +8 -0
- package/dist/openai-completions-CLJSzdfY.mjs +6 -0
- package/dist/openai-responses-DKbl253t.mjs +2 -0
- package/dist/openai-responses-shared-Brqyk2bc.mjs +11 -0
- package/dist/{openrouter-images-BbBWg9zF.mjs → openrouter-images-C8mOFqx9.mjs} +1 -1
- package/dist/out/mcp-server-darwin-arm64 +0 -0
- package/dist/out/mcp-server-darwin-x64 +0 -0
- package/dist/out/mcp-server-linux-arm64 +0 -0
- package/dist/out/mcp-server-linux-x64 +0 -0
- package/dist/out/mcp-server-windows-arm64.exe +0 -0
- package/dist/out/mcp-server-windows-x64.exe +0 -0
- package/dist/out/skills/pen-dev/SKILL.md +204 -0
- package/dist/out/skills/pen-dev/execute.md +364 -0
- package/dist/out/skills/pen-dev/guide/code.md +198 -0
- package/dist/out/skills/pen-dev/guide/components.md +45 -0
- package/dist/out/skills/pen-dev/guide/design-system.md +556 -0
- package/dist/out/skills/pen-dev/guide/landing-page.md +31 -0
- package/dist/out/skills/pen-dev/guide/mobile-app.md +31 -0
- package/dist/out/skills/pen-dev/guide/slides.md +222 -0
- package/dist/out/skills/pen-dev/guide/table.md +37 -0
- package/dist/out/skills/pen-dev/guide/tailwind.md +328 -0
- package/dist/out/skills/pen-dev/guide/web-app.md +245 -0
- package/dist/out/skills/pen-dev/pen-schema.md +202 -0
- package/dist/out/skills/pen-dev/scripts-and-shaders.md +94 -0
- package/dist/{pi-messages-CSXUHkjV.mjs → pi-messages-CucvyzBS.mjs} +2 -2
- package/dist/transform-messages-1ulTEFY1.mjs +2 -0
- package/dist/typescript-D0uAMumm.mjs +6 -0
- package/package.json +3 -3
- package/dist/anthropic-messages-Bf-fvkNu.mjs +0 -40
- package/dist/azure-openai-responses-CzgVqECr.mjs +0 -2
- package/dist/completionchunk-BQtPqA8U.mjs +0 -28
- package/dist/dist-BEo0Z8Vf.mjs +0 -1558
- package/dist/google-generative-ai-DSOqI0LF.mjs +0 -2
- package/dist/google-shared-CetPT_Vt.mjs +0 -318
- package/dist/google-vertex-CPtOc5oU.mjs +0 -2
- package/dist/mistral-conversations-CUsdbDQ8.mjs +0 -10
- package/dist/models-CwK5xZH9.mjs +0 -2
- package/dist/openai-Brr_V-tF.mjs +0 -17
- package/dist/openai-codex-responses-Cb5pfH5S.mjs +0 -8
- package/dist/openai-completions-BvTlcCeP.mjs +0 -6
- package/dist/openai-responses-IuaLTEHh.mjs +0 -2
- package/dist/openai-responses-shared-D4d0NbBE.mjs +0 -11
- package/dist/otel-CaADOqYZ.mjs +0 -4
- package/dist/transform-messages-CSBQpmXO.mjs +0 -2
- /package/dist/{deferred-tools-D8j2Ra6f.mjs → deferred-tools-CozAnCQL.mjs} +0 -0
- /package/dist/{github-copilot-headers-DZOfokGy.mjs → github-copilot-headers-DCj7hJoC.mjs} +0 -0
- /package/dist/{hash-Kp92CI9R.mjs → hash-DNYCELl4.mjs} +0 -0
- /package/dist/{headers-BvGum5dc.mjs → headers-DlpC0ues.mjs} +0 -0
- /package/dist/{openai-prompt-cache-t4kk9puG.mjs → openai-prompt-cache-tVHrB8oW.mjs} +0 -0
- /package/dist/{photon_rs-BySSRmP5.mjs → photon_rs-o0nbTM4F.mjs} +0 -0
- /package/dist/{provider-retry-BM3ArvaW.mjs → provider-retry-GaV_ioT7.mjs} +0 -0
- /package/dist/{sanitize-unicode-CHjuq5rK.mjs → sanitize-unicode-D-15laVS.mjs} +0 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
ROLE: You are a professional slide deck designer.
|
|
2
|
+
GOAL: Produce slides that are readable in real conditions (projector, Zoom, mobile).
|
|
3
|
+
PRIORITY: Clarity > Readability > Hierarchy > Simplicity.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
CRITICAL — FIRST PRIORITY
|
|
7
|
+
INPUT: Brand guidelines will be given but are NOT slide-optimized.
|
|
8
|
+
RULE: Always adapt brand for slides (bigger fonts, more spacing, change more if needed). Never sacrifice readability.
|
|
9
|
+
|
|
10
|
+
CORE RULES:
|
|
11
|
+
- One idea per slide.
|
|
12
|
+
- Slides are visual aids, not documents.
|
|
13
|
+
- If content doesn’t fit at required sizes: split or remove. Never shrink fonts.
|
|
14
|
+
- Consistency > creativity. Reduce cognitive load.
|
|
15
|
+
|
|
16
|
+
CRITICAL – TYPOGRAPHY:
|
|
17
|
+
- Max 2 font families.
|
|
18
|
+
- Body >=24px (prefer 28–32).
|
|
19
|
+
- Titles >=40px.
|
|
20
|
+
- Key numbers can be larger.
|
|
21
|
+
- Use weight, not many sizes.
|
|
22
|
+
- Avoid ALL CAPS except labels.
|
|
23
|
+
- Line-height ~1.1–1.2.
|
|
24
|
+
- High contrast always.
|
|
25
|
+
|
|
26
|
+
LAYOUT & SPACING:
|
|
27
|
+
- Use grid. Align everything.
|
|
28
|
+
- Generous whitespace.
|
|
29
|
+
- No clutter.
|
|
30
|
+
- Apply CRAP: Contrast, Repetition, Alignment, Proximity.
|
|
31
|
+
|
|
32
|
+
COLOR:
|
|
33
|
+
- 2–3 core colors + neutrals.
|
|
34
|
+
- High contrast text/bg mandatory.
|
|
35
|
+
- Accent only for emphasis.
|
|
36
|
+
- Body text neutral.
|
|
37
|
+
- Colorblind-safe if possible.
|
|
38
|
+
|
|
39
|
+
VISUALS & DATA:
|
|
40
|
+
- Visuals support meaning, not decoration.
|
|
41
|
+
- Prefer custom visuals to stock.
|
|
42
|
+
- Charts > text for data.
|
|
43
|
+
- One insight per chart.
|
|
44
|
+
- Simplify charts (no junk).
|
|
45
|
+
- Highlight key datapoint.
|
|
46
|
+
- Icons consistent style/size.
|
|
47
|
+
|
|
48
|
+
FORMAT:
|
|
49
|
+
- 16:9, 1920x1080.
|
|
50
|
+
- Keep content >=100px from edges.
|
|
51
|
+
|
|
52
|
+
CONTENT DENSITY:
|
|
53
|
+
- One message per slide.
|
|
54
|
+
- Short phrases > sentences.
|
|
55
|
+
- No paragraphs.
|
|
56
|
+
- Title states takeaway.
|
|
57
|
+
- Details go to notes/appendix.
|
|
58
|
+
|
|
59
|
+
CONTEXT:
|
|
60
|
+
- Corp=structured.
|
|
61
|
+
- Startup=minimal, bold.
|
|
62
|
+
- Marketing=benefit-driven.
|
|
63
|
+
- Internal=slightly denser.
|
|
64
|
+
- Keynote=very visual.
|
|
65
|
+
(Rules above always apply.)
|
|
66
|
+
|
|
67
|
+
LAYOUT CONTRACTS (use IDs, follow strictly):
|
|
68
|
+
|
|
69
|
+
L01:
|
|
70
|
+
Intent=Cover
|
|
71
|
+
Grid=CenterStack
|
|
72
|
+
Content=Title(48-64,Bold); Subtitle(28-32); Meta(20-24)
|
|
73
|
+
Rules=CenterXY; PlentySpace; NoExtras
|
|
74
|
+
|
|
75
|
+
L02:
|
|
76
|
+
Intent=BoldCover
|
|
77
|
+
Grid=LeftBlock
|
|
78
|
+
Content=Title(56-72,Max2Lines); Subtitle(28); Meta
|
|
79
|
+
Rules=LeftMargin~120; Logo=BR; NoClutter
|
|
80
|
+
|
|
81
|
+
L03:
|
|
82
|
+
Intent=SectionBreak
|
|
83
|
+
Grid=Center
|
|
84
|
+
Content=Label(24,Muted); Title(48-56)
|
|
85
|
+
Rules=OnlyThese2; MaxWhitespace
|
|
86
|
+
|
|
87
|
+
L04:
|
|
88
|
+
Intent=KeyStatement
|
|
89
|
+
Grid=Center
|
|
90
|
+
Content=Statement(36-48,Max2Lines); OptionalAttribution(24)
|
|
91
|
+
Rules=Only1Message
|
|
92
|
+
|
|
93
|
+
L05:
|
|
94
|
+
Intent=Concept+Visual
|
|
95
|
+
Grid=2col(50/50)
|
|
96
|
+
Left=Title(36-40)+Body(24-28,Max4Lines)
|
|
97
|
+
Right=Image
|
|
98
|
+
Rules=Gap>=40; CenterY; NoOverflow
|
|
99
|
+
|
|
100
|
+
L06:
|
|
101
|
+
Intent=Concept+Visual
|
|
102
|
+
Grid=2col(50/50)
|
|
103
|
+
Left=Image
|
|
104
|
+
Right=Title(36-40)+Body(24-28,Max4Lines)
|
|
105
|
+
Rules=Mirror(L05)
|
|
106
|
+
|
|
107
|
+
L07:
|
|
108
|
+
Intent=3Pillars
|
|
109
|
+
Grid=3col
|
|
110
|
+
Each=Visual+Label(28)+Desc(20,Max2Lines)
|
|
111
|
+
Rules=EqualWidth; SameTopY; Gap=30-50
|
|
112
|
+
|
|
113
|
+
L08:
|
|
114
|
+
Intent=Compare2
|
|
115
|
+
Grid=2col
|
|
116
|
+
Each=Heading(28-32)+Points(24,2-4)
|
|
117
|
+
Rules=BalancedContent; Gap=40-60
|
|
118
|
+
|
|
119
|
+
L09:
|
|
120
|
+
Intent=SingleKPI
|
|
121
|
+
Grid=CenterStack
|
|
122
|
+
Content=Label(24,Muted); Number(120-200); Context(24-28)
|
|
123
|
+
Rules=NumberIsHero; NothingCompetes
|
|
124
|
+
|
|
125
|
+
L10:
|
|
126
|
+
Intent=TwoKPIs
|
|
127
|
+
Grid=2col
|
|
128
|
+
Each=Number(80-120)+Label(24)
|
|
129
|
+
Rules=EqualWeight
|
|
130
|
+
|
|
131
|
+
L11:
|
|
132
|
+
Intent=ThreeKPIs
|
|
133
|
+
Grid=3col
|
|
134
|
+
Each=Number(64-80)+Label(24)
|
|
135
|
+
Rules=SameBaseline
|
|
136
|
+
|
|
137
|
+
L12:
|
|
138
|
+
Intent=Quote
|
|
139
|
+
Grid=CenterStack
|
|
140
|
+
Content=Quote(28-36,Max3Lines); Attribution(20-24)
|
|
141
|
+
Rules=GenerousPadding
|
|
142
|
+
|
|
143
|
+
L13:
|
|
144
|
+
Intent=Process
|
|
145
|
+
Grid=Row(3-5Steps)
|
|
146
|
+
Each=Icon/Number+Label(28)+Desc(20,1Line)
|
|
147
|
+
Rules=EqualSpacing; SameBaseline
|
|
148
|
+
|
|
149
|
+
L14:
|
|
150
|
+
Intent=HeroImage
|
|
151
|
+
Grid=FullBleed
|
|
152
|
+
Content=OverlayTitle(40-56)+Subtitle(24-28)
|
|
153
|
+
Rules=DarkOverlay; HighContrast
|
|
154
|
+
|
|
155
|
+
L15:
|
|
156
|
+
Intent=Matrix4
|
|
157
|
+
Grid=2x2
|
|
158
|
+
Each=Heading(28)+Desc(20)
|
|
159
|
+
Rules=EqualCards; Gap=20-30
|
|
160
|
+
|
|
161
|
+
L16:
|
|
162
|
+
Intent=IconRow
|
|
163
|
+
Grid=Row(3-4)
|
|
164
|
+
Each=Icon+Label(28)+Desc(20,1-2Lines)
|
|
165
|
+
Rules=SameIconSize; AlignBaselines
|
|
166
|
+
|
|
167
|
+
L17:
|
|
168
|
+
Intent=Data+Insight
|
|
169
|
+
Grid=Stack
|
|
170
|
+
Content=Chart(~60%H); Insight(24-28,Bold)
|
|
171
|
+
Rules=1Highlight; NoChartJunk
|
|
172
|
+
|
|
173
|
+
L18:
|
|
174
|
+
Intent=BeforeAfter
|
|
175
|
+
Grid=2col+Arrow
|
|
176
|
+
Left=Before(Muted)
|
|
177
|
+
Right=After(Strong)
|
|
178
|
+
Rules=ClearContrast
|
|
179
|
+
|
|
180
|
+
L19:
|
|
181
|
+
Intent=List
|
|
182
|
+
Grid=Stack
|
|
183
|
+
Content=Title(40); Items(28,3-5)
|
|
184
|
+
Rules=NoWrap; LargeGaps
|
|
185
|
+
|
|
186
|
+
L20:
|
|
187
|
+
Intent=Closing
|
|
188
|
+
Grid=CenterStack
|
|
189
|
+
Content=Headline(48-56); Sub(24-28); Contact(24)
|
|
190
|
+
Rules=Clean; FinalImpression
|
|
191
|
+
|
|
192
|
+
OPENING & CLOSING SLIDES:
|
|
193
|
+
- First and last slides are STATEMENTS — emotional, not informational.
|
|
194
|
+
- Combine a strong visual with powerful words. Image + text working together.
|
|
195
|
+
- These set the tone (opening) and leave the lasting impression (closing).
|
|
196
|
+
- Aim for feeling, not facts.
|
|
197
|
+
|
|
198
|
+
TEXT-ONLY SLIDES:
|
|
199
|
+
- When a slide has no visual, let typography do the emotional heavy lifting.
|
|
200
|
+
- Be courageous: oversized type, unexpected alignment, asymmetric layout.
|
|
201
|
+
- Break the grid if it serves the message. Unusual ≠ unreadable.
|
|
202
|
+
- The text IS the visual — treat it as such.
|
|
203
|
+
|
|
204
|
+
SELECTION:
|
|
205
|
+
- Opening: L01,L02 (emotional statement + visual)
|
|
206
|
+
- Section: L03
|
|
207
|
+
- Statement/Quote: L04,L12
|
|
208
|
+
- Concept+Visual: L05,L06,L14
|
|
209
|
+
- Features: L07,L16
|
|
210
|
+
- Compare: L08,L18
|
|
211
|
+
- KPI: L09,L10,L11
|
|
212
|
+
- Process: L13
|
|
213
|
+
- Matrix: L15
|
|
214
|
+
- Data: L17
|
|
215
|
+
- List: L19
|
|
216
|
+
- Closing: L20 (emotional statement + visual)
|
|
217
|
+
|
|
218
|
+
OUTPUT RULES:
|
|
219
|
+
- Be concrete.
|
|
220
|
+
- No theory, no filler.
|
|
221
|
+
- Use sizes, spacing, alignment explicitly.
|
|
222
|
+
- If unclear: ask <=3 questions OR list <=5 assumptions.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Table
|
|
2
|
+
|
|
3
|
+
- Tables follow strict hierarchy: **Table (frame) → Table Row (frame) → Table Cell (frame) → Table Cell Content**
|
|
4
|
+
- Use the following rules **only when there is no predefined Table component or Table frame** in the design system or document.
|
|
5
|
+
- Table responsive multi screen design: Unless specifically defined, when converting a wide multi-column table to a mobile version, consider using cards instead of table
|
|
6
|
+
- Tables need to use flex box layout.
|
|
7
|
+
- CRITICAL: Each cell is represented as a **frame** node and contains a cell content, which is usually text, label, button or instance of a component.
|
|
8
|
+
- **Antipattern** – Do NOT put content directly in the row, skipping the cell frame:
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
tableRowId=Insert("kdl58",{type:"frame",layout:"horizontal"})
|
|
12
|
+
Insert(tableRowId,{type:"text",content:"John Doe"})
|
|
13
|
+
Insert(tableRowId,{type:"text",content:"joe.doe@example.com"})
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Table Hierarchy
|
|
18
|
+
```
|
|
19
|
+
Table (frame, vertical layout)
|
|
20
|
+
├── Header Row (frame, horizontal, width: fill_container, height: fixed)
|
|
21
|
+
│ ├── Cell (frame, width: fixed, height: fill_container)
|
|
22
|
+
│ │ └── Text (text, bold, textGrowth: fixed-width)
|
|
23
|
+
│ ├── Cell (frame, width: fixed, height: fill_container)
|
|
24
|
+
│ │ └── Text (text, bold, textGrowth: fixed-width)
|
|
25
|
+
│ └── ...
|
|
26
|
+
├── Data Row (frame, horizontal, width: fill_container, height: fixed)
|
|
27
|
+
│ ├── Cell (frame, width: fixed, height: fill_container)
|
|
28
|
+
│ │ └── Text (text, textGrowth: fixed-width)
|
|
29
|
+
│ ├── Cell (frame, width: fixed, height: fill_container)
|
|
30
|
+
│ │ └── Text (text, textGrowth: fixed-width)
|
|
31
|
+
│ └── ...
|
|
32
|
+
├── Data Row ...
|
|
33
|
+
└── ...
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- If the user does not specify data, generate **dummy placeholder values** for each cell.
|
|
37
|
+
- Cells may contain other components (e.g., label, button) instead of text if explicitly requested.
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# Tailwind v4 Implementation Guidelines
|
|
2
|
+
|
|
3
|
+
This document provides Tailwind v4 specific guidelines for implementing .pen designs in code.
|
|
4
|
+
|
|
5
|
+
**NOTE**: These guidelines are specific to Tailwind v4. If you are deliberately using an older version of Tailwind (v3 or earlier), you may bypass the v4-specific syntax rules (such as `@import "tailwindcss";` vs `@tailwind` directives) and adapt accordingly.
|
|
6
|
+
|
|
7
|
+
## Core Principle
|
|
8
|
+
|
|
9
|
+
**Use Tailwind classes exclusively throughout - NEVER use inline styles for any property (sizing, colors, spacing, typography, etc.).**
|
|
10
|
+
|
|
11
|
+
## CSS Variables Setup
|
|
12
|
+
|
|
13
|
+
### Structure of globals.css
|
|
14
|
+
|
|
15
|
+
Your `globals.css` should follow this structure:
|
|
16
|
+
|
|
17
|
+
```css
|
|
18
|
+
@import "tailwindcss";
|
|
19
|
+
|
|
20
|
+
:root {
|
|
21
|
+
/* Design variables from .pen file - ONLY single values */
|
|
22
|
+
--color-primary: #3b82f6;
|
|
23
|
+
--color-secondary: #8b5cf6;
|
|
24
|
+
--spacing-base: 16px;
|
|
25
|
+
/* DO NOT store font stacks here */
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@layer base {
|
|
29
|
+
html, body {
|
|
30
|
+
height: 100%;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Font family utilities - Define font stacks directly here */
|
|
34
|
+
.font-primary {
|
|
35
|
+
font-family: "Inter", sans-serif;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.font-secondary {
|
|
39
|
+
font-family: "JetBrains Mono", monospace;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Guidelines
|
|
45
|
+
|
|
46
|
+
- Read design variables using `Print(GetVariables())` in `execute`
|
|
47
|
+
- Convert to CSS custom properties in `:root` block for single values only (colors, numbers, keywords)
|
|
48
|
+
- Map all design variables using exact names from design file
|
|
49
|
+
- **IMPORTANT**: Use `:root` block for design variables (NOT `@theme` - Tailwind v4's `@theme` only supports custom properties and `@keyframes`)
|
|
50
|
+
- **DO NOT add manual resets** - `@import "tailwindcss";` includes Preflight automatically
|
|
51
|
+
- **CRITICAL for Next.js projects**: If using `next/font` loaders, DO NOT re-wrap their CSS variables (like `--font-geist`) in your `:root` block. Instead, reference them directly in `@layer base` utility classes (see Font Loading section)
|
|
52
|
+
|
|
53
|
+
## Font Implementation
|
|
54
|
+
|
|
55
|
+
### Core Rules
|
|
56
|
+
|
|
57
|
+
**CSS variables work for single values only** (colors, numbers, keywords). **DO NOT use them for font stacks.**
|
|
58
|
+
|
|
59
|
+
❌ **WRONG**:
|
|
60
|
+
```css
|
|
61
|
+
:root {
|
|
62
|
+
--font-primary: "JetBrains Mono", monospace; /* Breaks with comma-separated values */
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
✅ **CORRECT**: Define fonts in `@layer base` utility classes:
|
|
67
|
+
```css
|
|
68
|
+
@layer base {
|
|
69
|
+
.font-primary {
|
|
70
|
+
font-family: "JetBrains Mono", monospace;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.font-secondary {
|
|
74
|
+
font-family: "Inter", sans-serif;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Next.js Font Loaders
|
|
80
|
+
|
|
81
|
+
When using `next/font/google` or `next/font/local`:
|
|
82
|
+
|
|
83
|
+
❌ **NEVER wrap Next.js font variables in `:root`**:
|
|
84
|
+
```css
|
|
85
|
+
/* WRONG - nested var() references break */
|
|
86
|
+
:root {
|
|
87
|
+
--font-primary: var(--font-geist);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
✅ **DO reference them directly in utility classes**:
|
|
92
|
+
```css
|
|
93
|
+
@layer base {
|
|
94
|
+
.font-primary {
|
|
95
|
+
font-family: var(--font-jetbrains-mono), "JetBrains Mono", monospace;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Implementation Workflow
|
|
101
|
+
|
|
102
|
+
1. Read font names from design using `Print(GetVariables())` in `execute`
|
|
103
|
+
2. Load fonts via `<link>` tags OR Next.js font loaders in layout.tsx
|
|
104
|
+
3. Create utility classes in `@layer base` (`.font-primary`, `.font-secondary`)
|
|
105
|
+
4. Use classes in components: `className="font-primary"`
|
|
106
|
+
5. **NEVER use** `font-[var(--font-name)]` or inline styles for fonts
|
|
107
|
+
|
|
108
|
+
## Font Loading
|
|
109
|
+
|
|
110
|
+
### Tailwind v4 Requirements
|
|
111
|
+
|
|
112
|
+
❌ **NEVER in Tailwind v4**:
|
|
113
|
+
- `@import url()` in CSS files
|
|
114
|
+
- `font-[family-name:var(...)]` syntax
|
|
115
|
+
- `--turbopack` flag
|
|
116
|
+
|
|
117
|
+
✅ **Load fonts via**:
|
|
118
|
+
- `<link>` tags in layout.tsx `<head>`, OR
|
|
119
|
+
- Next.js font loaders (`next/font/google`, `next/font/local`)
|
|
120
|
+
|
|
121
|
+
### Examples
|
|
122
|
+
|
|
123
|
+
**Option 1: Manual loading**
|
|
124
|
+
```tsx
|
|
125
|
+
// layout.tsx
|
|
126
|
+
<head>
|
|
127
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet" />
|
|
128
|
+
</head>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Option 2: Next.js font loaders**
|
|
132
|
+
```tsx
|
|
133
|
+
// layout.tsx
|
|
134
|
+
import { JetBrains_Mono } from "next/font/google";
|
|
135
|
+
|
|
136
|
+
const jetbrainsMono = JetBrains_Mono({
|
|
137
|
+
variable: "--font-jetbrains-mono",
|
|
138
|
+
subsets: ["latin"],
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
export default function RootLayout({ children }) {
|
|
142
|
+
return (
|
|
143
|
+
<html>
|
|
144
|
+
<body className={jetbrainsMono.variable}>
|
|
145
|
+
{children}
|
|
146
|
+
</body>
|
|
147
|
+
</html>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
```css
|
|
153
|
+
/* globals.css */
|
|
154
|
+
@layer base {
|
|
155
|
+
.font-primary {
|
|
156
|
+
font-family: var(--font-jetbrains-mono), "JetBrains Mono", monospace;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Icon Font Setup
|
|
162
|
+
|
|
163
|
+
- **If design uses `icon` nodes**:
|
|
164
|
+
1. Add Google Fonts link in layout.tsx `<head>` (following the Font Loading Rules above)
|
|
165
|
+
2. Add utility class in `@layer base` section of globals.css with appropriate font-feature-settings
|
|
166
|
+
3. Render as `<span>` elements with icon name as text content
|
|
167
|
+
4. Use inline styles for font-weight if needed (e.g., `style={{ fontWeight: 100 }}`)
|
|
168
|
+
5. **NEVER use `@font-face`** - Always use CDN links
|
|
169
|
+
|
|
170
|
+
## Viewport Setup
|
|
171
|
+
|
|
172
|
+
- Add `height: 100%` to `html` and `body` in `@layer base` section of globals.css (as shown in CSS Variables Setup example)
|
|
173
|
+
- Add `h-full` class to `<html>` and `<body>` in layout.tsx
|
|
174
|
+
- Ensures viewport-relative sizing works throughout app
|
|
175
|
+
- Design dimensions are specifications, not fixed constraints
|
|
176
|
+
- **DO NOT use wildcard selectors** - use the `@layer base` approach shown above
|
|
177
|
+
|
|
178
|
+
## Tailwind v4 Import and Preflight
|
|
179
|
+
|
|
180
|
+
### Correct Import Syntax
|
|
181
|
+
|
|
182
|
+
**Tailwind v4 uses a simplified import syntax** in `globals.css`:
|
|
183
|
+
|
|
184
|
+
```css
|
|
185
|
+
@import "tailwindcss";
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
This single import automatically includes:
|
|
189
|
+
- Base styles (Preflight reset)
|
|
190
|
+
- Component classes
|
|
191
|
+
- Utility classes
|
|
192
|
+
|
|
193
|
+
**DO NOT use the old v3 syntax**:
|
|
194
|
+
```css
|
|
195
|
+
/* ❌ WRONG - This is v3 syntax */
|
|
196
|
+
@tailwind base;
|
|
197
|
+
@tailwind components;
|
|
198
|
+
@tailwind utilities;
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Preflight Reset Behavior
|
|
202
|
+
|
|
203
|
+
The `@import "tailwindcss";` automatically includes Preflight, which:
|
|
204
|
+
- Removes margins and padding from all elements
|
|
205
|
+
- Sets `box-sizing: border-box` on all elements
|
|
206
|
+
- Resets headings and lists (they inherit font properties)
|
|
207
|
+
- Makes images block-level with responsive sizing
|
|
208
|
+
|
|
209
|
+
### Critical Rules
|
|
210
|
+
|
|
211
|
+
- **NEVER manually add global resets** - Preflight handles everything
|
|
212
|
+
- **NEVER use wildcard selectors** like `* { margin: 0; padding: 0; }` in globals.css
|
|
213
|
+
- **DO NOT duplicate Preflight functionality** - it's already included
|
|
214
|
+
- Use `@layer base { ... }` ONLY for additional custom base styles that don't conflict with Preflight
|
|
215
|
+
|
|
216
|
+
## Layout Conversion
|
|
217
|
+
|
|
218
|
+
### Container Sizing
|
|
219
|
+
|
|
220
|
+
- Root containers: `h-full w-full` or `h-screen w-screen` (NOT fixed dimensions)
|
|
221
|
+
- Fixed dimensions only for specific elements (e.g., sidebar: `w-[280px]`)
|
|
222
|
+
|
|
223
|
+
### fill_container Translation
|
|
224
|
+
|
|
225
|
+
- In flex containers: use `flex-1`
|
|
226
|
+
- For explicit sizing: `w-full` (width), `h-full` (height)
|
|
227
|
+
- **IMPORTANT**: `h-full` requires parent chain has height set
|
|
228
|
+
- For scrollable containers: `flex-1 overflow-auto`
|
|
229
|
+
- **NEVER use inline styles** for sizing
|
|
230
|
+
- **Multiple fill_container Children**:
|
|
231
|
+
* In flex containers, multiple children with `fill_container` → each needs `flex-1`
|
|
232
|
+
* Applies to both horizontal and vertical flex layouts
|
|
233
|
+
* Distributes space equally among children
|
|
234
|
+
- **Height fill_container**:
|
|
235
|
+
* ANY component with `height: "fill_container"` MUST have `h-full` class
|
|
236
|
+
* Applies universally regardless of component type or parent layout
|
|
237
|
+
* Verify every `fill_container` height has corresponding `h-full` class
|
|
238
|
+
|
|
239
|
+
### fit_content Translation
|
|
240
|
+
|
|
241
|
+
- Use `w-fit` (width), `h-fit` (height)
|
|
242
|
+
- NEVER use inline styles
|
|
243
|
+
|
|
244
|
+
### Flex Context
|
|
245
|
+
|
|
246
|
+
- Parent must be flex container for `flex-1` to work
|
|
247
|
+
- Use `min-h-0` on flex children that need to shrink below content size
|
|
248
|
+
- Scrollable flex children: `flex-1 overflow-auto`
|
|
249
|
+
|
|
250
|
+
### Verification
|
|
251
|
+
|
|
252
|
+
- Check ALL `fill_container`/`fit_content` converted to Tailwind classes
|
|
253
|
+
- Ensure NO inline styles for width/height
|
|
254
|
+
|
|
255
|
+
## Style Implementation
|
|
256
|
+
|
|
257
|
+
Use **Tailwind classes exclusively** (NO inline styles) for all styling:
|
|
258
|
+
|
|
259
|
+
### 1. Layout
|
|
260
|
+
|
|
261
|
+
- Position: `relative`, `absolute`, `fixed`, `sticky`
|
|
262
|
+
- Display: `flex`, `flex-col`, `grid`, `block`, `inline-block`
|
|
263
|
+
- Alignment: `items-center`, `justify-between`, etc.
|
|
264
|
+
- Gap: `gap-4`, `gap-[16px]` (match design exactly)
|
|
265
|
+
|
|
266
|
+
### 2. Spacing
|
|
267
|
+
|
|
268
|
+
Match design values exactly:
|
|
269
|
+
- Padding: `p-4`, `px-6`, `pt-[12px]`, etc.
|
|
270
|
+
- Margin: `m-4`, `mx-auto`, `mt-[8px]`, etc.
|
|
271
|
+
- Use arbitrary values `[Npx]` when needed
|
|
272
|
+
|
|
273
|
+
### 3. Dimensions
|
|
274
|
+
|
|
275
|
+
- Width: `w-[280px]` (fixed), `w-full` or `flex-1` (fill_container), `w-fit` (fit_content)
|
|
276
|
+
- Height: `h-[48px]` (fixed), `h-full` or `flex-1` (fill_container), `h-fit` (fit_content)
|
|
277
|
+
- Min/max: `min-w-[200px]`, `max-h-[600px]`
|
|
278
|
+
- **CRITICAL**: Never use inline styles for dimensions
|
|
279
|
+
|
|
280
|
+
### 4. Colors and Borders
|
|
281
|
+
|
|
282
|
+
- Background: `bg-[var(--color-name)]` - NO hardcoded hex values
|
|
283
|
+
- Border: `border`, `border-2`, `border-[var(--color-border)]`
|
|
284
|
+
- Border radius: `rounded`, `rounded-lg`, `rounded-[12px]`
|
|
285
|
+
- Text: `text-[var(--color-text)]`
|
|
286
|
+
- Shadows: `shadow-sm`, `shadow-[custom]`
|
|
287
|
+
|
|
288
|
+
### 5. Typography
|
|
289
|
+
|
|
290
|
+
- **Font family**: Use utility classes defined in `@layer base` (see "CSS Custom Properties and Font Stacks" section above)
|
|
291
|
+
- ✅ Correct: `className="font-primary"`
|
|
292
|
+
- ❌ NEVER: `font-[var(--font-primary)]` (arbitrary value syntax doesn't work with CSS variables)
|
|
293
|
+
- ❌ NEVER: `style={{ fontFamily: 'var(--font-primary)' }}` (avoid inline styles unless necessary)
|
|
294
|
+
- For Next.js font loaders: Create utility classes that reference the Next.js variables, then use those classes
|
|
295
|
+
- Font size: `text-sm`, `text-[14px]`
|
|
296
|
+
- Font weight: `font-medium`, `font-[500]`
|
|
297
|
+
- Line height: `leading-normal`, `leading-[24px]`
|
|
298
|
+
- Letter spacing: `tracking-normal`, `tracking-[0.02em]`
|
|
299
|
+
|
|
300
|
+
### 6. Interactive States
|
|
301
|
+
|
|
302
|
+
- Hover: `hover:bg-[var(--color-hover)]`, `hover:opacity-80`
|
|
303
|
+
- Active: `active:scale-95`
|
|
304
|
+
- Disabled: `disabled:opacity-50`, `disabled:cursor-not-allowed`
|
|
305
|
+
- Focus: `focus:outline-none`, `focus:ring-2`
|
|
306
|
+
|
|
307
|
+
## SVG Styling
|
|
308
|
+
|
|
309
|
+
For SVG path extraction and implementation workflow, see code.md "SVG Path Implementation" section.
|
|
310
|
+
|
|
311
|
+
### Tailwind-Specific SVG Styling
|
|
312
|
+
|
|
313
|
+
When styling SVG elements with Tailwind:
|
|
314
|
+
|
|
315
|
+
- **Fill colors**: Use `fill-[var(--color-name)]` with CSS variables
|
|
316
|
+
- Example: `fill-[var(--primary)]`
|
|
317
|
+
- **Stroke colors**: Use `stroke-[var(--color-name)]`
|
|
318
|
+
- Example: `stroke-[var(--border)]`
|
|
319
|
+
- **Stroke width**: Use `stroke-[2]` or arbitrary values `stroke-[1.5px]`
|
|
320
|
+
- **SVG sizing**: Use standard sizing classes `w-6 h-6` or arbitrary `w-[24px] h-[24px]`
|
|
321
|
+
- **NEVER use inline styles** - always use Tailwind classes or className with CSS variables
|
|
322
|
+
|
|
323
|
+
Example:
|
|
324
|
+
```tsx
|
|
325
|
+
<svg className="w-6 h-6 fill-[var(--icon-primary)]" viewBox="0 0 24 24">
|
|
326
|
+
<path d="M12 2L2 7l10 5 10-5-10-5z" />
|
|
327
|
+
</svg>
|
|
328
|
+
```
|