@easysociable/cli 0.1.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/LICENSE +21 -0
- package/README.md +95 -0
- package/bin/easysociable.js +15 -0
- package/dist/easysociable.js +35464 -0
- package/dist/easysociable.js.map +1 -0
- package/package.json +58 -0
- package/skills/ONBOARDING.md +61 -0
- package/skills/easysociable-content/SKILL.md +115 -0
- package/skills/easysociable-content/platforms/claude.md +5 -0
- package/skills/easysociable-content/platforms/codex.md +5 -0
- package/skills/easysociable-content/platforms/hermes.md +5 -0
- package/skills/easysociable-content/platforms/openclaw.md +5 -0
- package/skills/easysociable-content/references/CLI.md +27 -0
- package/skills/easysociable-content/references/MCP.md +20 -0
- package/skills/easysociable-content/references/PAGE_PACK.md +6 -0
- package/skills/easysociable-content/references/TROUBLESHOOTING.md +11 -0
- package/skills/easysociable-content/references/VAULT.md +20 -0
- package/skills/easysociable-content/scripts/setup.mjs +156 -0
- package/skills/easysociable-content/scripts/setup.test.mjs +71 -0
- package/skills/easysociable-content/scripts/starter.mjs +53 -0
- package/skills/easysociable-content/workflows/ANALYSIS_AND_COVERAGE.md +8 -0
- package/skills/easysociable-content/workflows/CONTENT_EXPORT.md +19 -0
- package/skills/easysociable-content/workflows/DEVICE_TASKS.md +5 -0
- package/skills/easysociable-content/workflows/EXPERIMENTS.md +6 -0
- package/skills/easysociable-content/workflows/MCP_FIRST.md +10 -0
- package/skills/easysociable-content/workflows/PUBLICATION.md +5 -0
- package/skills/easysociable-content/workflows/TOPIC_DRAFT.md +5 -0
- package/skills/easysociable-content/workflows/WORKING_DRAFT.md +10 -0
- package/skills/easysociable-slideshow/SKILL.md +77 -0
- package/skills/easysociable-slideshow/references/CONTENT_PACK.md +25 -0
- package/skills/easysociable-slideshow/references/GATEWAY.md +16 -0
- package/skills/easysociable-slideshow/references/PLATFORM_CAPS.md +17 -0
- package/skills/easysociable-slideshow/references/VAULT.md +18 -0
- package/skills/easysociable-slideshow/workflows/CREATE_RUN.md +7 -0
- package/skills/easysociable-slideshow/workflows/MCP_FIRST.md +14 -0
- package/skills/easysociable-slideshow/workflows/OUT_OF_SCOPE.md +8 -0
- package/skills/easysociable-slideshow/workflows/PUBLISH_RUN.md +4 -0
- package/skills/easysociable-slideshow/workflows/RENDER_RUN.md +6 -0
- package/skills/easysociable-template/SKILL.md +106 -0
- package/skills/easysociable-template/references/AUTHORING_SOURCE.md +129 -0
- package/skills/easysociable-template/references/CATALOG_METADATA.md +221 -0
- package/skills/easysociable-template/references/DESIGN_INTELLIGENCE.md +69 -0
- package/skills/easysociable-template/references/DESIGN_V2_1.md +278 -0
- package/skills/easysociable-template/references/EXTERNAL_RESOURCES.md +52 -0
- package/skills/easysociable-template/references/GATEWAY.md +25 -0
- package/skills/easysociable-template/references/PLATFORM_SPECS.md +134 -0
- package/skills/easysociable-template/references/SLOTS.md +104 -0
- package/skills/easysociable-template/references/THEME_PRESETS.md +48 -0
- package/skills/easysociable-template/references/THEME_TOKENS.md +89 -0
- package/skills/easysociable-template/references/fixtures/surface-gradient.design-plan.json +74 -0
- package/skills/easysociable-template/references/theme-presets.json +95 -0
- package/skills/easysociable-template/scripts/generate-theme-from-hex.mjs +402 -0
- package/skills/easysociable-template/scripts/validate-authoring-source.mjs +228 -0
- package/skills/easysociable-template/scripts/validate-design-v2.mjs +318 -0
- package/skills/easysociable-template/workflows/ASSET_PLAN.md +34 -0
- package/skills/easysociable-template/workflows/AUTHORING_FROM_BRIEF.md +52 -0
- package/skills/easysociable-template/workflows/AUTHORING_FROM_IMAGE.md +52 -0
- package/skills/easysociable-template/workflows/AUTHORING_STUDIO.md +122 -0
- package/skills/easysociable-template/workflows/DESIGN_BRIEF.md +92 -0
- package/skills/easysociable-template/workflows/DESIGN_CONCEPTS.md +41 -0
- package/skills/easysociable-template/workflows/DESIGN_PHILOSOPHY.md +69 -0
- package/skills/easysociable-template/workflows/FILL_AND_RENDER.md +86 -0
- package/skills/easysociable-template/workflows/MCP_FIRST.md +9 -0
- package/skills/easysociable-template/workflows/OUT_OF_SCOPE.md +15 -0
- package/skills/easysociable-template/workflows/PALETTE_REVIEW.md +71 -0
- package/skills/easysociable-template/workflows/PUBLISH_FROM_DRAFT.md +60 -0
- package/skills/easysociable-template/workflows/SURFACE_REVIEW.md +178 -0
- package/skills/easysociable-template/workflows/THEME_FROM_BRAND.md +73 -0
- package/skills/easysociable-template/workflows/VISUAL_QA.md +55 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Platform image specs (single-page template canvases)
|
|
2
|
+
|
|
3
|
+
Use agent-reach / industry guides (2026). Platforms change crop behavior; prefer the **Recommended** row for new templates. Always store exact `canvas.width/height` plus `canvasPreset`.
|
|
4
|
+
|
|
5
|
+
`platforms` is a **multi-select** array. Include every platform this page is intended for; add `generic` only when the board is intentionally cross-postable without a primary home.
|
|
6
|
+
|
|
7
|
+
## Platform enum (catalog)
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
xiaohongshu | tiktok | instagram | threads | x | linkedin | wechat_cover | generic
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Legacy alias: treat former Twitter as **`x`**.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Per-platform boards (for PageTemplate authoring)
|
|
18
|
+
|
|
19
|
+
### Xiaohongshu(小红书)— `xiaohongshu`
|
|
20
|
+
|
|
21
|
+
| Use | Preset | Pixels | Notes |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| **图文笔记(推荐)** | `3:4` | **1080×1440** | Largest feed footprint; keep cover + inner pages same ratio |
|
|
24
|
+
| Square note | `1:1` | 1080×1080 | OK, less feed height than 3:4 |
|
|
25
|
+
| Landscape | `custom` / avoid for cover | 1440×1080 (4:3) etc. | Weak in feed; not a default template target |
|
|
26
|
+
| Max images / note | — | up to ~18 | Product convention; not a canvas rule |
|
|
27
|
+
|
|
28
|
+
**Default for new XHS templates:** `3:4` @ 1080×1440.
|
|
29
|
+
|
|
30
|
+
### TikTok — `tiktok`
|
|
31
|
+
|
|
32
|
+
| Use | Preset | Pixels | Notes |
|
|
33
|
+
|---|---|---|---|
|
|
34
|
+
| **Photo Mode / slideshow(推荐)** | `9:16` | **1080×1920** | Full-screen; matches native video |
|
|
35
|
+
| Portrait alt | `4:5` | 1080×1350 | Supported; letterboxing vs 9:16 |
|
|
36
|
+
| Square | `1:1` | 1080×1080 | Supported; bars in vertical feed |
|
|
37
|
+
| Typical carousel count | — | ~4–35 photos | Design for 9:16; keep all slides same size |
|
|
38
|
+
|
|
39
|
+
**Default for TikTok page templates:** `9:16` @ 1080×1920. Keep UI/text out of bottom/side safe zones used by TikTok chrome.
|
|
40
|
+
|
|
41
|
+
### Instagram — `instagram`
|
|
42
|
+
|
|
43
|
+
Meta help: feed width up to **1080px**; aspect between ~**1.91:1** and **4:5** (taller may crop). Practical authoring:
|
|
44
|
+
|
|
45
|
+
| Use | Preset | Pixels | Notes |
|
|
46
|
+
|---|---|---|---|
|
|
47
|
+
| **Feed single / carousel(推荐竖版)** | `4:5` | **1080×1350** | Max common feed height |
|
|
48
|
+
| Square feed / safe carousel | `1:1` | 1080×1080 | Safest cross-placement |
|
|
49
|
+
| Tall grid-oriented | `3:4` | 1080×1440 | Within Meta’s upper portrait band; confirm crop |
|
|
50
|
+
| Stories / Reels still | `9:16` | 1080×1920 | Full-bleed stories; not default “feed card” |
|
|
51
|
+
| Landscape | ~`21:9` family | 1080×566 (1.91:1) | Link-style / wide; poor mobile height |
|
|
52
|
+
|
|
53
|
+
**Carousel rule:** all slides **same aspect** as slide 1 or later slides get center-cropped.
|
|
54
|
+
**Default for IG feed templates:** `4:5` @ 1080×1350 (or `1:1` if user wants max compatibility).
|
|
55
|
+
|
|
56
|
+
### Threads — `threads`
|
|
57
|
+
|
|
58
|
+
Aligned with Meta/IG feed conventions:
|
|
59
|
+
|
|
60
|
+
| Use | Preset | Pixels | Notes |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| **Feed(推荐)** | `4:5` | **1080×1350** | Best vertical presence |
|
|
63
|
+
| Square | `1:1` | 1080×1080 | Safe |
|
|
64
|
+
| Full-bleed vertical | `9:16` | 1080×1920 | OK for immersive; may crop in some feed contexts |
|
|
65
|
+
| Landscape | custom | ~1080×566 | Least feed height |
|
|
66
|
+
|
|
67
|
+
**Carousel:** keep one aspect for all slides (first slide wins). Cap commonly cited ~10–20 images — not a canvas constraint.
|
|
68
|
+
**Default:** `4:5` @ 1080×1350 (often shared with Instagram assets).
|
|
69
|
+
|
|
70
|
+
### X (Twitter) — `x`
|
|
71
|
+
|
|
72
|
+
| Use | Preset | Pixels | Notes |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| **Single in-stream(推荐)** | ~`16:9` → use `custom` or map to wide | **1200×675** | Timeline-friendly; less aggressive crop |
|
|
75
|
+
| Square | `1:1` | 1200×1200 or 1080×1080 | Good for multi-image / quotes |
|
|
76
|
+
| Tall | `4:5` | 1080×1350 | Often cropped toward landscape in timeline |
|
|
77
|
+
| Link / card style | custom | 1200×628 (~1.91:1) | Summary large image cards |
|
|
78
|
+
| Multi-image | often `1:1` or `16:9` | keep set consistent | Up to 4 images per post |
|
|
79
|
+
|
|
80
|
+
**Default for X single-card templates:** **1200×675** (`canvasPreset: custom` with note `x_instream_16x9`, or document as wide). Prefer landscape text layouts; center critical content.
|
|
81
|
+
|
|
82
|
+
### LinkedIn — `linkedin`
|
|
83
|
+
|
|
84
|
+
| Use | Preset | Pixels | Notes |
|
|
85
|
+
|---|---|---|---|
|
|
86
|
+
| **单图帖(推荐方)** | `1:1` | **1080×1080** | Broad desktop + mobile |
|
|
87
|
+
| 单图竖版 | `4:5` | 1080×1350 | Stronger mobile height |
|
|
88
|
+
| 单图横版 / link-ish | custom | 1200×627 (~1.91:1) | Link preview family |
|
|
89
|
+
| **Document carousel PDF 页** | `1:1` or `4:5` | **1080×1080** or **1080×1350** | Organic “carousel” is usually multi-page **PDF**; all pages same size |
|
|
90
|
+
| Landscape deck page | ~`16:9` | 1920×1080 | Data-heavy slides; weaker mobile |
|
|
91
|
+
|
|
92
|
+
**Default for LinkedIn page templates:** `1:1` @ 1080×1080, or `4:5` @ 1080×1350 when user wants mobile-first document carousels.
|
|
93
|
+
Note in `shortDescription` if the page is meant for **PDF document posts** vs single image posts.
|
|
94
|
+
|
|
95
|
+
### WeChat Official Account covers — `wechat_cover`
|
|
96
|
+
|
|
97
|
+
| Use | Preset | Pixels | Notes |
|
|
98
|
+
|---|---|---|---|
|
|
99
|
+
| **主封面 21:9** | `21:9` | **2100×900** (or 1125×481-class) | Wide hero |
|
|
100
|
+
| **分享 1:1** | `1:1` | **1080×1080** | Square share card |
|
|
101
|
+
|
|
102
|
+
Often authored as a **pair** of single-page templates (wide + square), not one carousel pack. Defaults match existing Guizang-style boards when users ask for 公众号封面对.
|
|
103
|
+
|
|
104
|
+
### Generic — `generic`
|
|
105
|
+
|
|
106
|
+
No platform chrome assumptions. Still pick a concrete preset (`1:1`, `4:5`, `3:4`, `9:16`, …). Use when the page is a reusable brick across networks **and** the chosen ratio is listed as Recommended or Supported for each target in `platforms`.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Preset → default pixel map (authoring shortcut)
|
|
111
|
+
|
|
112
|
+
| `canvasPreset` | Default pixels | Primary platforms |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| `3:4` | 1080×1440 | xiaohongshu, (instagram tall) |
|
|
115
|
+
| `4:5` | 1080×1350 | instagram, threads, linkedin portrait |
|
|
116
|
+
| `1:1` | 1080×1080 | linkedin, instagram/threads safe, x multi |
|
|
117
|
+
| `9:16` | 1080×1920 | tiktok, IG/Threads stories-style |
|
|
118
|
+
| `21:9` | 2100×900 | wechat_cover wide |
|
|
119
|
+
| `custom` | explicit only | **x** 1200×675, link cards 1200×628, etc. |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Selection rules for Agents
|
|
124
|
+
|
|
125
|
+
1. If user names one platform → set `platforms: [that]` and use that platform’s **Recommended** row.
|
|
126
|
+
2. If user names several → intersection of workable presets; if empty, ask them to pick a primary platform or accept letterboxing.
|
|
127
|
+
3. Never mix presets across slides of one deck without an explicit user choice (IG/Threads/TikTok crop to first slide).
|
|
128
|
+
4. Put platform + preset into P0 `selectionMetadata` before Publish.
|
|
129
|
+
5. Specs above are **practical authoring targets** (2026 guides + Meta help for IG). Re-verify if a platform announces breaking crop changes.
|
|
130
|
+
|
|
131
|
+
## Sources (research snapshot)
|
|
132
|
+
|
|
133
|
+
- Meta Instagram help: feed width ≤1080px; aspect ~1.91:1–4:5
|
|
134
|
+
- Industry 2026 guides: X 1200×675; LinkedIn 1080×1080 / 1080×1350 (+ PDF carousels); Threads ≈ IG 4:5; TikTok Photo Mode 1080×1920; 小红书 1080×1440 3:4
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Slot model (single-page template)
|
|
2
|
+
|
|
3
|
+
A **slot** is a fillable content contract on one page. A **node** is a positioned box on the canvas.
|
|
4
|
+
|
|
5
|
+
## Node vs slot vs decoration
|
|
6
|
+
|
|
7
|
+
| | Meaning |
|
|
8
|
+
|---|---|
|
|
9
|
+
| **Slot** | Declares what can change at render time: `key`, `type`, constraints |
|
|
10
|
+
| **Node with `bindingKey`** | Canvas element bound to `slot.key` — filled from bindings |
|
|
11
|
+
| **Node without `bindingKey`** | Decoration / fixed chrome — not in the slot table, never filled from content |
|
|
12
|
+
|
|
13
|
+
Agent must decide which regions are variable (slots) vs fixed (decoration) before create.
|
|
14
|
+
|
|
15
|
+
## MVP slot types
|
|
16
|
+
|
|
17
|
+
| `type` | Value | Constraints |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `text` | string | `maxCharacters`, **`maxLines`**, `overflow` |
|
|
20
|
+
| `number` | number | optional format hints in `aiHint` |
|
|
21
|
+
| `image` | image ref / URL handled by Gateway | optional `aspectRatio` |
|
|
22
|
+
|
|
23
|
+
**No `list` type in MVP.** The current renderer binds one value per `bindingKey` and uses absolute frames — there is no array repeater. Checklist-like pages use multiple text slots (`text_1`, `text_2`, …).
|
|
24
|
+
|
|
25
|
+
Also unused for typical authoring: put colors in **Theme**, not `color` slots.
|
|
26
|
+
|
|
27
|
+
## Naming
|
|
28
|
+
|
|
29
|
+
Stable opaque keys are allowed and preferred for MVP, e.g.:
|
|
30
|
+
|
|
31
|
+
- `text_0`, `text_1`, `text_2`
|
|
32
|
+
- `number_0`
|
|
33
|
+
- `image_0`
|
|
34
|
+
|
|
35
|
+
Keys must be unique within the page. After Publish, treat keys as immutable (rename = new template or migration).
|
|
36
|
+
|
|
37
|
+
There is **no global cap** on how many slots a page may have. Count is whatever the layout needs, as long as filled content respects per-slot limits and does not fail layout audit.
|
|
38
|
+
|
|
39
|
+
## Slot record (authoring-time contract)
|
|
40
|
+
|
|
41
|
+
Agent should maintain an explicit slot table (even if Gateway compiles bindings server-side):
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
type Slot = {
|
|
45
|
+
key: string
|
|
46
|
+
type: 'text' | 'number' | 'image'
|
|
47
|
+
required: boolean
|
|
48
|
+
overflow: 'error' | 'shrink' | 'truncate'
|
|
49
|
+
maxCharacters?: number // text
|
|
50
|
+
maxLines?: number // text — required in contract when type is text
|
|
51
|
+
aspectRatio?: string // image, optional
|
|
52
|
+
label?: string // human label for Studio / brief
|
|
53
|
+
aiHint?: string
|
|
54
|
+
placeholder?: unknown // preview-only sample, not the live contract value
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Align with server `TemplateBindingDefinition` where possible (`key`, `type`, `required`, `overflow`, `maxCharacters`, `aiHint`). Persist `maxLines` on the bound text node props and/or authoring metadata until contracts officially add the field.
|
|
59
|
+
|
|
60
|
+
## Required vs optional
|
|
61
|
+
|
|
62
|
+
- Default: slots that define the page’s main message are **`required: true`**.
|
|
63
|
+
- **`required: false`** is for whole optional blocks (e.g. optional `image_0`), not for “collapse a variable-length bullet list.”
|
|
64
|
+
- Variable bullet counts: prefer a template with the right number of text slots, or accept empty optional text slots under the omit rule below (layout will **not** reflow).
|
|
65
|
+
|
|
66
|
+
## Empty slot → omit node (not hide)
|
|
67
|
+
|
|
68
|
+
At render time:
|
|
69
|
+
|
|
70
|
+
1. If a slot value is `null` / `undefined` / `''` → **do not include** the bound node in the render tree.
|
|
71
|
+
2. This is **omit**, not CSS `display: none` / visibility hide.
|
|
72
|
+
3. Layout is **absolute positioning**. Omitting a node does **not** move other nodes; gaps may remain.
|
|
73
|
+
4. **Required** slots that are missing must **fail validation** before render — omit must not paper over missing required content.
|
|
74
|
+
|
|
75
|
+
## Absolute layout implications
|
|
76
|
+
|
|
77
|
+
- Do not promise “empty bullets automatically pack upward.”
|
|
78
|
+
- Prefer fixed slot counts for dense checklists under absolute layout.
|
|
79
|
+
- Optional omit works best for independent regions (corner image, optional CTA block), not mid-stack lists.
|
|
80
|
+
- Bound nodes should be **independent absolute frames** on the canvas. Do not put an image/text slot inside another absolute wrapper; omit would leave an empty parent box. See flat-tree rule in `AUTHORING_SOURCE.md`.
|
|
81
|
+
|
|
82
|
+
## Examples
|
|
83
|
+
|
|
84
|
+
### KPI / follower milestone (fixed)
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
text_0 text required maxLines=2 maxCharacters=24
|
|
88
|
+
number_0 number required
|
|
89
|
+
text_1 text required maxLines=1 maxCharacters=16 # label under metric
|
|
90
|
+
image_0 image optional aspectRatio≈1:1
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Decoration: background shapes, hairlines, fixed wordmarks — no `bindingKey`.
|
|
94
|
+
|
|
95
|
+
### Checklist page (fixed three lines — no list type)
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
text_0 text required maxLines=2 maxCharacters=20 # title
|
|
99
|
+
text_1 text required maxLines=1 maxCharacters=28
|
|
100
|
+
text_2 text required maxLines=1 maxCharacters=28
|
|
101
|
+
text_3 text required maxLines=1 maxCharacters=28
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If content only has two bullets, either use a 2-line template or mark `text_3` optional knowing omit leaves a visual gap under absolute layout.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Theme presets (EasySociable)
|
|
2
|
+
|
|
3
|
+
Curated menu adapted from Anthropic `theme-factory`, rewritten to EasySociable Theme contracts (`brandHex` + `mode` + Studio fonts + `bestFor`).
|
|
4
|
+
|
|
5
|
+
**Not** a replacement for `generate-theme-from-hex.mjs` — presets supply inputs; the generator still builds the 11-shade scale, six semantic colors, and WCAG report.
|
|
6
|
+
|
|
7
|
+
## How to use
|
|
8
|
+
|
|
9
|
+
1. When the user has no brand hex, offer **2–3 presets** (or show a short swatch table) from this list — see `workflows/PALETTE_REVIEW.md`.
|
|
10
|
+
2. Wait for **explicit confirmation** of preset (or custom hex) before locking `theme-tokens.json` or calling `theme.create`.
|
|
11
|
+
3. Generate:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
node scripts/generate-theme-from-hex.mjs --preset ocean-depths --mode light -o theme-tokens.json
|
|
15
|
+
# or with explicit hex override:
|
|
16
|
+
node scripts/generate-theme-from-hex.mjs --preset tech-innovation #2563EB --mode dark -o theme-tokens.json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Machine-readable source: [`theme-presets.json`](theme-presets.json).
|
|
20
|
+
|
|
21
|
+
## Preset catalog
|
|
22
|
+
|
|
23
|
+
| id | Name | Mode bias | brandHex | heading / body | bestFor |
|
|
24
|
+
|----|------|-----------|----------|----------------|---------|
|
|
25
|
+
| `ocean-depths` | Ocean Depths | light | `#1A6B6B` | Inter / Inter | Finance, consulting, trust-building metric cards |
|
|
26
|
+
| `sunset-boulevard` | Sunset Boulevard | light | `#E85D04` | Inter / Inter | Launch, lifestyle, warm creator promos |
|
|
27
|
+
| `forest-canopy` | Forest Canopy | light | `#2D6A4F` | Georgia / Inter | Sustainability, outdoor, grounded reports |
|
|
28
|
+
| `modern-minimalist` | Modern Minimalist | light | `#475569` | Inter / Inter | Architecture, product UI shots, clean SaaS |
|
|
29
|
+
| `golden-hour` | Golden Hour | light | `#B45309` | Playfair Display / Source Sans 3 | Premium, autumnal, milestone celebrate |
|
|
30
|
+
| `arctic-frost` | Arctic Frost | light | `#0284C7` | Inter / Inter | Winter campaigns, crisp tech, health |
|
|
31
|
+
| `desert-rose` | Desert Rose | light | `#C45C6A` | Inter / Inter | Soft beauty, hospitality, gentle social proof |
|
|
32
|
+
| `tech-innovation` | Tech Innovation | dark | `#2563EB` | Inter / Inter | Startups, AI updates, product launches |
|
|
33
|
+
| `botanical-garden` | Botanical Garden | light | `#16A34A` | Inter / Inter | Growth metrics, wellness, organic brands |
|
|
34
|
+
| `midnight-galaxy` | Midnight Galaxy | dark | `#7C3AED` | Inter / Inter | Entertainment, gaming, bold night creatives |
|
|
35
|
+
|
|
36
|
+
## Field mapping to Gateway
|
|
37
|
+
|
|
38
|
+
After generation, `themeTokens` carries:
|
|
39
|
+
|
|
40
|
+
- `colors`: `canvas`, `text`, `accent`, `muted`, `primary`, `border`
|
|
41
|
+
- `fonts.heading` / `fonts.body` from the preset (override with `--heading` / `--body`)
|
|
42
|
+
- `palette` with full scale + contrast
|
|
43
|
+
|
|
44
|
+
Suggested Theme **name** for `theme.create`: the preset display `name` (e.g. `Ocean Depths`), not `Theme draft_xxx`.
|
|
45
|
+
|
|
46
|
+
## Custom themes
|
|
47
|
+
|
|
48
|
+
If no preset fits, invent a name + `brandHex` + fonts the same way, show the swatch/contrast summary, get confirmation, then generate and apply (`THEME_FROM_BRAND.md`).
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Theme tokens (page authoring)
|
|
2
|
+
|
|
3
|
+
Theme is the **skin** (color / font / surface). The page template is the **structure + slots**.
|
|
4
|
+
|
|
5
|
+
**External gradients and photo washes are not Theme assets.** They are Surface decorations (`workflows/SURFACE_REVIEW.md`): confirm a Gateway `gradients` recipe or imported `imageId`, then inline CSS / CDN background nodes. Theme remains solid semantic colors for contrast and Studio editing. Authoring derives six explainable two-stop Brand Hex recommendations and brand-tinted previews of Gateway Catalog recipes for the left Theme panel (`palette.gradient`, exposed as `--es-gradient-from/to`). Editing Brand Hex refreshes those cards and any selected catalog variant linked to the brand; the original Catalog recipe remains immutable and traceable through `catalogRecipeId`. Clicking a card or applying a custom pair explicitly changes the active global gradient and records `palette.gradientSelection`. The right-side Gradient controller remains local to the selected element, and manual choices are marked fixed. These recommendations do not replace a confirmed Surface decoration.
|
|
6
|
+
|
|
7
|
+
## When creating a single-page template
|
|
8
|
+
|
|
9
|
+
1. Prefer **reuse** `themeId` if the user already has a Look.
|
|
10
|
+
2. Otherwise **co-create** full `ThemeTokens` with the draft (`theme.create`):
|
|
11
|
+
- If user provides brand hex → `workflows/THEME_FROM_BRAND.md` → `theme-tokens.json`
|
|
12
|
+
- If multiple palette directions → `workflows/PALETTE_REVIEW.md` first
|
|
13
|
+
- If no brand hex → seed from `references/DESIGN_INTELLIGENCE.md`, then generate
|
|
14
|
+
3. Page chrome should reference semantic CSS variables (`--es-color-*`, `--es-font-*`, `--es-surface-*`), not hard-coded brand colors on every node.
|
|
15
|
+
|
|
16
|
+
## Gateway payload (`theme_schema_v1`)
|
|
17
|
+
|
|
18
|
+
Gateway persists `themeTokens` in `TemplateTheme.tokens`. When `palette` is present, `theme_schema_version` is `theme_schema_v2`. The `colors` object includes six semantic roles: `canvas`, `text`, `accent`, `muted`, `primary`, `border`.
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
{
|
|
22
|
+
colors: {
|
|
23
|
+
canvas: '#FFFFFF',
|
|
24
|
+
text: '#042F2B',
|
|
25
|
+
accent: '#0D9B8F',
|
|
26
|
+
muted: '#0B7F75',
|
|
27
|
+
primary: '#0B7F75',
|
|
28
|
+
border: '#C6F5F1',
|
|
29
|
+
},
|
|
30
|
+
fonts: {
|
|
31
|
+
heading: 'Inter',
|
|
32
|
+
body: 'Inter',
|
|
33
|
+
},
|
|
34
|
+
surfaces: {
|
|
35
|
+
radius: '12px',
|
|
36
|
+
shadow: '0 8px 24px rgba(0,0,0,.12)',
|
|
37
|
+
},
|
|
38
|
+
logoAssetId?: string,
|
|
39
|
+
lockedKeys?: string[],
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Local artifact (`theme_tokens_v2`)
|
|
44
|
+
|
|
45
|
+
`theme-tokens.json` is a workflow artifact (not a Gateway DTO). Generate with:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
node scripts/generate-theme-from-hex.mjs <#hex> --mode light|dark -o theme-tokens.json
|
|
49
|
+
node scripts/validate-design-v2.mjs theme-tokens.json
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Contains:
|
|
53
|
+
|
|
54
|
+
| Field | Purpose |
|
|
55
|
+
|-------|---------|
|
|
56
|
+
| `scale` | 11-shade brand scale (`50`–`950`) |
|
|
57
|
+
| `semantic.light` / `semantic.dark` | Resolved semantic roles per mode |
|
|
58
|
+
| `themeTokens` | Active mode — use for `theme.create` |
|
|
59
|
+
| `themeTokensLight` / `themeTokensDark` | Both modes for comparison |
|
|
60
|
+
| `contrast` | WCAG ratio report per pair and mode |
|
|
61
|
+
| `contrastPass` | `true` when all pairs meet AA |
|
|
62
|
+
|
|
63
|
+
Semantic roles in scale (internal): `canvas`, `text`, `accent`, `muted`, `primary`, `border`. All six are stored in `themeTokens.colors` for v2; Authoring Studio displays them plus the 11-shade scale.
|
|
64
|
+
|
|
65
|
+
Runtime CSS variables (authoring + renderer):
|
|
66
|
+
|
|
67
|
+
| Variable | Source |
|
|
68
|
+
|----------|--------|
|
|
69
|
+
| `--es-color-canvas` / `text` / `accent` / `muted` | Active semantic colors |
|
|
70
|
+
| `--es-color-primary` / `border` | v2 palette semantic extras |
|
|
71
|
+
| `--es-scale-50` … `--es-scale-950` | Brand scale when `palette` present |
|
|
72
|
+
| `--es-font-*` / `--es-surface-*` | Fonts and surfaces |
|
|
73
|
+
|
|
74
|
+
Templates may use `var(--es-scale-600)` directly in inline styles or classNames.
|
|
75
|
+
|
|
76
|
+
## Light vs dark mode
|
|
77
|
+
|
|
78
|
+
- **Light canvas** (editorial, paper, playful): `--mode light` → white canvas, dark text, accent from scale 600
|
|
79
|
+
- **Dark canvas** (terminal, neon, cinematic): `--mode dark` → scale 950 canvas, light text, accent from scale 500
|
|
80
|
+
|
|
81
|
+
Match `activeMode` to the selected concept `colorStrategy`. Do not mix light tokens on a dark-canvas concept.
|
|
82
|
+
|
|
83
|
+
## Rules
|
|
84
|
+
|
|
85
|
+
- Do not model accent/canvas as content slots (`color` binding) for normal templates.
|
|
86
|
+
- Do not hand-pick four hex values when `brandHex` is known — run the generator.
|
|
87
|
+
- Co-created Theme may be published with the page when the Agent runs `PUBLISH_FROM_DRAFT.md` after user Save + approval.
|
|
88
|
+
- Legacy hardcoded templates may open in Studio without full Theme restyle; new authoring must be Theme-aware.
|
|
89
|
+
- If `contrastPass` is false, fix before `theme.create` (switch mode, adjust hex, or document trade-off).
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "design_plan_v2_1",
|
|
3
|
+
"sourceKind": "text_brief",
|
|
4
|
+
"intent": {
|
|
5
|
+
"jobToBeDone": "Fixture for SURFACE_REVIEW validation",
|
|
6
|
+
"primaryPlatform": "x",
|
|
7
|
+
"canvas": { "width": 1200, "height": 675 }
|
|
8
|
+
},
|
|
9
|
+
"philosophy": {
|
|
10
|
+
"movementName": "Quiet Proof",
|
|
11
|
+
"space": "Wide margins",
|
|
12
|
+
"color": "Soft wash under dark ink",
|
|
13
|
+
"rhythm": "Sparse rules",
|
|
14
|
+
"composition": "One metric focal",
|
|
15
|
+
"typographyAccent": "Large metric",
|
|
16
|
+
"craftBar": "One focal; refine before decoration"
|
|
17
|
+
},
|
|
18
|
+
"concepts": [
|
|
19
|
+
{
|
|
20
|
+
"id": "a",
|
|
21
|
+
"name": "A",
|
|
22
|
+
"rationale": "Primary",
|
|
23
|
+
"philosophyExpression": "Metric left; wash behind",
|
|
24
|
+
"visualMotif": "wash",
|
|
25
|
+
"layout": "metric left",
|
|
26
|
+
"hierarchy": "metric > title",
|
|
27
|
+
"typography": "display metric",
|
|
28
|
+
"colorStrategy": "soft gradient under ink",
|
|
29
|
+
"assetStrategy": "gradient wash",
|
|
30
|
+
"risks": []
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "b",
|
|
34
|
+
"name": "B",
|
|
35
|
+
"rationale": "Alt",
|
|
36
|
+
"philosophyExpression": "Centered metric on flat",
|
|
37
|
+
"visualMotif": "flat",
|
|
38
|
+
"layout": "centered",
|
|
39
|
+
"hierarchy": "metric > title",
|
|
40
|
+
"typography": "display metric",
|
|
41
|
+
"colorStrategy": "flat canvas",
|
|
42
|
+
"assetStrategy": "none",
|
|
43
|
+
"risks": []
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"selectedConceptId": "a",
|
|
47
|
+
"selectionReason": "Needs atmosphere",
|
|
48
|
+
"themePreview": {
|
|
49
|
+
"name": "Ocean Depths",
|
|
50
|
+
"brandHex": "#1A6B6B",
|
|
51
|
+
"activeMode": "light",
|
|
52
|
+
"contrastPass": true,
|
|
53
|
+
"themeTokensPath": "theme-tokens.json",
|
|
54
|
+
"userConfirmed": true
|
|
55
|
+
},
|
|
56
|
+
"surfacePreview": {
|
|
57
|
+
"kind": "gradient",
|
|
58
|
+
"userConfirmed": true,
|
|
59
|
+
"recipeId": "grad_001_warm-flame",
|
|
60
|
+
"name": "Warm Flame",
|
|
61
|
+
"provider": "webgradients",
|
|
62
|
+
"textSafeZone": "light_end",
|
|
63
|
+
"contrastAnchor": "#FAD0C4",
|
|
64
|
+
"placement": "full_bleed"
|
|
65
|
+
},
|
|
66
|
+
"assetPlan": [
|
|
67
|
+
{
|
|
68
|
+
"role": "background",
|
|
69
|
+
"source": "gradient_catalog",
|
|
70
|
+
"required": false,
|
|
71
|
+
"description": "Warm Flame wash"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "theme_presets_v1",
|
|
3
|
+
"presets": [
|
|
4
|
+
{
|
|
5
|
+
"id": "ocean-depths",
|
|
6
|
+
"name": "Ocean Depths",
|
|
7
|
+
"brandHex": "#1A6B6B",
|
|
8
|
+
"mode": "light",
|
|
9
|
+
"fonts": { "heading": "Inter", "body": "Inter" },
|
|
10
|
+
"bestFor": "Finance, consulting, trust-building metric cards",
|
|
11
|
+
"notFor": "High-energy nightlife or neon gaming creatives"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"id": "sunset-boulevard",
|
|
15
|
+
"name": "Sunset Boulevard",
|
|
16
|
+
"brandHex": "#E85D04",
|
|
17
|
+
"mode": "light",
|
|
18
|
+
"fonts": { "heading": "Inter", "body": "Inter" },
|
|
19
|
+
"bestFor": "Launch, lifestyle, warm creator promos",
|
|
20
|
+
"notFor": "Conservative financial disclosures"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "forest-canopy",
|
|
24
|
+
"name": "Forest Canopy",
|
|
25
|
+
"brandHex": "#2D6A4F",
|
|
26
|
+
"mode": "light",
|
|
27
|
+
"fonts": { "heading": "Georgia", "body": "Inter" },
|
|
28
|
+
"bestFor": "Sustainability, outdoor, grounded reports",
|
|
29
|
+
"notFor": "Ultra-minimal grayscale product UI"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "modern-minimalist",
|
|
33
|
+
"name": "Modern Minimalist",
|
|
34
|
+
"brandHex": "#475569",
|
|
35
|
+
"mode": "light",
|
|
36
|
+
"fonts": { "heading": "Inter", "body": "Inter" },
|
|
37
|
+
"bestFor": "Architecture, product UI shots, clean SaaS",
|
|
38
|
+
"notFor": "Maximalist sticker-led creator posts"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": "golden-hour",
|
|
42
|
+
"name": "Golden Hour",
|
|
43
|
+
"brandHex": "#B45309",
|
|
44
|
+
"mode": "light",
|
|
45
|
+
"fonts": { "heading": "Playfair Display", "body": "Source Sans 3" },
|
|
46
|
+
"bestFor": "Premium, autumnal, milestone celebrate",
|
|
47
|
+
"notFor": "Cold clinical healthcare dashboards"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"id": "arctic-frost",
|
|
51
|
+
"name": "Arctic Frost",
|
|
52
|
+
"brandHex": "#0284C7",
|
|
53
|
+
"mode": "light",
|
|
54
|
+
"fonts": { "heading": "Inter", "body": "Inter" },
|
|
55
|
+
"bestFor": "Winter campaigns, crisp tech, health",
|
|
56
|
+
"notFor": "Warm rustic food storytelling"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "desert-rose",
|
|
60
|
+
"name": "Desert Rose",
|
|
61
|
+
"brandHex": "#C45C6A",
|
|
62
|
+
"mode": "light",
|
|
63
|
+
"fonts": { "heading": "Inter", "body": "Inter" },
|
|
64
|
+
"bestFor": "Soft beauty, hospitality, gentle social proof",
|
|
65
|
+
"notFor": "Hard-edge industrial or terminal aesthetics"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "tech-innovation",
|
|
69
|
+
"name": "Tech Innovation",
|
|
70
|
+
"brandHex": "#2563EB",
|
|
71
|
+
"mode": "dark",
|
|
72
|
+
"fonts": { "heading": "Inter", "body": "Inter" },
|
|
73
|
+
"bestFor": "Startups, AI updates, product launches",
|
|
74
|
+
"notFor": "Warm editorial paper / folio looks"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "botanical-garden",
|
|
78
|
+
"name": "Botanical Garden",
|
|
79
|
+
"brandHex": "#16A34A",
|
|
80
|
+
"mode": "light",
|
|
81
|
+
"fonts": { "heading": "Inter", "body": "Inter" },
|
|
82
|
+
"bestFor": "Growth metrics, wellness, organic brands",
|
|
83
|
+
"notFor": "Luxury black-tie or neon nightlife"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "midnight-galaxy",
|
|
87
|
+
"name": "Midnight Galaxy",
|
|
88
|
+
"brandHex": "#7C3AED",
|
|
89
|
+
"mode": "dark",
|
|
90
|
+
"fonts": { "heading": "Inter", "body": "Inter" },
|
|
91
|
+
"bestFor": "Entertainment, gaming, bold night creatives",
|
|
92
|
+
"notFor": "Corporate earnings or government reports"
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|