Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>ComfyUI Workflow</title> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', system-ui, sans-serif; | |
| background-color: #000000; | |
| color: #f5f5f7; | |
| line-height: 1.6; | |
| padding: 20px; | |
| min-height: 100vh; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| } | |
| .header { | |
| text-align: center; | |
| margin-bottom: 40px; | |
| padding: 40px 20px; | |
| } | |
| .header h1 { | |
| font-size: 48px; | |
| font-weight: 600; | |
| color: #ffffff; | |
| margin-bottom: 12px; | |
| letter-spacing: -0.02em; | |
| } | |
| .header p { | |
| font-size: 18px; | |
| color: #86868b; | |
| font-weight: 400; | |
| } | |
| .controls { | |
| display: flex; | |
| gap: 12px; | |
| margin-bottom: 24px; | |
| justify-content: center; | |
| } | |
| .btn { | |
| padding: 12px 24px; | |
| border: none; | |
| border-radius: 24px; | |
| font-size: 14px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| font-family: inherit; | |
| } | |
| .btn-primary { | |
| background: #ffffff; | |
| color: #000000; | |
| } | |
| .btn-primary:hover { | |
| background: #f5f5f7; | |
| transform: scale(0.98); | |
| } | |
| .btn-secondary { | |
| background: #1d1d1f; | |
| color: #f5f5f7; | |
| border: 1px solid #424245; | |
| } | |
| .btn-secondary:hover { | |
| background: #2d2d2f; | |
| transform: scale(0.98); | |
| } | |
| .json-container { | |
| background-color: #1d1d1f; | |
| border-radius: 16px; | |
| padding: 32px; | |
| overflow-x: auto; | |
| border: 1px solid #424245; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); | |
| } | |
| pre { | |
| margin: 0; | |
| font-family: 'SF Mono', 'Monaco', 'Menlo', 'Consolas', monospace; | |
| font-size: 13px; | |
| line-height: 1.6; | |
| white-space: pre-wrap; | |
| word-wrap: break-word; | |
| } | |
| .json-key { | |
| color: #9cdcfe; | |
| } | |
| .json-string { | |
| color: #ce9178; | |
| } | |
| .json-number { | |
| color: #b5cea8; | |
| } | |
| .json-boolean { | |
| color: #569cd6; | |
| } | |
| .json-null { | |
| color: #569cd6; | |
| } | |
| .success { | |
| color: #30d158; | |
| } | |
| @media (max-width: 768px) { | |
| .header h1 { | |
| font-size: 32px; | |
| } | |
| .controls { | |
| flex-direction: column; | |
| } | |
| .json-container { | |
| padding: 20px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <h1>ComfyUI Workflow</h1> | |
| <p>View and download your workflow JSON</p> | |
| </div> | |
| <div class="controls"> | |
| <button class="btn btn-primary" onclick="downloadJSON()">Download JSON</button> | |
| <button class="btn btn-secondary" onclick="copyToClipboard()">Copy to Clipboard</button> | |
| </div> | |
| <div class="json-container"> | |
| <pre id="json-content">{ | |
| "last_node_id": 10, | |
| "last_link_id": 10, | |
| "nodes": [ | |
| { | |
| "id": 1, | |
| "type": "CheckpointLoaderSimple", | |
| "pos": [ | |
| 100, | |
| 100 | |
| ], | |
| "size": { | |
| "0": 300, | |
| "1": 200 | |
| }, | |
| "flags": {}, | |
| "order": 0, | |
| "mode": 0, | |
| "inputs": [ | |
| { | |
| "name": "ckpt_name", | |
| "type": "STRING", | |
| "link": null | |
| } | |
| ], | |
| "outputs": [ | |
| { | |
| "name": "MODEL", | |
| "type": "MODEL", | |
| "links": [ | |
| 1 | |
| ], | |
| "slot_index": 0 | |
| }, | |
| { | |
| "name": "CLIP", | |
| "type": "CLIP", | |
| "links": [ | |
| 2 | |
| ], | |
| "slot_index": 1 | |
| }, | |
| { | |
| "name": "VAE", | |
| "type": "VAE", | |
| "links": [ | |
| 3 | |
| ], | |
| "slot_index": 2 | |
| } | |
| ], | |
| "properties": { | |
| "Node name for S&R": "CheckpointLoaderSimple" | |
| }, | |
| "widgets_values": [ | |
| "ghibli_style_model.safetensors" | |
| ] | |
| }, | |
| { | |
| "id": 2, | |
| "type": "CLIPTextEncode", | |
| "pos": [ | |
| 100, | |
| 300 | |
| ], | |
| "size": { | |
| "0": 300, | |
| "1": 200 | |
| }, | |
| "flags": {}, | |
| "order": 1, | |
| "mode": 0, | |
| "inputs": [ | |
| { | |
| "name": "text", | |
| "type": "STRING", | |
| "link": null | |
| }, | |
| { | |
| "name": "clip", | |
| "type": "CLIP", | |
| "link": 2 | |
| } | |
| ], | |
| "outputs": [ | |
| { | |
| "name": "CONDITIONING", | |
| "type": "CONDITIONING", | |
| "links": [ | |
| 4 | |
| ], | |
| "slot_index": 0 | |
| } | |
| ], | |
| "properties": { | |
| "Node name for S&R": "CLIPTextEncode" | |
| }, | |
| "widgets_values": [ | |
| "a beautiful Ghibli-style portrait, soft lighting, warm colors, detailed background, anime aesthetic" | |
| ] | |
| }, | |
| { | |
| "id": 3, | |
| "type": "EmptyLatentImage", | |
| "pos": [ | |
| 100, | |
| 500 | |
| ], | |
| "size": { | |
| "0": 300, | |
| "1": 200 | |
| }, | |
| "flags": {}, | |
| "order": 2, | |
| "mode": 0, | |
| "inputs": [ | |
| { | |
| "name": "width", | |
| "type": "INT", | |
| "link": null | |
| }, | |
| { | |
| "name": "height", | |
| "type": "INT", | |
| "link": null | |
| }, | |
| { | |
| "name": "batch_size", | |
| "type": "INT", | |
| "link": null | |
| } | |
| ], | |
| "outputs": [ | |
| { | |
| "name": "LATENT", | |
| "type": "LATENT", | |
| "links": [ | |
| 5 | |
| ], | |
| "slot_index": 0 | |
| } | |
| ], | |
| "properties": { | |
| "Node name for S&R": "EmptyLatentImage" | |
| }, | |
| "widgets_values": [ | |
| 512, | |
| 768, | |
| 1 | |
| ] | |
| }, | |
| { | |
| "id": 4, | |
| "type": "KSampler", | |
| "pos": [ | |
| 500, | |
| 300 | |
| ], | |
| "size": { | |
| "0": 300, | |
| "1": 400 | |
| }, | |
| "flags": {}, | |
| "order": 3, | |
| "mode": 0, | |
| "inputs": [ | |
| { | |
| "name": "model", | |
| "type": "MODEL", | |
| "link": 1 | |
| }, | |
| { | |
| "name": "seed", | |
| "type": "INT", | |
| "link": null | |
| }, | |
| { | |
| "name": "steps", | |
| "type": "INT", | |
| "link": null | |
| }, | |
| { | |
| "name": "cfg", | |
| "type": "FLOAT", | |
| "link": null | |
| }, | |
| { | |
| "name": "sampler_name", | |
| "type": "STRING", | |
| "link": null | |
| }, | |
| { | |
| "name": "scheduler", | |
| "type": "STRING", | |
| "link": null | |
| }, | |
| { | |
| "name": "positive", | |
| "type": "CONDITIONING", | |
| "link": 4 | |
| }, | |
| { | |
| "name": "negative", | |
| "type": "CONDITIONING", | |
| "link": null | |
| }, | |
| { | |
| "name": "latent_image", | |
| "type": "LATENT", | |
| "link": 5 | |
| } | |
| ], | |
| "outputs": [ | |
| { | |
| "name": "LATENT", | |
| "type": "LATENT", | |
| "links": [ | |
| 6 | |
| ], | |
| "slot_index": 0 | |
| } | |
| ], | |
| "properties": { | |
| "Node name for S&R": "KSampler" | |
| }, | |
| "widgets_values": [ | |
| 12345, | |
| 20, | |
| 7.5, | |
| "euler", | |
| "normal", | |
| null | |
| ] | |
| }, | |
| { | |
| "id": 5, | |
| "type": "VAEDecode", | |
| "pos": [ | |
| 900, | |
| 300 | |
| ], | |
| "size": { | |
| "0": 300, | |
| "1": 200 | |
| }, | |
| "flags": {}, | |
| "order": 4, | |
| "mode": 0, | |
| "inputs": [ | |
| { | |
| "name": "samples", | |
| "type": "LATENT", | |
| "link": 6 | |
| }, | |
| { | |
| "name": "vae", | |
| "type": "VAE", | |
| "link": 3 | |
| } | |
| ], | |
| "outputs": [ | |
| { | |
| "name": "IMAGE", | |
| "type": "IMAGE", | |
| "links": [ | |
| 7 | |
| ], | |
| "slot_index": 0 | |
| } | |
| ], | |
| "properties": { | |
| "Node name for S&R": "VAEDecode" | |
| }, | |
| "widgets_values": [] | |
| }, | |
| { | |
| "id": 6, | |
| "type": "SaveImage", | |
| "pos": [ | |
| 1200, | |
| 300 | |
| ], | |
| "size": { | |
| "0": 300, | |
| "1": 200 | |
| }, | |
| "flags": {}, | |
| "order": 5, | |
| "mode": 0, | |
| "inputs": [ | |
| { | |
| "name": "images", | |
| "type": "IMAGE", | |
| "link": 7 | |
| } | |
| ], | |
| "outputs": [], | |
| "properties": { | |
| "Node name for S&R": "SaveImage" | |
| }, | |
| "widgets_values": [] | |
| }, | |
| { | |
| "id": 7, | |
| "type": "PreviewImage", | |
| "pos": [ | |
| 1200, | |
| 500 | |
| ], | |
| "size": { | |
| "0": 300, | |
| "1": 200 | |
| }, | |
| "flags": {}, | |
| "order": 6, | |
| "mode": 0, | |
| "inputs": [ | |
| { | |
| "name": "images", | |
| "type": "IMAGE", | |
| "link": 7 | |
| } | |
| ], | |
| "outputs": [], | |
| "properties": { | |
| "Node name for S&R": "PreviewImage" | |
| }, | |
| "widgets_values": [] | |
| } | |
| ], | |
| "links": [ | |
| [ | |
| 1, | |
| 0, | |
| 4, | |
| 0 | |
| ], | |
| [ | |
| 2, | |
| 1, | |
| 2, | |
| 1 | |
| ], | |
| [ | |
| 3, | |
| 2, | |
| 5, | |
| 1 | |
| ], | |
| [ | |
| 4, | |
| 0, | |
| 4, | |
| 6 | |
| ], | |
| [ | |
| 5, | |
| 0, | |
| 4, | |
| 8 | |
| ], | |
| [ | |
| 6, | |
| 0, | |
| 5, | |
| 0 | |
| ], | |
| [ | |
| 7, | |
| 0, | |
| 6, | |
| 0 | |
| ], | |
| [ | |
| 7, | |
| 0, | |
| 7, | |
| 0 | |
| ] | |
| ], | |
| "groups": [], | |
| "config": {}, | |
| "extra": {}, | |
| "version": 0.4 | |
| }</pre> | |
| </div> | |
| </div> | |
| <script> | |
| function copyToClipboard() { | |
| const jsonContent = document.getElementById('json-content').textContent; | |
| navigator.clipboard.writeText(jsonContent).then(() => { | |
| const btn = event.target; | |
| const originalText = btn.textContent; | |
| btn.textContent = 'Copied!'; | |
| btn.classList.add('success'); | |
| setTimeout(() => { | |
| btn.textContent = originalText; | |
| btn.classList.remove('success'); | |
| }, 2000); | |
| }).catch(err => { | |
| alert('Failed to copy to clipboard'); | |
| }); | |
| } | |
| function downloadJSON() { | |
| const jsonContent = document.getElementById('json-content').textContent; | |
| const blob = new Blob([jsonContent], { type: 'application/json' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = 'comfyui_workflow.json'; | |
| document.body.appendChild(a); | |
| a.click(); | |
| document.body.removeChild(a); | |
| URL.revokeObjectURL(url); | |
| const btn = event.target; | |
| const originalText = btn.textContent; | |
| btn.textContent = 'Downloaded!'; | |
| btn.classList.add('success'); | |
| setTimeout(() => { | |
| btn.textContent = originalText; | |
| btn.classList.remove('success'); | |
| }, 2000); | |
| } | |
| // Add syntax highlighting | |
| function highlightJSON() { | |
| const content = document.getElementById('json-content'); | |
| let html = content.innerHTML; | |
| // Highlight different JSON elements | |
| html = html.replace(/"([^"]+)":/g, '<span class="json-key">"$1":</span>'); | |
| html = html.replace(/: "([^"]*)"/g, ': <span class="json-string">"$1"</span>'); | |
| html = html.replace(/: (-?\d+\.?\d*)/g, ': <span class="json-number">$1</span>'); | |
| html = html.replace(/: (true|false)/g, ': <span class="json-boolean">$1</span>'); | |
| html = html.replace(/: null/g, ': <span class="json-null">null</span>'); | |
| content.innerHTML = html; | |
| } | |
| // Apply syntax highlighting after page load | |
| window.addEventListener('load', highlightJSON); | |
| </script> | |
| </body> | |
| </html> |