ima2-gen 2.0.15 → 2.0.16
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 +30 -0
- package/bin/commands/skill.js +336 -17
- package/bin/ima2.js +22 -2
- package/bin/lib/doctor-checks.js +6 -4
- package/config.js +1 -0
- package/docs/CLI.md +25 -3
- package/docs/PROMPT_STUDIO.ko.md +29 -0
- package/docs/PROMPT_STUDIO.md +31 -0
- package/docs/migration/runtime-test-inventory.md +7 -1
- package/lib/agentImageVideoGen.js +8 -0
- package/lib/agentQueueStore.js +36 -10
- package/lib/agentQueueWorker.js +79 -7
- package/lib/agentRuntime.js +2 -0
- package/lib/assetLifecycle.js +40 -8
- package/lib/canvasVersionStore.js +86 -0
- package/lib/cardNewsGenerator.js +37 -3
- package/lib/cardNewsJobStore.js +10 -0
- package/lib/cardNewsManifestStore.js +6 -12
- package/lib/cardNewsPath.js +25 -0
- package/lib/db.js +2 -0
- package/lib/generatePipeline.js +474 -0
- package/lib/generationInputValidation.js +32 -0
- package/lib/grokImageCore.js +18 -1
- package/lib/historyIndex.js +11 -4
- package/lib/historyList.js +3 -0
- package/lib/imageMetadata.js +3 -0
- package/lib/inflight.js +30 -3
- package/lib/multimodePipeline.js +462 -0
- package/lib/nodeGeneration.js +440 -0
- package/lib/nodeValidation.js +23 -0
- package/lib/oauthProxy/generators.js +3 -246
- package/lib/oauthProxy/multimodeGenerators.js +251 -0
- package/lib/routeHelpers.js +9 -2
- package/package.json +2 -2
- package/routes/agent.js +4 -4
- package/routes/canvasVersions.js +21 -1
- package/routes/cardNews.js +2 -1
- package/routes/edit.js +25 -9
- package/routes/events.js +5 -1
- package/routes/generate.js +2 -481
- package/routes/keys.js +31 -39
- package/routes/multimode.js +2 -502
- package/routes/nodes.js +3 -448
- package/routes/video.js +12 -3
- package/routes/videoExtended.js +19 -4
- package/server.js +53 -1
- package/skills/ima2/SKILL.md +204 -0
- package/skills/ima2-front/SKILL.md +611 -0
- package/skills/ima2-front/references/a11y-patterns.md +134 -0
- package/skills/ima2-front/references/aesthetics.md +327 -0
- package/skills/ima2-front/references/anti-slop.md +241 -0
- package/skills/ima2-front/references/asset-requirements.md +431 -0
- package/skills/ima2-front/references/brand-asset-sourcing.md +122 -0
- package/skills/ima2-front/references/color-system.md +132 -0
- package/skills/ima2-front/references/consistency-locks.md +20 -0
- package/skills/ima2-front/references/crud-ui.md +53 -0
- package/skills/ima2-front/references/dropdown-layer.md +110 -0
- package/skills/ima2-front/references/i18n-global.md +104 -0
- package/skills/ima2-front/references/iterative-design.md +90 -0
- package/skills/ima2-front/references/korea-2026.md +174 -0
- package/skills/ima2-front/references/layout-discipline.md +161 -0
- package/skills/ima2-front/references/liquid-glass.md +181 -0
- package/skills/ima2-front/references/logo-sections.md +194 -0
- package/skills/ima2-front/references/mobile-ux.md +144 -0
- package/skills/ima2-front/references/performance-budget.md +106 -0
- package/skills/ima2-front/references/preflight-full.md +58 -0
- package/skills/ima2-front/references/product-density.md +53 -0
- package/skills/ima2-front/references/prototype-variants.md +54 -0
- package/skills/ima2-front/references/reference-capture.md +120 -0
- package/skills/ima2-front/references/responsive-viewport.md +139 -0
- package/skills/ima2-front/references/seo-baseline.md +123 -0
- package/skills/ima2-front/references/soft-3d-asset-gates.md +70 -0
- package/skills/ima2-front/references/stacks/astro.md +204 -0
- package/skills/ima2-front/references/stacks/mobile-native.md +281 -0
- package/skills/ima2-front/references/stacks/nextjs.md +219 -0
- package/skills/ima2-front/references/stacks/react.md +264 -0
- package/skills/ima2-front/references/stacks/svelte.md +235 -0
- package/skills/ima2-front/references/stacks/vanilla.md +226 -0
- package/skills/ima2-front/references/theme-switching.md +82 -0
- package/skills/ima2-front/references/top-bar.md +126 -0
- package/skills/ima2-front/references/typography-wrapping.md +270 -0
- package/skills/ima2-front/references/ux-writing-ko.md +62 -0
- package/skills/ima2-front/references/visual-verification.md +102 -0
- package/skills/ima2-uiux/SKILL.md +477 -0
- package/skills/ima2-uiux/references/anti-slop-judgment.md +39 -0
- package/skills/ima2-uiux/references/color-system.md +80 -0
- package/skills/ima2-uiux/references/design-isms.md +194 -0
- package/skills/ima2-uiux/references/design-read-example.md +33 -0
- package/skills/ima2-uiux/references/design-system-bootstrap.md +133 -0
- package/skills/ima2-uiux/references/favicon-logo.md +355 -0
- package/skills/ima2-uiux/references/form-patterns.md +118 -0
- package/skills/ima2-uiux/references/intent-discovery-ladder.md +86 -0
- package/skills/ima2-uiux/references/korean-design-vocabulary.md +52 -0
- package/skills/ima2-uiux/references/layout-macrostructures.md +54 -0
- package/skills/ima2-uiux/references/logo-trust-sections.md +96 -0
- package/skills/ima2-uiux/references/mobile-native-ux.md +207 -0
- package/skills/ima2-uiux/references/product-personalities.md +118 -0
- package/skills/ima2-uiux/references/responsive-nav.md +66 -0
- package/skills/ima2-uiux/references/typography-line-breaks.md +193 -0
- package/skills/ima2-uiux/references/ux-preflight.md +65 -0
- package/skills/ima2-uiux/references/ux-states.md +197 -0
- package/skills/ima2-uiux/references/visual-hierarchy.md +115 -0
- package/ui/dist/.vite/manifest.json +13 -13
- package/ui/dist/assets/AgentWorkspace-CtYt4SF5.js +3 -0
- package/ui/dist/assets/{CardNewsWorkspace-Cdxn1ohU.js → CardNewsWorkspace-DN5cVqG5.js} +1 -1
- package/ui/dist/assets/GenerationRequestLogPanel-DnmUQdKR.js +1 -0
- package/ui/dist/assets/{NodeCanvas-C67sLboA.js → NodeCanvas-CxpfIBI0.js} +1 -1
- package/ui/dist/assets/PromptBuilderPanel-C2R3ObtR.js +2 -0
- package/ui/dist/assets/{PromptImportDialog-DeQXsEEv.js → PromptImportDialog-BIxz_yEx.js} +2 -2
- package/ui/dist/assets/PromptImportDiscoverySection-BQTlPMME.js +1 -0
- package/ui/dist/assets/PromptImportFolderSection-Ds_Th9O3.js +1 -0
- package/ui/dist/assets/{PromptLibraryPanel-Db3xEPM_.js → PromptLibraryPanel-Rs4l45pV.js} +2 -2
- package/ui/dist/assets/{SettingsWorkspace-BDk_1W-V.js → SettingsWorkspace-p1AZ6uT9.js} +1 -1
- package/ui/dist/assets/index-0-_vgFGs.js +4 -0
- package/ui/dist/assets/index-Dm3pFxV4.js +23 -0
- package/ui/dist/assets/index-J8yDF3Ch.css +1 -0
- package/ui/dist/index.html +2 -2
- package/ui/dist/assets/AgentWorkspace-DAg_7zpY.js +0 -3
- package/ui/dist/assets/GenerationRequestLogPanel-C_qvEUi2.js +0 -1
- package/ui/dist/assets/PromptBuilderPanel-DjvVdAie.js +0 -2
- package/ui/dist/assets/PromptImportDiscoverySection-CrwyUKYI.js +0 -1
- package/ui/dist/assets/PromptImportFolderSection-CToGMqYE.js +0 -1
- package/ui/dist/assets/index-2oG6in1i.css +0 -1
- package/ui/dist/assets/index-CoxMOXAU.js +0 -23
- package/ui/dist/assets/index-p8egnGHk.js +0 -4
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Logo Sections — Integration Grids, Marquees & Brand Walls
|
|
2
|
+
|
|
3
|
+
Patterns for displaying partner/integration logos. These sections are trust signals, not navigation.
|
|
4
|
+
For design judgment (when/why to use each pattern), see `dev-uiux-design/references/logo-trust-sections.md`.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Decision Table
|
|
9
|
+
|
|
10
|
+
| Condition | Pattern | Reason |
|
|
11
|
+
|-----------|---------|--------|
|
|
12
|
+
| ≤6 logos, need labels/links | Static grid | Clean, scannable, clickable |
|
|
13
|
+
| ≤6 logos, case study links | Static grid, clickable | Hover justified — links add value |
|
|
14
|
+
| 8+ logos, social proof | CSS marquee | Avoids orphan cells, feels dynamic |
|
|
15
|
+
| Many logos, save vertical space | Multi-row marquee | Opposing directions add depth |
|
|
16
|
+
| Portfolio/client list | Static grid with uniform treatment | Professional, organized |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Why Logo Sections Should NOT Have Individual Hover Effects
|
|
21
|
+
|
|
22
|
+
Logo/integration sections are **trust signals**, not interactive navigation.
|
|
23
|
+
|
|
24
|
+
1. **False affordance** — Hover implies clickability. Users expect navigation but get nothing.
|
|
25
|
+
2. **Visual noise** — Many logos + hover animations = busy, gimmicky, undermines credibility.
|
|
26
|
+
3. **Mobile incompatibility** — Hover states don't exist on touch devices.
|
|
27
|
+
4. **Brand guideline conflicts** — Heavy modifications can violate partner brand guidelines.
|
|
28
|
+
5. **Distraction from CTA** — The section's job is to build trust, not capture clicks.
|
|
29
|
+
|
|
30
|
+
**Acceptable alternatives:**
|
|
31
|
+
- Pause the entire marquee on hover (standard)
|
|
32
|
+
- Very subtle uniform opacity change on section hover (not individual items)
|
|
33
|
+
- No hover at all (cleanest, most common in premium sites)
|
|
34
|
+
- **Exception:** If logos link to case study pages, individual hover is justified.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## CSS-Only Marquee
|
|
39
|
+
|
|
40
|
+
The dominant production pattern. Duplicate the content for seamless looping.
|
|
41
|
+
|
|
42
|
+
```html
|
|
43
|
+
<div class="marquee" aria-label="Trusted by leading companies">
|
|
44
|
+
<div class="marquee-track">
|
|
45
|
+
<!-- Original set -->
|
|
46
|
+
<img src="/logos/kubernetes.svg" alt="Kubernetes" width="120" height="40">
|
|
47
|
+
<img src="/logos/docker.svg" alt="Docker" width="120" height="40">
|
|
48
|
+
<img src="/logos/aws.svg" alt="AWS" width="120" height="40">
|
|
49
|
+
<!-- Duplicate set for seamless loop -->
|
|
50
|
+
<img src="/logos/kubernetes.svg" alt="" aria-hidden="true" width="120" height="40">
|
|
51
|
+
<img src="/logos/docker.svg" alt="" aria-hidden="true" width="120" height="40">
|
|
52
|
+
<img src="/logos/aws.svg" alt="" aria-hidden="true" width="120" height="40">
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```css
|
|
58
|
+
.marquee {
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
user-select: none;
|
|
61
|
+
-webkit-mask-image: linear-gradient(
|
|
62
|
+
to right, transparent, black 10%, black 90%, transparent
|
|
63
|
+
);
|
|
64
|
+
mask-image: linear-gradient(
|
|
65
|
+
to right, transparent, black 10%, black 90%, transparent
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.marquee-track {
|
|
70
|
+
display: flex;
|
|
71
|
+
gap: 48px;
|
|
72
|
+
align-items: center;
|
|
73
|
+
width: max-content;
|
|
74
|
+
animation: marquee-scroll 40s linear infinite;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.marquee-track img {
|
|
78
|
+
height: 32px;
|
|
79
|
+
width: auto;
|
|
80
|
+
flex-shrink: 0;
|
|
81
|
+
filter: grayscale(1) brightness(0.7);
|
|
82
|
+
opacity: 0.5;
|
|
83
|
+
transition: none; /* No individual hover */
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@keyframes marquee-scroll {
|
|
87
|
+
from { transform: translateX(0); }
|
|
88
|
+
to { transform: translateX(-50%); }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.marquee:hover .marquee-track {
|
|
92
|
+
animation-play-state: paused;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@media (prefers-reduced-motion: reduce) {
|
|
96
|
+
.marquee-track { animation: none; }
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Marquee Speed Guide
|
|
101
|
+
|
|
102
|
+
| Speed | Duration | Feel | Use |
|
|
103
|
+
|-------|----------|------|-----|
|
|
104
|
+
| Very slow | 50-60s | Calm, premium | Enterprise, finance |
|
|
105
|
+
| Slow | 30-40s | Professional | General SaaS |
|
|
106
|
+
| Medium | 20-30s | Energetic | Startups, dev tools |
|
|
107
|
+
| Fast | <15s | Cheap, frantic | **Avoid** |
|
|
108
|
+
|
|
109
|
+
`linear` timing only — no easing. Constant speed feels intentional.
|
|
110
|
+
|
|
111
|
+
### Key Details
|
|
112
|
+
- Duplicate items get `aria-hidden="true"` and empty `alt=""`
|
|
113
|
+
- Fade edges with `mask-image` gradient — no hard cut
|
|
114
|
+
- `translateX(-50%)` only works when content is exactly duplicated
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Multi-Row Opposing Marquee
|
|
119
|
+
|
|
120
|
+
Two rows scrolling in opposite directions for visual depth.
|
|
121
|
+
|
|
122
|
+
```css
|
|
123
|
+
.marquee-reverse .marquee-track {
|
|
124
|
+
animation-direction: reverse;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Static Grid (≤6 Logos)
|
|
131
|
+
|
|
132
|
+
When logos need labels or link to documentation/case study pages.
|
|
133
|
+
|
|
134
|
+
```css
|
|
135
|
+
.logo-grid {
|
|
136
|
+
display: flex;
|
|
137
|
+
flex-wrap: wrap;
|
|
138
|
+
justify-content: center;
|
|
139
|
+
gap: 32px 48px;
|
|
140
|
+
align-items: center;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.logo-grid img {
|
|
144
|
+
height: 28px;
|
|
145
|
+
width: auto;
|
|
146
|
+
filter: grayscale(1) brightness(0.7);
|
|
147
|
+
opacity: 0.5;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Use `flexbox` with `justify-content: center`, NOT CSS grid** — flex avoids the orphan cell problem.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## The Orphan Cell Problem
|
|
156
|
+
|
|
157
|
+
When a CSS grid has e.g. 8 items in a 7-column layout, 1 item sits alone on the last row.
|
|
158
|
+
|
|
159
|
+
| Solution | When to use |
|
|
160
|
+
|----------|-------------|
|
|
161
|
+
| **Marquee** | 8+ logos — eliminates the problem entirely |
|
|
162
|
+
| **Flexbox with `justify-content: center`** | Items wrap naturally, no empty cells |
|
|
163
|
+
| **Match column count to item count** | Add or remove logos to fill the row |
|
|
164
|
+
|
|
165
|
+
**Never** leave a single item alone on a grid row.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Grayscale Treatment
|
|
170
|
+
|
|
171
|
+
Standard for logo walls: desaturated/monochrome by default.
|
|
172
|
+
|
|
173
|
+
```css
|
|
174
|
+
.logo-item img {
|
|
175
|
+
filter: grayscale(1) brightness(0.7);
|
|
176
|
+
opacity: 0.5;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
[data-theme="dark"] .logo-item img {
|
|
180
|
+
filter: grayscale(1) brightness(1.2) invert(1);
|
|
181
|
+
opacity: 0.4;
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Do NOT apply `filter: grayscale(0)` on individual hover. The grayscale-to-color-on-hover pattern feels gimmicky in 2026.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Performance
|
|
190
|
+
|
|
191
|
+
- Use SVGs — sharp at any size, tiny file size
|
|
192
|
+
- Set explicit `width` and `height` attributes — prevents layout shift
|
|
193
|
+
- `will-change: transform` on the marquee track
|
|
194
|
+
- Lazy-load below-fold logos with `loading="lazy"`
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Mobile UX Rules (MANDATORY for consumer/landing pages)
|
|
2
|
+
|
|
3
|
+
Mobile is NOT "desktop squished down." It is a different interaction model with different constraints, different user posture, and different conversion mechanics. These rules apply to any page serving mobile traffic.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Thumb Zone Geometry
|
|
8
|
+
|
|
9
|
+
49% of users hold their phone with one hand. The bottom 40% of the screen is the natural thumb reach zone ("easy"), the middle 40% is comfortable, and the top 20% is hard to reach.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌────────────────────┐
|
|
13
|
+
│ HARD TO REACH │ ← top 20%: status bar, back nav, secondary info
|
|
14
|
+
│ │
|
|
15
|
+
│ COMFORTABLE │ ← middle 40%: content, scrollable area
|
|
16
|
+
│ │
|
|
17
|
+
│ EASY / NATURAL │ ← bottom 40%: primary CTA, tab bar, key actions
|
|
18
|
+
└────────────────────┘
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Rules:
|
|
22
|
+
- Primary CTA → bottom 80% of viewport (easy + comfortable zones), or sticky-bottom
|
|
23
|
+
- Secondary actions (share, bookmark, settings) → top or overflow menu
|
|
24
|
+
- Destructive actions (delete, cancel) → require confirmation, never in thumb zone default
|
|
25
|
+
- FAB (floating action button) → bottom-right, 56px, 16px from edges
|
|
26
|
+
|
|
27
|
+
## Touch Targets (MANDATORY)
|
|
28
|
+
|
|
29
|
+
| Element | Minimum Size | Recommended |
|
|
30
|
+
|---------|-------------|-------------|
|
|
31
|
+
| Buttons | 44 x 44px | 48 x 48px |
|
|
32
|
+
| Form inputs | 44px height | 48px height |
|
|
33
|
+
| List items (tappable) | 44px height | 48-56px height |
|
|
34
|
+
| Icon buttons | 44 x 44px (including padding) | 48 x 48px |
|
|
35
|
+
| Links in body text | 44px touch area (padding) | — |
|
|
36
|
+
| Spacing between targets | 8px minimum | 12px |
|
|
37
|
+
|
|
38
|
+
Never rely on hover states for mobile — there is no hover. Every hover-revealed element needs a tap-accessible alternative.
|
|
39
|
+
|
|
40
|
+
## Sticky CTA Pattern (conversion pages)
|
|
41
|
+
|
|
42
|
+
On landing/marketing pages longer than 2 screen heights, the primary CTA scrolls out of view. Fix:
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<div class="fixed bottom-0 inset-x-0 p-4 bg-white/90 backdrop-blur-sm border-t
|
|
46
|
+
pb-[calc(1rem+env(safe-area-inset-bottom))] z-40 md:hidden">
|
|
47
|
+
<button class="w-full h-12 rounded-lg bg-primary text-white font-semibold">
|
|
48
|
+
Get Started
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Rules:
|
|
54
|
+
- Show only on mobile (< 768px)
|
|
55
|
+
- Appear after user scrolls past the hero CTA (use IntersectionObserver)
|
|
56
|
+
- Semi-transparent background so content beneath is visible
|
|
57
|
+
- Include safe-area bottom padding
|
|
58
|
+
- Do NOT show if the hero CTA is still visible
|
|
59
|
+
|
|
60
|
+
## Mobile Section Composition
|
|
61
|
+
|
|
62
|
+
Section order and density must adapt for mobile — not just stack unchanged.
|
|
63
|
+
|
|
64
|
+
### CTA Placement
|
|
65
|
+
- Hero: CTA visible without scroll (MANDATORY — same as desktop)
|
|
66
|
+
- After first proof/testimonial block: repeat CTA
|
|
67
|
+
- After FAQ/objection handling: final CTA
|
|
68
|
+
- Desktop can have 5-8 sections between CTAs. Mobile: max 3 sections between CTAs.
|
|
69
|
+
|
|
70
|
+
### Proof Proximity
|
|
71
|
+
On desktop, users tolerate claim → feature → feature → proof. On mobile, every claim needs proof within 1 scroll:
|
|
72
|
+
- Feature claim → immediately followed by testimonial, stat, or screenshot
|
|
73
|
+
- No more than 2 consecutive "claim" sections without evidence
|
|
74
|
+
|
|
75
|
+
### Section Density on Mobile
|
|
76
|
+
- Max content per mobile section: 1 heading + 1 paragraph (≤60 words) + 1 visual or CTA
|
|
77
|
+
- Long feature lists (>4 items): horizontal scroll-snap cards or accordion, not vertical list
|
|
78
|
+
- Pricing: 1 card visible at a time with swipe or tab selector
|
|
79
|
+
- Testimonials: swipe carousel, not stacked cards
|
|
80
|
+
|
|
81
|
+
### Content That Changes on Mobile
|
|
82
|
+
- Desktop side-by-side comparison → mobile tab selector or accordion
|
|
83
|
+
- Desktop data table → mobile card list or horizontal scroll
|
|
84
|
+
- Desktop multi-column footer → mobile accordion sections
|
|
85
|
+
- Desktop image gallery grid → mobile horizontal scroll-snap
|
|
86
|
+
|
|
87
|
+
## Mobile Hero Constraints
|
|
88
|
+
|
|
89
|
+
The mobile hero has ~390 x 600px of usable space. It must:
|
|
90
|
+
- Headline: max `text-3xl` (1.875rem), max 2 lines
|
|
91
|
+
- Subtext: max 15 words (not 20 — mobile has less width per line)
|
|
92
|
+
- CTA: visible without scroll, full-width button preferred
|
|
93
|
+
- Hero image: max 60vh, or background with overlay text
|
|
94
|
+
- No decorative elements (trust badges, taglines below CTA, scroll cues)
|
|
95
|
+
|
|
96
|
+
If the desktop hero has a side-by-side layout, mobile MUST stack: image first (if product/visual), text first (if story/narrative).
|
|
97
|
+
|
|
98
|
+
## Bottom Sheet Pattern
|
|
99
|
+
|
|
100
|
+
Mobile form selects and pickers use the same dropdown design-layer skin
|
|
101
|
+
(`dropdown-layer.md` FE-DROPDOWN-LAYER-01) rendered as a bottom sheet: no
|
|
102
|
+
nested scrolling, preserved form semantics and keyboard/AT behavior, and a tap
|
|
103
|
+
path for anything hover-spawned on desktop.
|
|
104
|
+
|
|
105
|
+
For mobile actions that need more space than a button but less than a full page:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
┌──────────────────────┐
|
|
109
|
+
│ ──── (drag handle) │
|
|
110
|
+
│ │
|
|
111
|
+
│ Action title │
|
|
112
|
+
│ Option 1 │
|
|
113
|
+
│ Option 2 │
|
|
114
|
+
│ Option 3 │
|
|
115
|
+
│ │
|
|
116
|
+
│ [Cancel] │
|
|
117
|
+
└──────────────────────┘
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Rules:
|
|
121
|
+
- Max height: 70vh (user must see the page behind it)
|
|
122
|
+
- Drag handle visible at top center
|
|
123
|
+
- Close on backdrop tap or swipe down
|
|
124
|
+
- No nested scrolling (if content is too long, use a full page instead)
|
|
125
|
+
- `overscroll-behavior: contain` to prevent background scroll
|
|
126
|
+
|
|
127
|
+
## Mobile Form Rules
|
|
128
|
+
|
|
129
|
+
- One input per row (never side-by-side on mobile)
|
|
130
|
+
- Use correct `inputmode`: `tel` for phone, `numeric` for zip/PIN, `email` for email, `url` for URLs
|
|
131
|
+
- Label above input, not inside (placeholder-only labels are inaccessible)
|
|
132
|
+
- Auto-advance between short fields (OTP, phone segments)
|
|
133
|
+
- Submit button full-width, sticky-bottom for long forms
|
|
134
|
+
- Error messages inline below the field, not in a toast or alert
|
|
135
|
+
- Keyboard-aware: scroll the active input into view above the keyboard
|
|
136
|
+
|
|
137
|
+
## Portrait Media Guidance
|
|
138
|
+
|
|
139
|
+
Mobile is portrait-first. Images optimized for desktop landscape crop poorly on mobile.
|
|
140
|
+
|
|
141
|
+
- Hero images: prepare portrait crop (4:5 or 3:4) for mobile, landscape (16:9 or 3:2) for desktop
|
|
142
|
+
- Product images: square (1:1) works for both orientations
|
|
143
|
+
- Background textures: use CSS `object-position` to control crop focal point
|
|
144
|
+
- Video: provide portrait version or use `object-fit: cover` with careful framing
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Performance Budget
|
|
2
|
+
|
|
3
|
+
## Core Web Vitals Targets
|
|
4
|
+
|
|
5
|
+
| Metric | Good | Needs Work | Poor | Measures |
|
|
6
|
+
|--------|------|------------|------|----------|
|
|
7
|
+
| LCP | ≤ 2.5s | ≤ 4.0s | > 4.0s | Hero load time |
|
|
8
|
+
| INP | ≤ 200ms | ≤ 500ms | > 500ms | Input responsiveness |
|
|
9
|
+
| CLS | ≤ 0.1 | ≤ 0.25 | > 0.25 | Visual stability |
|
|
10
|
+
|
|
11
|
+
- Every page targets "Good" on all three
|
|
12
|
+
- LCP element: identify early, preload it
|
|
13
|
+
- INP: never block main thread > 50ms
|
|
14
|
+
- CLS: every image/video/embed needs explicit `width`+`height` or `aspect-ratio`
|
|
15
|
+
|
|
16
|
+
## Bundle Size Budgets
|
|
17
|
+
|
|
18
|
+
| Resource | Budget (compressed) |
|
|
19
|
+
|----------|-------------------|
|
|
20
|
+
| Total page weight | <= 500KB first load (landing motion media exempt - see FE-MEDIA-BUDGET-01) |
|
|
21
|
+
| JavaScript (per route) | ≤ 150KB |
|
|
22
|
+
| CSS (total) | ≤ 50KB |
|
|
23
|
+
| Hero image | <= 100KB (landing motion media exempt - see FE-MEDIA-BUDGET-01) |
|
|
24
|
+
| Images (above fold) | <= 200KB (landing motion media exempt - see FE-MEDIA-BUDGET-01) |
|
|
25
|
+
| Web fonts | ≤ 100KB |
|
|
26
|
+
|
|
27
|
+
- Measure compressed (gzip/brotli) sizes
|
|
28
|
+
- Tree-shake: `import { x } from 'lib'`, never `import lib`
|
|
29
|
+
- Dynamic import for below-fold: `lazy(() => import('./Modal'))`
|
|
30
|
+
- Bundle analyzer mandatory for builds > 200KB JS
|
|
31
|
+
|
|
32
|
+
## Motion Media Budget Exemption (FE-MEDIA-BUDGET-01) (DEFAULT)
|
|
33
|
+
|
|
34
|
+
On LANDING-bucket surfaces (see `motion.md` FE-MOTION-BUCKET-01), motion media
|
|
35
|
+
is exempt from byte-cap rows with no byte ceiling: autoplay loop video,
|
|
36
|
+
scroll-scrub video, frame sequences, and large hero imagery. Budget freedom is
|
|
37
|
+
not correctness freedom: Core Web Vitals field gates remain supreme (LCP <= 2.5s,
|
|
38
|
+
INP <= 200ms, CLS <= 0.1).
|
|
39
|
+
|
|
40
|
+
This exemption applies only when the loading mechanics hold:
|
|
41
|
+
- Poster-first LCP; the poster itself counts toward the hero image budget.
|
|
42
|
+
- Lazy or Intersection Observer-gated loading outside first paint.
|
|
43
|
+
- `prefers-reduced-motion` and `prefers-reduced-data` fallbacks to poster/still.
|
|
44
|
+
- Stable layout; no CLS from media swap.
|
|
45
|
+
|
|
46
|
+
Heavy media still needs a product reason plus the mechanics above. Do not ship
|
|
47
|
+
large video, frame sequences, or heavy hero imagery just because the byte cap is
|
|
48
|
+
exempt.
|
|
49
|
+
|
|
50
|
+
## Font Loading
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<link rel="preload" href="/fonts/primary.woff2" as="font" type="font/woff2" crossorigin>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```css
|
|
57
|
+
@font-face {
|
|
58
|
+
font-family: 'Primary';
|
|
59
|
+
src: url('/fonts/primary.woff2') format('woff2');
|
|
60
|
+
font-display: swap;
|
|
61
|
+
unicode-range: U+0020-007F, U+AC00-D7AF;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- `font-display: swap` for body, `optional` for decorative
|
|
66
|
+
- Preload only the primary font file
|
|
67
|
+
- Subset: Latin + target script only
|
|
68
|
+
- Max 2 families, 4 weights total
|
|
69
|
+
- Self-host when possible
|
|
70
|
+
|
|
71
|
+
## Image Optimization
|
|
72
|
+
|
|
73
|
+
| Format | Use For | Quality |
|
|
74
|
+
|--------|---------|---------|
|
|
75
|
+
| WebP | Photos, complex | 75-85% |
|
|
76
|
+
| AVIF | Photos (modern) | 65-75% |
|
|
77
|
+
| SVG | Icons, logos | N/A |
|
|
78
|
+
| PNG | Screenshots, transparency | Lossless |
|
|
79
|
+
|
|
80
|
+
- `<picture>` with AVIF → WebP → fallback for hero
|
|
81
|
+
- `loading="lazy"` below-fold, `loading="eager" fetchpriority="high"` for hero
|
|
82
|
+
- Max 2x display size for retina
|
|
83
|
+
- Responsive `srcset` + `sizes` for content images
|
|
84
|
+
|
|
85
|
+
## Build-Time Gates
|
|
86
|
+
|
|
87
|
+
- Lighthouse Performance score is advisory smoke only; CWV field metrics are the gate
|
|
88
|
+
- Bundle regression: fail if JS increases > 10KB
|
|
89
|
+
- Image audit: flag > 200KB, excluding declared landing motion-media assets (frame sequences, posters of IO-gated video)
|
|
90
|
+
- Unused CSS: flag > 5KB dead CSS
|
|
91
|
+
|
|
92
|
+
## Runtime Rules
|
|
93
|
+
|
|
94
|
+
- No `querySelectorAll` in scroll/resize handlers
|
|
95
|
+
- Debounce scroll: 100ms min, `requestAnimationFrame` for visual
|
|
96
|
+
- Intersection Observer for lazy loading
|
|
97
|
+
- `content-visibility: auto` on below-fold sections
|
|
98
|
+
|
|
99
|
+
## Pre-flight
|
|
100
|
+
|
|
101
|
+
- [ ] Hero image <= 100KB, `fetchpriority="high"`, explicit dimensions; landing motion media exempt per FE-MEDIA-BUDGET-01 when poster-first/loading mechanics hold
|
|
102
|
+
- [ ] Below-fold images have `loading="lazy"`
|
|
103
|
+
- [ ] No JS bundle > 150KB compressed
|
|
104
|
+
- [ ] `font-display: swap` + `preload` on primary font
|
|
105
|
+
- [ ] Every `<img>`/`<video>` has `width`+`height`
|
|
106
|
+
- [ ] Lighthouse Performance score is advisory smoke only; CWV field metrics are the gate
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Full Pre-Flight Checklist (launch/audit depth)
|
|
2
|
+
|
|
3
|
+
Companion to `dev-frontend/SKILL.md` §14. The router keeps the minimum blocking gates;
|
|
4
|
+
this file is the full launch/audit list. Production surfaces only (the work classifier).
|
|
5
|
+
|
|
6
|
+
## Design & composition
|
|
7
|
+
- [ ] Domain-correct direction chosen and committed
|
|
8
|
+
- [ ] Product surface, locale, density, asset need, soft 3D gate, motion intensity classified
|
|
9
|
+
- [ ] Anti-slop patterns enforced (SKILL §5)
|
|
10
|
+
- [ ] Oversized hero text avoided unless a true hero surface
|
|
11
|
+
- [ ] Required assets are real, semantic, rendered — not generic decoration
|
|
12
|
+
- [ ] Soft 3D/miniature/character assets pass domain and semantic gates
|
|
13
|
+
- [ ] Eyebrow count ≤ ceil(sectionCount / 3) (layout-discipline.md)
|
|
14
|
+
- [ ] Section layout diversity: ≥4 different families per 8 sections
|
|
15
|
+
- [ ] Color/shape/theme locks consistent across all sections (consistency-locks.md)
|
|
16
|
+
|
|
17
|
+
## Responsive & mobile
|
|
18
|
+
- [ ] Mobile layout collapse guaranteed with per-section-type rules (layout-discipline.md § Responsive Transforms)
|
|
19
|
+
- [ ] Full-height sections use `min-h-[100dvh]` not `h-screen`
|
|
20
|
+
- [ ] Page containment: `max-w-[1400px] mx-auto` (responsive-viewport.md)
|
|
21
|
+
- [ ] Tested at 768px (tablet) and 1024px (split-screen) plus mobile/desktop
|
|
22
|
+
- [ ] Touch targets ≥ 44px on mobile; no hover-only interactions (mobile-ux.md)
|
|
23
|
+
- [ ] Responsive images use `srcset`/`sizes` or `<picture>` (responsive-viewport.md)
|
|
24
|
+
- [ ] Safe-area padding on fixed elements: `env(safe-area-inset-*)`
|
|
25
|
+
|
|
26
|
+
## States & behavior
|
|
27
|
+
- [ ] Loading, empty, and error states provided
|
|
28
|
+
- [ ] State classified before adding store/Context/Effect/cache (SKILL §12)
|
|
29
|
+
- [ ] Effects sync with external systems; derived state is not Effect-synced
|
|
30
|
+
- [ ] Container queries considered before viewport-query or JS layout workarounds
|
|
31
|
+
- [ ] View transitions respect reduced motion
|
|
32
|
+
- [ ] shadcn components follow local registry and token conventions
|
|
33
|
+
- [ ] AI UI states honest: no fake streaming, citations, or tool calls
|
|
34
|
+
- [ ] Forms validate with schema and show field-level errors (SKILL §8)
|
|
35
|
+
- [ ] Focus management on modals and popovers (SKILL §7)
|
|
36
|
+
- [ ] Interactive components isolated as Client Components (if RSC)
|
|
37
|
+
- [ ] Error Boundaries wrap major sections, not the entire app (SKILL §13)
|
|
38
|
+
|
|
39
|
+
## Korean-first
|
|
40
|
+
- [ ] CJK typography and Korean UX writing rules followed (korea-2026.md, ux-writing-ko.md)
|
|
41
|
+
- [ ] `word-break: keep-all`; `text-wrap: balance` on short descriptors
|
|
42
|
+
- [ ] Rendered screenshot check for lone particles/endings ("합니다.", "화.") at target viewports
|
|
43
|
+
|
|
44
|
+
## SEO, theme, i18n
|
|
45
|
+
- [ ] SEO meta present for public pages (title, description, canonical, OG) — seo-baseline.md
|
|
46
|
+
- [ ] JSON-LD structured data matches page type
|
|
47
|
+
- [ ] Theme toggle works: light/dark/system, no FOWT — theme-switching.md
|
|
48
|
+
- [ ] All colors use CSS custom properties (theme-ready)
|
|
49
|
+
- [ ] i18n: no hardcoded strings, CSS logical properties, Intl API — i18n-global.md
|
|
50
|
+
|
|
51
|
+
## Performance & verification
|
|
52
|
+
- [ ] Core Web Vitals field gate: LCP <= 2.5s, INP <= 200ms, CLS <= 0.1 - performance-budget.md
|
|
53
|
+
- [ ] Lighthouse Performance score is advisory smoke only; CWV field metrics are the gate; no JS bundle > 150KB compressed
|
|
54
|
+
- [ ] Hero image preloaded, below-fold images lazy-loaded; landing motion media exempt from byte caps only when FE-MEDIA-BUDGET-01 poster-first/loading mechanics hold
|
|
55
|
+
- [ ] Desktop/mobile/narrow screenshots checked for overlap, clipping, asset rendering
|
|
56
|
+
- [ ] No captured third-party asset (reference-capture.md) in the shipped build; capture manifest present for any reference captures
|
|
57
|
+
- [ ] Accessibility deep pass: modals trap focus, live regions — a11y-patterns.md
|
|
58
|
+
- [ ] Stack-specific rules followed (references/stacks/)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Product Density
|
|
2
|
+
|
|
3
|
+
Choose density before choosing visual style. Many frontend failures happen because a working tool is treated like a campaign page.
|
|
4
|
+
|
|
5
|
+
## Density Profiles
|
|
6
|
+
|
|
7
|
+
| Profile | Surface | Default |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| D1 | Campaign / editorial | expressive type, large media, low density |
|
|
10
|
+
| D2 | Landing / brand | strong first-viewport asset, concise copy |
|
|
11
|
+
| D3 | Consumer app | mobile-first, short labels, sticky actions |
|
|
12
|
+
| D4 | Productivity tool | task-first, moderate density, clear states |
|
|
13
|
+
| D5 | SaaS dashboard | dense panels, filters, tables, saved views |
|
|
14
|
+
| D6 | Admin / ops | compact controls, stable navigation, repeat actions |
|
|
15
|
+
| D7 | Finance / analytics | high trust, tabular numbers, explainable changes |
|
|
16
|
+
| D8 | Developer console | code/data density, logs, inspectable state |
|
|
17
|
+
|
|
18
|
+
### Cross-Density Enforcement (MANDATORY)
|
|
19
|
+
|
|
20
|
+
If Design Read declares page kind != SaaS/dashboard/admin:
|
|
21
|
+
- Stats rows (e.g., "368 오름 / 1,950m 한라산") — BANNED
|
|
22
|
+
- Metric comparison grids — BANNED
|
|
23
|
+
- Feature checkbox tables — BANNED
|
|
24
|
+
- Use narrative content blocks instead of data-dump sections
|
|
25
|
+
|
|
26
|
+
## Rules
|
|
27
|
+
|
|
28
|
+
- D1-D2 may use hero-scale typography and strong imagery.
|
|
29
|
+
- D3-D4 should prioritize the main workflow within the first viewport.
|
|
30
|
+
- D5-D8 should avoid decorative card stacks and oversized headings.
|
|
31
|
+
- Dense does not mean cramped. Use separators, hierarchy, table density controls, and stable toolbars.
|
|
32
|
+
- Keep repeated-work UI predictable. Surprise belongs in campaigns, not operations.
|
|
33
|
+
|
|
34
|
+
## Dashboard Defaults
|
|
35
|
+
|
|
36
|
+
Prefer:
|
|
37
|
+
|
|
38
|
+
- tables with sort/filter
|
|
39
|
+
- split panes
|
|
40
|
+
- compact metric rows
|
|
41
|
+
- visible state and timestamps
|
|
42
|
+
- saved filters/views
|
|
43
|
+
- inline editing when safe
|
|
44
|
+
- clear empty/loading/error states
|
|
45
|
+
|
|
46
|
+
Avoid:
|
|
47
|
+
|
|
48
|
+
- every metric boxed in a separate floating card
|
|
49
|
+
- giant hero headers
|
|
50
|
+
- chart decoration with no decision value
|
|
51
|
+
- one-note color palettes
|
|
52
|
+
- motion that slows repeated workflows
|
|
53
|
+
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Prototype Variants — Runnable UI Choice Protocol
|
|
2
|
+
|
|
3
|
+
Use this when the user wants to compare designs, when visual direction is uncertain,
|
|
4
|
+
or when `iterative-design.md` calls for multiple variants.
|
|
5
|
+
|
|
6
|
+
## Boundary
|
|
7
|
+
|
|
8
|
+
- `iterative-design.md` owns creative divergence: what directions to try and how to
|
|
9
|
+
kill/mutate them.
|
|
10
|
+
- This file owns the runnable mechanism: where variants live, how the user switches
|
|
11
|
+
between them, how screenshots are verified, and how temporary code is removed.
|
|
12
|
+
|
|
13
|
+
## Required Shape
|
|
14
|
+
|
|
15
|
+
Sequence: runnable structural variants come AFTER the pre-code concept lock
|
|
16
|
+
(`ima2-uiux` UX-CONCEPT-GEN-01 mockup synthesis) and only when structural
|
|
17
|
+
uncertainty genuinely survives that lock.
|
|
18
|
+
|
|
19
|
+
1. Build at least 3 structurally different variants. A color swap, copy tweak, icon
|
|
20
|
+
swap, or same card grid with different spacing is not a variant.
|
|
21
|
+
2. Prefer the existing target page/context so data, routing, constraints, and layout
|
|
22
|
+
pressure are real.
|
|
23
|
+
3. Use a throwaway route only when no host page exists or the host page would create
|
|
24
|
+
unrelated risk.
|
|
25
|
+
4. Expose variants with a stable `?variant=` URL parameter, plus an on-screen switcher
|
|
26
|
+
or keyboard shortcut when useful for review.
|
|
27
|
+
5. Keep variant state deterministic. Reloading the same URL must show the same option.
|
|
28
|
+
|
|
29
|
+
## Variant Quality Gate
|
|
30
|
+
|
|
31
|
+
Each variant should differ in at least two structural dimensions:
|
|
32
|
+
|
|
33
|
+
- navigation or information architecture
|
|
34
|
+
- layout rhythm and density
|
|
35
|
+
- primary interaction model
|
|
36
|
+
- visual hierarchy
|
|
37
|
+
- content grouping
|
|
38
|
+
- motion or transition model
|
|
39
|
+
|
|
40
|
+
Do not count these as structural differences: theme color only, font only, card radius
|
|
41
|
+
only, copy tone only, or swapping illustration assets while keeping the same layout.
|
|
42
|
+
|
|
43
|
+
## Verification
|
|
44
|
+
|
|
45
|
+
- Capture screenshots for every variant at the relevant desktop and mobile viewport.
|
|
46
|
+
- Check text fit, overlap, scroll containment, and empty/error/loading states when
|
|
47
|
+
those states are in scope.
|
|
48
|
+
- If a variant is interactive, click through the primary path once before presenting it.
|
|
49
|
+
|
|
50
|
+
## Cleanup
|
|
51
|
+
|
|
52
|
+
After the user selects a winner, fold the winning direction into production code and
|
|
53
|
+
remove the loser variants, switcher, temporary route, and prototype-only fixtures unless
|
|
54
|
+
the user explicitly asks to keep a gallery.
|