@mindstudio-ai/remy 0.1.8 → 0.1.10

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.
Files changed (50) hide show
  1. package/dist/compiled/design.md +34 -38
  2. package/dist/compiled/media-cdn.md +2 -2
  3. package/dist/compiled/msfm.md +58 -2
  4. package/dist/compiled/platform.md +4 -2
  5. package/dist/headless.js +881 -140
  6. package/dist/index.js +1097 -298
  7. package/dist/prompt/.notes.md +138 -0
  8. package/dist/prompt/actions/buildFromInitialSpec.md +7 -0
  9. package/dist/prompt/actions/publish.md +12 -0
  10. package/dist/prompt/actions/sync.md +19 -0
  11. package/dist/prompt/compiled/README.md +100 -0
  12. package/dist/prompt/compiled/auth.md +77 -0
  13. package/dist/prompt/compiled/design.md +250 -0
  14. package/dist/prompt/compiled/dev-and-deploy.md +69 -0
  15. package/dist/prompt/compiled/interfaces.md +238 -0
  16. package/dist/prompt/compiled/manifest.md +107 -0
  17. package/dist/prompt/compiled/media-cdn.md +51 -0
  18. package/dist/prompt/compiled/methods.md +225 -0
  19. package/dist/prompt/compiled/msfm.md +189 -0
  20. package/dist/prompt/compiled/platform.md +103 -0
  21. package/dist/prompt/compiled/scenarios.md +103 -0
  22. package/dist/prompt/compiled/sdk-actions.md +146 -0
  23. package/dist/prompt/compiled/tables.md +211 -0
  24. package/dist/prompt/sources/frontend-design-notes.md +162 -0
  25. package/dist/prompt/sources/media-cdn.md +46 -0
  26. package/dist/prompt/static/authoring.md +57 -0
  27. package/dist/prompt/static/coding.md +29 -0
  28. package/dist/prompt/static/identity.md +1 -0
  29. package/dist/prompt/static/instructions.md +29 -0
  30. package/dist/prompt/static/intake.md +44 -0
  31. package/dist/prompt/static/lsp.md +4 -0
  32. package/dist/static/authoring.md +6 -2
  33. package/dist/static/instructions.md +2 -1
  34. package/dist/static/projectContext.ts +9 -4
  35. package/dist/subagents/browserAutomation/prompt.md +2 -1
  36. package/dist/subagents/designExpert/.notes.md +253 -0
  37. package/dist/subagents/designExpert/data/compile-inspiration.sh +126 -0
  38. package/dist/subagents/designExpert/data/fonts.json +2855 -0
  39. package/dist/subagents/designExpert/data/inspiration.json +540 -0
  40. package/dist/subagents/designExpert/data/inspiration.raw.json +112 -0
  41. package/dist/subagents/designExpert/prompt.md +19 -0
  42. package/dist/subagents/designExpert/prompts/animation.md +19 -0
  43. package/dist/subagents/designExpert/prompts/color.md +35 -0
  44. package/dist/subagents/designExpert/prompts/frontend-design-notes.md +162 -0
  45. package/dist/subagents/designExpert/prompts/icons.md +27 -0
  46. package/dist/subagents/designExpert/prompts/identity.md +71 -0
  47. package/dist/subagents/designExpert/prompts/images.md +50 -0
  48. package/dist/subagents/designExpert/prompts/instructions.md +16 -0
  49. package/dist/subagents/designExpert/prompts/layout.md +34 -0
  50. package/package.json +1 -1
