@deckspec/cli 0.1.1 → 0.1.3
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/dist/cli.js +13 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/dev.d.ts +3 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +4 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +22 -17
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/render.d.ts.map +1 -1
- package/dist/commands/render.js +13 -4
- package/dist/commands/render.js.map +1 -1
- package/package.json +6 -5
- package/src/cli.ts +12 -2
- package/src/commands/dev.ts +3 -2
- package/src/commands/init.ts +22 -17
- package/src/commands/render.ts +13 -4
- package/templates/noir-display/components/card/index.tsx +31 -0
- package/templates/noir-display/components/index.ts +2 -0
- package/templates/noir-display/components/slide-header/index.tsx +47 -0
- package/templates/noir-display/design.md +289 -0
- package/templates/noir-display/globals.css +263 -0
- package/templates/noir-display/package.json +39 -0
- package/templates/noir-display/patterns/_lib/chart-colors.ts +12 -0
- package/templates/noir-display/patterns/_lib/icon.tsx +50 -0
- package/templates/noir-display/patterns/big-number/index.tsx +87 -0
- package/templates/noir-display/patterns/body-message/index.tsx +295 -0
- package/templates/noir-display/patterns/bullet-list/index.tsx +132 -0
- package/templates/noir-display/patterns/challenge-cards/index.tsx +112 -0
- package/templates/noir-display/patterns/chart-bar/index.tsx +107 -0
- package/templates/noir-display/patterns/comparison-columns/index.tsx +115 -0
- package/templates/noir-display/patterns/feature-metrics/index.tsx +94 -0
- package/templates/noir-display/patterns/flow-diagram/index.tsx +151 -0
- package/templates/noir-display/patterns/hero-statement/index.tsx +72 -0
- package/templates/noir-display/patterns/icon-grid/index.tsx +126 -0
- package/templates/noir-display/patterns/index.ts +17 -0
- package/templates/noir-display/patterns/phased-roadmap/index.tsx +179 -0
- package/templates/noir-display/patterns/photo-split/index.tsx +110 -0
- package/templates/noir-display/patterns/pricing-tiers/index.tsx +127 -0
- package/templates/noir-display/patterns/showcase-grid/index.tsx +99 -0
- package/templates/noir-display/patterns/thank-you/index.tsx +86 -0
- package/templates/noir-display/patterns/three-pillars/index.tsx +112 -0
- package/templates/noir-display/patterns/title-center/index.tsx +46 -0
- package/templates/noir-display/tokens.json +30 -0
- package/templates/noir-display/tsconfig.json +13 -0
- package/templates/skills/deckspec-add-pattern/SKILL.md +78 -0
- package/templates/skills/deckspec-make-slides/SKILL.md +70 -0
- package/templates/skills/deckspec-promote-pattern/SKILL.md +133 -0
- package/templates/skills/deckspec-screenshot/SKILL.md +41 -0
- package/templates/skills/deckspec-to-pptx/SKILL.md +36 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
const pillarSchema = z.object({
|
|
4
|
+
title: z.string().min(1).describe("Pillar title"),
|
|
5
|
+
description: z.string().min(1).describe("Pillar description"),
|
|
6
|
+
value: z.string().optional().describe("Optional large display value"),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export const schema = z.object({
|
|
10
|
+
label: z.string().min(1).max(30).optional().describe("Accent eyebrow"),
|
|
11
|
+
heading: z.string().min(1).max(60).describe("Section heading"),
|
|
12
|
+
pillars: z.array(pillarSchema).min(2).max(3).describe("Pillars (2-3)"),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
type Props = z.infer<typeof schema>;
|
|
16
|
+
|
|
17
|
+
export default function ThreePillars({ label, heading, pillars }: Props) {
|
|
18
|
+
return (
|
|
19
|
+
<div className="slide-stack" style={{ justifyContent: "center", gap: 48 }}>
|
|
20
|
+
{/* Header */}
|
|
21
|
+
<div style={{ textAlign: "center" }}>
|
|
22
|
+
{label && (
|
|
23
|
+
<span
|
|
24
|
+
style={{
|
|
25
|
+
fontSize: 17,
|
|
26
|
+
fontWeight: 600,
|
|
27
|
+
letterSpacing: "-0.022em",
|
|
28
|
+
color: "var(--color-primary)",
|
|
29
|
+
display: "block",
|
|
30
|
+
marginBottom: 8,
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
{label}
|
|
34
|
+
</span>
|
|
35
|
+
)}
|
|
36
|
+
<h2
|
|
37
|
+
style={{
|
|
38
|
+
fontSize: 48,
|
|
39
|
+
fontWeight: 600,
|
|
40
|
+
lineHeight: 1.08,
|
|
41
|
+
letterSpacing: "-0.003em",
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
{heading}
|
|
45
|
+
</h2>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
{/* Pillars as white cards on gray canvas */}
|
|
49
|
+
<div
|
|
50
|
+
style={{
|
|
51
|
+
display: "grid",
|
|
52
|
+
gridTemplateColumns: `repeat(${pillars.length}, 1fr)`,
|
|
53
|
+
gap: 20,
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
{pillars.map((p, i) => (
|
|
57
|
+
<div
|
|
58
|
+
key={i}
|
|
59
|
+
style={{
|
|
60
|
+
backgroundColor: "#ffffff",
|
|
61
|
+
borderRadius: 18,
|
|
62
|
+
padding: "36px 32px",
|
|
63
|
+
display: "flex",
|
|
64
|
+
flexDirection: "column",
|
|
65
|
+
gap: 12,
|
|
66
|
+
boxShadow: "4px 4px 12px rgba(0,0,0,0.06)",
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
{p.value && (
|
|
70
|
+
<span
|
|
71
|
+
style={{
|
|
72
|
+
fontSize: 40,
|
|
73
|
+
fontWeight: 600,
|
|
74
|
+
fontFamily: "var(--font-heading)",
|
|
75
|
+
lineHeight: 1,
|
|
76
|
+
letterSpacing: "-0.009em",
|
|
77
|
+
color: "var(--color-primary)",
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
{p.value}
|
|
81
|
+
</span>
|
|
82
|
+
)}
|
|
83
|
+
<span
|
|
84
|
+
style={{
|
|
85
|
+
fontSize: 21,
|
|
86
|
+
fontWeight: 600,
|
|
87
|
+
fontFamily: "var(--font-heading)",
|
|
88
|
+
letterSpacing: "0.011em",
|
|
89
|
+
color: "var(--color-foreground)",
|
|
90
|
+
lineHeight: 1.24,
|
|
91
|
+
}}
|
|
92
|
+
>
|
|
93
|
+
{p.title}
|
|
94
|
+
</span>
|
|
95
|
+
<span
|
|
96
|
+
style={{
|
|
97
|
+
fontSize: 17,
|
|
98
|
+
fontWeight: 400,
|
|
99
|
+
fontFamily: "var(--font-body)",
|
|
100
|
+
letterSpacing: "-0.022em",
|
|
101
|
+
color: "var(--color-muted-foreground)",
|
|
102
|
+
lineHeight: 1.47,
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
{p.description}
|
|
106
|
+
</span>
|
|
107
|
+
</div>
|
|
108
|
+
))}
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const schema = z.object({
|
|
4
|
+
title: z.string().min(1).max(40).describe("Display headline — large, dramatic"),
|
|
5
|
+
subtitle: z.string().min(1).max(80).describe("Muted subtitle beneath headline"),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
type Props = z.infer<typeof schema>;
|
|
9
|
+
|
|
10
|
+
export default function TitleCenter({ title, subtitle }: Props) {
|
|
11
|
+
return (
|
|
12
|
+
<div
|
|
13
|
+
className="slide"
|
|
14
|
+
style={{
|
|
15
|
+
display: "flex",
|
|
16
|
+
alignItems: "center",
|
|
17
|
+
justifyContent: "center",
|
|
18
|
+
background: "#ffffff",
|
|
19
|
+
}}
|
|
20
|
+
>
|
|
21
|
+
<div className="stack-center" style={{ gap: 16, maxWidth: 900, marginBottom: 32 }}>
|
|
22
|
+
<h1
|
|
23
|
+
style={{
|
|
24
|
+
fontSize: 72,
|
|
25
|
+
fontWeight: 600,
|
|
26
|
+
lineHeight: 1.05,
|
|
27
|
+
letterSpacing: "-0.015em",
|
|
28
|
+
}}
|
|
29
|
+
>
|
|
30
|
+
{title}
|
|
31
|
+
</h1>
|
|
32
|
+
<p
|
|
33
|
+
style={{
|
|
34
|
+
fontSize: 24,
|
|
35
|
+
fontWeight: 400,
|
|
36
|
+
lineHeight: 1.17,
|
|
37
|
+
letterSpacing: "0.009em",
|
|
38
|
+
color: "var(--color-muted-foreground)",
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
{subtitle}
|
|
42
|
+
</p>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "noir-display",
|
|
3
|
+
"displayName": "Pristine Display",
|
|
4
|
+
"description": "Apple.com inspired light theme — canvas gray background, display typography, dramatic whitespace, and cinematic clarity.",
|
|
5
|
+
"colors": {
|
|
6
|
+
"background": "#f5f5f7",
|
|
7
|
+
"foreground": "#1d1d1f",
|
|
8
|
+
"primary": "#0071e3",
|
|
9
|
+
"muted": "#e8e8ed",
|
|
10
|
+
"muted-foreground": "#6e6e73",
|
|
11
|
+
"border": "rgba(0,0,0,0.08)",
|
|
12
|
+
"accent": "#0066cc",
|
|
13
|
+
"card-background": "#ffffff"
|
|
14
|
+
},
|
|
15
|
+
"fonts": {
|
|
16
|
+
"heading": "'SF Pro JP', 'SF Pro Display', 'Hiragino Sans', 'Helvetica Neue', 'Noto Sans JP', sans-serif",
|
|
17
|
+
"body": "'SF Pro JP', 'SF Pro Text', 'Hiragino Sans', 'Helvetica Neue', 'Noto Sans JP', sans-serif"
|
|
18
|
+
},
|
|
19
|
+
"spacing": {
|
|
20
|
+
"slide-padding": "60px",
|
|
21
|
+
"slide-padding-x": "80px",
|
|
22
|
+
"slide-gap": "32px"
|
|
23
|
+
},
|
|
24
|
+
"borderRadius": "12px",
|
|
25
|
+
"slide": {
|
|
26
|
+
"width": 1200,
|
|
27
|
+
"height": 675,
|
|
28
|
+
"aspectRatio": "16/9"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deckspec-add-pattern
|
|
3
|
+
description: "Use this skill when the user asks to create a new pattern, add a layout, or make a reusable slide template. Triggers on: 'add pattern', 'create pattern', 'new layout', 'パターン作って', 'レイアウト追加'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Add Pattern Skill
|
|
7
|
+
|
|
8
|
+
Create a new reusable pattern in the theme.
|
|
9
|
+
|
|
10
|
+
## Arguments
|
|
11
|
+
|
|
12
|
+
The user should specify:
|
|
13
|
+
- Pattern name (kebab-case)
|
|
14
|
+
- What the pattern displays (layout description)
|
|
15
|
+
- Which theme to add it to
|
|
16
|
+
|
|
17
|
+
## Workflow
|
|
18
|
+
|
|
19
|
+
### 1. Read the theme's design system
|
|
20
|
+
- Read `themes/<theme>/design.md` for design philosophy and rules
|
|
21
|
+
- Read `themes/<theme>/tokens.json` for colors, fonts, spacing
|
|
22
|
+
- Read `themes/<theme>/globals.css` for available semantic classes
|
|
23
|
+
- Look at existing patterns for conventions
|
|
24
|
+
|
|
25
|
+
### 2. Create the pattern
|
|
26
|
+
|
|
27
|
+
Create `themes/<theme>/patterns/<name>/index.tsx`:
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { z } from "zod";
|
|
31
|
+
import React from "react";
|
|
32
|
+
|
|
33
|
+
export const schema = z.object({
|
|
34
|
+
// Define vars with .describe() for clarity
|
|
35
|
+
heading: z.string().describe("Main heading text"),
|
|
36
|
+
items: z.array(z.object({
|
|
37
|
+
label: z.string(),
|
|
38
|
+
value: z.string(),
|
|
39
|
+
})).describe("List of items to display"),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
type Props = z.infer<typeof schema>;
|
|
43
|
+
|
|
44
|
+
export default function PatternName(props: Props) {
|
|
45
|
+
return (
|
|
46
|
+
<div className="slide-pad slide-stack">
|
|
47
|
+
<h1>{props.heading}</h1>
|
|
48
|
+
{/* Layout using semantic classes */}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 3. Create examples.yaml
|
|
55
|
+
|
|
56
|
+
Create `themes/<theme>/patterns/<name>/examples.yaml`:
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
- name: "Basic example"
|
|
60
|
+
vars:
|
|
61
|
+
heading: "Example Heading"
|
|
62
|
+
items:
|
|
63
|
+
- label: "Item 1"
|
|
64
|
+
value: "Value 1"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 4. Validate and preview
|
|
68
|
+
|
|
69
|
+
Create a test deck referencing the new pattern, validate it, and preview with `npx deckspec dev`.
|
|
70
|
+
|
|
71
|
+
## Design Rules
|
|
72
|
+
- Use semantic CSS classes (`.slide-pad`, `.card`, `.list`, etc.)
|
|
73
|
+
- Colors via CSS custom properties (`var(--color-primary)`) — never hardcode hex
|
|
74
|
+
- Minimum font size: 16px
|
|
75
|
+
- No serif fonts
|
|
76
|
+
- No Tailwind CSS
|
|
77
|
+
- Export both `schema` (Zod) and `default` (React component)
|
|
78
|
+
- Use `.describe()` on Zod fields for AI-friendly documentation
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deckspec-make-slides
|
|
3
|
+
description: "Use this skill when the user asks to create a presentation, make slides, build a deck, or write deck.yaml. Triggers on: 'make slides', 'create presentation', 'build a deck', 'プレゼン作って', 'スライド作って', 'デッキ作って'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Make Slides Skill
|
|
7
|
+
|
|
8
|
+
Create a DeckSpec presentation from a user request.
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
|
|
12
|
+
### 1. Understand the request
|
|
13
|
+
- What is the presentation about?
|
|
14
|
+
- How many slides?
|
|
15
|
+
- What tone? (business, technical, casual)
|
|
16
|
+
|
|
17
|
+
### 2. Check available patterns
|
|
18
|
+
Run: `npx deckspec patterns --examples`
|
|
19
|
+
Read: `themes/*/design.md` for design philosophy and pattern catalog.
|
|
20
|
+
|
|
21
|
+
### 3. Create deck.yaml
|
|
22
|
+
|
|
23
|
+
Create `decks/<deck-name>/deck.yaml`:
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
meta:
|
|
27
|
+
title: "Presentation Title"
|
|
28
|
+
theme: noir-display
|
|
29
|
+
slides:
|
|
30
|
+
- file: <pattern-name>
|
|
31
|
+
vars:
|
|
32
|
+
# ... content
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Pattern selection guide:**
|
|
36
|
+
- Opening: `title-center` or `hero-statement`
|
|
37
|
+
- Data/metrics: `feature-metrics`, `big-number`, `chart-bar`
|
|
38
|
+
- Comparison: `comparison-columns`, `pricing-tiers`
|
|
39
|
+
- Process/flow: `flow-diagram`, `three-pillars`
|
|
40
|
+
- Content: `bullet-list`, `icon-grid`
|
|
41
|
+
- Closing: `thank-you`
|
|
42
|
+
|
|
43
|
+
### 4. Validate
|
|
44
|
+
```bash
|
|
45
|
+
npx deckspec validate decks/<deck-name>/deck.yaml
|
|
46
|
+
```
|
|
47
|
+
Fix any schema errors.
|
|
48
|
+
|
|
49
|
+
### 5. Preview
|
|
50
|
+
```bash
|
|
51
|
+
npx deckspec dev
|
|
52
|
+
```
|
|
53
|
+
Open http://localhost:3002 and navigate to the deck.
|
|
54
|
+
|
|
55
|
+
### 6. Iterate
|
|
56
|
+
Ask the user for feedback and adjust slides accordingly.
|
|
57
|
+
|
|
58
|
+
## If no existing pattern fits
|
|
59
|
+
|
|
60
|
+
Create a deck-local pattern at `decks/<deck-name>/patterns/<name>/index.tsx`:
|
|
61
|
+
- Export `schema` (Zod) and `default` (React component)
|
|
62
|
+
- Use semantic CSS classes from the theme's `globals.css`
|
|
63
|
+
- Do NOT hardcode colors — use CSS custom properties
|
|
64
|
+
- The pattern is compiled on-the-fly with esbuild, no build step needed
|
|
65
|
+
|
|
66
|
+
## Rules
|
|
67
|
+
- Always validate before presenting to the user
|
|
68
|
+
- Use pattern `examples.yaml` as reference for vars structure
|
|
69
|
+
- Minimum font size: 16px, no serif fonts
|
|
70
|
+
- Colors via CSS custom properties only
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deckspec-promote-pattern
|
|
3
|
+
description: "Use this skill when the user asks to promote, elevate, or graduate a deck-local pattern to a theme pattern. Triggers on: 'promote pattern', 'elevate to theme', 'make it reusable', 'add to theme', 'graduate pattern', 'パターン昇格', 'テーマに昇格', or any request to move a deck-local pattern into the theme."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Promote Pattern Skill
|
|
7
|
+
|
|
8
|
+
Promote a deck-local pattern to a theme pattern. Abstract hardcoded values into vars, making it a reusable, generic pattern.
|
|
9
|
+
|
|
10
|
+
## Arguments
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
/promote-pattern <deck-pattern-path> [--theme <theme-name>]
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
| Argument | Default | Description |
|
|
17
|
+
|----------|---------|-------------|
|
|
18
|
+
| `deck-pattern-path` | (required) | Path to the deck-local pattern (e.g., `decks/my-project/patterns/product-comparison`) |
|
|
19
|
+
| `--theme` | `noir-display` | Target theme name |
|
|
20
|
+
|
|
21
|
+
## Workflow
|
|
22
|
+
|
|
23
|
+
This skill proceeds **interactively**. Each step asks for user confirmation before moving on.
|
|
24
|
+
|
|
25
|
+
### Phase 1: Analysis
|
|
26
|
+
|
|
27
|
+
1. Read the specified deck-local pattern's `index.tsx`
|
|
28
|
+
2. Analyze the source code to identify:
|
|
29
|
+
- **Hardcoded values**: text strings, numbers, currency symbols, proper nouns, industry terms
|
|
30
|
+
- **Domain-specific variable names**: names tied to a particular domain (e.g., `products` → `items`, `competitors` → `columns`)
|
|
31
|
+
- **Domain-specific logic**: fixed format functions (e.g., hardcoded currency locale)
|
|
32
|
+
- **Values already in vars**: can be kept as-is
|
|
33
|
+
3. Present the analysis to the user
|
|
34
|
+
|
|
35
|
+
### Phase 2: Interactive design decisions
|
|
36
|
+
|
|
37
|
+
**All design decisions use `AskUserQuestion` with `options`.** Let the user click choices rather than type free text.
|
|
38
|
+
|
|
39
|
+
#### 2a. Pattern name
|
|
40
|
+
|
|
41
|
+
`AskUserQuestion` with candidates:
|
|
42
|
+
- header: "Pattern name"
|
|
43
|
+
- options: suggested names (mark recommended with `(Recommended)`) + 2-3 alternatives
|
|
44
|
+
- e.g., `["product-comparison (Recommended)", "feature-grid", "data-table"]`
|
|
45
|
+
|
|
46
|
+
#### 2b. Hardcoded value → vars decisions
|
|
47
|
+
|
|
48
|
+
For each detected hardcoded value, use `AskUserQuestion`:
|
|
49
|
+
- header: "Hardcoded value"
|
|
50
|
+
- question: `"Total" (table footer label) — what should we do?`
|
|
51
|
+
- options:
|
|
52
|
+
- `Add to vars: footerLabel (string, optional)` — recommended
|
|
53
|
+
- `Keep hardcoded`
|
|
54
|
+
- `Remove`
|
|
55
|
+
|
|
56
|
+
For many values, use `multiSelect: true` for batch selection:
|
|
57
|
+
- question: `Which hardcoded values should become vars?`
|
|
58
|
+
- options: list each value
|
|
59
|
+
|
|
60
|
+
#### 2c. Variable renaming
|
|
61
|
+
|
|
62
|
+
`AskUserQuestion`:
|
|
63
|
+
- header: "Rename vars"
|
|
64
|
+
- options:
|
|
65
|
+
- `Apply suggested renames (Recommended)` — description lists the rename map
|
|
66
|
+
- `Keep current names`
|
|
67
|
+
|
|
68
|
+
#### 2d. Extra options
|
|
69
|
+
|
|
70
|
+
`AskUserQuestion` with `multiSelect: true`:
|
|
71
|
+
- header: "Extra options"
|
|
72
|
+
- question: `Select additional options to add`
|
|
73
|
+
- options: each candidate option with description
|
|
74
|
+
|
|
75
|
+
### Phase 3: Implementation
|
|
76
|
+
|
|
77
|
+
Based on user answers:
|
|
78
|
+
|
|
79
|
+
1. **Create pattern file**: `themes/{theme}/patterns/{new-name}/index.tsx`
|
|
80
|
+
- Replace hardcoded values with vars
|
|
81
|
+
- Rename variables as agreed
|
|
82
|
+
- Implement extra options
|
|
83
|
+
- Add `.describe()` to all Zod schema fields
|
|
84
|
+
|
|
85
|
+
2. **Create examples.yaml**: `themes/{theme}/patterns/{new-name}/examples.yaml`
|
|
86
|
+
- First example: the original deck's vars (proof it works as-is)
|
|
87
|
+
- Second example: usage in a different domain (proof of generality)
|
|
88
|
+
- Third example (optional): demonstrate optional features
|
|
89
|
+
|
|
90
|
+
3. **Update index.ts**: Add re-export to `themes/{theme}/patterns/index.ts`
|
|
91
|
+
|
|
92
|
+
4. **Update design.md**: Add the pattern to the catalog section with vars spec
|
|
93
|
+
|
|
94
|
+
### Phase 4: Verification
|
|
95
|
+
|
|
96
|
+
1. Run `pnpm build` to confirm the theme builds
|
|
97
|
+
2. Create a test deck with examples.yaml vars, run `npx deckspec validate` + `npx deckspec render`
|
|
98
|
+
3. Take screenshots and present to user
|
|
99
|
+
4. Fix issues based on user feedback
|
|
100
|
+
|
|
101
|
+
### Phase 5: Old pattern disposition
|
|
102
|
+
|
|
103
|
+
`AskUserQuestion`:
|
|
104
|
+
- header: "Old pattern"
|
|
105
|
+
- question: `What should we do with the original deck-local pattern?`
|
|
106
|
+
- options:
|
|
107
|
+
- `Keep it (Recommended)` — description: maintains backward compatibility
|
|
108
|
+
- `Delete and update deck.yaml` — description: replace with new theme pattern name
|
|
109
|
+
|
|
110
|
+
## Analysis hints
|
|
111
|
+
|
|
112
|
+
### Detecting hardcoded values
|
|
113
|
+
- String literals in the target language (any natural language text)
|
|
114
|
+
- Currency/unit symbols (`"$"`, `"%"`, `"EUR"`, etc.)
|
|
115
|
+
- Fixed locale strings (e.g., `"en-US"` in `.toLocaleString()`)
|
|
116
|
+
- Hardcoded CSS colors (`"#xxx"` — anything not using `var()`)
|
|
117
|
+
- Fixed number formatting
|
|
118
|
+
|
|
119
|
+
### Naming conventions
|
|
120
|
+
- Pattern names: kebab-case, replace domain terms with generic ones (e.g., `product-comparison` → `comparison-table`)
|
|
121
|
+
- Var names: camelCase, use `.describe()` in Zod schema
|
|
122
|
+
- Array names: plural (`rows`, `columns`, `items`)
|
|
123
|
+
|
|
124
|
+
### examples.yaml best practices
|
|
125
|
+
- Example 1: original deck's real data (proof of migration)
|
|
126
|
+
- Example 2: different domain usage (proof of generality)
|
|
127
|
+
- Example 3: optional feature showcase (e.g., `showTotal: false`)
|
|
128
|
+
|
|
129
|
+
## Important notes
|
|
130
|
+
|
|
131
|
+
- Read the target theme's `design.md` first to understand design rules
|
|
132
|
+
- Keep var naming consistent with existing patterns (`label`, `heading`, etc.)
|
|
133
|
+
- If the pattern uses theme utilities like `_lib/icon.tsx`, verify they exist in the target theme
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deckspec-screenshot
|
|
3
|
+
description: "Use this skill when the user asks to screenshot, capture, or photograph slides from a DeckSpec deck. Triggers on: 'screenshot', 'capture slides', 'save slide images', 'スクリーンショット', 'スライド撮影'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Screenshot Deck Skill
|
|
7
|
+
|
|
8
|
+
Capture all slides of a DeckSpec deck as individual PNG images (1200x675, 16:9).
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- Playwright installed: `npm install -D playwright && npx playwright install chromium`
|
|
13
|
+
|
|
14
|
+
## Workflow
|
|
15
|
+
|
|
16
|
+
### 1. Render the deck to HTML
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx deckspec render decks/<deck-name>/deck.yaml -o output/<deck-name>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 2. Run the screenshot script
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node scripts/screenshot-deck.mjs output/<deck-name>/index.html output/<deck-name>-slides
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This will:
|
|
29
|
+
- Open the HTML in headless Chromium at 1200x675 viewport
|
|
30
|
+
- Hide navigation controls
|
|
31
|
+
- Screenshot each slide as `slide-01.png`, `slide-02.png`, etc.
|
|
32
|
+
|
|
33
|
+
### 3. Verify
|
|
34
|
+
|
|
35
|
+
Read the generated PNG files to visually confirm the output.
|
|
36
|
+
|
|
37
|
+
## Output
|
|
38
|
+
|
|
39
|
+
- `output/<deck-name>-slides/slide-01.png`
|
|
40
|
+
- `output/<deck-name>-slides/slide-02.png`
|
|
41
|
+
- Each image is 1200x675px PNG (16:9)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deckspec-to-pptx
|
|
3
|
+
description: "Use this skill when the user asks to convert a DeckSpec deck to PowerPoint (.pptx). Triggers on: 'PowerPoint', 'pptx', 'convert to pptx', 'export to PowerPoint', 'パワポ', 'パワーポイント'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deck to PowerPoint Skill
|
|
7
|
+
|
|
8
|
+
Convert a DeckSpec deck.yaml to a PowerPoint (.pptx) file.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- pptxgenjs installed: `npm install -D pptxgenjs`
|
|
13
|
+
|
|
14
|
+
## Workflow
|
|
15
|
+
|
|
16
|
+
### 1. Run the conversion
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
node scripts/deck-to-pptx.mjs decks/<deck-name>/deck.yaml -o output/<deck-name>.pptx
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 2. Check for warnings
|
|
23
|
+
|
|
24
|
+
The script warns for unregistered patterns: `⚠ No pptx renderer for pattern "<name>" — blank slide`
|
|
25
|
+
|
|
26
|
+
To fix, add a renderer function in `scripts/deck-to-pptx.mjs`.
|
|
27
|
+
|
|
28
|
+
### 3. Open and verify
|
|
29
|
+
|
|
30
|
+
Open the .pptx in PowerPoint or Google Slides to verify.
|
|
31
|
+
|
|
32
|
+
## Notes
|
|
33
|
+
|
|
34
|
+
- Colors and fonts are loaded from `themes/<theme>/tokens.json`
|
|
35
|
+
- Local images are embedded as base64
|
|
36
|
+
- Not all patterns have pptx renderers yet — unregistered patterns produce blank slides
|