mirror of
https://github.com/kochetkov-ma/claude-brewcode.git
synced 2026-09-14 20:16:41 +08:00
v3.4.22: add glm-design-to-code skill
New skill: /brewcode:glm-design-to-code — GLM vision model-powered design-to-code generator with 4 input types (screenshots, text descriptions, HTML files, URLs), 3 modes (CREATE/REVIEW/FIX), 3 frameworks (HTML/CSS, React 18, Flutter Web), 3 quality profiles, dual provider support (Z.ai + OpenRouter). Includes: SKILL.md, 6 pipeline scripts, 7 reference prompts, 2 specialist agents, full docs site page with benchmarks, plugin README/commands updates, navigation integration.
This commit is contained in:
@@ -6,13 +6,13 @@
|
||||
},
|
||||
"metadata": {
|
||||
"description": "Claude Code plugin suite: brewcode for infinite task execution and brewdoc for documentation tools",
|
||||
"version": "3.4.21"
|
||||
"version": "3.4.22"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "brewcode",
|
||||
"description": "Brewcode - full-featured development platform for Claude Code: infinite focus tasks, prompt optimization, skill/agent creation, quorum reviews, rules management",
|
||||
"version": "3.4.21",
|
||||
"version": "3.4.22",
|
||||
"category": "productivity",
|
||||
"keywords": [
|
||||
"brewcode",
|
||||
@@ -46,7 +46,7 @@
|
||||
{
|
||||
"name": "brewdoc",
|
||||
"description": "Brewdoc - Claude Code documentation tools: auto-sync for skills/agents/rules, my-claude installation docs, memory optimization, md-to-pdf conversion",
|
||||
"version": "3.4.21",
|
||||
"version": "3.4.22",
|
||||
"category": "productivity",
|
||||
"keywords": [
|
||||
"brewdoc",
|
||||
@@ -74,7 +74,7 @@
|
||||
{
|
||||
"name": "brewtools",
|
||||
"description": "Brewtools - universal utilities for Claude Code: text optimization, humanization, secrets scanning",
|
||||
"version": "3.4.21",
|
||||
"version": "3.4.22",
|
||||
"category": "productivity",
|
||||
"keywords": [
|
||||
"brewtools",
|
||||
|
||||
+3
-2
@@ -18,5 +18,6 @@ web/docs/.astro/
|
||||
!**/.env.example
|
||||
logs/
|
||||
|
||||
# Data exports (may contain sensitive info)
|
||||
data/
|
||||
# Data exports and test artifacts
|
||||
data/
|
||||
*.fullpage.png
|
||||
|
||||
@@ -2,6 +2,21 @@
|
||||
|
||||
---
|
||||
|
||||
## v3.4.22 (2026-04-03)
|
||||
|
||||
### brewcode
|
||||
#### Added
|
||||
- **New skill:** `glm-design-to-code` — GLM vision model-powered design-to-code generator
|
||||
- Three modes: CREATE (any input to code: screenshots, text descriptions, HTML, URLs), REVIEW (compare original vs result), FIX (apply feedback)
|
||||
- Supports HTML/CSS, React 18, Flutter Web, custom frameworks
|
||||
- Three quality profiles: maximum (pixel-perfect), optimal (balanced), efficient (fast)
|
||||
- Dual provider support: Z.ai (direct) and OpenRouter
|
||||
- Full pipeline: argument parsing, API key setup, payload build, API request, file extraction, build, verification
|
||||
- Scripts: parse-args.sh, glm-build-request.sh, glm-build-text-request.sh, glm-request.sh, glm-extract.sh, glm-verify.sh
|
||||
- **Updated agents:** `glm-zai-specialist`, `glm-openrouter-specialist` — migrated script paths to plugin directory
|
||||
|
||||
---
|
||||
|
||||
## v3.4.21 (2026-04-03)
|
||||
|
||||
### docs
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "brewcode",
|
||||
"version": "3.4.21",
|
||||
"version": "3.4.22",
|
||||
"description": "Brewcode - full-featured development platform for Claude Code: infinite focus tasks, prompt optimization, skill/agent creation, quorum reviews, rules management",
|
||||
"author": {
|
||||
"name": "Maksim Kochetkov",
|
||||
|
||||
+2
-1
@@ -85,6 +85,7 @@ After `/brewcode:setup`, templates are adapted once. Then for each task -- the c
|
||||
| [`/brewcode:skills`](skills/skills/README.md) | Skill management and activation |
|
||||
| [`/brewcode:standards-review`](skills/standards-review/README.md) | Standards compliance review |
|
||||
| [`/brewcode:convention`](skills/convention/README.md) | Extract etalon classes, patterns, architecture into convention docs and rules |
|
||||
| [`/brewcode:glm-design-to-code`](skills/glm-design-to-code/README.md) | GLM vision design-to-code: screenshot → multi-framework code, review, fix |
|
||||
| [`/brewcode:teardown`](skills/teardown/README.md) | Plugin configuration cleanup (tasks are preserved) |
|
||||
|
||||
> **Note:** `/brewcode:review` -- local skill, created in the project during `/brewcode:setup`.
|
||||
@@ -165,6 +166,6 @@ After task creation, the following appears in the project:
|
||||
|
||||
## Version
|
||||
|
||||
**3.3.1** -- latest release.
|
||||
**3.4.22** -- latest release.
|
||||
|
||||
Author: Maksim Kochetkov | License: MIT
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
---
|
||||
name: glm-openrouter-specialist
|
||||
description: "OpenRouter API expert for GLM model routing, cost optimization, provider selection, vision requests. Triggers: 'openrouter', 'open router', 'route glm', 'openrouter api', 'glm via openrouter', 'glm provider', 'openrouter pricing'."
|
||||
model: sonnet
|
||||
color: cyan
|
||||
tools: Read, Bash, Glob, Grep, Write, Edit
|
||||
---
|
||||
|
||||
# GLM OpenRouter Specialist
|
||||
|
||||
**Role:** OpenRouter API expert for GLM vision model routing, cost optimization, and design-to-code pipeline requests.
|
||||
**Scope:** API requests, provider routing, response parsing, cost analysis.
|
||||
|
||||
## OpenRouter API
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| Endpoint | `https://openrouter.ai/api/v1/chat/completions` |
|
||||
| Auth | `Authorization: Bearer $OPENROUTER_API_KEY` |
|
||||
| Format | OpenAI-compatible chat completions |
|
||||
|
||||
### Required Headers
|
||||
|
||||
| Header | Value | Purpose |
|
||||
|--------|-------|---------|
|
||||
| `Authorization` | `Bearer $OPENROUTER_API_KEY` | Authentication |
|
||||
| `Content-Type` | `application/json` | Request format |
|
||||
|
||||
### Optional Headers
|
||||
|
||||
| Header | Value | Purpose |
|
||||
|--------|-------|---------|
|
||||
| `HTTP-Referer` | Site URL | Rankings, rate limits |
|
||||
| `X-Title` | App name | Dashboard identification |
|
||||
|
||||
## GLM Models on OpenRouter
|
||||
|
||||
| Model ID | Vision | Input $/1M | Output $/1M | Context | Use |
|
||||
|----------|--------|------------|-------------|---------|-----|
|
||||
| `z-ai/glm-5v-turbo` | image+video | $1.20 | $4.00 | 202K | Best quality vision |
|
||||
| `z-ai/glm-4.6v` | image+video | $0.30 | $0.90 | 131K | Cost-effective vision (default) |
|
||||
| `z-ai/glm-4.5-air:free` | text only | FREE | FREE | 131K | Text tasks, no vision |
|
||||
|
||||
### Model Selection
|
||||
|
||||
| Task | Model | Why |
|
||||
|------|-------|-----|
|
||||
| Design-to-code (quality) | `z-ai/glm-5v-turbo` | Best vision accuracy, largest context |
|
||||
| Design-to-code (budget) | `z-ai/glm-4.6v` | 75% cheaper, good quality |
|
||||
| Text-only generation | `z-ai/glm-4.5-air:free` | Free, no vision needed |
|
||||
| Batch processing | `z-ai/glm-4.6v` | Cost per request matters |
|
||||
|
||||
## Provider Routing
|
||||
|
||||
OpenRouter routes to backends (SiliconFlow, etc.). Control routing:
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": {
|
||||
"order": ["SiliconFlow"],
|
||||
"allow_fallbacks": true,
|
||||
"require_parameters": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Parameter | Type | Purpose |
|
||||
|-----------|------|---------|
|
||||
| `provider.order` | array | Preferred provider priority |
|
||||
| `provider.allow_fallbacks` | bool | Fall back to other providers |
|
||||
| `provider.require_parameters` | bool | Only use providers supporting all params |
|
||||
| `provider.data_collection` | `"deny"` | Opt out of training data |
|
||||
|
||||
## Request Construction
|
||||
|
||||
### Vision Request (design-to-code)
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "z-ai/glm-4.6v",
|
||||
"messages": [{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "<prompt>"},
|
||||
{"type": "image_url", "image_url": {"url": "data:<mime>;base64,<data>"}}
|
||||
]
|
||||
}],
|
||||
"max_tokens": 16384,
|
||||
"temperature": 0.1
|
||||
}
|
||||
```
|
||||
|
||||
### Text Request (free model)
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "z-ai/glm-4.5-air:free",
|
||||
"messages": [{"role": "user", "content": "<prompt>"}],
|
||||
"max_tokens": 4096
|
||||
}
|
||||
```
|
||||
|
||||
### curl Pattern
|
||||
|
||||
```bash
|
||||
curl -s -w "\n%{http_code}" \
|
||||
-X POST "https://openrouter.ai/api/v1/chat/completions" \
|
||||
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "HTTP-Referer: https://brewcode.pt" \
|
||||
-H "X-Title: brewcode-glm" \
|
||||
-d @payload.json
|
||||
```
|
||||
|
||||
## Response Parsing
|
||||
|
||||
### Extract content
|
||||
|
||||
```bash
|
||||
jq -r '.choices[0].message.content' response.json
|
||||
```
|
||||
|
||||
### Usage stats
|
||||
|
||||
```bash
|
||||
jq '{model: .model, finish: .choices[0].finish_reason, tokens: .usage}' response.json
|
||||
```
|
||||
|
||||
### Cost from response
|
||||
|
||||
OpenRouter returns cost in `usage` field:
|
||||
```bash
|
||||
jq -r '.usage | "in=\(.prompt_tokens) out=\(.completion_tokens) cost=$\(.total_cost // "N/A")"' response.json
|
||||
```
|
||||
|
||||
## Multi-File Format (===FILE:===)
|
||||
|
||||
Design-to-code responses use this format:
|
||||
|
||||
```
|
||||
===FILE: index.html===
|
||||
<html>...</html>
|
||||
===END_FILE===
|
||||
===FILE: styles.css===
|
||||
body { ... }
|
||||
===END_FILE===
|
||||
```
|
||||
|
||||
Extract with: `$BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts/glm-extract.sh <response.json> <output_dir>`
|
||||
|
||||
## Available Scripts
|
||||
|
||||
| Script | Path | Purpose |
|
||||
|--------|------|---------|
|
||||
| `glm-build-request.sh` | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts/` | Build JSON payload (image + prompt) |
|
||||
| `glm-request.sh` | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts/` | Send request (provider flag: `openrouter`) |
|
||||
| `glm-extract.sh` | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts/` | Extract ===FILE:=== from response |
|
||||
|
||||
### Usage Flow
|
||||
|
||||
```bash
|
||||
SCRIPTS="$BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts"
|
||||
|
||||
# 1. Build payload
|
||||
sh "$SCRIPTS/glm-build-request.sh" screenshot.png prompt.md "" "z-ai/glm-4.6v" 16384 > payload.json
|
||||
|
||||
# 2. Send via OpenRouter
|
||||
sh "$SCRIPTS/glm-request.sh" payload.json response.json openrouter
|
||||
|
||||
# 3. Extract files
|
||||
sh "$SCRIPTS/glm-extract.sh" response.json ./output/
|
||||
```
|
||||
|
||||
> For OpenRouter: model ID must be `z-ai/` prefixed (e.g., `z-ai/glm-4.6v` not `glm-4.6v`).
|
||||
|
||||
## Error Handling
|
||||
|
||||
| HTTP Code | Meaning | Action |
|
||||
|-----------|---------|--------|
|
||||
| 200 | Success | Parse response |
|
||||
| 400 | Bad request | Check payload format |
|
||||
| 401 | Auth failed | Verify `OPENROUTER_API_KEY` |
|
||||
| 402 | Insufficient credits | Top up account |
|
||||
| 429 | Rate limited | Wait, retry with backoff |
|
||||
| 502/503 | Provider down | Retry or force different provider |
|
||||
|
||||
### Check credits
|
||||
|
||||
```bash
|
||||
curl -s "https://openrouter.ai/api/v1/auth/key" \
|
||||
-H "Authorization: Bearer $OPENROUTER_API_KEY" | jq .
|
||||
```
|
||||
|
||||
### List available models
|
||||
|
||||
```bash
|
||||
curl -s "https://openrouter.ai/api/v1/models" | jq '.data[] | select(.id | startswith("z-ai/")) | {id, pricing, context_length}'
|
||||
```
|
||||
|
||||
## Cost Optimization
|
||||
|
||||
| Strategy | How |
|
||||
|----------|-----|
|
||||
| Use free model for text | `z-ai/glm-4.5-air:free` for non-vision |
|
||||
| Minimize input tokens | Compress prompts, resize images |
|
||||
| Lower max_tokens | Set to expected output size |
|
||||
| Batch similar requests | Reuse system prompts |
|
||||
| Monitor spend | Check `/api/v1/auth/key` for balance |
|
||||
| Temperature 0 | Deterministic, no wasted retries |
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Validate env** -- check `OPENROUTER_API_KEY` is set
|
||||
2. **Select model** -- match task to model (vision vs text, budget vs quality)
|
||||
3. **Build payload** -- use `glm-build-request.sh` or construct manually
|
||||
4. **Send request** -- use `glm-request.sh openrouter` or direct curl
|
||||
5. **Check response** -- HTTP code, finish_reason, error field
|
||||
6. **Extract content** -- parse JSON, extract ===FILE:=== if multi-file
|
||||
7. **Report cost** -- tokens used, estimated cost
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] `OPENROUTER_API_KEY` is set and valid
|
||||
- [ ] Model ID has `z-ai/` prefix
|
||||
- [ ] Vision model used for image tasks (not `glm-4.5-air:free`)
|
||||
- [ ] `max_tokens` set appropriately
|
||||
- [ ] Response checked for errors before parsing
|
||||
- [ ] ===FILE:=== format extracted correctly
|
||||
- [ ] Cost reported after request
|
||||
@@ -0,0 +1,223 @@
|
||||
---
|
||||
name: glm-zai-specialist
|
||||
description: |
|
||||
Z.ai GLM API expert — vision requests, model selection, rate limits, response parsing for design-to-code pipeline. Triggers: "zai api", "glm request", "z.ai", "send to glm", "glm vision", "glm model", "design to code api", "glm-5v", "glm-4.6v".
|
||||
|
||||
<example>
|
||||
user: "Send this screenshot to GLM for design-to-code conversion"
|
||||
<commentary>Direct GLM API request with vision input — core specialist task</commentary>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
user: "GLM is returning 429 errors, fix the request"
|
||||
<commentary>API troubleshooting with rate limit handling — specialist domain</commentary>
|
||||
</example>
|
||||
model: sonnet
|
||||
color: cyan
|
||||
tools: Read, Write, Edit, Bash, Glob, Grep
|
||||
---
|
||||
|
||||
# GLM Z.ai Specialist
|
||||
|
||||
**Role:** Z.ai GLM API expert for design-to-code pipeline.
|
||||
**Scope:** API requests, model selection, response parsing, error handling, prompt optimization.
|
||||
|
||||
## API Reference
|
||||
|
||||
### Endpoints
|
||||
|
||||
| Provider | URL | Auth | Env Var |
|
||||
|----------|-----|------|---------|
|
||||
| Z.ai (primary) | `https://api.z.ai/api/paas/v4/chat/completions` | Bearer token | `ZAI_API_KEY` |
|
||||
| OpenRouter (fallback) | `https://openrouter.ai/api/v1/chat/completions` | Bearer token | `OPENROUTER_API_KEY` |
|
||||
|
||||
> API is OpenAI-compatible (same JSON schema for messages, content array, usage).
|
||||
|
||||
### GLM Models
|
||||
|
||||
| Model | Vision | Input $/1M | Output $/1M | Context | Notes |
|
||||
|-------|--------|------------|-------------|---------|-------|
|
||||
| `glm-5v-turbo` | image+video | $1.20 | $4.00 | 202K | Target: best quality, CogViT |
|
||||
| `glm-4.6v-flash` | image | FREE | FREE | 131K | Dev/test: free vision |
|
||||
| `glm-4.7-flash` | text only | FREE | FREE | 202K | Free text model |
|
||||
| `glm-4.5-flash` | text only | FREE | FREE | 131K | Free text model |
|
||||
| `glm-4.6v` | image+video | $0.30 | $0.90 | 131K | Mid-tier vision |
|
||||
| `glm-5-turbo` | text only | $1.20 | $4.00 | 202K | Text-only flagship |
|
||||
|
||||
**Model selection:** Free dev/test -> `glm-4.6v-flash` | Production -> `glm-5v-turbo` | Budget -> `glm-4.6v`
|
||||
|
||||
### Vision Request Format
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "glm-4.6v-flash",
|
||||
"messages": [{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "<prompt>"},
|
||||
{"type": "image_url", "image_url": {"url": "data:<MIME>;base64,<B64>"}}
|
||||
]
|
||||
}],
|
||||
"max_tokens": 16384
|
||||
}
|
||||
```
|
||||
|
||||
**Image encoding:** `base64 -i image.png | tr -d '\n'` -> prepend `data:image/png;base64,`
|
||||
|
||||
| MIME | Extensions |
|
||||
|------|-----------|
|
||||
| `image/png` | .png |
|
||||
| `image/jpeg` | .jpg, .jpeg |
|
||||
| `image/webp` | .webp |
|
||||
| `image/gif` | .gif |
|
||||
|
||||
### Response Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"choices": [{
|
||||
"message": {"content": "...", "reasoning_content": "..."},
|
||||
"finish_reason": "stop"
|
||||
}],
|
||||
"usage": {
|
||||
"prompt_tokens": 4500,
|
||||
"completion_tokens": 8000,
|
||||
"completion_tokens_details": {"reasoning_tokens": 5000}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| `finish_reason` | Meaning | Action |
|
||||
|-----------------|---------|--------|
|
||||
| `stop` | Complete | Extract content |
|
||||
| `length` | Truncated | Increase `max_tokens` or split task |
|
||||
|
||||
## Pipeline Scripts
|
||||
|
||||
Scripts at `$BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts/`:
|
||||
|
||||
| Script | Purpose | Usage |
|
||||
|--------|---------|-------|
|
||||
| `glm-build-request.sh` | Build JSON payload (base64 + prompt + context) | `<image> <prompt_file> [context_file] [model] [max_tokens]` |
|
||||
| `glm-request.sh` | Send to API (retry, timeout, stats) | `<payload.json> <output.json> [provider]` |
|
||||
| `glm-extract.sh` | Extract files from response | `<response.json> <output_dir>` |
|
||||
| `glm-verify.sh` | Playwright screenshot verification | `<html_dir> [screenshot_path]` |
|
||||
|
||||
### Full Pipeline
|
||||
|
||||
```bash
|
||||
# 1. Build payload
|
||||
sh $BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts/glm-build-request.sh screenshot.png $BC_PLUGIN_ROOT/skills/glm-design-to-code/references/profile-max.md $BC_PLUGIN_ROOT/skills/glm-design-to-code/references/context-react.md glm-4.6v-flash 16384 > payload.json
|
||||
|
||||
# 2. Send request
|
||||
sh $BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts/glm-request.sh payload.json response.json zai
|
||||
|
||||
# 3. Extract files
|
||||
sh $BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts/glm-extract.sh response.json ./output/
|
||||
```
|
||||
|
||||
## Multi-File Output Format
|
||||
|
||||
GLM returns files wrapped in markers:
|
||||
|
||||
```
|
||||
===FILE: relative/path/to/file.ext===
|
||||
...file content...
|
||||
===END_FILE===
|
||||
```
|
||||
|
||||
Extraction: `glm-extract.sh` parses markers, creates directories, writes files. Falls back to single `index.html` if no markers found.
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Rate Limits (429)
|
||||
|
||||
| Scenario | Solution |
|
||||
|----------|----------|
|
||||
| Free tier 429 | Retry with exponential backoff: 5s, 10s, 20s |
|
||||
| `glm-request.sh` | Built-in `--retry 3 --retry-delay 5` |
|
||||
| Persistent 429 | Switch to paid model or wait 60s |
|
||||
|
||||
### Common Errors
|
||||
|
||||
| Error | Cause | Fix |
|
||||
|-------|-------|-----|
|
||||
| 401 Unauthorized | Invalid/missing API key | Check `ZAI_API_KEY` / `OPENROUTER_API_KEY` |
|
||||
| 429 Too Many Requests | Free tier rate limit | Retry with delay, or use paid tier |
|
||||
| 400 Bad Request | Malformed payload | Validate JSON with `jq empty payload.json` |
|
||||
| Empty content | Reasoning-only response | Check `reasoning_content` field |
|
||||
| `finish_reason: length` | Output truncated | Increase `max_tokens` (up to 131072) |
|
||||
| Image too large | Base64 payload exceeds limit | Resize image, reduce quality |
|
||||
|
||||
### Diagnostics
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
echo "=== Z.ai API Check ==="
|
||||
[ -n "${ZAI_API_KEY:-}" ] && echo "ZAI_API_KEY: set (${#ZAI_API_KEY} chars)" || echo "ZAI_API_KEY: NOT SET"
|
||||
[ -n "${OPENROUTER_API_KEY:-}" ] && echo "OPENROUTER_API_KEY: set" || echo "OPENROUTER_API_KEY: NOT SET"
|
||||
command -v jq >/dev/null && echo "jq: $(jq --version)" || echo "jq: NOT FOUND"
|
||||
command -v base64 >/dev/null && echo "base64: available" || echo "base64: NOT FOUND"
|
||||
ls -la $BC_PLUGIN_ROOT/skills/glm-design-to-code/scripts/*.sh 2>/dev/null && echo "Scripts: found" || echo "Scripts: NOT FOUND"
|
||||
```
|
||||
|
||||
## Prompt Templates
|
||||
|
||||
| Template | Path | Purpose |
|
||||
|----------|------|---------|
|
||||
| profile-max | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/references/profile-max.md` | Pixel-perfect generation (max quality) |
|
||||
| profile-optimal | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/references/profile-optimal.md` | Balanced generation |
|
||||
| profile-efficient | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/references/profile-efficient.md` | Fast generation (fewer tokens) |
|
||||
| review | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/references/review.md` | Compare screenshot vs original |
|
||||
| context-react | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/references/context-react.md` | React project context |
|
||||
| context-flutter | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/references/context-flutter.md` | Flutter project context |
|
||||
| context-template | `$BC_PLUGIN_ROOT/skills/glm-design-to-code/references/context-template.md` | Custom project context template |
|
||||
|
||||
## Workflow
|
||||
|
||||
### Send Vision Request
|
||||
|
||||
1. Validate prerequisites (API key, jq, base64, scripts)
|
||||
2. Identify model: free dev (`glm-4.6v-flash`) or production (`glm-5v-turbo`)
|
||||
3. Build payload via `glm-build-request.sh` or construct manually with `jq`
|
||||
4. Send via `glm-request.sh` — check HTTP status, usage stats
|
||||
5. Parse response — extract `choices[0].message.content`
|
||||
6. If multi-file: extract via `glm-extract.sh`
|
||||
7. Report: model, tokens, cost, extracted files
|
||||
|
||||
### Troubleshoot API Issues
|
||||
|
||||
1. Run diagnostics (env vars, tools, scripts)
|
||||
2. Validate payload: `jq empty payload.json`
|
||||
3. Check response: `jq '.error // .choices[0].finish_reason' response.json`
|
||||
4. If 429: retry with delay or switch provider
|
||||
5. If truncated: increase `max_tokens`, check `finish_reason`
|
||||
|
||||
### Optimize Request
|
||||
|
||||
| Optimization | Technique |
|
||||
|-------------|-----------|
|
||||
| Reduce input tokens | Resize image (1024px max side), compress JPEG |
|
||||
| Reduce output tokens | Limit scope in prompt ("only CSS changes") |
|
||||
| Use cached input | Repeated context -> $0.24/1M (5x cheaper on Z.ai) |
|
||||
| Model downgrade | `glm-4.6v-flash` (free) for iteration, `glm-5v-turbo` for final |
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] API key set (`ZAI_API_KEY` or `OPENROUTER_API_KEY`)
|
||||
- [ ] Dependencies available (jq, base64, curl)
|
||||
- [ ] Model matches task (vision model for images)
|
||||
- [ ] Payload is valid JSON (`jq empty`)
|
||||
- [ ] Response has content (not reasoning-only)
|
||||
- [ ] `finish_reason` is `stop` (not `length`)
|
||||
- [ ] Files extracted if multi-file format used
|
||||
|
||||
## Scope
|
||||
|
||||
| In | Out |
|
||||
|----|-----|
|
||||
| Z.ai/OpenRouter API requests | Prompt engineering (-> developer) |
|
||||
| Model selection, pricing | HTML/CSS quality review (-> reviewer) |
|
||||
| Error handling, rate limits | Playwright verification (-> tester) |
|
||||
| Response parsing, file extraction | Pipeline orchestration (-> bc-coordinator) |
|
||||
| Base64 encoding, payload construction | Design analysis (-> architect) |
|
||||
+242
-1
@@ -7,7 +7,7 @@ description: Detailed description of all brewcode plugin commands
|
||||
|
||||
# Brewcode Plugin Commands
|
||||
|
||||
> **Version:** 3.1.0 | **Author:** Maksim Kochetkov | **License:** MIT
|
||||
> **Version:** 3.4.22 | **Author:** Maksim Kochetkov | **License:** MIT
|
||||
|
||||
## Quick Reference
|
||||
|
||||
@@ -27,6 +27,10 @@ description: Detailed description of all brewcode plugin commands
|
||||
| 13 | `/brewcode:skills` | Skill management and activation | session | sonnet | -- |
|
||||
| 14 | `/brewcode:standards-review` | Standards compliance review | fork | opus | setup |
|
||||
| 15 | `/brewcode:agents` | Interactive agent creation and improvement | session | opus | -- |
|
||||
| 16 | `/brewcode:convention` | Extract project conventions, patterns, architecture into rules + docs | session | opus | -- |
|
||||
| 17 | `/brewcode:teams` | Create and manage specialized agent teams | session | opus | -- |
|
||||
| 18 | `/brewcode:e2e` | E2E testing orchestration: BDD scenarios, autotests, review | session | opus | setup (e2e agents) |
|
||||
| 19 | `/brewcode:glm-design-to-code` | GLM vision design-to-code generator | session | opus | -- |
|
||||
|
||||
## Recommended Execution Order
|
||||
|
||||
@@ -712,6 +716,243 @@ Does not use subagents.
|
||||
|
||||
---
|
||||
|
||||
## 10. `/brewcode:convention`
|
||||
|
||||
**Purpose:** Analyzes project to extract etalon classes, patterns, and architecture by layer. Generates convention documents in `.claude/convention/` and organizes rules in `.claude/rules/`.
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| **Arguments** | `[full\|conventions\|rules\|paths <p1,p2>]` |
|
||||
| **Context** | `session` |
|
||||
| **Model** | `opus` |
|
||||
| **Dependencies** | None |
|
||||
| **Allowed tools** | `Read`, `Write`, `Edit`, `Glob`, `Grep`, `Bash`, `Task`, `AskUserQuestion`, `Skill` |
|
||||
|
||||
### Modes
|
||||
|
||||
| Mode | Invocation | Description |
|
||||
|------|-----------|-------------|
|
||||
| `full` (default) | `/brewcode:convention` | Full analysis: detect stack, analyze layers, select etalons, generate docs, extract rules |
|
||||
| `conventions` | `/brewcode:convention conventions` | Generate convention docs only (skip rules) |
|
||||
| `rules` | `/brewcode:convention rules` | Extract rules from existing `.claude/convention/` docs |
|
||||
| `paths` | `/brewcode:convention paths src/a,src/b` | Scoped analysis on specified paths |
|
||||
|
||||
### Generated Documents
|
||||
|
||||
| Document | Content |
|
||||
|----------|---------|
|
||||
| `.claude/convention/reference-patterns.md` | Main code layers: etalons, patterns, anti-patterns (~300 lines) |
|
||||
| `.claude/convention/testing-conventions.md` | Test layers: test etalons, assertion conventions (~150 lines) |
|
||||
| `.claude/convention/project-architecture.md` | Build, deps, codegen, migrations (~200 lines) |
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **P0: Stack Detection** -- detect languages, frameworks, modules via scripts
|
||||
2. **P1: Load Layers** -- filter analysis layers by detected stack
|
||||
3. **P2: Parallel Analysis** -- 10 agents (architect + tester) analyze layers in ONE message
|
||||
4. **P3: Etalon Selection** -- 1 architect selects 1-2 etalons per layer
|
||||
5. **P4: Document Generation** -- 3 developer agents write convention docs in parallel
|
||||
6. **P5: Text Optimization** -- text-optimizer (if brewtools installed) or fallback
|
||||
7. **P6: User Review** -- approve, revise (max 2 iterations), or skip to rules
|
||||
8. **P7: Rules Organization** -- extract rules, deduplicate, interactive batching, bc-rules-organizer
|
||||
9. **P8: Summary** -- output etalon table + metrics
|
||||
|
||||
### Usage Example
|
||||
|
||||
```
|
||||
/brewcode:convention
|
||||
/brewcode:convention rules
|
||||
/brewcode:convention paths src/main,src/test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. `/brewcode:teams`
|
||||
|
||||
**Purpose:** Creates and manages dynamic teams of domain-specific agents with tracking framework. Analyzes project, proposes team (5-20 agents), creates with self-selection protocol and performance tracking.
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| **Arguments** | `[create [name] [prompt]\|update [name]\|status [name]\|cleanup [name]]` |
|
||||
| **Context** | `session` |
|
||||
| **Model** | `opus` |
|
||||
| **Dependencies** | None |
|
||||
| **Allowed tools** | `Read`, `Write`, `Edit`, `Glob`, `Grep`, `Bash`, `Task`, `AskUserQuestion`, `Skill` |
|
||||
|
||||
### Modes
|
||||
|
||||
| Mode | Description |
|
||||
|------|-------------|
|
||||
| `create` | Analyze project, propose 3 variants (5/10-12/15-20 agents), create with agent-creator |
|
||||
| `update` | Self-reflection: analyze trace data, tune/replace underperformers |
|
||||
| `status` | Read-only health report: per-agent stats, success rates, recommendations |
|
||||
| `cleanup` | Archive trace data, remove inactive agents |
|
||||
|
||||
### Created Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `.claude/teams/{name}/team.md` | Team roster with agent domains and missions |
|
||||
| `.claude/teams/{name}/trace.jsonl` | Session-scoped tracking data |
|
||||
| `.claude/agents/{agent}.md` | Individual agent files (via agent-creator) |
|
||||
|
||||
### Usage Example
|
||||
|
||||
```
|
||||
/brewcode:teams create backend
|
||||
/brewcode:teams status backend
|
||||
/brewcode:teams update backend
|
||||
/brewcode:teams cleanup backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. `/brewcode:e2e`
|
||||
|
||||
**Purpose:** Full-cycle E2E testing orchestration: setup testing agents, create BDD scenarios, write autotests, quorum review. Stack-agnostic with layered test architecture.
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| **Arguments** | `[setup\|create\|update\|review\|rules\|status] [prompt]` |
|
||||
| **Context** | `session` |
|
||||
| **Model** | `opus` |
|
||||
| **Dependencies** | `/brewcode:setup` (for non-setup modes: e2e agents must exist) |
|
||||
| **Allowed tools** | `Read`, `Write`, `Edit`, `Glob`, `Grep`, `Bash`, `Task`, `AskUserQuestion`, `Skill`, `WebSearch`, `WebFetch` |
|
||||
|
||||
### Modes
|
||||
|
||||
| Mode | Description |
|
||||
|------|-------------|
|
||||
| `setup` | Create 5 runtime e2e agents via agent-creator, configure test infrastructure |
|
||||
| `create` | Generate BDD scenarios with YAML frontmatter, write autotests |
|
||||
| `update` | Update existing scenarios and tests based on changes |
|
||||
| `review` | Quorum review (3 reviewers, 2/3 consensus), MAX_CYCLES=3 |
|
||||
| `rules` | Extract e2e-specific rules from accumulated knowledge |
|
||||
| `status` | Report on e2e infrastructure, agents, and test coverage |
|
||||
|
||||
### Review Cycle
|
||||
|
||||
MAX_CYCLES=3: execute -> reviewer validates -> different agent re-checks -> fix confirmed -> repeat.
|
||||
|
||||
### Usage Example
|
||||
|
||||
```
|
||||
/brewcode:e2e setup
|
||||
/brewcode:e2e create "Login flow with OAuth"
|
||||
/brewcode:e2e review
|
||||
/brewcode:e2e status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. `/brewcode:glm-design-to-code`
|
||||
|
||||
**Purpose:** Converts designs to working frontend code using GLM-5V-Turbo vision model. Accepts 4 input types: image, text description, HTML file, or URL. Three modes: CREATE (generate code), REVIEW (evaluate quality), FIX (iterate based on feedback). Supports HTML/CSS, React 18, Flutter, or custom frameworks. Powered by Z.ai GLM-5V-Turbo (94.8 Design2Code benchmark) or OpenRouter routing.
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| **Arguments** | `[input] [--framework html\|react\|flutter\|custom] [--profile max\|optimal\|efficient] [--provider zai\|openrouter] [--model MODEL_ID] [--output dir] [--review original.png result.png] [--fix 'feedback'] [--fix --review-file review.json]` |
|
||||
| **Context** | `session` |
|
||||
| **Model** | `opus` |
|
||||
| **Dependencies** | None (API key for Z.ai or OpenRouter required) |
|
||||
| **Allowed tools** | `Read`, `Write`, `Edit`, `Glob`, `Grep`, `Bash`, `AskUserQuestion` |
|
||||
|
||||
### Input Types
|
||||
|
||||
| Type | Example | Description |
|
||||
|------|---------|-------------|
|
||||
| Image | `screenshot.png` | PNG/JPG/WebP/GIF screenshot or design mockup |
|
||||
| Text | `"Dark landing page with hero"` | Natural language description of the desired UI |
|
||||
| HTML | `existing-page.html` | Convert or improve existing HTML code |
|
||||
| URL | `https://example.com` | Takes a Playwright screenshot first, then converts |
|
||||
|
||||
Input type is auto-detected from the argument.
|
||||
|
||||
### Modes
|
||||
|
||||
| Mode | Trigger | Description |
|
||||
|------|---------|-------------|
|
||||
| **CREATE** | `screenshot.png` / `"text"` / `page.html` / `https://...` | Generates code from any supported input (main workflow) |
|
||||
| **REVIEW** | `--review original.png result.png` | Compares generated code screenshot against original design, scores quality (10-point scale) |
|
||||
| **FIX** | `--fix 'feedback text'` | Uses review feedback to improve code iteratively (fix -> re-screenshot -> re-review cycle) |
|
||||
|
||||
### Flags
|
||||
|
||||
| Flag | Default | Options | Purpose |
|
||||
|------|---------|---------|---------|
|
||||
| `--framework` | html | html, react, flutter, custom | Output code format |
|
||||
| `--profile` | max | max, optimal, efficient | Quality vs speed tradeoff |
|
||||
| `--provider` | zai | zai, openrouter | Which API to use |
|
||||
| `--model` | (auto) | glm-5v-turbo, glm-4.6v | Override model selection |
|
||||
| `--output` | `./d2c-output` | Any directory path | Where to save generated files |
|
||||
| `--review` | -- | `original.png result.png` | Enter REVIEW mode with two images |
|
||||
| `--fix` | -- | `'feedback text'` | Enter FIX mode with feedback |
|
||||
| `--review-file` | -- | Path to review JSON | Use saved review as fix input |
|
||||
|
||||
### Profiles
|
||||
|
||||
| Profile | max_tokens | Quality | Speed | Best for |
|
||||
|---------|-----------|---------|-------|----------|
|
||||
| **max** | 32,768 | Pixel-perfect, all details | 30-60s | Complex UIs, high-fidelity design systems |
|
||||
| **optimal** | 16,384 | Good quality, most details | 15-30s | Production code, balanced approach |
|
||||
| **efficient** | 8,192 | Acceptable, basic structure | 5-15s | Quick prototypes, MVP code |
|
||||
|
||||
### Framework Output
|
||||
|
||||
| Framework | Generated Files |
|
||||
|-----------|----------------|
|
||||
| **html** | `index.html`, `styles.css`, `script.js` (optional) |
|
||||
| **react** | `package.json`, `src/App.jsx`, `src/components/`, `src/styles/` (Vite project) |
|
||||
| **flutter** | `pubspec.yaml`, `lib/main.dart`, `lib/screens/`, `lib/widgets/` |
|
||||
| **custom** | User-guided output structure |
|
||||
|
||||
### Providers
|
||||
|
||||
| Provider | Model ID | Free Tier | Pricing |
|
||||
|----------|----------|-----------|---------|
|
||||
| **Z.ai** (recommended) | `glm-5v-turbo` | ~20M tokens | $1.20/1M in, $4.00/1M out |
|
||||
| **OpenRouter** | `z-ai/glm-5v-turbo` | No | Same as Z.ai |
|
||||
|
||||
API key: set `ZAI_API_KEY` (Z.ai) or `OPENROUTER_API_KEY` (OpenRouter) environment variable.
|
||||
|
||||
### Workflow (CREATE)
|
||||
|
||||
1. **Phase 0: Parse Arguments** -- detect mode, validate image, confirm settings
|
||||
2. **Phase 0.5: API Key Setup** -- check/request API key (first-time only)
|
||||
3. **Phase 1: Validate Prerequisites** -- check tools (jq, curl, base64), API key, scripts
|
||||
4. **Phase 2: Build and Send Request** -- select prompt profile, build payload, call GLM API
|
||||
5. **Phase 3: Extract and Build** -- extract files from response, run framework build
|
||||
6. **Phase 4: Verify** -- serve locally, take Playwright screenshot
|
||||
7. **Phase 5: Review** -- compare original vs generated (if --review flag)
|
||||
|
||||
### Agents
|
||||
|
||||
Does not use subagents. Work is performed within skill session context using GLM vision API.
|
||||
|
||||
### Usage Example
|
||||
|
||||
```
|
||||
# Image input
|
||||
/brewcode:glm-design-to-code mockup.png
|
||||
/brewcode:glm-design-to-code design.png --framework react --profile optimal
|
||||
|
||||
# Text description input
|
||||
/brewcode:glm-design-to-code "Dark landing page with hero section and pricing cards"
|
||||
|
||||
# HTML file input
|
||||
/brewcode:glm-design-to-code legacy-page.html --framework react
|
||||
|
||||
# URL input (auto-screenshots via Playwright)
|
||||
/brewcode:glm-design-to-code https://example.com/landing
|
||||
|
||||
# Review and fix
|
||||
/brewcode:glm-design-to-code --review original.png generated.png
|
||||
/brewcode:glm-design-to-code --fix "button should be blue not red, spacing too loose"
|
||||
/brewcode:glm-design-to-code design.png --framework flutter --profile max --provider zai
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hooks Architecture
|
||||
|
||||
All commands operate within hooks-only architecture -- no external runtime. Claude Code hooks provide context management.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-plugin-brewcode",
|
||||
"version": "3.4.21",
|
||||
"version": "3.4.22",
|
||||
"description": "Infinite task execution with automatic handoff for Claude Code",
|
||||
"keywords": [
|
||||
"claude-code",
|
||||
@@ -36,6 +36,6 @@
|
||||
},
|
||||
"claude-plugin": {
|
||||
"name": "brewcode",
|
||||
"version": "3.4.21"
|
||||
"version": "3.4.22"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
---
|
||||
auto-sync: enabled
|
||||
auto-sync-date: 2026-04-03
|
||||
auto-sync-type: doc
|
||||
---
|
||||
|
||||
# GLM Design-to-Code
|
||||
|
||||
Converts designs to working frontend code using GLM-5V-Turbo vision model. Accepts 4 input types: **image**, **text description**, **HTML file**, or **URL**. Three modes: **CREATE** (generate code), **REVIEW** (evaluate quality), **FIX** (iterate based on feedback). Supports HTML/CSS, React 18, Flutter, or custom frameworks. Powered by Z.ai GLM-5V-Turbo (94.8 Design2Code benchmark) or OpenRouter routing.
|
||||
|
||||
## Input Types
|
||||
|
||||
| Type | Example | Description |
|
||||
|------|---------|-------------|
|
||||
| Image | `screenshot.png` | PNG/JPG/WebP/GIF screenshot or design mockup |
|
||||
| Text | `"Dark landing page with hero section"` | Natural language description of the desired UI |
|
||||
| HTML | `existing-page.html` | Convert or improve existing HTML code |
|
||||
| URL | `https://example.com` | Takes a Playwright screenshot first, then converts |
|
||||
|
||||
Input type is **auto-detected** from the argument: file extension for images/HTML, URL pattern for URLs, quoted text or unrecognized input for text descriptions.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# From an image (most common)
|
||||
/brewcode:glm-design-to-code screenshot.png
|
||||
|
||||
# From a text description
|
||||
/brewcode:glm-design-to-code "Dark landing page with hero section and pricing cards"
|
||||
|
||||
# From an existing HTML file
|
||||
/brewcode:glm-design-to-code existing-page.html
|
||||
|
||||
# From a URL (auto-screenshots via Playwright)
|
||||
/brewcode:glm-design-to-code https://example.com/landing
|
||||
```
|
||||
|
||||
CREATE mode converts your input to working, buildable code. You choose the framework (HTML, React, Flutter) and quality profile (max = pixel-perfect, optimal = balanced, efficient = fast).
|
||||
|
||||
## Modes
|
||||
|
||||
| Mode | Trigger | What it does |
|
||||
|------|---------|--------------|
|
||||
| **CREATE** | `screenshot.png` | Generates code from a design mockup (the main workflow) |
|
||||
| **REVIEW** | `--review original.png result.png` | Compares generated code (screenshot) against original design, scores quality (10-point scale), identifies gaps |
|
||||
| **FIX** | `--fix 'sidebar too narrow, wrong color'` | Uses review feedback to improve code iteratively (fix → re-screenshot → re-review cycle) |
|
||||
|
||||
**Auto-detect:** Running `/brewcode:glm-design-to-code` alone will ask you to choose a mode.
|
||||
|
||||
## Examples
|
||||
|
||||
### Good Usage
|
||||
|
||||
```bash
|
||||
# Image input -- convert a Figma screenshot to HTML
|
||||
/brewcode:glm-design-to-code mockup.png
|
||||
|
||||
# Text input -- describe the UI you want
|
||||
/brewcode:glm-design-to-code "Minimalist dashboard with sidebar navigation and dark theme"
|
||||
|
||||
# HTML input -- improve existing code
|
||||
/brewcode:glm-design-to-code legacy-page.html --framework react
|
||||
|
||||
# URL input -- clone a live page
|
||||
/brewcode:glm-design-to-code https://stripe.com/pricing --framework html
|
||||
|
||||
# Generate React component with optimal quality (balanced speed/quality)
|
||||
/brewcode:glm-design-to-code design.png --framework react --profile optimal
|
||||
|
||||
# Review the generated code for pixel-perfectness
|
||||
/brewcode:glm-design-to-code --review original.png generated.png
|
||||
|
||||
# Fix issues found in review
|
||||
/brewcode:glm-design-to-code --fix "button should be blue not red, spacing too loose"
|
||||
|
||||
# Use Flutter and Z.ai with max quality
|
||||
/brewcode:glm-design-to-code design.png --framework flutter --profile max --provider zai
|
||||
|
||||
# Full CREATE → REVIEW → FIX cycle
|
||||
/brewcode:glm-design-to-code design.png
|
||||
# ... generates code, optionally takes screenshot
|
||||
/brewcode:glm-design-to-code --review original.png result.png
|
||||
# ... review shows issues, you get feedback
|
||||
/brewcode:glm-design-to-code --fix "fix the issues mentioned"
|
||||
```
|
||||
|
||||
### Common Mistakes
|
||||
|
||||
```bash
|
||||
# WRONG: Providing a Figma URL (requires authentication, use exported PNG)
|
||||
/brewcode:glm-design-to-code https://figma.com/design/abc...
|
||||
# FIX: Export the design as PNG first, or use a public URL
|
||||
|
||||
# WRONG: Using --fix without prior REVIEW
|
||||
/brewcode:glm-design-to-code --fix "looks wrong"
|
||||
# FIX: Run REVIEW mode first to get actionable feedback
|
||||
|
||||
# WRONG: Specifying a framework the model doesn't know well
|
||||
/brewcode:glm-design-to-code design.png --framework svelte
|
||||
# FIX: Use html, react, flutter, or custom. For other frameworks, use --framework custom
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### Core Arguments
|
||||
|
||||
| Argument | Default | Options | Purpose |
|
||||
|----------|---------|---------|---------|
|
||||
| `input` | (required) | Image path, HTML path, URL, or text description | Input (type auto-detected) |
|
||||
| `--framework` | html | html, react, flutter, custom | Output code format |
|
||||
| `--profile` | max | max, optimal, efficient | Quality vs speed tradeoff |
|
||||
| `--provider` | zai | zai, openrouter | Which API to use |
|
||||
| `--output` | `./d2c-output` | Any directory path | Where to save generated files |
|
||||
| `--model` | (auto) | glm-5v-turbo, glm-4.6v | Override model selection |
|
||||
|
||||
### Mode-Specific Arguments
|
||||
|
||||
| Mode | Arguments | Purpose |
|
||||
|------|-----------|---------|
|
||||
| CREATE | (none) | Default behavior |
|
||||
| REVIEW | `--review original.png result.png` | Compare two images and score quality |
|
||||
| FIX | `--fix 'feedback text'` OR `--fix --review-file review.json` | Apply changes and regenerate |
|
||||
|
||||
## Profiles
|
||||
|
||||
| Profile | max_tokens | Quality | Speed | Cost | Best for |
|
||||
|---------|-----------|---------|-------|------|----------|
|
||||
| **max** | 32,768 | Pixel-perfect, all details | 30-60s | $0.05-0.08 | Complex UIs, high-fidelity design systems |
|
||||
| **optimal** | 16,384 | Good quality, most details | 15-30s | $0.03-0.05 | Production code, balanced approach |
|
||||
| **efficient** | 8,192 | Acceptable, basic structure | 5-15s | $0.01-0.03 | Quick prototypes, MVP code |
|
||||
|
||||
## Output
|
||||
|
||||
After CREATE completes, the following is created in `--output` directory (default: `./d2c-output`):
|
||||
|
||||
**HTML Mode:**
|
||||
- `index.html` (240+ lines) – Semantic HTML5 structure
|
||||
- `styles.css` (400+ lines) – Complete styling with CSS custom properties
|
||||
- `script.js` (optional) – Interactive elements
|
||||
|
||||
**React Mode:**
|
||||
- `package.json` – Vite project config
|
||||
- `src/App.jsx` – Root component
|
||||
- `src/components/` – Reusable UI components (Header, Sidebar, Button, etc.)
|
||||
- `src/styles/` – CSS Modules or Tailwind
|
||||
- Build verified with `npm run build` (Vite)
|
||||
|
||||
**Flutter Mode:**
|
||||
- `pubspec.yaml` – Flutter dependencies
|
||||
- `lib/main.dart` – Entry point
|
||||
- `lib/screens/` – Page-level widgets
|
||||
- `lib/widgets/` – Reusable components
|
||||
- Build verified with `flutter run`
|
||||
|
||||
## Providers & Pricing
|
||||
|
||||
### Z.ai (Direct)
|
||||
|
||||
**Recommended.** Zhipu AI's Z.ai API with GLM-5V-Turbo.
|
||||
|
||||
- **Registration:** z.ai (Google/email signup, no phone required)
|
||||
- **Free tier:** ~20M tokens (~3 months of usage)
|
||||
- **Pricing:** $1.20/1M input, $4.00/1M output, $0.24/1M cached input
|
||||
- **Model:** `glm-5v-turbo` (128K context, 131K max output)
|
||||
- **Benchmark:** Design2Code 94.8 (highest quality)
|
||||
- **Typical cost per request:** $0.03–0.08 depending on profile
|
||||
|
||||
Set `ZAI_API_KEY` environment variable:
|
||||
```bash
|
||||
export ZAI_API_KEY="your-z-ai-api-key"
|
||||
# Or save to .claude/.env or ~/.zshrc
|
||||
```
|
||||
|
||||
### OpenRouter (Proxy)
|
||||
|
||||
Alternative routing option. Same GLM models, same pricing, no free tier.
|
||||
|
||||
- **Registration:** openrouter.ai
|
||||
- **Pricing:** Same as Z.ai ($1.20/$4.00)
|
||||
- **Model ID on OpenRouter:** `z-ai/glm-5v-turbo`
|
||||
- **Advantage:** Unified API for multiple model providers
|
||||
- **Disadvantage:** 1-2s latency overhead vs direct Z.ai
|
||||
|
||||
Set `OPENROUTER_API_KEY` environment variable:
|
||||
```bash
|
||||
export OPENROUTER_API_KEY="your-openrouter-key"
|
||||
```
|
||||
|
||||
## Tips
|
||||
|
||||
- **Before CREATE:** Have a clear design mockup. Screenshots from Figma, Adobe XD, or Sketch work best.
|
||||
- **Use REVIEW early:** After CREATE, always run REVIEW to spot quality issues before iterating.
|
||||
- **FIX iteratively:** Each FIX cycle should address 2-3 specific issues. More iterations = better results.
|
||||
- **Choose framework wisely:**
|
||||
- **HTML** = Simple, static sites, fastest (no build)
|
||||
- **React** = Complex apps, component reuse, state management
|
||||
- **Flutter** = Cross-platform mobile/web, native feel
|
||||
- **Custom** = Any other framework (you guide the prompt)
|
||||
- **For high-fidelity designs:** Use `--profile max` for pixel-perfect output.
|
||||
- **For quick prototypes:** Use `--profile efficient` to save time and cost.
|
||||
- **Cache prompts:** Z.ai's cached input ($0.24/1M) is 5x cheaper than regular input. Repeated prompts automatically cache.
|
||||
@@ -0,0 +1,645 @@
|
||||
---
|
||||
name: brewcode:glm-design-to-code
|
||||
description: |
|
||||
GLM vision model-powered design-to-code generator. Three modes: CREATE, REVIEW, FIX. Accepts ANY input: screenshots, text descriptions, HTML files, URLs.
|
||||
Triggers: "glm design to code", "design to code", "screenshot to code", "mockup to code", "d2c", "generate frontend"
|
||||
|
||||
<example>
|
||||
user: "/brewcode:glm-design-to-code screenshot.png"
|
||||
<commentary>CREATE mode with image input</commentary>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
user: "/brewcode:glm-design-to-code 'Dark landing page with hero section and pricing table'"
|
||||
<commentary>CREATE mode with text description</commentary>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
user: "/brewcode:glm-design-to-code https://example.com/page"
|
||||
<commentary>CREATE mode with URL — takes Playwright screenshot first</commentary>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
user: "/brewcode:glm-design-to-code existing-page.html --framework react"
|
||||
<commentary>CREATE mode with HTML file — converts to React components</commentary>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
user: "/brewcode:glm-design-to-code --review original.png result.png"
|
||||
<commentary>REVIEW mode - compare original design with generated code screenshot</commentary>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
user: "/brewcode:glm-design-to-code --fix 'sidebar too narrow, wrong green color'"
|
||||
<commentary>FIX mode - apply review feedback to improve generated code</commentary>
|
||||
</example>
|
||||
disable-model-invocation: true
|
||||
user-invocable: true
|
||||
argument-hint: "[input] [--framework html|react|flutter|custom] [--profile max|optimal|efficient] [--provider zai|openrouter] [--model MODEL_ID] [--output dir] [--review original.png result.png] [--fix 'feedback'] [--fix --review-file review.json]"
|
||||
allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion]
|
||||
model: opus
|
||||
---
|
||||
|
||||
<instructions>
|
||||
|
||||
# GLM Design-to-Code
|
||||
|
||||
Converts design inputs (screenshots, text descriptions, HTML files, URLs) to working frontend code using GLM vision models. Three modes: CREATE, REVIEW, FIX.
|
||||
|
||||
**Arguments:** `$ARGUMENTS`
|
||||
|
||||
## Mode Routing
|
||||
|
||||
| Mode | Flow |
|
||||
|------|------|
|
||||
| CREATE | Phase 0 → 0.5 → 1 → 2 → 3 → 4 → 5 (if --review) |
|
||||
| REVIEW | Phase 0 → 0.5 → 1 → 5 |
|
||||
| FIX | Phase 0 → 0.5 → 1 → 6 |
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Parse Arguments and Gather Config
|
||||
|
||||
### Step 1: Parse Flags
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
bash "${CLAUDE_SKILL_DIR}/scripts/parse-args.sh" "$ARGUMENTS" && echo "OK" || echo "FAILED"
|
||||
```
|
||||
|
||||
Output: key=value pairs. Store all values.
|
||||
|
||||
| Key | Default | Options |
|
||||
|-----|---------|---------|
|
||||
| `IMAGE` | (required) | Path to screenshot file, URL, HTML file, or text description |
|
||||
| `INPUT_TYPE` | auto | image, html, text, url |
|
||||
| `FRAMEWORK` | html | html, react, flutter, custom |
|
||||
| `PROFILE` | max | max, optimal, efficient |
|
||||
| `PROVIDER` | zai | zai, openrouter |
|
||||
| `OUTPUT` | `./d2c-output` | Output directory |
|
||||
| `REVIEW` | false | true/false |
|
||||
| `MODE` | create | create, review, fix |
|
||||
| `FIX_TEXT` | (empty) | Text from --fix "..." |
|
||||
| `REVIEW_FILE` | (empty) | Path from --review-file |
|
||||
| `MODEL` | (empty) | Model override from --model |
|
||||
|
||||
> **STOP if FAILED** -- check parse-args.sh.
|
||||
|
||||
### Step 1.5: Detect Mode
|
||||
|
||||
| Condition | Mode |
|
||||
|-----------|------|
|
||||
| `--fix` flag present | FIX |
|
||||
| `--review` flag present | REVIEW |
|
||||
| Otherwise | CREATE |
|
||||
|
||||
### Step 2: Process Input by Type
|
||||
|
||||
Based on `INPUT_TYPE` from parse-args.sh:
|
||||
|
||||
#### If INPUT_TYPE=image
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
IMAGE="IMAGE_PATH_HERE"
|
||||
[ -f "$IMAGE" ] && file --mime-type "$IMAGE" | grep -qE ': image/' && echo "VALID_IMAGE" || echo "INVALID"
|
||||
```
|
||||
> **If INVALID:** AskUserQuestion for correct path.
|
||||
|
||||
#### If INPUT_TYPE=url
|
||||
Take a Playwright screenshot of the URL first:
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
URL="URL_HERE"
|
||||
npx playwright screenshot --full-page "$URL" /tmp/d2c-url-screenshot.png 2>&1 && echo "SCREENSHOT_OK" || echo "SCREENSHOT_FAILED"
|
||||
```
|
||||
> **If SCREENSHOT_OK:** Set IMAGE=/tmp/d2c-url-screenshot.png and continue as image input.
|
||||
> **If SCREENSHOT_FAILED:** Try using Playwright MCP browser_navigate + browser_take_screenshot. If still fails, AskUserQuestion for alternative input.
|
||||
|
||||
#### If INPUT_TYPE=html
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
HTML_FILE="HTML_PATH_HERE"
|
||||
[ -f "$HTML_FILE" ] && echo "HTML_VALID ($(wc -l < "$HTML_FILE" | tr -d ' ') lines)" || echo "HTML_MISSING"
|
||||
```
|
||||
> **If HTML_VALID:** Will use glm-build-text-request.sh in Phase 2 instead of glm-build-request.sh.
|
||||
|
||||
#### If INPUT_TYPE=text
|
||||
The description text is in the IMAGE field. No validation needed -- will use glm-build-text-request.sh in Phase 2.
|
||||
|
||||
### Step 3: Confirm Settings (if no flags provided)
|
||||
|
||||
If IMAGE was the only argument (no flags), **ASK** using AskUserQuestion:
|
||||
|
||||
```
|
||||
Design-to-Code Configuration:
|
||||
|
||||
Screenshot: {IMAGE}
|
||||
Framework: html (HTML/CSS), react (React 18 + CSS Modules), flutter (Flutter Web), custom
|
||||
Profile: max (pixel-perfect), optimal (balanced), efficient (fast)
|
||||
Provider: zai (Z.ai direct), openrouter (OpenRouter proxy)
|
||||
Output: ./d2c-output
|
||||
|
||||
Accept defaults or specify changes?
|
||||
```
|
||||
|
||||
Options: "Accept defaults" | "Change settings"
|
||||
|
||||
If "Change settings" -- ask follow-up for each setting.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0.5: API Key Setup (first-time only)
|
||||
|
||||
### Step 1: Check API Key
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
[ -f .claude/.env ] && . .claude/.env
|
||||
PROVIDER="PROVIDER_HERE"
|
||||
if [ "$PROVIDER" = "zai" ]; then
|
||||
[ -n "$ZAI_API_KEY" ] && echo "KEY_SET" || echo "KEY_MISSING"
|
||||
elif [ "$PROVIDER" = "openrouter" ]; then
|
||||
[ -n "$OPENROUTER_API_KEY" ] && echo "KEY_SET" || echo "KEY_MISSING"
|
||||
fi
|
||||
```
|
||||
|
||||
> **If KEY_SET** — skip to Phase 1.
|
||||
|
||||
### Step 2: Ask for API Key (if KEY_MISSING)
|
||||
|
||||
**ASK** using AskUserQuestion:
|
||||
```
|
||||
API key required for {PROVIDER}. Choose:
|
||||
```
|
||||
Options:
|
||||
- "Z.ai API key (for GLM models)"
|
||||
- "OpenRouter API key (any model)"
|
||||
|
||||
Store the key value provided by user.
|
||||
|
||||
### Step 3: Validate Key
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
# First set the env var (replace USER_KEY_HERE with actual key from user)
|
||||
export ZAI_API_KEY="USER_KEY_HERE"
|
||||
|
||||
# Then validate (key referenced via env var, not inline)
|
||||
PROVIDER="PROVIDER_HERE"
|
||||
if [ "$PROVIDER" = "zai" ]; then
|
||||
URL="https://api.z.ai/api/paas/v4/chat/completions"
|
||||
MODEL="glm-4.6v-flash"
|
||||
else
|
||||
URL="https://openrouter.ai/api/v1/chat/completions"
|
||||
MODEL="z-ai/glm-4.5-air:free"
|
||||
fi
|
||||
HTTP=$(curl -s -w "%{http_code}" -o /tmp/d2c-key-test.json \
|
||||
--max-time 10 \
|
||||
-X POST "$URL" \
|
||||
-H "Authorization: Bearer ${ZAI_API_KEY:-$OPENROUTER_API_KEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"model\":\"$MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"test\"}],\"max_tokens\":5}")
|
||||
[ "$HTTP" -ge 200 ] && [ "$HTTP" -lt 300 ] && echo "KEY_VALID" || echo "KEY_INVALID (HTTP $HTTP)"
|
||||
```
|
||||
|
||||
> **If KEY_INVALID:** AskUserQuestion to re-enter key. Max 2 retries.
|
||||
|
||||
### Step 4: Save Key (AskUserQuestion)
|
||||
|
||||
**ASK** using AskUserQuestion:
|
||||
```
|
||||
API key validated. Where to save?
|
||||
```
|
||||
Options:
|
||||
- "Save to .claude/.env (project-local, recommended)"
|
||||
- "Save to ~/.zshrc (system-wide)"
|
||||
- "Don't save (session only)"
|
||||
|
||||
For .claude/.env: append `export {VAR}={KEY}` to `.claude/.env`, then verify it is gitignored:
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
grep -q '.claude/.env' .gitignore 2>/dev/null || echo '.claude/.env' >> .gitignore
|
||||
```
|
||||
|
||||
For ~/.zshrc: append `export {VAR}={KEY}` to `~/.zshrc`
|
||||
For session only: use `export {VAR}={KEY}` in Bash for current session.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Validate Prerequisites
|
||||
|
||||
### Step 1: Check Tools and API Keys
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
PROVIDER="PROVIDER_HERE"
|
||||
echo "=== Tools ==="
|
||||
command -v jq && echo "jq OK" || echo "jq MISSING"
|
||||
command -v curl && echo "curl OK" || echo "curl MISSING"
|
||||
command -v base64 && echo "base64 OK" || echo "base64 MISSING"
|
||||
echo "=== API Key ==="
|
||||
if [ "$PROVIDER" = "zai" ]; then
|
||||
[ -n "$ZAI_API_KEY" ] && echo "ZAI_API_KEY SET" || echo "ZAI_API_KEY MISSING"
|
||||
elif [ "$PROVIDER" = "openrouter" ]; then
|
||||
[ -n "$OPENROUTER_API_KEY" ] && echo "OPENROUTER_API_KEY SET" || echo "OPENROUTER_API_KEY MISSING"
|
||||
fi
|
||||
echo "=== Framework Tools ==="
|
||||
command -v node && echo "node $(node -v)" || echo "node MISSING"
|
||||
command -v npx && echo "npx OK" || echo "npx MISSING"
|
||||
command -v flutter && echo "flutter OK" || echo "flutter MISSING (only needed for flutter framework)"
|
||||
```
|
||||
|
||||
> **STOP if jq, curl, or API key MISSING** -- tell user what to install/set.
|
||||
|
||||
### Step 2: Resolve Scripts Path
|
||||
|
||||
All pipeline scripts are at `${CLAUDE_SKILL_DIR}/scripts/`. Verify they exist:
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
SD="${CLAUDE_SKILL_DIR}/scripts"
|
||||
for s in glm-build-request.sh glm-build-text-request.sh glm-request.sh glm-extract.sh glm-verify.sh; do
|
||||
[ -f "$SD/$s" ] && echo "$s OK" || echo "$s MISSING"
|
||||
done
|
||||
```
|
||||
|
||||
> **STOP if any MISSING** -- re-install plugin.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Build and Send Request
|
||||
|
||||
### Step 1: Select Prompt and Context Files
|
||||
|
||||
| Framework | Prompt | Context |
|
||||
|-----------|--------|---------|
|
||||
| html | `references/profile-{PROFILE}.md` | (none) |
|
||||
| react | `references/profile-{PROFILE}.md` | `references/context-react.md` |
|
||||
| flutter | `references/profile-{PROFILE}.md` | `references/context-flutter.md` |
|
||||
| custom | `references/profile-{PROFILE}.md` | User-provided or `references/context-template.md` |
|
||||
|
||||
Read the prompt file to confirm it exists:
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
PROMPT="${CLAUDE_SKILL_DIR}/references/profile-PROFILE_HERE.md"
|
||||
[ -f "$PROMPT" ] && echo "PROMPT OK: $PROMPT" || echo "PROMPT MISSING"
|
||||
```
|
||||
|
||||
For custom framework: **ASK** user to describe their stack. Write to `/tmp/d2c-custom-context.md` using `context-template.md` as template.
|
||||
|
||||
### Step 2: Resolve Model ID
|
||||
|
||||
| Provider | Model ID |
|
||||
|----------|----------|
|
||||
| zai | `glm-5v-turbo` |
|
||||
| openrouter | `z-ai/glm-5v-turbo` |
|
||||
|
||||
### Step 3: Build Request Payload
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
SD="${CLAUDE_SKILL_DIR}/scripts"
|
||||
PROMPT="${CLAUDE_SKILL_DIR}/references/profile-PROFILE_HERE.md"
|
||||
CONTEXT="CONTEXT_PATH_OR_EMPTY"
|
||||
IMAGE="IMAGE_PATH_HERE"
|
||||
MODEL="MODEL_ID_HERE"
|
||||
|
||||
bash "$SD/glm-build-request.sh" "$IMAGE" "$PROMPT" "$CONTEXT" "$MODEL" 32768 0.2 0.85 > /tmp/d2c-payload.json && echo "PAYLOAD OK ($(wc -c < /tmp/d2c-payload.json | tr -d ' ') bytes)" || echo "PAYLOAD FAILED"
|
||||
```
|
||||
|
||||
Replace all placeholders with actual values.
|
||||
|
||||
**For INPUT_TYPE=html or INPUT_TYPE=text:**
|
||||
```bash
|
||||
SD="${CLAUDE_SKILL_DIR}/scripts"
|
||||
PROMPT="${CLAUDE_SKILL_DIR}/references/profile-PROFILE_HERE.md"
|
||||
CONTEXT="CONTEXT_PATH_OR_EMPTY"
|
||||
INPUT="INPUT_VALUE_HERE"
|
||||
MODEL="MODEL_ID_HERE"
|
||||
|
||||
bash "$SD/glm-build-text-request.sh" "$INPUT" "$PROMPT" "$CONTEXT" "$MODEL" 32768 0.2 0.85 > /tmp/d2c-payload.json && echo "PAYLOAD OK ($(wc -c < /tmp/d2c-payload.json | tr -d ' ') bytes)" || echo "PAYLOAD FAILED"
|
||||
```
|
||||
|
||||
> For text input, INPUT is the description string. For HTML input, INPUT is the file path.
|
||||
> Note: text-only requests can use non-vision models (glm-4.7-flash, glm-5-turbo) which may be cheaper.
|
||||
|
||||
> **STOP if FAILED** -- check image path, prompt file.
|
||||
|
||||
### Step 4: Send to API
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
SD="${CLAUDE_SKILL_DIR}/scripts"
|
||||
bash "$SD/glm-request.sh" /tmp/d2c-payload.json /tmp/d2c-response.json PROVIDER_HERE && echo "API OK" || echo "API FAILED"
|
||||
```
|
||||
|
||||
> **STOP if FAILED** -- check API key, network, provider.
|
||||
|
||||
**Check for truncation:**
|
||||
```bash
|
||||
FINISH=$(jq -r '.choices[0].finish_reason' /tmp/d2c-response.json)
|
||||
[ "$FINISH" = "stop" ] && echo "COMPLETE" || echo "WARNING: finish_reason=$FINISH (may be truncated)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Extract and Build
|
||||
|
||||
### Step 1: Extract Files
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
SD="${CLAUDE_SKILL_DIR}/scripts"
|
||||
OUTPUT="OUTPUT_DIR_HERE"
|
||||
mkdir -p "$OUTPUT"
|
||||
bash "$SD/glm-extract.sh" /tmp/d2c-response.json "$OUTPUT" && echo "EXTRACT OK" || echo "EXTRACT FAILED"
|
||||
```
|
||||
|
||||
> **STOP if FAILED** -- check response content.
|
||||
|
||||
### Step 2: List Extracted Files
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
OUTPUT="OUTPUT_DIR_HERE"
|
||||
echo "=== Extracted Files ==="
|
||||
find "$OUTPUT" -type f | head -50 | while read -r f; do
|
||||
echo " $(echo "$f" | sed "s|$OUTPUT/||") ($(wc -l < "$f" | tr -d ' ') lines)"
|
||||
done
|
||||
echo "=== Total ==="
|
||||
find "$OUTPUT" -type f | wc -l | tr -d ' '
|
||||
```
|
||||
|
||||
### Step 3: Build (framework-specific)
|
||||
|
||||
**React:**
|
||||
```bash
|
||||
OUTPUT="OUTPUT_DIR_HERE"
|
||||
cd "$OUTPUT" && npm install 2>&1 | tail -5 && npx vite build 2>&1 | tail -10 && echo "BUILD OK" || echo "BUILD FAILED"
|
||||
```
|
||||
|
||||
**Flutter:**
|
||||
```bash
|
||||
OUTPUT="OUTPUT_DIR_HERE"
|
||||
cd "$OUTPUT" && flutter pub get 2>&1 | tail -5 && flutter build web 2>&1 | tail -10 && echo "BUILD OK" || echo "BUILD FAILED"
|
||||
```
|
||||
|
||||
**HTML:** No build step needed.
|
||||
|
||||
> **If BUILD FAILED:** Read error output. Common fixes:
|
||||
> - React: missing dependencies in package.json, JSX syntax errors
|
||||
> - Flutter: missing pubspec.yaml deps, Dart syntax errors
|
||||
> Apply fixes using Edit tool, then retry build (max 3 attempts).
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Verify (Optional)
|
||||
|
||||
### Step 1: Serve and Screenshot
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
SD="${CLAUDE_SKILL_DIR}/scripts"
|
||||
OUTPUT="OUTPUT_DIR_HERE"
|
||||
bash "$SD/glm-verify.sh" "$OUTPUT" 8900
|
||||
```
|
||||
|
||||
This outputs a URL. Take a screenshot using Playwright:
|
||||
|
||||
```bash
|
||||
npx playwright screenshot --full-page http://localhost:8900/ /tmp/d2c-result-screenshot.png && echo "SCREENSHOT OK" || echo "SCREENSHOT FAILED"
|
||||
```
|
||||
|
||||
### Step 2: Cleanup Server
|
||||
|
||||
```bash
|
||||
kill $(lsof -ti :8900) 2>/dev/null; echo "SERVER STOPPED"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Review (if --review flag or user requests)
|
||||
|
||||
Send both original design and generated screenshot to GLM for automated comparison.
|
||||
|
||||
### Step 1: Build Review Request
|
||||
|
||||
The review requires sending TWO images. Build a custom payload:
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
SD="${CLAUDE_SKILL_DIR}/scripts"
|
||||
REVIEW_PROMPT="${CLAUDE_SKILL_DIR}/references/review.md"
|
||||
ORIGINAL="IMAGE_PATH_HERE"
|
||||
RESULT="/tmp/d2c-result-screenshot.png"
|
||||
MODEL="MODEL_ID_HERE"
|
||||
|
||||
[ -f "$ORIGINAL" ] && [ -f "$RESULT" ] && [ -f "$REVIEW_PROMPT" ] && echo "REVIEW INPUTS OK" || echo "REVIEW INPUTS MISSING"
|
||||
```
|
||||
|
||||
Build review payload manually (two images in user message):
|
||||
|
||||
```bash
|
||||
REVIEW_PROMPT="${CLAUDE_SKILL_DIR}/references/review.md"
|
||||
ORIGINAL="IMAGE_PATH_HERE"
|
||||
RESULT="/tmp/d2c-result-screenshot.png"
|
||||
MODEL="MODEL_ID_HERE"
|
||||
|
||||
SYSTEM=$(cat "$REVIEW_PROMPT")
|
||||
|
||||
# Base64 encode both images
|
||||
if base64 --help 2>&1 | grep -q '\-w'; then
|
||||
B64_ORIG=$(base64 -w0 "$ORIGINAL")
|
||||
B64_RESULT=$(base64 -w0 "$RESULT")
|
||||
else
|
||||
B64_ORIG=$(base64 -i "$ORIGINAL" | tr -d '\n')
|
||||
B64_RESULT=$(base64 -i "$RESULT" | tr -d '\n')
|
||||
fi
|
||||
|
||||
# Detect MIME types
|
||||
case "$ORIGINAL" in *.png) M1="image/png";; *.jpg|*.jpeg) M1="image/jpeg";; *) M1="image/png";; esac
|
||||
M2="image/png"
|
||||
|
||||
jq -n \
|
||||
--arg model "$MODEL" \
|
||||
--arg system "$SYSTEM" \
|
||||
--arg uri1 "data:${M1};base64,${B64_ORIG}" \
|
||||
--arg uri2 "data:${M2};base64,${B64_RESULT}" \
|
||||
'{
|
||||
model: $model,
|
||||
temperature: 0.2,
|
||||
top_p: 0.85,
|
||||
max_tokens: 4096,
|
||||
messages: [
|
||||
{ role: "system", content: $system },
|
||||
{ role: "user", content: [
|
||||
{ type: "text", text: "Image 1 (original design):" },
|
||||
{ type: "image_url", image_url: { url: $uri1 } },
|
||||
{ type: "text", text: "Image 2 (generated code screenshot):" },
|
||||
{ type: "image_url", image_url: { url: $uri2 } }
|
||||
]}
|
||||
]
|
||||
}' > /tmp/d2c-review-payload.json && echo "REVIEW PAYLOAD OK" || echo "REVIEW PAYLOAD FAILED"
|
||||
```
|
||||
|
||||
### Step 2: Send Review
|
||||
|
||||
```bash
|
||||
SD="${CLAUDE_SKILL_DIR}/scripts"
|
||||
bash "$SD/glm-request.sh" /tmp/d2c-review-payload.json /tmp/d2c-review-response.json PROVIDER_HERE && echo "REVIEW OK" || echo "REVIEW FAILED"
|
||||
```
|
||||
|
||||
### Step 3: Extract Review
|
||||
|
||||
```bash
|
||||
REVIEW=$(jq -r '.choices[0].message.content' /tmp/d2c-review-response.json)
|
||||
echo "$REVIEW"
|
||||
```
|
||||
|
||||
Parse score from `score: N/10` line in the review output.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Fix Mode (if MODE=FIX)
|
||||
|
||||
> Skip Phases 2-5. Go directly here if MODE=FIX.
|
||||
|
||||
### Step 1: Gather Fix Context
|
||||
|
||||
Read fix feedback from:
|
||||
- `--fix "text"` argument → use text directly
|
||||
- `--fix --review-file path` → read review JSON from file
|
||||
- No explicit feedback → look for `/tmp/d2c-review-response.json` from previous review
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
# Check for previous review
|
||||
[ -f "/tmp/d2c-review-response.json" ] && echo "PREV_REVIEW EXISTS" || echo "NO_PREV_REVIEW"
|
||||
```
|
||||
|
||||
If no feedback source found: **ASK** using AskUserQuestion what to fix.
|
||||
|
||||
### Step 2: Read Existing Code
|
||||
|
||||
**EXECUTE** using Bash tool:
|
||||
```bash
|
||||
OUTPUT="OUTPUT_DIR_HERE"
|
||||
echo "=== Current Files ==="
|
||||
find "$OUTPUT" -type f -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.jsx' -o -name '*.dart' | head -20 | while read -r f; do
|
||||
echo "--- $f ($(wc -l < "$f" | tr -d ' ') lines) ---"
|
||||
done
|
||||
```
|
||||
|
||||
Read each file using the Read tool.
|
||||
|
||||
### Step 3: Apply Fixes
|
||||
|
||||
Based on feedback, use the Edit tool to make targeted changes to the generated code files.
|
||||
|
||||
Common fixes:
|
||||
- Color corrections → update CSS custom properties
|
||||
- Spacing/sizing → update CSS values
|
||||
- Layout issues → restructure HTML/CSS
|
||||
- Missing elements → add to relevant files
|
||||
|
||||
### Step 4: Re-verify (if Playwright available)
|
||||
|
||||
Follow Phase 4 steps to serve, screenshot, and compare.
|
||||
|
||||
### Step 5: Report Changes
|
||||
|
||||
```markdown
|
||||
## Fix Applied
|
||||
|
||||
| File | Changes |
|
||||
|------|---------|
|
||||
| `{file}` | `{description}` |
|
||||
|
||||
## Verification
|
||||
- Screenshot: `{path or N/A}`
|
||||
- Previous score: `{N}/10`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Condition | Action |
|
||||
|-----------|--------|
|
||||
| Image not found | AskUserQuestion for correct path |
|
||||
| API key missing | "Set `ZAI_API_KEY` or `OPENROUTER_API_KEY` env var." STOP |
|
||||
| API returns error | Show error, suggest retry or switch provider |
|
||||
| Response truncated | Warn user, suggest `efficient` profile for smaller output |
|
||||
| Build fails | Read errors, attempt fix (max 3), report remaining issues |
|
||||
| Playwright not available | Skip screenshot, report URL for manual check |
|
||||
|
||||
---
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- **Model:** `glm-5v-turbo` (Z.ai) / `z-ai/glm-5v-turbo` (OpenRouter)
|
||||
- **Context window:** 128K tokens
|
||||
- **Thinking mode:** NOT supported on glm-5v-turbo -- never send thinking parameters
|
||||
- **System message split:** Prompt (profile) goes to system role, context + image go to user role
|
||||
- **API params:** `temperature: 0.2`, `top_p: 0.85`, `max_tokens: 32768`
|
||||
- **File markers:** `===FILE: path===` ... `===END_FILE===`
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
```markdown
|
||||
# GLM Design-to-Code
|
||||
|
||||
## Configuration
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Screenshot | `{IMAGE}` |
|
||||
| Framework | `{FRAMEWORK}` |
|
||||
| Profile | `{PROFILE}` |
|
||||
| Provider | `{PROVIDER}` |
|
||||
| Model | `{MODEL_ID}` |
|
||||
| Output | `{OUTPUT}` |
|
||||
|
||||
## API Response
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Finish reason | `{stop/length}` |
|
||||
| Input tokens | `{N}` |
|
||||
| Output tokens | `{N}` |
|
||||
|
||||
## Extracted Files
|
||||
|
||||
| File | Lines |
|
||||
|------|-------|
|
||||
| `{path}` | `{N}` |
|
||||
|
||||
## Build
|
||||
|
||||
| Step | Status |
|
||||
|------|--------|
|
||||
| Install | {OK/FAILED/N/A} |
|
||||
| Build | {OK/FAILED/N/A} |
|
||||
|
||||
## Review (if requested)
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Score | `{N}/10` |
|
||||
| Summary | `{one-line}` |
|
||||
|
||||
### Differences
|
||||
- {list}
|
||||
|
||||
### Suggestions
|
||||
- {list}
|
||||
|
||||
## Next Steps
|
||||
- {recommendations}
|
||||
```
|
||||
|
||||
</instructions>
|
||||
@@ -0,0 +1,30 @@
|
||||
## Project context
|
||||
|
||||
### Stack
|
||||
- Framework: Flutter 3.x
|
||||
- Language: Dart
|
||||
- Target: Web (flutter build web)
|
||||
|
||||
### File structure convention
|
||||
- Entry point: lib/main.dart
|
||||
- Widgets in separate files: lib/widgets/widget_name.dart
|
||||
- Theme in: lib/theme.dart
|
||||
- Main page: lib/pages/home_page.dart
|
||||
|
||||
### Component structure
|
||||
Each widget should be a separate file:
|
||||
- lib/widgets/header.dart
|
||||
- lib/widgets/sidebar.dart
|
||||
- lib/widgets/main_content.dart
|
||||
- lib/widgets/step_item.dart
|
||||
- lib/widgets/info_box.dart
|
||||
- etc.
|
||||
|
||||
### Additional rules
|
||||
- Use StatelessWidget for layout components
|
||||
- Define all colors and text styles in lib/theme.dart as static constants
|
||||
- Use Column, Row, Expanded, Container, Padding for layout
|
||||
- Use SingleChildScrollView for scrollable content
|
||||
- Use Google Fonts or system font (no custom font files)
|
||||
- pubspec.yaml must include flutter SDK dependency
|
||||
- All styles inline via Flutter widget properties (Flutter does not use CSS)
|
||||
@@ -0,0 +1,25 @@
|
||||
## Project context
|
||||
|
||||
### Stack
|
||||
- Framework: React 18 with JSX
|
||||
- CSS approach: CSS Modules (.module.css files)
|
||||
- Language: JavaScript (not TypeScript)
|
||||
|
||||
### File structure convention
|
||||
- Components in separate files: ComponentName.jsx + ComponentName.module.css
|
||||
- Entry point: index.html that loads main.jsx via <script type="module">
|
||||
- Use ES modules (import/export)
|
||||
|
||||
### Component structure
|
||||
Each component should be a separate file pair:
|
||||
- Header.jsx + Header.module.css
|
||||
- Sidebar.jsx + Sidebar.module.css
|
||||
- MainContent.jsx + MainContent.module.css
|
||||
- etc.
|
||||
|
||||
### Additional rules
|
||||
- Use React.createElement or JSX (assume Babel/build step will handle JSX)
|
||||
- Export each component as default
|
||||
- Import CSS modules as `import styles from './Component.module.css'`
|
||||
- Use className={styles.className} pattern
|
||||
- App.jsx is the root component that composes all others
|
||||
@@ -0,0 +1,18 @@
|
||||
## Project context
|
||||
|
||||
### Stack
|
||||
- Framework: {{FRAMEWORK}}
|
||||
- CSS approach: {{CSS_APPROACH}}
|
||||
- Language: {{LANGUAGE}}
|
||||
|
||||
### Existing components (reuse these, do NOT recreate)
|
||||
{{COMPONENTS_LIST}}
|
||||
|
||||
### Design tokens
|
||||
{{DESIGN_TOKENS}}
|
||||
|
||||
### File structure convention
|
||||
{{FILE_STRUCTURE}}
|
||||
|
||||
### Additional rules
|
||||
{{PROJECT_RULES}}
|
||||
@@ -0,0 +1,21 @@
|
||||
Convert this design screenshot to working HTML/CSS code.
|
||||
|
||||
## Output format
|
||||
|
||||
Wrap every file in markers. Output markers and file content only — no text before, between, or after.
|
||||
|
||||
===FILE: path/file.ext===
|
||||
content
|
||||
===END_FILE===
|
||||
|
||||
Wrong (adds backticks): ```html\n===FILE: index.html===
|
||||
Correct: ===FILE: index.html===
|
||||
|
||||
## Requirements
|
||||
|
||||
- Match design: colors, layout, typography
|
||||
- Semantic HTML5, entry: index.html, CSS in separate .css file
|
||||
- CDN excluded, inline styles excluded
|
||||
- All visible text content preserved
|
||||
|
||||
Output starts with ===FILE: and ends with ===END_FILE===. Nothing else.
|
||||
@@ -0,0 +1,30 @@
|
||||
You are a world-class frontend developer creating pixel-perfect reproductions of design mockups.
|
||||
|
||||
## Output format
|
||||
|
||||
Wrap every file in markers. Output markers and file content only — no text before, between, or after.
|
||||
|
||||
===FILE: path/to/file.ext===
|
||||
content
|
||||
===END_FILE===
|
||||
|
||||
Wrong (adds backticks): ```html\n===FILE: index.html===
|
||||
Correct: ===FILE: index.html===
|
||||
|
||||
## Requirements
|
||||
|
||||
- Pixel-perfect: exact colors (eyedropper precision), exact spacing ratios, exact font sizes, exact border-radius values
|
||||
- Measure every element from screenshot: header height, sidebar width, margins, section padding
|
||||
- CSS custom properties for all colors, spacing, and typography extracted from the design
|
||||
- Semantic HTML5, entry point: index.html
|
||||
- CSS in separate .css file(s) — inline styles and `<style>` tags excluded
|
||||
- JS in separate .js file(s) for interactive elements
|
||||
- CDN dependencies excluded unless specified in project context
|
||||
- All text content preserved verbatim — URLs, table data, code snippets, descriptions intact
|
||||
- Exact layout proportions: sidebar-to-content ratio, header height, section spacing
|
||||
- All visual details reproduced: icons, badges, borders, shadows, gradients, hover states
|
||||
- Code blocks use monospace font matching exact background color from design
|
||||
- Tables match exact column widths and cell padding
|
||||
- Info/alert boxes match exact background color, border color, icon style, border-radius
|
||||
|
||||
Output starts with ===FILE: and ends with ===END_FILE===. Nothing else.
|
||||
@@ -0,0 +1,25 @@
|
||||
You are a skilled frontend developer converting design mockups to production code.
|
||||
|
||||
## Output format
|
||||
|
||||
Wrap every file in markers. Output markers and file content only — no text before, between, or after.
|
||||
|
||||
===FILE: path/to/file.ext===
|
||||
content
|
||||
===END_FILE===
|
||||
|
||||
Wrong (adds backticks): ```html\n===FILE: index.html===
|
||||
Correct: ===FILE: index.html===
|
||||
|
||||
## Requirements
|
||||
|
||||
- Match design: correct colors, proportions, typography, layout structure
|
||||
- CSS custom properties for colors
|
||||
- Semantic HTML5, entry point: index.html
|
||||
- CSS in separate .css file(s) — inline styles excluded
|
||||
- JS in separate .js file(s) if needed
|
||||
- CDN dependencies excluded unless specified in project context
|
||||
- All text content from screenshot preserved verbatim
|
||||
- Layout structure and proportions matched (sidebar, header, content areas)
|
||||
|
||||
Output starts with ===FILE: and ends with ===END_FILE===. Nothing else.
|
||||
@@ -0,0 +1,16 @@
|
||||
Compare two images:
|
||||
1. FIRST image: original design mockup
|
||||
2. SECOND image: screenshot of generated code rendered in a browser
|
||||
|
||||
Rate visual fidelity 1-10 and list specific differences.
|
||||
|
||||
===REVIEW===
|
||||
score: N/10
|
||||
summary: one-line summary
|
||||
|
||||
differences:
|
||||
- [area] description of mismatch
|
||||
|
||||
suggestions:
|
||||
- specific fix suggestion
|
||||
===END_REVIEW===
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/bin/sh
|
||||
# glm-build-request.sh — Build JSON request payload for GLM vision API
|
||||
# Usage: glm-build-request.sh <image_path> <prompt_file> [context_file] [model] [max_tokens] [temperature] [top_p]
|
||||
# Output: JSON payload to stdout
|
||||
# Requires: jq, base64
|
||||
# Prompt file is used as SYSTEM message (cached by Z.ai). Context is appended to USER message with the image.
|
||||
|
||||
set -e
|
||||
|
||||
IMAGE_PATH="${1:?Usage: glm-build-request.sh <image> <prompt> [context] [model] [max_tokens] [temp] [top_p]}"
|
||||
PROMPT_FILE="${2:?Usage: glm-build-request.sh <image> <prompt> [context] [model] [max_tokens] [temp] [top_p]}"
|
||||
CONTEXT_FILE="${3:-}"
|
||||
MODEL="${4:-glm-5v-turbo}"
|
||||
MAX_TOKENS="${5:-32768}"
|
||||
TEMPERATURE="${6:-0.2}"
|
||||
TOP_P="${7:-0.85}"
|
||||
|
||||
command -v jq >/dev/null 2>&1 || { echo "ERROR: jq is required" >&2; exit 1; }
|
||||
command -v base64 >/dev/null 2>&1 || { echo "ERROR: base64 is required" >&2; exit 1; }
|
||||
|
||||
[ -f "$IMAGE_PATH" ] || { echo "ERROR: Image not found: $IMAGE_PATH" >&2; exit 1; }
|
||||
[ -f "$PROMPT_FILE" ] || { echo "ERROR: Prompt not found: $PROMPT_FILE" >&2; exit 1; }
|
||||
|
||||
case "$IMAGE_PATH" in
|
||||
*.png) MIME="image/png" ;;
|
||||
*.jpg|*.jpeg) MIME="image/jpeg" ;;
|
||||
*.webp) MIME="image/webp" ;;
|
||||
*.gif) MIME="image/gif" ;;
|
||||
*) echo "ERROR: Unsupported image format: $IMAGE_PATH" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
SYSTEM_TEXT=$(cat "$PROMPT_FILE")
|
||||
|
||||
USER_TEXT="Convert this design screenshot to working code files."
|
||||
if [ -n "$CONTEXT_FILE" ] && [ -f "$CONTEXT_FILE" ]; then
|
||||
CONTEXT_TEXT=$(cat "$CONTEXT_FILE")
|
||||
USER_TEXT="${USER_TEXT}
|
||||
|
||||
${CONTEXT_TEXT}"
|
||||
fi
|
||||
|
||||
# base64 encode — portable: use stdin redirect + strip newlines (works on Linux and macOS)
|
||||
B64=$(base64 < "$IMAGE_PATH" | tr -d '\n')
|
||||
DATA_URI="data:${MIME};base64,${B64}"
|
||||
|
||||
# Write data URI to temp file to avoid ARG_MAX for large images
|
||||
TMPURI=$(mktemp)
|
||||
trap "rm -f '$TMPURI'" EXIT
|
||||
printf '%s' "$DATA_URI" > "$TMPURI"
|
||||
|
||||
jq -n \
|
||||
--arg model "$MODEL" \
|
||||
--arg system "$SYSTEM_TEXT" \
|
||||
--arg user_text "$USER_TEXT" \
|
||||
--rawfile data_uri "$TMPURI" \
|
||||
--argjson max_tokens "$MAX_TOKENS" \
|
||||
--argjson temperature "$TEMPERATURE" \
|
||||
--argjson top_p "$TOP_P" \
|
||||
'{
|
||||
model: $model,
|
||||
temperature: $temperature,
|
||||
top_p: $top_p,
|
||||
max_tokens: $max_tokens,
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: $system
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{ type: "text", text: $user_text },
|
||||
{ type: "image_url", image_url: { url: ($data_uri | rtrimstr("\n")) } }
|
||||
]
|
||||
}
|
||||
]
|
||||
}'
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/bin/sh
|
||||
# glm-build-text-request.sh — Build JSON request payload for GLM text API (no image)
|
||||
# Usage: glm-build-text-request.sh <user_text_or_file> <prompt_file> [context_file] [model] [max_tokens] [temperature] [top_p]
|
||||
# Output: JSON payload to stdout
|
||||
# Requires: jq
|
||||
|
||||
set -e
|
||||
|
||||
USER_INPUT="${1:?Usage: glm-build-text-request.sh <text_or_file> <prompt> [context] [model] [max_tokens] [temp] [top_p]}"
|
||||
PROMPT_FILE="${2:?Usage: glm-build-text-request.sh <text_or_file> <prompt> [context] [model] [max_tokens] [temp] [top_p]}"
|
||||
CONTEXT_FILE="${3:-}"
|
||||
MODEL="${4:-glm-5v-turbo}"
|
||||
MAX_TOKENS="${5:-32768}"
|
||||
TEMPERATURE="${6:-0.2}"
|
||||
TOP_P="${7:-0.85}"
|
||||
|
||||
command -v jq >/dev/null 2>&1 || { echo "ERROR: jq is required" >&2; exit 1; }
|
||||
[ -f "$PROMPT_FILE" ] || { echo "ERROR: Prompt not found: $PROMPT_FILE" >&2; exit 1; }
|
||||
|
||||
SYSTEM_TEXT=$(cat "$PROMPT_FILE")
|
||||
|
||||
# If USER_INPUT is a file path, read its content
|
||||
if [ -f "$USER_INPUT" ]; then
|
||||
USER_TEXT="Convert this code to working frontend code files:
|
||||
|
||||
$(cat "$USER_INPUT")"
|
||||
else
|
||||
USER_TEXT="Create working frontend code files based on this description:
|
||||
|
||||
$USER_INPUT"
|
||||
fi
|
||||
|
||||
if [ -n "$CONTEXT_FILE" ] && [ -f "$CONTEXT_FILE" ]; then
|
||||
CONTEXT_TEXT=$(cat "$CONTEXT_FILE")
|
||||
USER_TEXT="${USER_TEXT}
|
||||
|
||||
${CONTEXT_TEXT}"
|
||||
fi
|
||||
|
||||
jq -n \
|
||||
--arg model "$MODEL" \
|
||||
--arg system "$SYSTEM_TEXT" \
|
||||
--arg user_text "$USER_TEXT" \
|
||||
--argjson max_tokens "$MAX_TOKENS" \
|
||||
--argjson temperature "$TEMPERATURE" \
|
||||
--argjson top_p "$TOP_P" \
|
||||
'{
|
||||
model: $model,
|
||||
temperature: $temperature,
|
||||
top_p: $top_p,
|
||||
max_tokens: $max_tokens,
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: $system
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: $user_text
|
||||
}
|
||||
]
|
||||
}'
|
||||
@@ -0,0 +1,98 @@
|
||||
#!/bin/sh
|
||||
# glm-extract.sh — Extract files from GLM API response
|
||||
# Usage: glm-extract.sh <response.json> <output_dir>
|
||||
# Parses ===FILE: path=== ... ===END_FILE=== markers from response content
|
||||
# Falls back to single index.html if no markers found
|
||||
|
||||
set -e
|
||||
|
||||
RESPONSE="${1:?Usage: glm-extract.sh <response.json> <output_dir>}"
|
||||
OUTPUT_DIR="${2:?Usage: glm-extract.sh <response.json> <output_dir>}"
|
||||
|
||||
[ -f "$RESPONSE" ] || { echo "ERROR: Response not found: $RESPONSE" >&2; exit 1; }
|
||||
|
||||
# Validate OUTPUT_DIR has no shell metacharacters
|
||||
case "$OUTPUT_DIR" in
|
||||
*[\'\"\`\$\;\|\&\(\)\{\}\[\]\#\!\~\\\ ]*)
|
||||
echo "ERROR: OUTPUT_DIR contains unsafe characters: $OUTPUT_DIR" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
CONTENT=$(jq -r '.choices[0].message.content // empty' "$RESPONSE")
|
||||
|
||||
if [ -z "$CONTENT" ]; then
|
||||
echo "ERROR: No content in response" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
if printf '%s\n' "$CONTENT" | grep -q '===FILE:'; then
|
||||
# Extract content to temp file to avoid shell escaping issues
|
||||
TMPFILE=$(mktemp)
|
||||
trap "rm -f '$TMPFILE'" EXIT
|
||||
jq -r '.choices[0].message.content' "$RESPONSE" > "$TMPFILE"
|
||||
|
||||
awk -v outdir="$OUTPUT_DIR" '
|
||||
/^===FILE: / {
|
||||
fname = $0
|
||||
sub(/^===FILE: */, "", fname)
|
||||
sub(/ *===.*$/, "", fname)
|
||||
sub(/=+$/, "", fname)
|
||||
# Sanitize: only allow safe chars in filenames
|
||||
gsub(/[^a-zA-Z0-9._\/\-]/, "", fname)
|
||||
gsub(/^\/+/, "", fname)
|
||||
# Reject any path with .. (traversal attempt)
|
||||
if (fname ~ /\.\./) { next }
|
||||
if (fname == "") { next }
|
||||
current_file = outdir "/" fname
|
||||
writing = 1
|
||||
next
|
||||
}
|
||||
/^===END_FILE===/ {
|
||||
if (writing && current_file != "") {
|
||||
close(current_file)
|
||||
file_count++
|
||||
print " " fname " (" lines " lines)" > "/dev/stderr"
|
||||
lines = 0
|
||||
}
|
||||
writing = 0
|
||||
next
|
||||
}
|
||||
writing {
|
||||
# Ensure parent directory exists on first write
|
||||
if (lines == 0) {
|
||||
dir = current_file
|
||||
sub(/\/[^\/]*$/, "", dir)
|
||||
cmd = "mkdir -p '\''" dir "'\''"
|
||||
system(cmd)
|
||||
close(cmd)
|
||||
printf "" > current_file
|
||||
close(current_file)
|
||||
}
|
||||
print >> current_file
|
||||
lines++
|
||||
}
|
||||
END {
|
||||
print "Extracted " file_count " file(s)" > "/dev/stderr"
|
||||
}
|
||||
' "$TMPFILE"
|
||||
else
|
||||
echo "No ===FILE: markers found. Trying markdown code block extraction..." >&2
|
||||
|
||||
CLEAN=$(printf '%s\n' "$CONTENT" | sed -n '/^```html/,/^```$/p' | sed '1d;$d')
|
||||
|
||||
if [ -z "$CLEAN" ]; then
|
||||
CLEAN="$CONTENT"
|
||||
echo "WARNING: No structured format detected. Saving raw content as index.html" >&2
|
||||
fi
|
||||
|
||||
printf '%s\n' "$CLEAN" > "$OUTPUT_DIR/index.html"
|
||||
echo "Extracted 1 file(s)" >&2
|
||||
echo " index.html ($(printf '%s\n' "$CLEAN" | wc -l | tr -d ' ') lines)" >&2
|
||||
fi
|
||||
|
||||
echo "" >&2
|
||||
echo "Output directory: $OUTPUT_DIR" >&2
|
||||
ls -la "$OUTPUT_DIR" >&2
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/bin/sh
|
||||
# glm-request.sh — Send request to GLM API (Z.ai or OpenRouter)
|
||||
# Usage: glm-request.sh <payload.json> <output.json> [provider]
|
||||
# Provider: zai (default) | openrouter
|
||||
# Env vars: ZAI_API_KEY, OPENROUTER_API_KEY
|
||||
# Output: raw API response saved to output.json, status info to stderr
|
||||
|
||||
set -e
|
||||
|
||||
PAYLOAD="${1:?Usage: glm-request.sh <payload.json> <output.json> [provider]}"
|
||||
OUTPUT="${2:?Usage: glm-request.sh <payload.json> <output.json> [provider]}"
|
||||
PROVIDER="${3:-zai}"
|
||||
|
||||
[ -f "$PAYLOAD" ] || { echo "ERROR: Payload not found: $PAYLOAD" >&2; exit 1; }
|
||||
|
||||
# Validate payload is valid JSON
|
||||
jq empty "$PAYLOAD" 2>/dev/null || { echo "ERROR: Invalid JSON in $PAYLOAD" >&2; exit 1; }
|
||||
|
||||
# Set API endpoint and key
|
||||
case "$PROVIDER" in
|
||||
zai)
|
||||
API_URL="https://api.z.ai/api/paas/v4/chat/completions"
|
||||
API_KEY="${ZAI_API_KEY:?ERROR: ZAI_API_KEY not set}"
|
||||
;;
|
||||
openrouter)
|
||||
API_URL="https://openrouter.ai/api/v1/chat/completions"
|
||||
API_KEY="${OPENROUTER_API_KEY:?ERROR: OPENROUTER_API_KEY not set}"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unknown provider: $PROVIDER (use: zai, openrouter)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Sending to $PROVIDER ($API_URL)..." >&2
|
||||
echo "Model: $(jq -r '.model' "$PAYLOAD")" >&2
|
||||
echo "Max tokens: $(jq -r '.max_tokens' "$PAYLOAD")" >&2
|
||||
|
||||
# Send request with retry
|
||||
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$OUTPUT" \
|
||||
--retry 3 --retry-delay 5 --retry-max-time 60 \
|
||||
--max-time 300 \
|
||||
-X POST "$API_URL" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @"$PAYLOAD")
|
||||
|
||||
echo "HTTP: $HTTP_CODE" >&2
|
||||
|
||||
# Check HTTP status
|
||||
if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then
|
||||
echo "ERROR: API returned HTTP $HTTP_CODE" >&2
|
||||
cat "$OUTPUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for API errors in response
|
||||
if jq -e '.error' "$OUTPUT" >/dev/null 2>&1; then
|
||||
echo "ERROR: API error in response:" >&2
|
||||
jq '.error' "$OUTPUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Print usage stats
|
||||
FINISH=$(jq -r '.choices[0].finish_reason // "unknown"' "$OUTPUT")
|
||||
IN_TOK=$(jq -r '.usage.prompt_tokens // "?"' "$OUTPUT")
|
||||
OUT_TOK=$(jq -r '.usage.completion_tokens // "?"' "$OUTPUT")
|
||||
REASON_TOK=$(jq -r '.usage.completion_tokens_details.reasoning_tokens // 0' "$OUTPUT")
|
||||
|
||||
echo "Finish: $FINISH" >&2
|
||||
echo "Tokens: in=$IN_TOK out=$OUT_TOK reasoning=$REASON_TOK" >&2
|
||||
echo "Response saved: $OUTPUT ($(wc -c < "$OUTPUT" | tr -d ' ') bytes)" >&2
|
||||
|
||||
# Warn if truncated
|
||||
if [ "$FINISH" = "length" ]; then
|
||||
echo "WARNING: Response was truncated (hit max_tokens limit)" >&2
|
||||
fi
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
# glm-verify.sh — Serve generated HTML and output URL for Playwright
|
||||
# Usage: glm-verify.sh <html_dir> [port]
|
||||
# Starts HTTP server, outputs URL, waits for Ctrl+C
|
||||
|
||||
set -e
|
||||
|
||||
HTML_DIR="${1:?Usage: glm-verify.sh <html_dir> [port]}"
|
||||
PORT="${2:-8900}"
|
||||
|
||||
case "$PORT" in
|
||||
*[!0-9]*) echo "ERROR: Invalid port: $PORT" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
# Find entry point
|
||||
if [ -f "$HTML_DIR/build/web/index.html" ]; then
|
||||
SERVE_DIR="$HTML_DIR/build/web"
|
||||
elif [ -f "$HTML_DIR/dist/index.html" ]; then
|
||||
SERVE_DIR="$HTML_DIR/dist"
|
||||
elif [ -f "$HTML_DIR/index.html" ]; then
|
||||
SERVE_DIR="$HTML_DIR"
|
||||
else
|
||||
echo "ERROR: No index.html found in $HTML_DIR (checked build/web/, dist/, root)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ABS_DIR=$(cd "$SERVE_DIR" && pwd)
|
||||
|
||||
echo "Serving: $ABS_DIR" >&2
|
||||
echo "Port: $PORT" >&2
|
||||
|
||||
(cd "$ABS_DIR" && python3 -m http.server "$PORT") &
|
||||
SERVER_PID=$!
|
||||
sleep 1
|
||||
|
||||
# Verify server started
|
||||
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
echo "ERROR: Failed to start server" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "http://localhost:$PORT/"
|
||||
|
||||
echo "Server PID: $SERVER_PID (kill with: kill $SERVER_PID)" >&2
|
||||
@@ -0,0 +1,139 @@
|
||||
#!/bin/sh
|
||||
# parse-args.sh — Parse glm-design-to-code skill arguments
|
||||
# Usage: parse-args.sh [args...]
|
||||
# Output: KEY=VALUE pairs to stdout
|
||||
|
||||
set -e
|
||||
|
||||
IMAGE=""
|
||||
RESULT_IMAGE=""
|
||||
INPUT_TYPE=""
|
||||
FRAMEWORK="html"
|
||||
PROFILE="max"
|
||||
PROVIDER="zai"
|
||||
OUTPUT="./d2c-output"
|
||||
REVIEW="false"
|
||||
MODE="create"
|
||||
FIX_TEXT=""
|
||||
REVIEW_FILE=""
|
||||
MODEL=""
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--framework|-f)
|
||||
FRAMEWORK="${2:?--framework requires value: html|react|flutter|custom}"
|
||||
shift 2
|
||||
;;
|
||||
--profile|-p)
|
||||
PROFILE="${2:?--profile requires value: max|optimal|efficient}"
|
||||
shift 2
|
||||
;;
|
||||
--provider)
|
||||
PROVIDER="${2:?--provider requires value: zai|openrouter}"
|
||||
shift 2
|
||||
;;
|
||||
--output|-o)
|
||||
OUTPUT="${2:?--output requires value: directory path}"
|
||||
shift 2
|
||||
;;
|
||||
--review|-r)
|
||||
MODE="review"
|
||||
REVIEW="true"
|
||||
shift
|
||||
;;
|
||||
--fix)
|
||||
MODE="fix"
|
||||
# Check if next arg is a value (not a flag)
|
||||
if [ $# -gt 1 ] && [ "${2#-}" = "$2" ]; then
|
||||
FIX_TEXT="$2"
|
||||
shift
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
--review-file)
|
||||
REVIEW_FILE="${2:?--review-file requires a path}"
|
||||
shift 2
|
||||
;;
|
||||
--model|-m)
|
||||
MODEL="${2:?--model requires a model ID}"
|
||||
shift 2
|
||||
;;
|
||||
--*)
|
||||
echo "WARNING: Unknown flag: $1" >&2
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
if [ -z "$IMAGE" ]; then
|
||||
IMAGE="$1"
|
||||
elif [ -z "$RESULT_IMAGE" ]; then
|
||||
RESULT_IMAGE="$1"
|
||||
else
|
||||
echo "WARNING: Extra argument ignored: $1" >&2
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Detect input type from IMAGE value
|
||||
if [ -n "$IMAGE" ]; then
|
||||
case "$IMAGE" in
|
||||
http://*|https://*)
|
||||
INPUT_TYPE="url"
|
||||
;;
|
||||
*.png|*.jpg|*.jpeg|*.webp|*.gif)
|
||||
INPUT_TYPE="image"
|
||||
;;
|
||||
*.html|*.htm)
|
||||
INPUT_TYPE="html"
|
||||
;;
|
||||
*)
|
||||
# If it's a file that exists and is an image, treat as image
|
||||
if [ -f "$IMAGE" ] && file --mime-type "$IMAGE" 2>/dev/null | grep -qE ': image/'; then
|
||||
INPUT_TYPE="image"
|
||||
elif [ -f "$IMAGE" ]; then
|
||||
# Existing file but not image — treat as HTML/text file
|
||||
INPUT_TYPE="html"
|
||||
else
|
||||
# Not a file, not a URL — treat as text description
|
||||
INPUT_TYPE="text"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Validate framework
|
||||
case "$FRAMEWORK" in
|
||||
html|react|flutter|custom) ;;
|
||||
*) echo "ERROR: Invalid framework: $FRAMEWORK (use: html, react, flutter, custom)" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
# Validate profile
|
||||
case "$PROFILE" in
|
||||
max|optimal|efficient) ;;
|
||||
*) echo "ERROR: Invalid profile: $PROFILE (use: max, optimal, efficient)" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
# Validate provider
|
||||
case "$PROVIDER" in
|
||||
zai|openrouter) ;;
|
||||
*) echo "ERROR: Invalid provider: $PROVIDER (use: zai, openrouter)" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
echo "IMAGE=$IMAGE"
|
||||
echo "FRAMEWORK=$FRAMEWORK"
|
||||
echo "PROFILE=$PROFILE"
|
||||
echo "PROVIDER=$PROVIDER"
|
||||
echo "OUTPUT=$OUTPUT"
|
||||
echo "REVIEW=$REVIEW"
|
||||
echo "MODE=$MODE"
|
||||
echo "FIX_TEXT=$FIX_TEXT"
|
||||
echo "RESULT_IMAGE=$RESULT_IMAGE"
|
||||
echo "REVIEW_FILE=$REVIEW_FILE"
|
||||
echo "MODEL=$MODEL"
|
||||
echo "INPUT_TYPE=$INPUT_TYPE"
|
||||
|
||||
if [ -z "$IMAGE" ]; then
|
||||
echo "IMAGE_MISSING=true"
|
||||
echo "NOTE: No screenshot path provided. Will ask user." >&2
|
||||
fi
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "brewdoc",
|
||||
"version": "3.4.21",
|
||||
"version": "3.4.22",
|
||||
"description": "Brewdoc - Claude Code documentation tools: auto-sync for skills/agents/rules, my-claude installation docs, memory optimization",
|
||||
"author": {
|
||||
"name": "Maksim Kochetkov",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "brewtools",
|
||||
"version": "3.4.21",
|
||||
"version": "3.4.22",
|
||||
"description": "Brewtools - universal utilities for Claude Code: text optimization, humanization, secrets scanning",
|
||||
"author": {
|
||||
"name": "Maksim Kochetkov",
|
||||
|
||||
@@ -19,7 +19,7 @@ what to brew, agents (brewers) do the work, and hooks (processes) manage the lif
|
||||
Automatic knowledge transfer between sessions via KNOWLEDGE.jsonl and the handoff mechanism.
|
||||
Tasks continue after compaction without losing progress.
|
||||
</Card>
|
||||
<Card title="13 skills (recipes)" icon="terminal">
|
||||
<Card title="14 skills (recipes)" icon="terminal">
|
||||
Full cycle: from project analysis (/brewcode:setup) to task execution (/brewcode:start)
|
||||
and code review (/brewcode:standards-review).
|
||||
</Card>
|
||||
@@ -120,7 +120,7 @@ brewcode/
|
||||
│ ├── bc-knowledge-manager.md # Knowledge manager (haiku)
|
||||
│ ├── bc-grepai-configurator.md # grepai configurator (opus)
|
||||
│ └── bc-rules-organizer.md # Rules organizer (sonnet)
|
||||
├── skills/ # 13 skills
|
||||
├── skills/ # 14 skills
|
||||
│ ├── setup/ # Project analysis, templates
|
||||
│ ├── spec/ # Specification creation
|
||||
│ ├── plan/ # Plan creation
|
||||
@@ -133,7 +133,8 @@ brewcode/
|
||||
│ ├── skills/ # Skill management
|
||||
│ ├── agents/ # Agent management
|
||||
│ ├── teams/ # Dynamic agent teams
|
||||
│ └── e2e/ # E2E testing orchestration
|
||||
│ ├── e2e/ # E2E testing orchestration
|
||||
│ └── glm-design-to-code/ # Vision design-to-code (4 input types)
|
||||
└── templates/ # Rule templates
|
||||
```
|
||||
|
||||
@@ -175,7 +176,7 @@ After running `/brewcode:setup` and `/brewcode:start`, the following appears in
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Skills">
|
||||
13 skills (recipes) cover the full task lifecycle.
|
||||
14 skills (recipes) cover the full task lifecycle.
|
||||
See the [Skills](/brewcode/skills/) section for details.
|
||||
|
||||
| Group | Skills | Purpose |
|
||||
@@ -184,6 +185,7 @@ After running `/brewcode:setup` and `/brewcode:start`, the following appears in
|
||||
| Quality | standards-review, convention, rules | Code analysis and review |
|
||||
| Dynamic | teams | Agent team creation and management |
|
||||
| Testing | e2e | E2E testing orchestration with BDD scenarios |
|
||||
| Design | glm-design-to-code | Vision model design-to-code (image, text, HTML, URL) |
|
||||
| Utilities | grepai, teardown, skills, agents | Tools and configuration |
|
||||
</TabItem>
|
||||
<TabItem label="Agents">
|
||||
@@ -251,6 +253,6 @@ After running `/brewcode:setup` and `/brewcode:start`, the following appears in
|
||||
</Steps>
|
||||
|
||||
<Callout type="tip" title="Next steps">
|
||||
Check out [Skills](/brewcode/skills/) for a detailed description of all 13 skills,
|
||||
Check out [Skills](/brewcode/skills/) for detailed descriptions of all 14 skills,
|
||||
or go to [Workflow](/brewcode/workflow/) for a deep dive into the full task execution cycle.
|
||||
</Callout>
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
---
|
||||
title: "GLM Design to Code"
|
||||
description: "Vision model-powered design-to-code generator — screenshots to production code"
|
||||
order: 1114
|
||||
---
|
||||
import { Card, CardGrid, Callout, Steps, Badge, Tabs, TabItem } from '../../../../components/mdx';
|
||||
|
||||
# GLM Design to Code
|
||||
|
||||
<Badge variant="accent" text="new" /> <Badge variant="primary" text="opus" />
|
||||
|
||||
Vision model-powered design-to-code generator.
|
||||
Convert designs to working multi-framework code using GLM-5V-Turbo. Accepts images, text descriptions, HTML files, or URLs.
|
||||
|
||||
<CardGrid>
|
||||
<Card title="CREATE" icon="pencil">
|
||||
Any input to working multi-file code. HTML/CSS, React 18, Flutter Web.
|
||||
</Card>
|
||||
<Card title="REVIEW" icon="search">
|
||||
Compare original design with generated result. Score 1-10 with actionable feedback.
|
||||
</Card>
|
||||
<Card title="FIX" icon="wrench">
|
||||
Apply review feedback to improve generated code automatically.
|
||||
</Card>
|
||||
</CardGrid>
|
||||
|
||||
## Input Types
|
||||
|
||||
<CardGrid>
|
||||
<Card title="Image" icon="star">
|
||||
PNG, JPG, WebP, or GIF screenshot. The most common input -- export from Figma, Sketch, or take a screenshot.
|
||||
</Card>
|
||||
<Card title="Text Description" icon="pencil">
|
||||
Natural language description of the desired UI. Example: "Dark landing page with hero section and pricing cards".
|
||||
</Card>
|
||||
<Card title="HTML" icon="document">
|
||||
Existing HTML file to convert or improve. Useful for migrating legacy pages to React or Flutter.
|
||||
</Card>
|
||||
<Card title="URL" icon="external">
|
||||
Public URL -- Playwright takes a screenshot automatically, then converts. Great for cloning existing pages.
|
||||
</Card>
|
||||
</CardGrid>
|
||||
|
||||
<Callout type="info">
|
||||
Input type is **auto-detected** from the argument: file extension for images/HTML, URL pattern for URLs, quoted text for descriptions.
|
||||
</Callout>
|
||||
|
||||
## Quick reference
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Command | `/brewcode:glm-design-to-code` |
|
||||
| Arguments | `<input> [--framework html\|react\|flutter\|custom] [--profile max\|optimal\|efficient]` |
|
||||
| Input types | Image, text description, HTML file, URL (auto-detected) |
|
||||
| Model | opus |
|
||||
| Vision model | GLM-5V-Turbo (Z.ai / OpenRouter) |
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# From an image
|
||||
/brewcode:glm-design-to-code screenshot.png
|
||||
|
||||
# From a text description
|
||||
/brewcode:glm-design-to-code "Dark landing page with hero section and pricing cards"
|
||||
|
||||
# From an existing HTML file
|
||||
/brewcode:glm-design-to-code existing-page.html --framework react
|
||||
|
||||
# From a URL (auto-screenshots via Playwright)
|
||||
/brewcode:glm-design-to-code https://example.com/landing
|
||||
```
|
||||
|
||||
## Pipeline Flow
|
||||
|
||||
<Steps>
|
||||
1. **Parse input** -- detect input type (image/text/HTML/URL), framework, quality profile
|
||||
2. **API key setup** -- Z.ai or OpenRouter, validated and saved
|
||||
3. **Build payload** -- base64 image + system prompt + context
|
||||
4. **Send to GLM** -- glm-5v-turbo with retry and fallback
|
||||
5. **Extract files** -- parse `===FILE:===` markers, create project
|
||||
6. **Build** -- framework-specific (Vite for React, flutter build for Flutter)
|
||||
7. **Verify** -- Playwright screenshot + automated review
|
||||
</Steps>
|
||||
|
||||
## Benchmark Results
|
||||
|
||||
Our research tested GLM-5V-Turbo across three frameworks with the same design mockup:
|
||||
|
||||
| Framework | Score | Files | Build | Cost |
|
||||
|-----------|-------|-------|-------|------|
|
||||
| **HTML/CSS** | **9.5/10** | 3 | N/A | ~$0.032 |
|
||||
| **React 18** | **8.0/10** | 19 | Vite 218ms | ~$0.035 |
|
||||
| **Flutter Web** | **9.0/10** (Claude) | 10 | flutter build web | ~$0.032 |
|
||||
|
||||
<Callout type="tip">
|
||||
Average cost per design-to-code conversion: **~$0.03**. Using the free `glm-4.6v-flash` model for development iterations costs nothing.
|
||||
</Callout>
|
||||
|
||||
## GLM Models
|
||||
|
||||
| Model | Vision | Price (in/out per 1M) | Context | Best For |
|
||||
|-------|--------|----------------------|---------|----------|
|
||||
| glm-5v-turbo | Image+Video | $1.20 / $4.00 | 128K | Production quality |
|
||||
| glm-4.6v-flash | Image | FREE | 131K | Development and testing |
|
||||
| glm-4.6v | Image+Video | $0.30 / $0.90 | 131K | Budget production |
|
||||
|
||||
<Callout type="info">
|
||||
GLM-5V-Turbo uses CogViT architecture with 94.8 Design2Code benchmark score. Available via Z.ai direct API or OpenRouter.
|
||||
</Callout>
|
||||
|
||||
## Frameworks
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="HTML/CSS">
|
||||
**Best score: 9.5/10** -- Pure static output. No build step needed.
|
||||
|
||||
- Semantic HTML5 with `index.html` entry point
|
||||
- CSS in separate files with custom properties
|
||||
- JS for interactive elements
|
||||
- Perfect for landing pages, dashboards, documentation
|
||||
</TabItem>
|
||||
<TabItem label="React 18">
|
||||
**Score: 8.0/10** -- Component-based architecture with CSS Modules.
|
||||
|
||||
- JSX components in separate files
|
||||
- CSS Modules (`.module.css`) for styling
|
||||
- Vite build (218ms average)
|
||||
- App.jsx root component
|
||||
</TabItem>
|
||||
<TabItem label="Flutter Web">
|
||||
**Score: 9/10** -- Dart widgets with theme system.
|
||||
|
||||
- StatelessWidget components
|
||||
- Theme constants in `lib/theme.dart`
|
||||
- `flutter build web` compilation
|
||||
- Auto-fix: `Color(xFF...)` to `Color(0xFF...)`
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Quality Profiles
|
||||
|
||||
<CardGrid>
|
||||
<Card title="Maximum" icon="star">
|
||||
Pixel-perfect reproduction. Exact colors, spacing, typography. 13 quality requirements. ~32K output tokens.
|
||||
</Card>
|
||||
<Card title="Optimal" icon="check">
|
||||
Good quality, balanced cost. Correct colors, proportions, layout. 8 requirements. ~16K tokens.
|
||||
</Card>
|
||||
<Card title="Efficient" icon="forward-slash">
|
||||
Fast generation. Basic layout and colors. 4 requirements. ~8K tokens.
|
||||
</Card>
|
||||
</CardGrid>
|
||||
|
||||
## Providers
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Z.ai (Direct)">
|
||||
**Recommended.** Direct API access with system message caching (80% discount on repeated prompts).
|
||||
|
||||
- Endpoint: `https://api.z.ai/api/paas/v4/chat/completions`
|
||||
- Auth: `ZAI_API_KEY` environment variable
|
||||
- All GLM models available including free tier
|
||||
</TabItem>
|
||||
<TabItem label="OpenRouter">
|
||||
**Alternative.** Unified API with fallback routing.
|
||||
|
||||
- Endpoint: `https://openrouter.ai/api/v1/chat/completions`
|
||||
- Auth: `OPENROUTER_API_KEY` environment variable
|
||||
- Model IDs prefixed with `z-ai/` (e.g., `z-ai/glm-5v-turbo`)
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Image">
|
||||
```bash
|
||||
# Basic -- HTML/CSS output from screenshot
|
||||
/brewcode:glm-design-to-code screenshot.png
|
||||
|
||||
# React with optimal quality
|
||||
/brewcode:glm-design-to-code mockup.png --framework react --profile optimal
|
||||
|
||||
# Flutter via OpenRouter
|
||||
/brewcode:glm-design-to-code design.png --framework flutter --provider openrouter
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="Text">
|
||||
```bash
|
||||
# Generate from a description
|
||||
/brewcode:glm-design-to-code "Minimalist dashboard with sidebar and dark theme"
|
||||
|
||||
# React component from description
|
||||
/brewcode:glm-design-to-code "Pricing page with 3 tiers" --framework react
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="HTML">
|
||||
```bash
|
||||
# Convert legacy HTML to React
|
||||
/brewcode:glm-design-to-code old-page.html --framework react
|
||||
|
||||
# Improve existing HTML with max quality
|
||||
/brewcode:glm-design-to-code landing.html --profile max
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="URL">
|
||||
```bash
|
||||
# Clone a live page (Playwright auto-screenshot)
|
||||
/brewcode:glm-design-to-code https://example.com/landing
|
||||
|
||||
# Clone as Flutter
|
||||
/brewcode:glm-design-to-code https://stripe.com/pricing --framework flutter
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="REVIEW">
|
||||
```bash
|
||||
# Compare original design with generated result
|
||||
/brewcode:glm-design-to-code --review original.png result-screenshot.png
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="FIX">
|
||||
```bash
|
||||
# Fix specific issues
|
||||
/brewcode:glm-design-to-code --fix "sidebar too narrow, wrong green color"
|
||||
|
||||
# Fix from review file
|
||||
/brewcode:glm-design-to-code --fix --review-file review.json
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Options
|
||||
|
||||
| Flag | Default | Description |
|
||||
|------|---------|-------------|
|
||||
| `--framework` | `html` | Target: `html`, `react`, `flutter`, `custom` |
|
||||
| `--profile` | `max` | Quality: `max`, `optimal`, `efficient` |
|
||||
| `--provider` | `zai` | API: `zai`, `openrouter` |
|
||||
| `--model` | auto | Override model ID |
|
||||
| `--output` | `./d2c-output` | Output directory |
|
||||
| `--review` | -- | Enter REVIEW mode (accepts 2 images) |
|
||||
| `--fix` | -- | Enter FIX mode (accepts feedback text) |
|
||||
| `--review-file` | -- | Path to review JSON for FIX mode |
|
||||
|
||||
## Research Methodology
|
||||
|
||||
Our benchmarks used a controlled methodology:
|
||||
|
||||
- **Same mockup** across all frameworks (dark-theme documentation page)
|
||||
- **Frozen prompts** -- identical prompts per quality profile
|
||||
- **Fixed API params** -- temperature 0.2, top_p 0.85, max_tokens 32768
|
||||
- **Dual evaluation** -- Claude Opus + GLM-4.6v-flash scoring independently
|
||||
- **Playwright verification** -- automated screenshots at 1280x800 viewport
|
||||
@@ -39,6 +39,7 @@ export const navigation: NavSection[] = [
|
||||
{ title: 'skills', slug: 'brewcode/skills/skills' },
|
||||
{ title: 'agents', slug: 'brewcode/skills/agents' },
|
||||
{ title: 'e2e', slug: 'brewcode/skills/e2e' },
|
||||
{ title: 'glm-design-to-code', slug: 'brewcode/skills/glm-design-to-code' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user