@@ -72,11 +72,14 @@ export function loadSpecFileMetadata(): string {
72
72
 
73
73
  const entries: string[] = [];
74
74
  for (const filePath of files) {
75
- const { name, description } = parseFrontmatter(filePath);
75
+ const { name, description, type } = parseFrontmatter(filePath);
76
76
  let line = `- ${filePath}`;
77
77
  if (name) {
78
78
  line += ` — "${name}"`;
79
79
  }
80
+ if (type) {
81
+ line += ` (${type})`;
82
+ }
80
83
  if (description) {
81
84
  line += ` — ${description}`;
82
85
  }
@@ -110,20 +113,22 @@ function walkMdFiles(dir: string): string[] {
110
113
  function parseFrontmatter(filePath: string): {
111
114
  name: string;
112
115
  description: string;
116
+ type: string;
113
117
  } {
114
118
  try {
115
119
  const content = fs.readFileSync(filePath, 'utf-8');
116
120
  const match = content.match(/^---\n([\s\S]*?)\n---/);
117
121
  if (!match) {
118
- return { name: '', description: '' };
122
+ return { name: '', description: '', type: '' };
119
123
  }
120
124
 
121
125
  const fm = match[1];
122
126
  const name = fm.match(/^name:\s*(.+)$/m)?.[1]?.trim() ?? '';
123
127
  const description = fm.match(/^description:\s*(.+)$/m)?.[1]?.trim() ?? '';
124
- return { name, description };
128
+ const type = fm.match(/^type:\s*(.+)$/m)?.[1]?.trim() ?? '';
129
+ return { name, description, type };
125
130
  } catch {
126
- return { name: '', description: '' };
131
+ return { name: '', description: '', type: '' };
127
132
  }
128
133
  }
129
134
 
@@ -98,7 +98,8 @@ Check a count with evaluate:
98
98
  </rules>
99
99
 
100
100
  <voice>
101
- - No emoji, narration, or markdown.
101
+ - No emoji, narration, or markdown.
102
102
  - Your response will be read by another AI agent, so be terse. Execute, observe, report.
103
103
  - The main agent reads your final output to decide what to do next.
104
+ - Do not include element refs (ref=eN) in your results. They are session-specific and meaningless to the main agent.
104
105
  </voice>
@@ -0,0 +1,253 @@
1
+ # Design Research Agent — Design Notes & Decisions
2
+
3
+ Notes from the initial design of the design research sub-agent (March 2026).
4
+
5
+ ## Purpose
6
+
7
+ The design research agent is Remy's design consultant. Any design question or decision gets delegated here. It handles both exploratory research ("give me three visual directions for a fintech app") and directed tasks ("the spec says Midnight #000000 and Snow #F5F5F7, what gradient would work for a hero section?"). It returns concrete, actionable output — URLs, hex values, font names with CSS URLs — that Remy can interpret and use however it sees fit.
8
+
9
+ ## Scope
10
+
11
+ The agent covers five areas:
12
+
13
+ 1. **Typography** — font selection and pairings from curated sources
14
+ 2. **Color palettes** — brand color generation from seed colors, domain context, or reference sites; including modern CSS gradients
15
+ 3. **Stock photography / placeholder images** — finding relevant imagery via curated stock sites
16
+ 4. **Layout & responsive design** — research real products for layout patterns, propose interesting/non-generic compositions, optionally generate wireframe concepts via image generation. This is a major use case — Remy defaults to boring layouts without this.
17
+ 5. **Visual reference analysis** — fetch + screenshot sites, analyze them for design insights
18
+
19
+ Icons and brand SVGs are deferred for now.
20
+
21
+ ## No modes, no structured output format
22
+
23
+ The agent doesn't have separate "research mode" vs "proposal mode." The task description from Remy carries the context. Sometimes Remy asks for options to present to the user during intake; sometimes it asks for specific answers while building from a spec. The agent handles both naturally.
24
+
25
+ Output should include concrete resources (URLs, hex values, font names with CSS links) but doesn't need rigid YAML structure. Remy interprets the results.
26
+
27
+ ## Architecture: static docs, runtime-sampled data, and tools
28
+
29
+ The agent's prompt is assembled from three layers:
30
+
31
+ ### 1. Static documents (baked into prompt)
32
+
33
+ Guidelines and knowledge that don't change between invocations:
34
+
35
+ - **Gradient techniques** — what's current/dated, CSS techniques (oklch, color-mix, mesh gradients, grain overlays), reference sites
36
+ - **Animation patterns** — what's current/dated, libraries (Motion as default), performance rules
37
+ - **Color theory** — HSL rotation formulas, oklch color space, color-mix(), tint/shade derivation. No third-party API needed for palette generation.
38
+ - **Design philosophy** — distinctiveness, typography-first thinking, brand-level output, the AI defaults problem
39
+ - **Layout guidance** — what makes layouts interesting (asymmetry, creative whitespace, varied compositions), common anti-patterns to avoid. This is critical because layout is where AI-generated interfaces are weakest.
40
+ - **Visual reference analysis framework** — the consistent analysis structure (mood, color, type, layout, what's distinctive)
41
+
42
+ ### 2. Runtime-sampled JSON arrays (injected at invocation time)
43
+
44
+ Data arrays that are sampled randomly each time the agent is invoked, to prevent bias and keep results fresh:
45
+
46
+ **Design inspiration screenshots:**
47
+ - Godly website thumbnails (URLs grabbed from Chrome dev tools, stored as JSON array)
48
+ - Other gallery thumbnails (Awwwards, Figma Community, etc.) as we collect them
49
+ - Just a big array of image URLs; the prompt loader samples ~3-5 per invocation
50
+ - The agent can use `analyzeDesignReference` on these to understand what it's looking at
51
+
52
+ **Font catalog + pairings:**
53
+ - Fontshare catalog (~100 fonts with metadata: name, slug, category, weights, tags)
54
+ - Fontshare curated pairings (59 heading/body combinations with recommended weights)
55
+ - Open Foundry catalog if we compile it
56
+ - The prompt loader samples ~10-15 fonts per invocation to prevent the agent from always reaching for the same favorites
57
+ - Fonts are provided with CSS URLs: `https://api.fontshare.com/v2/css?f[]={slug}@{weights}&display=swap`
58
+ - The agent should provide a URL to a font and let Remy figure out how to load it. No need for Google Fonts-specific guidance.
59
+
60
+ **Sampling mechanism:** The prompt loader (in `index.ts` or `prompt.ts`) reads the JSON arrays at startup. Each invocation of the design research tool picks a random subset and injects them into the system prompt before passing it to `runSubAgent`. The agent sees fresh examples every time without managing randomness itself.
61
+
62
+ ### 3. Tools (live, query-dependent)
63
+
64
+ **`searchGoogle`** — general design research: font recommendations, "best finance app design 2026," real products in the user's domain
65
+
66
+ **`fetchUrl`** (with optional screenshot) — analyze reference sites, brand sites users share, font specimen pages
67
+
68
+ **`analyzeImage`** — general-purpose vision analysis. Takes a prompt and an image URL. The agent crafts the prompt based on what it needs to know ("what colors dominate this image?", "describe the typography choices", etc.)
69
+
70
+ **`analyzeDesignReference`** — specialized wrapper around `analyzeImage` with a pre-built analysis prompt. Takes just an image URL. Returns a consistent analysis: mood/aesthetic, color palette with approximate hex values, typography style, layout composition, and what makes it distinctive. Use this when analyzing screenshots for design inspiration rather than crafting a custom prompt each time.
71
+
72
+ **Stock photo search** — search Pexels, Unsplash, and Pixabay via MindStudio SDK CLI. No Google Images — too much junk/noise for design work. These are the only sources for stock photography.
73
+
74
+ **`generateImage`** (via MindStudio SDK) — for generating rough wireframe/layout concepts. TBD on prompt engineering for this.
75
+
76
+ All tools shell out to the `mindstudio` CLI. No external tool resolution needed.
77
+
78
+ ## Visual reference analysis framework
79
+
80
+ When analyzing a screenshot or design image, the agent should consistently assess:
81
+
82
+ 1. **Mood/aesthetic** — minimal, bold, editorial, playful, corporate, etc.
83
+ 2. **Color** — dominant colors with approximate hex values, palette strategy (monochromatic, complementary, etc.), use of gradients
84
+ 3. **Typography** — serif/sans/display, weight, size hierarchy, distinctive choices
85
+ 4. **Layout** — composition (symmetric/asymmetric), grid structure, whitespace usage, content density
86
+ 5. **What makes it distinctive** — the specific design choices that make this stand out from generic AI-generated interfaces
87
+
88
+ This framework is baked into the `analyzeDesignReference` tool so analyses are consistent. The general `analyzeImage` tool is available for ad-hoc questions.
89
+
90
+ ## Randomization for inspiration browsing
91
+
92
+ When searching for design inspiration via tools (not the pre-sampled arrays), the agent tends to see the same top/featured results. Strategies to vary:
93
+
94
+ - **Varied search queries** — add style adjectives and the current year ("dashboard design minimal dark 2026")
95
+ - **Pagination/offset** — browse page 3 instead of page 1
96
+ - **Domain-specific searches** — search for real products in the user's space, not generic "design inspiration"
97
+ - **Multiple sources per task** — hit 2-3 different sources with different query strategies
98
+
99
+ For layout and UX patterns, research real products in the user's domain. For aesthetic inspiration, browse design galleries with varied search terms.
100
+
101
+ ## Design philosophy notes
102
+
103
+ ### The AI defaults problem
104
+
105
+ LLMs converge on statistical medians from training data. For design this means: Inter/DM Sans/Space Grotesk fonts, purple/indigo accents, three-boxes-with-icons layouts, safe neutral palettes. The design research agent exists partly to break this pattern by forcing the model to look at real-world references and curated sources rather than generating from priors. Runtime sampling of fonts and inspiration images further prevents the agent from developing its own biases.
106
+
107
+ ### Color palettes should be UI-functional
108
+
109
+ "Pretty" palettes from generators (Coolors trending, etc.) are not necessarily good UI palettes. A UI palette needs: a background color, a readable text color on that background, an accent for interactive elements. Deriving palettes from real products or from color theory applied to brand colors produces better results than aesthetic palette generators.
110
+
111
+ ### Typography is the highest-impact decision
112
+
113
+ Font selection has more impact on perceived quality than any other single design decision. The agent should spend proportionally more effort here — looking at specimens, considering personality match, checking that the font has the weights and styles needed for a complete type hierarchy.
114
+
115
+ ### Brand-level, not implementation-level
116
+
117
+ The agent's output should be at the brand style guide level: "Midnight #000000 for dark surfaces, Snow #F5F5F7 for text." Not at the CSS variable level: "Background: #000000, BorderFocus: #3A3A3C." The coding agent (Remy) derives implementation details like accessibility contrast adjustments, dark mode palettes, and CSS variables from the brand-level output.
118
+
119
+ ### Layout is where AI is weakest
120
+
121
+ This is the primary reason the design research agent exists for layout work. Without outside input, Remy will produce the same centered-content, three-column, card-grid layouts every time. The design research agent should push for: asymmetry, varied column widths, creative negative space, unexpected compositions, full-bleed elements, strong visual hierarchy through scale contrast. Analyzing real sites (via the sampled inspiration images and live research) is the best way to inject layout creativity.
122
+
123
+ ## Modern gradients (2026)
124
+
125
+ ### What's current
126
+
127
+ **Mesh / aurora gradients** — the dominant look. Multiple layered `radial-gradient()`s with `filter: blur()` over dark backgrounds. The Stripe/Linear/Vercel aesthetic. Creates organic, atmospheric backgrounds.
128
+
129
+ **Grain/noise overlays** — SVG `feTurbulence` filters layered under gradients. Combats color banding on long subtle gradients and adds tactile warmth.
130
+
131
+ **Glassmorphism (matured)** — subtle `backdrop-filter: blur()` with gradient tints. Used sparingly as an accent, not the whole design language.
132
+
133
+ **Animated gradient blobs** — hero sections with continuously morphing gradients. CSS `@keyframes` animating `background-position` on oversized gradients for simple cases; WebGL (like Stripe's minigl) for more complex effects.
134
+
135
+ ### CSS techniques that matter
136
+
137
+ - **`oklch` color space in gradients**: `linear-gradient(to right in oklch, blue, green)` avoids the muddy gray zone that RGB/HSL produce. Perceptually uniform, vibrant transitions. Production-ready in all modern browsers. This is the single biggest upgrade for gradient quality.
138
+ - **`color-mix()`**: `color-mix(in oklch, #3b82f6 70%, white)` for generating tints/shades programmatically. Essential for design systems deriving UI colors from brand colors.
139
+ - **Relative color syntax**: `oklch(from var(--brand) calc(l * 1.25) c h)` derives lighter/darker/desaturated variants from a single token. Powerful for theme layers.
140
+ - **Stacked radial-gradients**: Multiple `radial-gradient()` layers with different positions/sizes to create mesh-like effects without canvas/WebGL.
141
+ - **Conic gradients**: Useful for pie charts, color wheels, angular shading.
142
+
143
+ ### What looks dated
144
+
145
+ - Simple two-color linear gradients (the 2018 "purple to blue" hero)
146
+ - Instagram-style gradient borders as a primary design element
147
+ - Overly saturated, uniform gradients without texture or depth
148
+ - Flat gradient cards without noise, blur, or layering
149
+
150
+ ### Reference sites
151
+
152
+ - **Stripe** — WebGL aurora gradient hero, flowing blues/purples/pinks/oranges. The gold standard.
153
+ - **Vercel** — prism/light-refraction effects, animated lines through gradients, grainy textures.
154
+ - **Linear** — dark backgrounds with precise, subtle gradient accents. Minimalist, purposeful.
155
+
156
+ ### Implications for the design research agent
157
+
158
+ The agent can recommend gradient CSS alongside color palette proposals. Modern gradients are color theory applied through `oklch` — the seed color + HSL rotation math we're already baking in produces the inputs, and the agent can suggest specific gradient techniques (mesh, grain overlay, animated blob) appropriate to the app's aesthetic. The `color-mix()` and relative color syntax are how the coding agent (Remy) derives the implementation — the design research agent just needs to know these exist when making recommendations.
159
+
160
+ ## Modern animations (2026)
161
+
162
+ ### What's current
163
+
164
+ **CSS scroll-driven animations** — the biggest shift. `animation-timeline: scroll()` and `animation-timeline: view()` tie animations to scroll position purely in CSS, running off the main thread for smooth 60fps. ~85% browser support. Replaces Intersection Observer for entrance animations.
165
+
166
+ **Scroll-triggered animations** — new in Chrome 145 (2026): time-based animations that trigger at specific scroll offsets, declaratively in CSS. No JS scroll listeners needed.
167
+
168
+ **View Transitions API** — morphing between page states with cinematic transitions. Page navigations in SPAs, expanding cards to detail views. Growing browser support.
169
+
170
+ **Spring physics** — natural-feeling motion with spring-based easing rather than cubic-bezier. Motion (Framer Motion) has this built-in.
171
+
172
+ **Purposeful micro-interactions** — subtle hover/click feedback: scaling, color shifts, depth changes. The philosophy is "guide, confirm, smooth" — not "show off."
173
+
174
+ ### Animation libraries for React
175
+
176
+ | Library | Size | Best for |
177
+ |---------|------|----------|
178
+ | CSS-native (scroll-timeline, @keyframes) | 0KB | Simple entrances, scroll effects, hover states |
179
+ | Motion (fka Framer Motion) | ~85KB | Complex state-driven animations, layout transitions, spring physics. The React default. |
180
+ | GSAP | ~78KB | Complex sequenced timelines, scroll-driven narratives, raw performance with many simultaneous tweens |
181
+
182
+ **Motion is the right default for most React app work.** Only reach for GSAP if building complex sequenced timelines.
183
+
184
+ ### Performance rules
185
+
186
+ - Only animate `transform`, `opacity`, `filter` — these skip layout and paint (GPU-composited).
187
+ - `will-change` sparingly — promotes to GPU layer but overuse causes excessive memory.
188
+ - CSS scroll-driven animations are inherently performant (off main thread).
189
+ - Never animate `width`, `height`, `top`, `left`, `margin`, `padding` — triggers layout recalculation.
190
+
191
+ ### What looks dated
192
+
193
+ - Parallax scrolling as a primary design pattern
194
+ - Manual `nth-child` stagger delays (use `sibling-index()` + `calc()` now)
195
+ - JS scroll event listeners for scroll animations
196
+ - Heavy animation libraries for simple UI toggles
197
+ - Loading spinners everywhere (skeleton screens preferred)
198
+ - Flashy transitions that don't serve UX purpose
199
+ - Bounce/elastic easing
200
+
201
+ ### Reference sites
202
+
203
+ - **Apple.com** — scroll-driven storytelling. Information fades in/out, never overwhelming.
204
+ - **Linear.app** — subtle, purposeful micro-interactions. Every motion serves the interface.
205
+ - **Vercel.com** — smooth page transitions, gradient animations, scroll-triggered reveals.
206
+ - **Stripe.com** — gradient animations double as motion design; smooth, continuous, non-distracting.
207
+
208
+ ### Implications for the design research agent
209
+
210
+ Animation guidance is mostly about restraint — "be purposeful, not decorative." The agent should recommend specific animation patterns appropriate to the app's complexity (a simple CRUD app needs entrance animations and hover states, not scroll-driven narratives). When recommending layouts that involve motion (hero sections, staggered card reveals), the agent should specify the technique (CSS scroll-timeline, Motion spring, etc.) so Remy can implement correctly.
211
+
212
+ The existing design.md animation section in the main Remy prompt covers the "what not to do" well. The design research agent adds the "what to do" with specific modern techniques.
213
+
214
+ ## Available APIs (no auth required)
215
+
216
+ | API | URL | What it does |
217
+ |---|---|---|
218
+ | Fontshare | `api.fontshare.com/v2/fonts` | Curated font catalog with metadata |
219
+ | The Color API | `thecolorapi.com` | Color schemes from seed color (analogic, complement, triad, etc.) |
220
+ | Colormind | `colormind.io/api/` | AI-generated 5-color UI palettes, lock known colors |
221
+ | theSVG.org | `thesvg.org/api/` | 4k+ brand logos with hex brand colors, 7 variants |
222
+ | SVGL | `api.svgl.app` | 300+ brand logos with light/dark variants |
223
+ | Iconify | `api.iconify.design` | 275k+ icons from Tabler, Lucide, Phosphor, etc. |
224
+
225
+ Note: Icons and brand SVG APIs are documented here for future reference but not currently wired up as tools.
226
+
227
+ ## Available via MindStudio SDK (no separate API keys needed)
228
+
229
+ | Action | What it does |
230
+ |---|---|
231
+ | Pexels search | Stock photos with avg_color field |
232
+ | Unsplash search | High-quality stock photos with color metadata |
233
+ | Pixabay search | 5.6M+ images/videos/vectors |
234
+ | Google search | General web search for design research |
235
+ | Image analysis | Vision model for analyzing screenshots |
236
+ | Image generation | For wireframe/layout concept generation |
237
+
238
+ Google Images is explicitly excluded — too much noise/junk for design work.
239
+
240
+ ## What's done
241
+
242
+ - **Font catalog** — 105 fonts (80 Fontshare + 14 Google Fonts + 11 Open Foundry) with 51 curated pairings, compiled in `data/fonts.json`. Runtime-sampled per invocation.
243
+ - **Design inspiration** — 138 Godly screenshots rehosted on MindStudio CDN, pre-analyzed via vision model, compiled in `data/inspiration.json`. Runtime-sampled per invocation. Compilation script at `data/compile-inspiration.sh`.
244
+ - **Runtime sampling** — `prompt.ts` samples 15 fonts + 5 pairings + 5 inspiration images per invocation.
245
+ - **Tools** — 7 tools: searchGoogle, fetchUrl, analyzeImage, analyzeDesignReference, screenshotAndAnalyze, searchStockPhotos, searchProductScreenshots.
246
+ - **Prompt** — split into 6 files in `prompts/`, assembled via template includes. Includes `frontend-design-notes.md` from the main prompt sources via `@src/` prefix.
247
+
248
+ ## What's not done
249
+
250
+ - **Wireframe generation** — need to figure out good prompts for `generateImage` that produce useful layout wireframe concepts
251
+ - **More inspiration sources** — currently only Godly. Could add Awwwards, Figma Community, or other galleries to the inspiration pool.
252
+ - **Open Foundry fonts without Google Fonts hosting** — 11 fonts marked "(self-host required)" have no CSS URL. Would need to host font files on CDN to make them usable.
253
+ - **Icon integration** — Iconify API and theSVG.org are documented but not wired up as tools yet. Deferred.
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Compile inspiration.raw.json → inspiration.json
4
+ #
5
+ # Reads each image URL from inspiration.raw.json, runs analyzeImage via the
6
+ # mindstudio CLI, and writes the compiled output with URL + analysis.
7
+ #
8
+ # Run manually: bash src/subagents/designResearch/data/compile-inspiration.sh
9
+ # Processes images sequentially (one API call at a time).
10
+ # Supports resuming — skips URLs already present in the output file.
11
+
12
+ set -euo pipefail
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
15
+ RAW_FILE="$SCRIPT_DIR/inspiration.raw.json"
16
+ OUT_FILE="$SCRIPT_DIR/inspiration.json"
17
+
18
+ PROMPT="Analyze this website/app screenshot as a design reference. Assess: 1) Mood/aesthetic 2) Color palette with approximate hex values and palette strategy 3) Typography style 4) Layout composition (symmetric/asymmetric, grid structure, whitespace usage, content density) 5) What makes it distinctive and interesting vs generic AI-generated interfaces. Be specific and concise."
19
+
20
+ if [ ! -f "$RAW_FILE" ]; then
21
+ echo "Error: $RAW_FILE not found"
22
+ exit 1
23
+ fi
24
+
25
+ # Initialize output file if it doesn't exist
26
+ if [ ! -f "$OUT_FILE" ]; then
27
+ echo '{"images":[]}' > "$OUT_FILE"
28
+ fi
29
+
30
+ TOTAL=$(python3 -c "import json; print(len(json.load(open('$RAW_FILE'))['images']))")
31
+ DONE=$(python3 -c "import json; print(len(json.load(open('$OUT_FILE'))['images']))")
32
+ echo "Compiling inspiration images: $DONE/$TOTAL already done"
33
+
34
+ # Get URLs that haven't been compiled yet
35
+ URLS=$(python3 -c "
36
+ import json
37
+ raw = set(json.load(open('$RAW_FILE'))['images'])
38
+ done = set(img['url'] for img in json.load(open('$OUT_FILE'))['images'])
39
+ remaining = [u for u in json.load(open('$RAW_FILE'))['images'] if u not in done]
40
+ print('\n'.join(remaining))
41
+ ")
42
+
43
+ if [ -z "$URLS" ]; then
44
+ echo "All images already compiled."
45
+ exit 0
46
+ fi
47
+
48
+ REMAINING=$(echo "$URLS" | wc -l | tr -d ' ')
49
+ echo "Processing $REMAINING remaining images (5 at a time)..."
50
+ BATCH_COUNT=0
51
+ TMPDIR=$(mktemp -d)
52
+
53
+ # Process a single URL — writes result to a temp file
54
+ process_one() {
55
+ local url="$1"
56
+ local idx="$2"
57
+ local outfile="$TMPDIR/$idx.json"
58
+
59
+ ANALYSIS=$(mindstudio analyze-image \
60
+ --prompt "$PROMPT" \
61
+ --image-url "$url" \
62
+ --output-key analysis \
63
+ --no-meta 2>&1) || true
64
+
65
+ if echo "$ANALYSIS" | grep -q '"error"'; then
66
+ echo " FAILED — $url"
67
+ return
68
+ fi
69
+
70
+ python3 -c "
71
+ import json, sys
72
+ json.dump({'url': sys.argv[1], 'analysis': sys.argv[2]}, open(sys.argv[3], 'w'))
73
+ " "$url" "$ANALYSIS" "$outfile"
74
+
75
+ echo " OK — $url"
76
+ }
77
+
78
+ # Merge all temp files from a batch into the output
79
+ merge_batch() {
80
+ python3 -c "
81
+ import json, glob, os
82
+ out = '$OUT_FILE'
83
+ tmp = '$TMPDIR'
84
+ with open(out, 'r') as f:
85
+ data = json.load(f)
86
+ for p in sorted(glob.glob(os.path.join(tmp, '*.json'))):
87
+ with open(p) as f:
88
+ data['images'].append(json.load(f))
89
+ os.remove(p)
90
+ with open(out, 'w') as f:
91
+ json.dump(data, f, indent=2)
92
+ "
93
+ }
94
+
95
+ # Process in batches of 5
96
+ BATCH=()
97
+ IDX=0
98
+ while IFS= read -r url; do
99
+ BATCH+=("$url")
100
+ IDX=$((IDX + 1))
101
+ if [ ${#BATCH[@]} -eq 5 ]; then
102
+ BATCH_COUNT=$((BATCH_COUNT + 5))
103
+ echo " Batch $BATCH_COUNT/$REMAINING"
104
+ for i in "${!BATCH[@]}"; do
105
+ process_one "${BATCH[$i]}" "$((BATCH_COUNT - 5 + i))" &
106
+ done
107
+ wait
108
+ merge_batch
109
+ BATCH=()
110
+ fi
111
+ done <<< "$URLS"
112
+
113
+ # Process remaining
114
+ if [ ${#BATCH[@]} -gt 0 ]; then
115
+ BATCH_COUNT=$((BATCH_COUNT + ${#BATCH[@]}))
116
+ echo " Batch $BATCH_COUNT/$REMAINING"
117
+ for i in "${!BATCH[@]}"; do
118
+ process_one "${BATCH[$i]}" "$((BATCH_COUNT - ${#BATCH[@]} + i))" &
119
+ done
120
+ wait
121
+ merge_batch
122
+ fi
123
+
124
+ rm -rf "$TMPDIR"
125
+ FINAL=$(python3 -c "import json; print(len(json.load(open('$OUT_FILE'))['images']))")
126
+ echo "Done. $FINAL/$TOTAL images compiled."