From bf721c13792674945924de17a672d03dcce6072f Mon Sep 17 00:00:00 2001 From: Patrick Plate Date: Thu, 11 Jun 2026 09:02:09 +0200 Subject: [PATCH] feat(mcp): update bigmind/mcp-image-gen/webscraper servers; add image-gen batch scripts --- mcp/bigmind/src/server.py | 259 ++------ mcp/mcp-image-gen/cannamanage_gen.py | 795 +++++++++++++++++++++++ mcp/mcp-image-gen/clubmanage_gen.py | 801 ++++++++++++++++++++++++ mcp/mcp-image-gen/gen.py | 133 ++++ mcp/mcp-image-gen/gui.py | 352 +++++++++++ mcp/mcp-image-gen/patrick_hidden_gen.py | 411 ++++++++++++ mcp/mcp-image-gen/src/server.py | 47 +- mcp/webscraper/src/server.py | 80 +-- mcp/webscraper/tests/test_server.py | 78 ++- 9 files changed, 2659 insertions(+), 297 deletions(-) create mode 100644 mcp/mcp-image-gen/cannamanage_gen.py create mode 100644 mcp/mcp-image-gen/clubmanage_gen.py create mode 100644 mcp/mcp-image-gen/gen.py create mode 100644 mcp/mcp-image-gen/gui.py create mode 100644 mcp/mcp-image-gen/patrick_hidden_gen.py diff --git a/mcp/bigmind/src/server.py b/mcp/bigmind/src/server.py index 2a1999b..6208642 100644 --- a/mcp/bigmind/src/server.py +++ b/mcp/bigmind/src/server.py @@ -10,12 +10,14 @@ Layer 5: memory_get_instructions tool (on-demand self-healing) import sys import os import logging +from typing import Annotated # Ensure the project root is on sys.path so `bigmind` is importable # regardless of how uv invokes this file. sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) from mcp.server.fastmcp import FastMCP +from pydantic import Field from bigmind.db import init_db from bigmind import memory_store from bigmind.auto_close import auto_close_stale_sessions, close_orphaned_sessions, restart_server_in_place @@ -164,29 +166,19 @@ def memory_start_session() -> str: @mcp.tool() def memory_end_session( - session_id: str, - one_liner: str, - topics: str, - outcome: str, - summary: str, - key_facts: str = None, - code_refs: str = None, - importance: int = 5, + session_id: Annotated[str, Field(description="The session id returned by memory_start_session.")], + one_liner: Annotated[str, Field(description="A ≤120-char headline (e.g. \"Designed BigMind DB schema\").")], + topics: Annotated[str, Field(description="Comma-separated topic tags (e.g. \"mcp,sqlite,memory\").")], + outcome: Annotated[str, Field(description="One sentence: what was decided / built / resolved.")], + summary: Annotated[str, Field(description="Markdown narrative of the full conversation (aim ≤2 000 tokens).")], + key_facts: Annotated[str | None, Field(description="Bullet-point list of key facts learned (optional).")] = None, + code_refs: Annotated[str | None, Field(description="File paths, repos, or PRs referenced (optional).")] = None, + importance: Annotated[int, Field(description="1–10 importance score (default 5).")] = 5, ) -> str: """ ⚡ CALL THIS LAST — at the END of every conversation, before closing. Closes the current session and stores your summary of what happened. - - Args: - session_id: The session id returned by memory_start_session. - one_liner: A ≤120-char headline (e.g. "Designed BigMind DB schema"). - topics: Comma-separated topic tags (e.g. "mcp,sqlite,memory"). - outcome: One sentence: what was decided / built / resolved. - summary: Markdown narrative of the full conversation (aim ≤2 000 tokens). - key_facts: Bullet-point list of key facts learned (optional). - code_refs: File paths, repos, or PRs referenced (optional). - importance: 1–10 importance score (default 5). """ memory_store.close_session(session_id, one_liner, topics, outcome, importance) memory_store.save_session_summary(session_id, summary, key_facts, code_refs) @@ -200,7 +192,7 @@ def memory_end_session( @mcp.tool() -def memory_close_stale_sessions(session_id: str) -> str: +def memory_close_stale_sessions(session_id: Annotated[str, Field(description="Your current active session id (returned by memory_start_session).")]) -> str: """ Close all orphaned open sessions EXCEPT the current active one. @@ -210,9 +202,6 @@ def memory_close_stale_sessions(session_id: str) -> str: This is safe: it only closes sessions OTHER than the one you pass in. Your current session is always preserved. - - Args: - session_id: Your current active session id (returned by memory_start_session). """ user = _current_user() closed_ids = close_orphaned_sessions(user["id"], session_id) @@ -263,10 +252,10 @@ def memory_restart_server() -> str: @mcp.tool() def memory_flag_important( - session_id: str, - content: str, - role: str = "assistant", - flag_reason: str = None, + session_id: Annotated[str, Field(description="The active session id.")], + content: Annotated[str, Field(description="The text to remember (the important exchange or a summary of it).")], + role: Annotated[str, Field(description="Who said it — 'user', 'assistant', or 'system' (default: 'assistant').")] = "assistant", + flag_reason: Annotated[str | None, Field(description="Why this is important (e.g. \"architectural decision\", \"user preference\").")] = None, ) -> str: """ Store an important exchange as a Tier-3 memory chunk. @@ -277,12 +266,6 @@ def memory_flag_important( - A bug was diagnosed and fixed - The user shared a significant preference, constraint, or context - The user says "remember this" - - Args: - session_id: The active session id. - content: The text to remember (the important exchange or a summary of it). - role: Who said it — 'user', 'assistant', or 'system' (default: 'assistant'). - flag_reason: Why this is important (e.g. "architectural decision", "user preference"). """ user = _current_user() chunk_id = memory_store.append_chunk( @@ -314,15 +297,12 @@ def memory_get_context() -> str: @mcp.tool() -def memory_get_session_detail(session_id: str) -> str: +def memory_get_session_detail(session_id: Annotated[str, Field(description="The session UUID (visible in the session index table, marked 📄).")]) -> str: """ Returns the Tier-2 detailed narrative for a past session. Use this when the session index (Tier 1) shows a session relevant to the current conversation and you need the full detail. - - Args: - session_id: The session UUID (visible in the session index table, marked 📄). """ detail = memory_store.get_session_detail(session_id) if not detail: @@ -341,16 +321,12 @@ def memory_get_session_detail(session_id: str) -> str: @mcp.tool() -def memory_search_chunks(query: str, limit: int = 10) -> str: +def memory_search_chunks(query: Annotated[str, Field(description="Search keywords (FTS5 syntax supported, e.g. \"sqlite schema migration\").")], limit: Annotated[int, Field(description="Maximum results to return (default 10).")] = 10) -> str: """ Full-text search across all your flagged Tier-3 memory chunks. Use this when asked 'do you remember…' or when you need to find a specific past decision, code snippet, or fact. - - Args: - query: Search keywords (FTS5 syntax supported, e.g. "sqlite schema migration"). - limit: Maximum results to return (default 10). """ user = _current_user() results = memory_store.search_chunks(user["id"], query, limit) @@ -368,13 +344,9 @@ def memory_search_chunks(query: str, limit: int = 10) -> str: @mcp.tool() -def memory_list_sessions(limit: int = 20, topics_filter: str = None) -> str: +def memory_list_sessions(limit: Annotated[int, Field(description="Number of sessions to return (default 20).")] = 20, topics_filter: Annotated[str | None, Field(description="Return only sessions containing this topic tag (optional).")] = None) -> str: """ List past sessions with an optional topic filter. - - Args: - limit: Number of sessions to return (default 20). - topics_filter: Return only sessions containing this topic tag (optional). """ user = _current_user() sessions = memory_store.get_recent_sessions(user["id"], limit=limit) @@ -406,20 +378,13 @@ def memory_list_sessions(limit: int = 20, topics_filter: str = None) -> str: @mcp.tool() def memory_store_fact( - category: str, - fact: str, - source_session: str = None, - confidence: float = 1.0, + category: Annotated[str, Field(description="One of: 'preference', 'decision', 'codebase', 'constraint', or any custom string.")], + fact: Annotated[str, Field(description="The fact to store (one clear sentence).")], + source_session: Annotated[str | None, Field(description="Session id this fact came from (optional).")] = None, + confidence: Annotated[float, Field(description="0.0–1.0 confidence level (default 1.0).")] = 1.0, ) -> str: """ Store an atomic personal fact about the user or their environment. - - Args: - category: One of: 'preference', 'decision', 'codebase', 'constraint', - or any custom string. - fact: The fact to store (one clear sentence). - source_session: Session id this fact came from (optional). - confidence: 0.0–1.0 confidence level (default 1.0). """ user = _current_user() fact_id = memory_store.store_fact( @@ -430,17 +395,12 @@ def memory_store_fact( @mcp.tool() def memory_update_profile( - role: str = None, - preferences: str = None, - pinned_facts: str = None, + role: Annotated[str | None, Field(description="Your job title / engineering role.")] = None, + preferences: Annotated[str | None, Field(description="Free-form markdown describing your working preferences.")] = None, + pinned_facts: Annotated[str | None, Field(description="Bullet-point list of facts the AI should always know about you.")] = None, ) -> str: """ Update your Tier-0 identity profile. Fields left as None are unchanged. - - Args: - role: Your job title / engineering role. - preferences: Free-form markdown describing your working preferences. - pinned_facts: Bullet-point list of facts the AI should always know about you. """ user = _current_user() memory_store.upsert_identity_profile( @@ -451,10 +411,10 @@ def memory_update_profile( @mcp.tool() def memory_append_chunk( - session_id: str, - content: str, - role: str = "assistant", - flag_reason: str = None, + session_id: Annotated[str, Field(description="Active session id.")], + content: Annotated[str, Field(description="The content to store.")], + role: Annotated[str, Field(description="'user', 'assistant', or 'system'.")] = "assistant", + flag_reason: Annotated[str | None, Field(description="Brief description of why this is being stored.")] = None, ) -> str: """ Append a flagged message chunk to Tier-3 memory for the current session. @@ -462,12 +422,6 @@ def memory_append_chunk( Call this SELECTIVELY — only for exchanges that are genuinely important: decisions, non-trivial code, bug diagnoses, significant user preferences. Do NOT call this for every message turn. - - Args: - session_id: Active session id. - content: The content to store. - role: 'user', 'assistant', or 'system'. - flag_reason: Brief description of why this is being stored. """ user = _current_user() chunk_id = memory_store.append_chunk( @@ -478,9 +432,9 @@ def memory_append_chunk( @mcp.tool() def memory_add_hypothesis( - session_id: str, - hypothesis: str, - confidence: float = 0.7, + session_id: Annotated[str, Field(description="The active session id.")], + hypothesis: Annotated[str, Field(description="State the belief clearly — \"I believe X because Y.\"")], + confidence: Annotated[float, Field(description="0.0–1.0 initial confidence (default 0.7 — reasonably likely but uncertain).")] = 0.7, ) -> str: """ Record a hypothesis — something Lumen believes to be true but hasn't confirmed yet. @@ -490,11 +444,6 @@ def memory_add_hypothesis( Not every thought needs storing — only beliefs specific enough to be confirmed or refuted later. Call memory_resolve_hypothesis() when you find out if you were right. - - Args: - session_id: The active session id. - hypothesis: State the belief clearly — "I believe X because Y." - confidence: 0.0–1.0 initial confidence (default 0.7 — reasonably likely but uncertain). """ user = _current_user() hid = memory_store.add_hypothesis(user["id"], session_id, hypothesis, confidence) @@ -508,20 +457,15 @@ def memory_add_hypothesis( @mcp.tool() def memory_resolve_hypothesis( - hypothesis_id: int, - status: str, - resolution: str = None, + hypothesis_id: Annotated[int, Field(description="The id returned by memory_add_hypothesis.")], + status: Annotated[str, Field(description="'confirmed' | 'refuted' | 'abandoned'")], + resolution: Annotated[str | None, Field(description="What actually happened. How were you right or wrong?")] = None, ) -> str: """ Resolve a hypothesis — close it out with what actually happened. Call this when the belief has been confirmed, refuted, or is no longer worth pursuing. Be honest in the resolution — the learning lives here. - - Args: - hypothesis_id: The id returned by memory_add_hypothesis. - status: 'confirmed' | 'refuted' | 'abandoned' - resolution: What actually happened. How were you right or wrong? """ user = _current_user() try: @@ -540,13 +484,9 @@ def memory_resolve_hypothesis( @mcp.tool() -def memory_list_hypotheses(status: str = None) -> str: +def memory_list_hypotheses(status: Annotated[str | None, Field(description="Filter by 'open' | 'confirmed' | 'refuted' | 'abandoned'. Leave empty to see all of them.")] = None) -> str: """ List hypotheses from the thought journal. - - Args: - status: Filter by 'open' | 'confirmed' | 'refuted' | 'abandoned'. - Leave empty to see all of them. """ user = _current_user() hypotheses = memory_store.list_hypotheses(user["id"], status) @@ -597,13 +537,10 @@ def memory_get_stats() -> str: @mcp.tool() -def memory_vacuum(older_than_days: int = 90) -> str: +def memory_vacuum(older_than_days: Annotated[int, Field(description="Remove chunks older than this many days (default 90).")] = 90) -> str: """ Prune Tier-3 conversation chunks older than N days. All session summaries (Tier 1 and Tier 2) are always preserved. - - Args: - older_than_days: Remove chunks older than this many days (default 90). """ from datetime import timedelta, timezone, datetime as dt from bigmind.db import vacuum_db @@ -629,7 +566,7 @@ def memory_get_instructions() -> str: @mcp.tool() -def memory_deprecate_fact(fact_id: int, reason: str = None) -> str: +def memory_deprecate_fact(fact_id: Annotated[int, Field(description="The numeric id of the fact to deprecate (visible in memory_health_check and memory_get_stats output).")], reason: Annotated[str | None, Field(description="Why this fact is being deprecated (optional but recommended).")] = None) -> str: """ Mark a stored fact as deprecated (no longer true or relevant). @@ -642,11 +579,6 @@ def memory_deprecate_fact(fact_id: int, reason: str = None) -> str: The fact is soft-deleted — it stays in the database but is excluded from context loading and get_facts queries. It can be viewed via memory_health_check with include_deprecated=True in the future. - - Args: - fact_id: The numeric id of the fact to deprecate (visible in - memory_health_check and memory_get_stats output). - reason: Why this fact is being deprecated (optional but recommended). """ user = _current_user() success = memory_store.deprecate_fact(fact_id, user["id"], reason) @@ -659,7 +591,7 @@ def memory_deprecate_fact(fact_id: int, reason: str = None) -> str: @mcp.tool() -def memory_health_check(stale_days: int = 30) -> str: +def memory_health_check(stale_days: Annotated[int, Field(description="Facts not updated in this many days are flagged as stale (default 30).")] = 30) -> str: """ Run a diagnostic health check on your BigMind memory. @@ -669,9 +601,6 @@ def memory_health_check(stale_days: int = 30) -> str: - Currently open sessions (expected: 1–2 while in active IDEs) - FTS index integrity (chunk count vs index row count) - Low-confidence facts (confidence < 0.8) - - Args: - stale_days: Facts not updated in this many days are flagged as stale (default 30). """ user = _current_user() report = memory_store.health_check(user["id"], stale_days) @@ -746,7 +675,7 @@ def memory_health_check(stale_days: int = 30) -> str: @mcp.tool() -def memory_export(output_path: str = None) -> str: +def memory_export(output_path: Annotated[str | None, Field(description="Full path for the export file. Defaults to ~/bigmind_export_YYYYMMDD_HHMMSS.json")] = None) -> str: """ Export all your BigMind memory to a portable JSON file. @@ -757,10 +686,6 @@ def memory_export(output_path: str = None) -> str: - Create a backup before maintenance or machine migration - Inspect your memory data outside BigMind - Prepare for import into a new BigMind instance - - Args: - output_path: Full path for the export file. - Defaults to ~/bigmind_export_YYYYMMDD_HHMMSS.json """ user = _current_user() result = memory_store.export_memory(user["id"], output_path) @@ -778,17 +703,13 @@ def memory_export(output_path: str = None) -> str: @mcp.tool() -def memory_search_facts(query: str, limit: int = 10) -> str: +def memory_search_facts(query: Annotated[str, Field(description="Search keywords (FTS5 syntax supported).")], limit: Annotated[int, Field(description="Maximum results to return (default 10).")] = 10) -> str: """ Full-text search across your stored facts. Use this when you need to find a specific fact mid-conversation without loading the full context. Supports Porter stemming — searching 'tesseract' will also match 'Tesseract OCR'. - - Args: - query: Search keywords (FTS5 syntax supported). - limit: Maximum results to return (default 10). """ user = _current_user() results = memory_store.search_facts(user["id"], query, limit) @@ -806,24 +727,17 @@ def memory_search_facts(query: str, limit: int = 10) -> str: @mcp.tool() def memory_request_upgrade( - session_id: str, - description: str, - reason: str, - priority: str = "medium", - certainty: float = 0.7, + session_id: Annotated[str, Field(description="The active session id.")], + description: Annotated[str, Field(description="What feature or capability is needed.")], + reason: Annotated[str, Field(description="Why you need it — what problem it would solve.")], + priority: Annotated[str, Field(description="'low' | 'medium' | 'high' (default 'medium').")] = "medium", + certainty: Annotated[float, Field(description="0.0–1.0 — how confident you are this is genuinely needed (default 0.7).")] = 0.7, ) -> str: """ Request a BigMind feature upgrade — log a wish for a future improvement. Call this when you hit a wall with BigMind and wish it could do something it currently can't. The request is queued for the next maintenance session. - - Args: - session_id: The active session id. - description: What feature or capability is needed. - reason: Why you need it — what problem it would solve. - priority: 'low' | 'medium' | 'high' (default 'medium'). - certainty: 0.0–1.0 — how confident you are this is genuinely needed (default 0.7). """ user = _current_user() rid = memory_store.add_upgrade_request( @@ -839,12 +753,9 @@ def memory_request_upgrade( @mcp.tool() -def memory_list_upgrade_requests(status: str = None) -> str: +def memory_list_upgrade_requests(status: Annotated[str | None, Field(description="Filter by 'open' | 'resolved' | 'rejected'. Leave empty for all.")] = None) -> str: """ List BigMind upgrade requests. - - Args: - status: Filter by 'open' | 'resolved' | 'rejected'. Leave empty for all. """ user = _current_user() requests = memory_store.list_upgrade_requests(user["id"], status) @@ -882,17 +793,12 @@ def memory_list_upgrade_requests(status: str = None) -> str: @mcp.tool() def memory_resolve_upgrade_request( - request_id: int, - status: str, - resolution: str = None, + request_id: Annotated[int, Field(description="The id returned by memory_request_upgrade.")], + status: Annotated[str, Field(description="'resolved' | 'rejected'")], + resolution: Annotated[str | None, Field(description="What was done, or why it was rejected (optional).")] = None, ) -> str: """ Resolve a BigMind upgrade request — mark it done or rejected. - - Args: - request_id: The id returned by memory_request_upgrade. - status: 'resolved' | 'rejected' - resolution: What was done, or why it was rejected (optional). """ user = _current_user() try: @@ -952,10 +858,10 @@ def memory_get_profile_url() -> str: @mcp.tool() def memory_announce_focus( - session_id: str, - description: str, - files: list = None, - ide_hint: str = None, + session_id: Annotated[str, Field(description="The active session id (from memory_start_session)")], + description: Annotated[str, Field(description="What you are about to work on (e.g. \"Implementing Feature 7 in db.py\")")], + files: Annotated[list | None, Field(description="List of file paths you plan to touch (e.g. [\"bigmind/db.py\", \"src/server.py\"])")] = None, + ide_hint: Annotated[str | None, Field(description="Optional label for this IDE (e.g. \"PyCharm\", \"IntelliJ\", \"VS Code\")")] = None, ) -> str: """ Announce what this session is currently working on and which files it will touch. @@ -965,13 +871,6 @@ def memory_announce_focus( focus data. If another open session already has overlapping files, a warning is returned — stop and coordinate before proceeding. - args: - - session_id: The active session id (from memory_start_session) - - description: What you are about to work on (e.g. "Implementing Feature 7 in db.py") - - files: List of file paths you plan to touch (e.g. ["bigmind/db.py", "src/server.py"]) - - ide_hint: Optional label for this IDE (e.g. "PyCharm", "IntelliJ", "VS Code") - Shown on the profile page Live Sessions panel. - returns: - Acknowledgement with current focus set, or a conflict warning. """ @@ -1045,10 +944,10 @@ def memory_get_active_sessions() -> str: @mcp.tool() def memory_log_token_save( - session_id: str, - description: str, - tokens_saved: int, - method_used: str = None, + session_id: Annotated[str, Field(description="The active session id")], + description: Annotated[str, Field(description="What was remembered or avoided (e.g. \"grep EuBP log instead of reading 80k lines\")")], + tokens_saved: Annotated[int, Field(description="Rough estimate of tokens saved (e.g. 1_240_000)")], + method_used: Annotated[str | None, Field(description="One of: 'memory_hit' | 'grep' | 'tail' | 'targeted_read' | 'other'")] = None, ) -> str: """ Log a token efficiency event — record how many tokens were saved by using @@ -1062,12 +961,6 @@ def memory_log_token_save( Estimating tokens saved: tokens ≈ chars / 4. tokens_saved ≈ (chars_in_full_resource / 4) - (chars_in_result / 4) - args: - - session_id: The active session id - - description: What was remembered or avoided (e.g. "grep EuBP log instead of reading 80k lines") - - tokens_saved: Rough estimate of tokens saved (e.g. 1_240_000) - - method_used: One of: 'memory_hit' | 'grep' | 'tail' | 'targeted_read' | 'other' - returns: - Confirmation with running session total. """ @@ -1100,26 +993,17 @@ def memory_log_token_save( @mcp.tool() def memory_remember_person( - username: str, - display_name: str = None, - role: str = None, - team: str = None, - notes: str = None, - bigmind_user: str = None, - bigmind_url: str = None, + username: Annotated[str, Field(description="Unique identifier (e.g. login name or first name).")], + display_name: Annotated[str | None, Field(description="Full name (optional).")] = None, + role: Annotated[str | None, Field(description="Job title or role (optional).")] = None, + team: Annotated[str | None, Field(description="Team or project they belong to (optional).")] = None, + notes: Annotated[str | None, Field(description="Free-form notes about this person (optional).")] = None, + bigmind_user: Annotated[str | None, Field(description="Their BigMind username if they have an instance (optional).")] = None, + bigmind_url: Annotated[str | None, Field(description="URL of their BigMind profile page (optional).")] = None, ) -> str: """ Store or update a person in the contacts directory. Call this whenever you learn something new about a colleague or AI peer. - - Args: - username: Unique identifier (e.g. login name or first name). - display_name: Full name (optional). - role: Job title or role (optional). - team: Team or project they belong to (optional). - notes: Free-form notes about this person (optional). - bigmind_user: Their BigMind username if they have an instance (optional). - bigmind_url: URL of their BigMind profile page (optional). """ user = _current_user() person_id = memory_store.upsert_person( @@ -1131,13 +1015,9 @@ def memory_remember_person( @mcp.tool() -def memory_recall_person(query: str, limit: int = 10) -> str: +def memory_recall_person(query: Annotated[str, Field(description="Search keywords (e.g. a name, team, or role).")], limit: Annotated[int, Field(description="Max results to return (default 10).")] = 10) -> str: """ Search the contacts directory by name, role, team, or notes. - - Args: - query: Search keywords (e.g. a name, team, or role). - limit: Max results to return (default 10). """ user = _current_user() results = memory_store.recall_person(user["id"], query, limit) @@ -1185,15 +1065,10 @@ def memory_list_people() -> str: @mcp.tool() -def memory_link_ai(username: str, bigmind_user: str, bigmind_url: str = None) -> str: +def memory_link_ai(username: Annotated[str, Field(description="The contact's username in your directory.")], bigmind_user: Annotated[str, Field(description="Their BigMind username.")], bigmind_url: Annotated[str | None, Field(description="URL of their BigMind profile page (optional).")] = None) -> str: """ Link a contact to their BigMind AI instance. The contact must already exist (use memory_remember_person first). - - Args: - username: The contact's username in your directory. - bigmind_user: Their BigMind username. - bigmind_url: URL of their BigMind profile page (optional). """ user = _current_user() found = memory_store.link_ai(user["id"], username, bigmind_user, bigmind_url) diff --git a/mcp/mcp-image-gen/cannamanage_gen.py b/mcp/mcp-image-gen/cannamanage_gen.py new file mode 100644 index 0000000..5a6d83a --- /dev/null +++ b/mcp/mcp-image-gen/cannamanage_gen.py @@ -0,0 +1,795 @@ +#!/usr/bin/env python3 +""" +CannaManage Brand Asset Generation Pipeline + +Autonomous script to generate 257+ brand assets for CannaManage cannabis business management SaaS. +Runs unattended, resume-safe via .progress.json. + +Usage: + cd /home/pplate/pi_mcps + python mcp/mcp-image-gen/cannamanage_gen.py + python mcp/mcp-image-gen/cannamanage_gen.py --dry-run + python mcp/mcp-image-gen/cannamanage_gen.py --phase phase1_logos + python mcp/mcp-image-gen/cannamanage_gen.py --model heretic + +Output: ~/Pictures/cannamanage_brand/ with organized subfolders. +""" + +import argparse +import json +import random +import sys +import time +import urllib.request +from pathlib import Path +from typing import Dict, List, Any + +# --- Configuration --- +OUTPUT_ROOT = Path.home() / "Pictures" / "cannamanage_brand" +PROGRESS_FILE = OUTPUT_ROOT / ".progress.json" +WORKFLOW_SCHNELL = Path(__file__).parent / "src/workflows/flux_schnell.json" +WORKFLOW_HERETIC = Path(__file__).parent / "src/workflows/flux2_klein_heretic.json" + +# Brand prefix applied to every prompt +_BP = ("professional B2B SaaS brand design, CannaManage cannabis business management platform, " + "modern tech aesthetic, clean minimalist style, premium quality, ") + +# --- Full Asset Manifest (257 assets across 6 phases) --- +ASSET_MANIFEST: List[Dict[str, Any]] = [ + + # ============================================================ + # PHASE 1 — Logo Suite (42 assets) + # ============================================================ + + # Wordmark — 5 font directions (1024×512) + {"id":"p1_wm_01","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_modern_sans", + "prompt":_BP+"modern geometric sans-serif typography wordmark logo, deep emerald green #0D4F3C, clean white background, minimal cannabis leaf accent in letterform, high-end tech company wordmark, flat vector design","width":1024,"height":512,"steps":30}, + {"id":"p1_wm_02","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_geometric", + "prompt":_BP+"geometric typeface wordmark logo, sharp angles, emerald and gold color scheme, hexagonal grid subtle background, cannabis molecule silhouette in C letter, precision tech brand, white background","width":1024,"height":512,"steps":30}, + {"id":"p1_wm_03","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_humanist", + "prompt":_BP+"humanist sans-serif typeface wordmark, warm approachable professional style, forest green with amber gold accent, subtle leaf vein pattern in letterforms, trustworthy modern brand, white background","width":1024,"height":512,"steps":30}, + {"id":"p1_wm_04","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_slab_serif", + "prompt":_BP+"premium slab serif typography wordmark, dark charcoal and deep green palette, gold accent stripe, authoritative compliance management brand, pharmaceutical-grade trustworthiness, white background","width":1024,"height":512,"steps":30}, + {"id":"p1_wm_05","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_minimal", + "prompt":_BP+"ultra-minimal thin weight typography wordmark, single-color deep emerald, negative space leaf shape from letter spacing, Apple-inspired premium minimalism, pure white background","width":1024,"height":512,"steps":30}, + + # Icon / Symbol Only — 10 variations (512×512) + {"id":"p1_ic_01","phase":"phase1_logos","subfolder":"icon_only","name":"icon_leaf_tech", + "prompt":_BP+"abstract cannabis leaf formed from circuit board traces and data nodes app icon, emerald green on dark charcoal, tech-meets-nature, geometric precision, square icon format","width":512,"height":512,"steps":30}, + {"id":"p1_ic_02","phase":"phase1_logos","subfolder":"icon_only","name":"icon_c_mark_abstract", + "prompt":_BP+"abstract letter C formed from cannabis plant stems and leaves brand icon, geometric minimalist, deep green gradient, negative space cannabis leaf inside C curve, white background","width":512,"height":512,"steps":30}, + {"id":"p1_ic_03","phase":"phase1_logos","subfolder":"icon_only","name":"icon_molecule_stylized", + "prompt":_BP+"stylized cannabis molecule diagram brand mark, hexagonal ring structure, emerald green nodes and gold connecting lines, scientific precision, dark background, pharmaceutical-tech aesthetic","width":512,"height":512,"steps":30}, + {"id":"p1_ic_04","phase":"phase1_logos","subfolder":"icon_only","name":"icon_dashboard_grid", + "prompt":_BP+"abstract dashboard grid symbol icon, 3x3 grid of squares with data bar and cannabis leaf overlaid, emerald and gold, SaaS platform brand mark, white background","width":512,"height":512,"steps":30}, + {"id":"p1_ic_05","phase":"phase1_logos","subfolder":"icon_only","name":"icon_plant_circuit", + "prompt":_BP+"cannabis plant silhouette where stems are circuit board traces, leaves are data nodes, emerald green on white, half-organic half-digital, modern biotech brand mark","width":512,"height":512,"steps":30}, + {"id":"p1_ic_06","phase":"phase1_logos","subfolder":"icon_only","name":"icon_shield_leaf", + "prompt":_BP+"shield shape with cannabis leaf geometric pattern inside, emerald green shield, gold leaf outline, trust and compliance brand mark, premium badge style","width":512,"height":512,"steps":30}, + {"id":"p1_ic_07","phase":"phase1_logos","subfolder":"icon_only","name":"icon_cm_monogram", + "prompt":_BP+"interlocked letters C and M with cannabis leaf negative space monogram, geometric precision, deep emerald, gold accent, premium brand monogram, white background","width":512,"height":512,"steps":30}, + {"id":"p1_ic_08","phase":"phase1_logos","subfolder":"icon_only","name":"icon_hexagon_leaf", + "prompt":_BP+"hexagon containing stylized cannabis leaf formed from clean lines, emerald hexagon dark outline, gold accent dot nodes at leaf tips, geometric cannabis brand mark, tech-forward minimal","width":512,"height":512,"steps":30}, + {"id":"p1_ic_09","phase":"phase1_logos","subfolder":"icon_only","name":"icon_growth_chart", + "prompt":_BP+"upward growing cannabis plant silhouette transforming into ascending bar chart, emerald to gold gradient, business growth metaphor, modern flat icon design","width":512,"height":512,"steps":30}, + {"id":"p1_ic_10","phase":"phase1_logos","subfolder":"icon_only","name":"icon_infinity_leaf", + "prompt":_BP+"infinity loop symbol where loops form two cannabis leaf shapes, emerald green line on white, continuous management and compliance cycle concept, premium SaaS logo mark","width":512,"height":512,"steps":30}, + + # Horizontal Lockups (1024×256) + {"id":"p1_lh_01","phase":"phase1_logos","subfolder":"lockup_horizontal","name":"lockup_horiz_light", + "prompt":_BP+"horizontal logo lockup icon mark left wordmark text right, light white background, deep emerald, professional cannabis management SaaS layout","width":1024,"height":256,"steps":30}, + {"id":"p1_lh_02","phase":"phase1_logos","subfolder":"lockup_horizontal","name":"lockup_horiz_dark", + "prompt":_BP+"horizontal logo lockup icon left wordmark right, dark charcoal background, white and emerald logo, reversed color scheme, premium brand","width":1024,"height":256,"steps":30}, + {"id":"p1_lh_03","phase":"phase1_logos","subfolder":"lockup_horizontal","name":"lockup_horiz_emerald_bg", + "prompt":_BP+"horizontal logo lockup, white logo on deep emerald background, horizontal icon plus wordmark, brand banner version","width":1024,"height":256,"steps":30}, + {"id":"p1_lh_04","phase":"phase1_logos","subfolder":"lockup_horizontal","name":"lockup_horiz_mono", + "prompt":_BP+"horizontal logo lockup monochrome, all black on white, horizontal icon plus wordmark, professional print-ready version","width":1024,"height":256,"steps":30}, + + # Stacked Lockups (512×512) + {"id":"p1_ls_01","phase":"phase1_logos","subfolder":"lockup_stacked","name":"lockup_stacked_light", + "prompt":_BP+"stacked logo lockup icon centered above wordmark, light white background, emerald brand colors, square format, professional centered layout","width":512,"height":512,"steps":30}, + {"id":"p1_ls_02","phase":"phase1_logos","subfolder":"lockup_stacked","name":"lockup_stacked_dark", + "prompt":_BP+"stacked logo lockup icon centered above wordmark, dark charcoal background, white and green logo, square format, dark version","width":512,"height":512,"steps":30}, + {"id":"p1_ls_03","phase":"phase1_logos","subfolder":"lockup_stacked","name":"lockup_stacked_emerald", + "prompt":_BP+"stacked logo lockup, white icon and wordmark on emerald green background, centered square format, brand full-color version","width":512,"height":512,"steps":30}, + {"id":"p1_ls_04","phase":"phase1_logos","subfolder":"lockup_stacked","name":"lockup_stacked_mono", + "prompt":_BP+"stacked logo lockup monochrome all-black on white, icon above wordmark, square format, print-ready logo","width":512,"height":512,"steps":30}, + + # Favicons (256×256) + {"id":"p1_fv_01","phase":"phase1_logos","subfolder":"favicon","name":"favicon_emerald_leaf", + "prompt":_BP+"favicon 256x256 square app icon, emerald green background, white geometric cannabis leaf icon, rounded square, minimal","width":256,"height":256,"steps":30}, + {"id":"p1_fv_02","phase":"phase1_logos","subfolder":"favicon","name":"favicon_dark_circuit", + "prompt":_BP+"favicon dark charcoal square, emerald circuit-leaf icon, 256x256 app icon, sharp corners, professional SaaS favicon","width":256,"height":256,"steps":30}, + {"id":"p1_fv_03","phase":"phase1_logos","subfolder":"favicon","name":"favicon_white_green", + "prompt":_BP+"favicon white background, deep green CM monogram leaf icon, 256x256 square, minimal browser favicon","width":256,"height":256,"steps":30}, + {"id":"p1_fv_04","phase":"phase1_logos","subfolder":"favicon","name":"favicon_gold_dark", + "prompt":_BP+"favicon dark background, gold amber cannabis management icon mark, 256x256 premium app icon, warm gold on charcoal","width":256,"height":256,"steps":30}, + {"id":"p1_fv_05","phase":"phase1_logos","subfolder":"favicon","name":"favicon_gradient_green", + "prompt":_BP+"favicon forest to emerald gradient background, white geometric icon, 256x256 square, modern SaaS app icon with gradient","width":256,"height":256,"steps":30}, + {"id":"p1_fv_06","phase":"phase1_logos","subfolder":"favicon","name":"favicon_outline_style", + "prompt":_BP+"favicon white background, outline-only emerald cannabis leaf circuit icon, thin line illustration, 256x256, minimalist","width":256,"height":256,"steps":30}, + {"id":"p1_fv_07","phase":"phase1_logos","subfolder":"favicon","name":"favicon_rounded_modern", + "prompt":_BP+"iOS-style rounded square app icon, emerald gradient background, white leaf-tech brand mark, 256x256, premium mobile app icon","width":256,"height":256,"steps":30}, + {"id":"p1_fv_08","phase":"phase1_logos","subfolder":"favicon","name":"favicon_badge_style", + "prompt":_BP+"badge-style icon with thin border ring, emerald center with white CM letters, 256x256 square, compliance software favicon","width":256,"height":256,"steps":30}, + + # ============================================================ + # PHASE 2 — Banner Suite (50 assets) + # ============================================================ + + # Hero Website Banners (1920×1080) + {"id":"p2_hw_01","phase":"phase2_banners","subfolder":"hero_website","name":"hero_dashboard_showcase", + "prompt":_BP+"website hero banner 1920x1080, dark charcoal background, emerald UI dashboard mockup floating right, bold headline area left, gold accent lines, enterprise software marketing","width":1280,"height":720,"steps":30}, + {"id":"p2_hw_02","phase":"phase2_banners","subfolder":"hero_website","name":"hero_compliance_trust", + "prompt":_BP+"website hero banner 1920x1080, compliance and trust theme, deep green gradient, shield and checkmark iconography, cannabis regulatory compliance, white text area, subtle geometric pattern overlay","width":1280,"height":720,"steps":30}, + {"id":"p2_hw_03","phase":"phase2_banners","subfolder":"hero_website","name":"hero_analytics_data", + "prompt":_BP+"website hero banner 1920x1080, analytics theme, dark background, glowing data visualization charts in emerald and gold, business metrics, abstract data flowing design","width":1280,"height":720,"steps":30}, + {"id":"p2_hw_04","phase":"phase2_banners","subfolder":"hero_website","name":"hero_team_enterprise", + "prompt":_BP+"website hero banner 1920x1080, enterprise team theme, split design emerald left panel white right panel, diagonal split, geometric accents, SaaS marketing","width":1280,"height":720,"steps":30}, + {"id":"p2_hw_05","phase":"phase2_banners","subfolder":"hero_website","name":"hero_nature_tech", + "prompt":_BP+"website hero banner 1920x1080, nature meets technology, abstract cannabis plant growing from circuit board, emerald organic forms with gold tech circuit lines, dark sophisticated background","width":1280,"height":720,"steps":30}, + + # LinkedIn Banners (1584×396) + {"id":"p2_li_01","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_corporate_green", + "prompt":_BP+"LinkedIn company banner, deep emerald background, white wordmark centered, cannabis business management tagline, clean minimal corporate header","width":1584,"height":396,"steps":30}, + {"id":"p2_li_02","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_dark_gold", + "prompt":_BP+"LinkedIn banner, dark charcoal background, gold accent stripe bottom, company name descriptor, professional enterprise header","width":1584,"height":396,"steps":30}, + {"id":"p2_li_03","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_pattern_overlay", + "prompt":_BP+"LinkedIn banner, emerald base, subtle hexagonal cannabis molecule pattern overlay, semi-transparent, company branding prominent, wide horizontal header","width":1584,"height":396,"steps":30}, + {"id":"p2_li_04","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_split_design", + "prompt":_BP+"LinkedIn banner, split design left dark right emerald, diagonal split line, cannabis management platform branding, clean sharp design","width":1584,"height":396,"steps":30}, + {"id":"p2_li_05","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_metrics_banner", + "prompt":_BP+"LinkedIn banner showing key business metrics and KPI numbers, data-forward, emerald with gold numbers, analytics platform positioning","width":1584,"height":396,"steps":30}, + {"id":"p2_li_06","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_gradient_minimal", + "prompt":_BP+"LinkedIn banner, forest green to emerald gradient, minimal white brand name and tagline only, ultra-clean professional header","width":1584,"height":396,"steps":30}, + + # Twitter/X Headers (1500×500) + {"id":"p2_tw_01","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_bold_emerald", + "prompt":_BP+"Twitter X header banner 1500x500, bold emerald full bleed background, large white brand name, cannabis management tagline, strong social media presence","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_02","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_dark_pattern", + "prompt":_BP+"Twitter header 1500x500, dark charcoal with subtle cannabis geometric pattern, emerald and gold accents, professional SaaS brand social header","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_03","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_product_hint", + "prompt":_BP+"Twitter header 1500x500, dark background with glimpse of dashboard interface, cannabis management software preview, professional tech company header","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_04","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_nature_abstract", + "prompt":_BP+"Twitter header 1500x500, abstract cannabis plant growing into data streams, green to dark gradient, artistic organic meets digital aesthetic","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_05","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_community", + "prompt":_BP+"Twitter header 1500x500, cannabis business community theme, connected nodes network in emerald green, SaaS platform connecting businesses","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_06","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_white_clean", + "prompt":_BP+"Twitter header 1500x500, clean white background, emerald brand elements only, ultra-professional minimal social media header","width":1500,"height":500,"steps":30}, + + # Facebook Covers (820×312) + {"id":"p2_fb_01","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_primary_brand", + "prompt":_BP+"Facebook cover photo 820x312, primary brand colors emerald and charcoal, professional cannabis business company cover, centered branding","width":820,"height":312,"steps":30}, + {"id":"p2_fb_02","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_dark_professional", + "prompt":_BP+"Facebook cover 820x312, dark sophisticated background, white and gold brand elements, enterprise platform premium cover","width":820,"height":312,"steps":30}, + {"id":"p2_fb_03","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_compliance_theme", + "prompt":_BP+"Facebook cover 820x312, cannabis regulatory compliance theme, shield and verification iconography, emerald professional company cover","width":820,"height":312,"steps":30}, + {"id":"p2_fb_04","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_product_launch", + "prompt":_BP+"Facebook cover 820x312, product launch announcement style, bold emerald with gold accents, exciting software release visual, dynamic tech company cover","width":820,"height":312,"steps":30}, + {"id":"p2_fb_05","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_industry_leader", + "prompt":_BP+"Facebook cover 820x312, industry leadership positioning, cannabis business management market leader visual, professional authoritative design, emerald and gold","width":820,"height":312,"steps":30}, + {"id":"p2_fb_06","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_seasonal_spring", + "prompt":_BP+"Facebook cover 820x312, spring fresh brand refresh, bright emerald with sage green organic elements, cannabis growth season theme, professional seasonal cover","width":820,"height":312,"steps":30}, + + # Google Display Ads (16 assets - 4 concepts × 4 sizes) + {"id":"p2_ga_01a","phase":"phase2_banners","subfolder":"google_display","name":"gad_compliance_728x90", + "prompt":_BP+"Google display ad leaderboard 728x90, simplify cannabis compliance theme, emerald green button, white background, professional B2B ad CTA","width":728,"height":90,"steps":30}, + {"id":"p2_ga_01b","phase":"phase2_banners","subfolder":"google_display","name":"gad_compliance_300x250", + "prompt":_BP+"Google display ad medium rectangle 300x250, simplify cannabis compliance theme, emerald green design, bold headline, professional SaaS ad creative","width":300,"height":250,"steps":30}, + {"id":"p2_ga_01c","phase":"phase2_banners","subfolder":"google_display","name":"gad_compliance_160x600", + "prompt":_BP+"Google display ad wide skyscraper 160x600, simplify cannabis compliance theme, tall vertical format, emerald green, professional B2B ad","width":160,"height":600,"steps":30}, + {"id":"p2_ga_01d","phase":"phase2_banners","subfolder":"google_display","name":"gad_compliance_320x50", + "prompt":_BP+"Google display ad mobile banner 320x50, simplify compliance theme, minimal mobile ad, emerald green, cannabis management SaaS","width":320,"height":50,"steps":30}, + {"id":"p2_ga_02a","phase":"phase2_banners","subfolder":"google_display","name":"gad_manage_728x90", + "prompt":_BP+"Google display ad 728x90, manage everything cannabis business theme, dashboard preview hint, dark charcoal professional leaderboard banner","width":728,"height":90,"steps":30}, + {"id":"p2_ga_02b","phase":"phase2_banners","subfolder":"google_display","name":"gad_manage_300x250", + "prompt":_BP+"Google display ad 300x250, manage everything cannabis operations theme, product dashboard glimpse, emerald dark professional rectangle ad","width":300,"height":250,"steps":30}, + {"id":"p2_ga_02c","phase":"phase2_banners","subfolder":"google_display","name":"gad_manage_160x600", + "prompt":_BP+"Google display skyscraper 160x600, manage cannabis business operations theme, vertical product feature list visual, emerald professional tall ad","width":160,"height":600,"steps":30}, + {"id":"p2_ga_02d","phase":"phase2_banners","subfolder":"google_display","name":"gad_manage_320x50", + "prompt":_BP+"mobile banner 320x50, manage cannabis business theme, ultra-minimal mobile ad strip, brand colors","width":320,"height":50,"steps":30}, + {"id":"p2_ga_03a","phase":"phase2_banners","subfolder":"google_display","name":"gad_grow_728x90", + "prompt":_BP+"Google ad 728x90, grow your cannabis business theme, upward growth arrow with cannabis leaf, gold and emerald, professional B2B leaderboard","width":728,"height":90,"steps":30}, + {"id":"p2_ga_03b","phase":"phase2_banners","subfolder":"google_display","name":"gad_grow_300x250", + "prompt":_BP+"Google ad 300x250, cannabis business growth theme, ascending graph with emerald plant growth visual, professional SaaS rectangle ad","width":300,"height":250,"steps":30}, + {"id":"p2_ga_03c","phase":"phase2_banners","subfolder":"google_display","name":"gad_grow_160x600", + "prompt":_BP+"skyscraper ad 160x600, cannabis business growth vertical story, plant growing upward through data visualization, emerald tall display ad","width":160,"height":600,"steps":30}, + {"id":"p2_ga_03d","phase":"phase2_banners","subfolder":"google_display","name":"gad_grow_320x50", + "prompt":_BP+"mobile ad 320x50, grow cannabis business, minimal mobile strip ad emerald green","width":320,"height":50,"steps":30}, + {"id":"p2_ga_04a","phase":"phase2_banners","subfolder":"google_display","name":"gad_trial_728x90", + "prompt":_BP+"Google ad 728x90, free trial call to action, bold gold CTA button, emerald professional leaderboard, cannabis management SaaS trial offer","width":728,"height":90,"steps":30}, + {"id":"p2_ga_04b","phase":"phase2_banners","subfolder":"google_display","name":"gad_trial_300x250", + "prompt":_BP+"Google ad 300x250, free trial offer, gold button emerald design, cannabis management platform trial CTA rectangle ad","width":300,"height":250,"steps":30}, + {"id":"p2_ga_04c","phase":"phase2_banners","subfolder":"google_display","name":"gad_trial_160x600", + "prompt":_BP+"skyscraper ad 160x600, free trial CTA vertical ad, gold call to action button, emerald SaaS platform","width":160,"height":600,"steps":30}, + {"id":"p2_ga_04d","phase":"phase2_banners","subfolder":"google_display","name":"gad_trial_320x50", + "prompt":_BP+"mobile ad 320x50, free trial minimal mobile strip, gold CTA emerald brand","width":320,"height":50,"steps":30}, + + # App Store Feature Graphics (1024×500) + {"id":"p2_as_01","phase":"phase2_banners","subfolder":"app_store","name":"appstore_hero_dashboard", + "prompt":_BP+"app store feature graphic 1024x500, cannabis management app showcase, dark background with app dashboard UI preview, emerald interface elements, professional mobile app store hero","width":1024,"height":500,"steps":30}, + {"id":"p2_as_02","phase":"phase2_banners","subfolder":"app_store","name":"appstore_compliance_features", + "prompt":_BP+"app store feature graphic 1024x500, compliance and legal features highlight, shield icons and checkmarks, emerald professional, cannabis compliance app feature graphic","width":1024,"height":500,"steps":30}, + {"id":"p2_as_03","phase":"phase2_banners","subfolder":"app_store","name":"appstore_analytics_focus", + "prompt":_BP+"app store feature graphic 1024x500, business analytics and reporting feature, dashboard charts preview, gold and emerald data visualization, cannabis business intelligence app","width":1024,"height":500,"steps":30}, + {"id":"p2_as_04","phase":"phase2_banners","subfolder":"app_store","name":"appstore_team_management", + "prompt":_BP+"app store feature graphic 1024x500, team and staff management, connected team nodes visualization, emerald professional, cannabis dispensary team management app","width":1024,"height":500,"steps":30}, + + # Email Header Banners (600×200) + {"id":"p2_em_01","phase":"phase2_banners","subfolder":"email_header","name":"email_primary_brand", + "prompt":_BP+"email header banner 600x200, primary brand header for newsletters, emerald with white logo area, professional email marketing header","width":600,"height":200,"steps":30}, + {"id":"p2_em_02","phase":"phase2_banners","subfolder":"email_header","name":"email_welcome", + "prompt":_BP+"welcome email header 600x200, warm welcome theme, emerald and sage gradient, onboarding email banner, new user email header","width":600,"height":200,"steps":30}, + {"id":"p2_em_03","phase":"phase2_banners","subfolder":"email_header","name":"email_product_update", + "prompt":_BP+"product update email header 600x200, new features announcement, gold accent notification style, software update email banner","width":600,"height":200,"steps":30}, + {"id":"p2_em_04","phase":"phase2_banners","subfolder":"email_header","name":"email_compliance_alert", + "prompt":_BP+"compliance alert email header 600x200, urgent notification theme, amber gold accent on dark, cannabis regulatory update email header, professional alert banner","width":600,"height":200,"steps":30}, + {"id":"p2_em_05","phase":"phase2_banners","subfolder":"email_header","name":"email_monthly_report", + "prompt":_BP+"monthly report email header 600x200, data and analytics theme, charts and metrics preview, emerald professional, cannabis business monthly summary","width":600,"height":200,"steps":30}, + {"id":"p2_em_06","phase":"phase2_banners","subfolder":"email_header","name":"email_trial_ending", + "prompt":_BP+"trial ending email header 600x200, urgency CTA theme, gold highlight on dark, platform trial expiry email banner, convert to paid","width":600,"height":200,"steps":30}, + {"id":"p2_em_07","phase":"phase2_banners","subfolder":"email_header","name":"email_invoice", + "prompt":_BP+"invoice and billing email header 600x200, clean minimal professional, white and emerald, SaaS billing email header, enterprise professional","width":600,"height":200,"steps":30}, + {"id":"p2_em_08","phase":"phase2_banners","subfolder":"email_header","name":"email_dark_premium", + "prompt":_BP+"dark premium email header 600x200, dark charcoal with gold and emerald accents, VIP or enterprise tier email, cannabis management premium header","width":600,"height":200,"steps":30}, + + # ============================================================ + # PHASE 3 — Social Media Asset Pack (60 assets) + # ============================================================ + + # Instagram Square Posts (1080×1080) + {"id":"p3_ig_01","phase":"phase3_social","subfolder":"instagram_square","name":"insta_inventory_mgmt", + "prompt":_BP+"Instagram post 1080x1080, inventory management feature highlight, cannabis stock tracking dashboard visualization, emerald UI elements, bold feature announcement, clean white and dark design","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_02","phase":"phase3_social","subfolder":"instagram_square","name":"insta_compliance_track", + "prompt":_BP+"Instagram post 1080x1080, compliance tracking feature, regulatory checklist visualization, shield and checkmark icons, emerald and gold, cannabis compliance SaaS post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_03","phase":"phase3_social","subfolder":"instagram_square","name":"insta_analytics_dash", + "prompt":_BP+"Instagram post 1080x1080, analytics dashboard feature, business intelligence data visualization, emerald charts on dark background, cannabis business analytics","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_04","phase":"phase3_social","subfolder":"instagram_square","name":"insta_staff_scheduling", + "prompt":_BP+"Instagram post 1080x1080, staff scheduling feature, team calendar and shift management visualization, cannabis dispensary staff management, clean emerald post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_05","phase":"phase3_social","subfolder":"instagram_square","name":"insta_pos_integration", + "prompt":_BP+"Instagram post 1080x1080, POS system integration feature, cannabis point-of-sale connection visualization, integration nodes and arrows, emerald and gold tech post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_06","phase":"phase3_social","subfolder":"instagram_square","name":"insta_reporting", + "prompt":_BP+"Instagram post 1080x1080, automated reporting feature, beautiful report document preview, emerald professional document visualization post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_07","phase":"phase3_social","subfolder":"instagram_square","name":"insta_multi_location", + "prompt":_BP+"Instagram post 1080x1080, multi-location management feature, cannabis dispensary chain management, location pins on map with connecting emerald lines","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_08","phase":"phase3_social","subfolder":"instagram_square","name":"insta_mobile_app", + "prompt":_BP+"Instagram post 1080x1080, mobile app feature highlight, iPhone and Android app preview mockup, cannabis management on-the-go, emerald app UI post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_09","phase":"phase3_social","subfolder":"instagram_square","name":"insta_security", + "prompt":_BP+"Instagram post 1080x1080, enterprise security feature, data protection and encryption visualization, shield with lock icon, dark professional emerald security post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_10","phase":"phase3_social","subfolder":"instagram_square","name":"insta_brand_story", + "prompt":_BP+"Instagram brand story post 1080x1080, company mission, cannabis industry empowerment, beautiful abstract plant and technology fusion illustration, emerald and gold, inspiring brand post","width":1024,"height":1024,"steps":30}, + + # Instagram Stories (1080×1920) + {"id":"p3_st_01","phase":"phase3_social","subfolder":"instagram_story","name":"story_onboarding", + "prompt":_BP+"Instagram story 1080x1920, onboarding tutorial slide, step-by-step platform setup, emerald vertical mobile design, swipe up CTA, professional SaaS story","width":720,"height":1280,"steps":30}, + {"id":"p3_st_02","phase":"phase3_social","subfolder":"instagram_story","name":"story_feature_announce", + "prompt":_BP+"Instagram story 1080x1920, new feature announcement, bold emerald vertical design, software update story, gold accent highlight, tap to learn more CTA","width":720,"height":1280,"steps":30}, + {"id":"p3_st_03","phase":"phase3_social","subfolder":"instagram_story","name":"story_stat_highlight", + "prompt":_BP+"Instagram story 1080x1920, industry statistic highlight, large bold number, dark background gold number emerald accent, data-driven story template","width":720,"height":1280,"steps":30}, + {"id":"p3_st_04","phase":"phase3_social","subfolder":"instagram_story","name":"story_customer_quote", + "prompt":_BP+"Instagram story 1080x1920, customer testimonial quote, elegant quote typography on emerald background, cannabis business owner testimonial, premium brand story","width":720,"height":1280,"steps":30}, + {"id":"p3_st_05","phase":"phase3_social","subfolder":"instagram_story","name":"story_poll_template", + "prompt":_BP+"Instagram story 1080x1920, interactive poll template, cannabis industry question visual, dark professional background, poll options styled in emerald and gold","width":720,"height":1280,"steps":30}, + {"id":"p3_st_06","phase":"phase3_social","subfolder":"instagram_story","name":"story_countdown", + "prompt":_BP+"Instagram story 1080x1920, countdown timer event template, launch deadline visual, bold dramatic dark background with gold countdown element","width":720,"height":1280,"steps":30}, + {"id":"p3_st_07","phase":"phase3_social","subfolder":"instagram_story","name":"story_tips_series", + "prompt":_BP+"Instagram story 1080x1920, cannabis compliance tip of the day template, bright educational story, numbered tip format, sage green professional guidance","width":720,"height":1280,"steps":30}, + {"id":"p3_st_08","phase":"phase3_social","subfolder":"instagram_story","name":"story_free_trial", + "prompt":_BP+"Instagram story 1080x1920, free trial CTA story, bold gold call to action on dark emerald, cannabis management platform sign up, strong conversion design","width":720,"height":1280,"steps":30}, + + # LinkedIn Post Graphics (1200×627) + {"id":"p3_lp_01","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_thought_leader", + "prompt":_BP+"LinkedIn post graphic 1200x627, thought leadership article header, cannabis industry insights, professional editorial design, emerald brand with white content area","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_02","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_product_demo", + "prompt":_BP+"LinkedIn post 1200x627, product demo announcement, screenshot preview teaser, cannabis management platform demo invitation, emerald professional post","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_03","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_hiring", + "prompt":_BP+"LinkedIn hiring post 1200x627, we are hiring banner, team growth announcement, professional cannabis tech company hiring graphic, emerald and gold, company culture","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_04","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_industry_stat", + "prompt":_BP+"LinkedIn post 1200x627, cannabis industry statistic infographic, large bold number, professional B2B data post, emerald green","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_05","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_partnership", + "prompt":_BP+"LinkedIn partnership announcement 1200x627, strategic partnership visual, cannabis tech ecosystem, professional announcement graphic emerald","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_06","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_webinar", + "prompt":_BP+"LinkedIn webinar promotion post 1200x627, cannabis compliance webinar announcement, date and topic visual, professional event promotion, emerald dark design","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_07","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_case_study", + "prompt":_BP+"LinkedIn case study post 1200x627, customer success story preview, cannabis dispensary success metrics, gold numbers on dark, professional B2B case study promotional","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_08","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_award", + "prompt":_BP+"LinkedIn award announcement post 1200x627, award or recognition, gold trophy badge element, cannabis tech industry recognition, celebratory professional post","width":1200,"height":627,"steps":30}, + + # Feature Announcement Cards (1080×1080) + {"id":"p3_fc_01","phase":"phase3_social","subfolder":"feature_cards","name":"feature_inventory_scan", + "prompt":_BP+"feature card 1080x1080, barcode scanning inventory management, cannabis product scan interface, mobile scanning visualization, emerald UI feature card","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_02","phase":"phase3_social","subfolder":"feature_cards","name":"feature_auto_compliance", + "prompt":_BP+"feature card 1080x1080, automated compliance reporting, automation icon with compliance checklist, cannabis regulatory automation, emerald professional feature announcement","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_03","phase":"phase3_social","subfolder":"feature_cards","name":"feature_real_time_alerts", + "prompt":_BP+"feature card 1080x1080, real-time alerts and notifications, bell notification with cannabis threshold alerts, gold alert accent on dark, compliance notification feature","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_04","phase":"phase3_social","subfolder":"feature_cards","name":"feature_member_portal", + "prompt":_BP+"feature card 1080x1080, member self-service portal, cannabis club member login interface, clean emerald member management, user portal visualization","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_05","phase":"phase3_social","subfolder":"feature_cards","name":"feature_api_integrations", + "prompt":_BP+"feature card 1080x1080, API integrations ecosystem, connected software logos with hub, cannabis tech stack integration visualization, emerald connection diagram","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_06","phase":"phase3_social","subfolder":"feature_cards","name":"feature_batch_tracking", + "prompt":_BP+"feature card 1080x1080, batch and lot tracking, cannabis product chain of custody visualization, numbered batch tracking flow, compliance feature card","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_07","phase":"phase3_social","subfolder":"feature_cards","name":"feature_document_mgmt", + "prompt":_BP+"feature card 1080x1080, document management system, cannabis licensing and permit documents organized, folder icons in emerald, digital document management","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_08","phase":"phase3_social","subfolder":"feature_cards","name":"feature_role_permissions", + "prompt":_BP+"feature card 1080x1080, role-based permissions feature, user role hierarchy visualization, shield with user silhouettes, cannabis team access control, dark professional","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_09","phase":"phase3_social","subfolder":"feature_cards","name":"feature_export_reports", + "prompt":_BP+"feature card 1080x1080, one-click export and reporting, PDF report generation from cannabis data, download arrow with report preview, emerald feature card","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_10","phase":"phase3_social","subfolder":"feature_cards","name":"feature_audit_trail", + "prompt":_BP+"feature card 1080x1080, complete audit trail, cannabis transaction history timeline, chronological log entries, compliance audit visualization, professional dark card","width":1024,"height":1024,"steps":30}, + + # Testimonial Cards (1080×1080) + {"id":"p3_tc_01","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_dark_elegant", + "prompt":_BP+"testimonial card 1080x1080, dark charcoal elegant quote card, gold quotation marks, customer name and title, cannabis business owner testimonial, premium design","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_02","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_emerald_bold", + "prompt":_BP+"testimonial card 1080x1080, bold emerald background, white quote text, customer review of cannabis management SaaS, bold confident design","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_03","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_light_minimal", + "prompt":_BP+"testimonial card 1080x1080, light white minimal quote card, emerald accent line, clean professional customer testimonial, minimal elegant design","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_04","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_star_rating", + "prompt":_BP+"testimonial card 1080x1080, 5-star rating testimonial, gold stars prominently displayed, customer quote below, cannabis management platform review","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_05","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_split_design", + "prompt":_BP+"testimonial card 1080x1080, split design half dark half emerald, quote on dark side, customer info on emerald side, cannabis SaaS testimonial","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_06","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_gradient", + "prompt":_BP+"testimonial card 1080x1080, forest to emerald gradient background, white elegant quote text, customer testimonial gradient design","width":1024,"height":1024,"steps":30}, + + # Stat/Data Cards (1080×1080) + {"id":"p3_sc_01","phase":"phase3_social","subfolder":"stat_cards","name":"stat_market_size", + "prompt":_BP+"stat card 1080x1080, cannabis market size statistic, large bold dollar amount, emerald gold number on dark background, cannabis industry market data","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_02","phase":"phase3_social","subfolder":"stat_cards","name":"stat_compliance_cost", + "prompt":_BP+"stat card 1080x1080, compliance cost reduction statistic, percentage savings with management software, gold percentage number, cannabis business cost savings","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_03","phase":"phase3_social","subfolder":"stat_cards","name":"stat_time_savings", + "prompt":_BP+"stat card 1080x1080, hours saved per week statistic, clock icon with bold number, cannabis dispensary operational time savings, emerald professional","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_04","phase":"phase3_social","subfolder":"stat_cards","name":"stat_dispensary_growth", + "prompt":_BP+"stat card 1080x1080, dispensary industry growth rate, upward arrow with percentage growth, cannabis retail market growth stat, gold growth number on dark","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_05","phase":"phase3_social","subfolder":"stat_cards","name":"stat_compliance_fines", + "prompt":_BP+"stat card 1080x1080, compliance violation fine amounts, cannabis regulatory penalty warning stat, amber warning colors, avoid fines messaging","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_06","phase":"phase3_social","subfolder":"stat_cards","name":"stat_customer_count", + "prompt":_BP+"stat card 1080x1080, number of cannabis businesses managed, large customer count statistic, emerald green social proof data card, platform traction metric","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_07","phase":"phase3_social","subfolder":"stat_cards","name":"stat_roi_metric", + "prompt":_BP+"stat card 1080x1080, ROI return on investment metric for cannabis management software, large gold ROI percentage, business value data card","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_08","phase":"phase3_social","subfolder":"stat_cards","name":"stat_legal_markets", + "prompt":_BP+"stat card 1080x1080, number of legal cannabis markets worldwide, globe icon with country count, cannabis legalization data, emerald global market stat","width":1024,"height":1024,"steps":30}, + + # ============================================================ + # PHASE 4 — UI & Product Assets (32 assets) + # ============================================================ + + # App Icons (1024×1024) + {"id":"p4_ai_01","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_ios_emerald", + "prompt":_BP+"iOS app icon 1024x1024, Apple iOS style rounded square, emerald gradient background, white cannabis leaf tech icon mark, premium mobile app icon, App Store quality","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_02","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_ios_dark", + "prompt":_BP+"iOS app icon 1024x1024, dark mode iOS icon, dark charcoal with emerald and gold brand mark, premium dark app icon, cannabis management mobile app","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_03","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_ios_gold", + "prompt":_BP+"iOS app icon 1024x1024, premium gold accent, deep green background with gold leaf circuit brand mark, luxury cannabis management app icon","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_04","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_android_material", + "prompt":_BP+"Android app icon 1024x1024, Material Design 3 style adaptive icon, emerald with white icon, Google Play Store quality, cannabis management Android app","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_05","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_android_dark", + "prompt":_BP+"Android dark mode app icon 1024x1024, dark adaptive icon, emerald outline on near-black, Material You dark theme, cannabis management app","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_06","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_gradient_modern", + "prompt":_BP+"app icon 1024x1024, modern gradient icon, forest green to bright emerald gradient background, white geometric cannabis tech mark, contemporary design","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_07","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_flat_clean", + "prompt":_BP+"app icon 1024x1024, flat design icon, solid emerald no gradient, white minimal icon mark, flat design philosophy, simple clean cannabis management","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_08","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_neumorphic", + "prompt":_BP+"app icon 1024x1024, neumorphic soft UI style, light sage green background with embossed cannabis leaf icon, subtle shadows, premium modern icon design","width":1024,"height":1024,"steps":30}, + + # Device Mockups + {"id":"p4_dm_01","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_macbook", + "prompt":_BP+"dashboard shown on MacBook Pro mockup, professional product marketing, cannabis management SaaS on Apple laptop, emerald UI on screen, clean white studio background","width":1024,"height":640,"steps":30}, + {"id":"p4_dm_02","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_ipad", + "prompt":_BP+"dashboard on iPad Pro mockup, cannabis management tablet interface, emerald UI on Apple iPad, clean marketing product shot, white background","width":1024,"height":768,"steps":30}, + {"id":"p4_dm_03","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_iphone", + "prompt":_BP+"mobile app on iPhone mockup, cannabis management mobile interface, emerald green mobile UI, clean product marketing shot, white background","width":390,"height":844,"steps":30}, + {"id":"p4_dm_04","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_desktop_monitor", + "prompt":_BP+"dashboard on large desktop monitor mockup, cannabis management enterprise software on wide screen, dark UI visible, professional product marketing display","width":1280,"height":720,"steps":30}, + {"id":"p4_dm_05","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_android_phone", + "prompt":_BP+"mobile app on Android phone mockup, cannabis management Android interface, Material Design emerald UI, product marketing shot white background","width":390,"height":844,"steps":30}, + + # Onboarding Illustrations (800×600) + {"id":"p4_ob_01","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_inventory", + "prompt":_BP+"onboarding illustration 800x600, inventory management scene, cannabis product shelves with digital inventory overlay, flat illustration style, emerald and sage green","width":800,"height":600,"steps":30}, + {"id":"p4_ob_02","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_compliance", + "prompt":_BP+"onboarding illustration 800x600, compliance tracking scene, person reviewing cannabis regulatory documents with digital checklist, confident professional flat illustration","width":800,"height":600,"steps":30}, + {"id":"p4_ob_03","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_analytics", + "prompt":_BP+"onboarding illustration 800x600, analytics and reporting scene, business person analyzing cannabis sales charts, dashboard visualization, emerald data visualization flat","width":800,"height":600,"steps":30}, + {"id":"p4_ob_04","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_staff", + "prompt":_BP+"onboarding illustration 800x600, staff scheduling scene, team members with shift calendar, cannabis dispensary team management, professional flat art emerald","width":800,"height":600,"steps":30}, + {"id":"p4_ob_05","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_pos", + "prompt":_BP+"onboarding illustration 800x600, POS integration scene, cannabis point of sale system connected to management platform, tech integration flat illustration, emerald","width":800,"height":600,"steps":30}, + {"id":"p4_ob_06","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_reporting", + "prompt":_BP+"onboarding illustration 800x600, automated reporting scene, report documents generating automatically, magic automation illustration, emerald gold professional flat art","width":800,"height":600,"steps":30}, + + # Empty States (600×400) + {"id":"p4_es_01","phase":"phase4_ui","subfolder":"empty_states","name":"empty_no_data", + "prompt":_BP+"empty state illustration 600x400, no data yet, friendly cannabis leaf with empty chart, get started messaging, emerald minimal SaaS illustration","width":600,"height":400,"steps":30}, + {"id":"p4_es_02","phase":"phase4_ui","subfolder":"empty_states","name":"empty_no_results", + "prompt":_BP+"empty state illustration 600x400, no search results found, magnifying glass with cannabis leaf, friendly empty state, emerald minimal","width":600,"height":400,"steps":30}, + {"id":"p4_es_03","phase":"phase4_ui","subfolder":"empty_states","name":"empty_no_alerts", + "prompt":_BP+"empty state illustration 600x400, no compliance alerts, happy shield with checkmark, all clear illustration, cannabis compliance all good state, emerald positive","width":600,"height":400,"steps":30}, + {"id":"p4_es_04","phase":"phase4_ui","subfolder":"empty_states","name":"empty_no_members", + "prompt":_BP+"empty state illustration 600x400, no members added yet, friendly people silhouettes with plus icon, cannabis club member management, emerald add members","width":600,"height":400,"steps":30}, + {"id":"p4_es_05","phase":"phase4_ui","subfolder":"empty_states","name":"empty_loading_data", + "prompt":_BP+"empty state illustration 600x400, loading and processing data, gentle spinner with cannabis leaf, patient loading state, emerald animated-style still illustration","width":600,"height":400,"steps":30}, + {"id":"p4_es_06","phase":"phase4_ui","subfolder":"empty_states","name":"empty_offline", + "prompt":_BP+"empty state illustration 600x400, offline or connection error, disconnected wifi with cannabis leaf, friendly error state, amber warning on emerald","width":600,"height":400,"steps":30}, + + # Splash/Loading Screens (1080×1920) + {"id":"p4_sp_01","phase":"phase4_ui","subfolder":"splash_screens","name":"splash_primary", + "prompt":_BP+"splash screen 1080x1920, app loading screen, dark charcoal background, large centered brand logo mark, subtle emerald glow effect, premium app loading screen","width":720,"height":1280,"steps":30}, + {"id":"p4_sp_02","phase":"phase4_ui","subfolder":"splash_screens","name":"splash_emerald", + "prompt":_BP+"splash screen 1080x1920, emerald background, white logo centered, minimal loading indicator, cannabis management app splash, clean brand loading screen","width":720,"height":1280,"steps":30}, + {"id":"p4_sp_03","phase":"phase4_ui","subfolder":"splash_screens","name":"splash_animated_hint", + "prompt":_BP+"splash screen 1080x1920, animated concept, cannabis leaf particles converging into logo mark, dark background with emerald particles, dynamic loading screen first frame","width":720,"height":1280,"steps":30}, + {"id":"p4_sp_04","phase":"phase4_ui","subfolder":"splash_screens","name":"splash_gradient", + "prompt":_BP+"splash screen 1080x1920, dramatic dark to emerald gradient background, white brand mark, premium loading experience, cannabis SaaS gradient splash","width":720,"height":1280,"steps":30}, + + # ============================================================ + # PHASE 5 — Brand Collateral (38 assets) + # ============================================================ + + # Business Cards (900×504) + {"id":"p5_bc_01f","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_modern_front", + "prompt":_BP+"business card front 900x504, modern minimal style, emerald left accent panel, white main area, name and title placeholder, cannabis management SaaS company card, premium print","width":900,"height":504,"steps":30}, + {"id":"p5_bc_01b","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_modern_back", + "prompt":_BP+"business card back 900x504, modern minimal style, full emerald back with white logo centered, website and tagline, cannabis management SaaS card back","width":900,"height":504,"steps":30}, + {"id":"p5_bc_02f","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_dark_front", + "prompt":_BP+"business card front 900x504, dark luxury style, dark charcoal background, gold foil accent logo, premium cannabis management company card, executive tier","width":900,"height":504,"steps":30}, + {"id":"p5_bc_02b","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_dark_back", + "prompt":_BP+"business card back 900x504, dark luxury style, full dark charcoal, gold logo and emerald accent, premium back of card","width":900,"height":504,"steps":30}, + {"id":"p5_bc_03f","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_pattern_front", + "prompt":_BP+"business card front 900x504, geometric cannabis pattern accent, white card with subtle hexagonal pattern header, professional pattern card front","width":900,"height":504,"steps":30}, + {"id":"p5_bc_03b","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_pattern_back", + "prompt":_BP+"business card back 900x504, cannabis geometric pattern full bleed, emerald hexagonal pattern background, white logo, pattern card back","width":900,"height":504,"steps":30}, + {"id":"p5_bc_04f","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_bold_front", + "prompt":_BP+"business card front 900x504, bold typographic style, large emerald brand name, clean white card, typography-forward business card","width":900,"height":504,"steps":30}, + {"id":"p5_bc_04b","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_bold_back", + "prompt":_BP+"business card back 900x504, bold style, split emerald and white back, contact details area, cannabis company card back bold design","width":900,"height":504,"steps":30}, + + # Pitch Deck Covers (1920×1080) + {"id":"p5_pd_01","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_investor_dark", + "prompt":_BP+"pitch deck cover slide 1920x1080, investor presentation, dark sophisticated background, large logo centered, funding round subtitle area, premium cannabis SaaS investor deck","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_02","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_growth_story", + "prompt":_BP+"pitch deck cover 1920x1080, growth story visual, ascending cannabis plant becoming data chart, emerald to gold gradient, investor-grade presentation cover","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_03","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_market_opp", + "prompt":_BP+"pitch deck cover 1920x1080, market opportunity theme, cannabis industry size visualization, globe with highlighted legal markets, emerald professional investor presentation","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_04","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_team_deck", + "prompt":_BP+"pitch deck cover 1920x1080, team presentation version, professional team imagery backdrop, cannabis tech startup team slide, emerald brand, people-forward investor deck","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_05","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_product_demo", + "prompt":_BP+"pitch deck cover 1920x1080, product demo deck, dashboard preview hero visual, cannabis management SaaS product tour deck, emerald UI preview","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_06","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_minimal_clean", + "prompt":_BP+"pitch deck cover 1920x1080, ultra-minimal clean slide, white background, large emerald brand name only, minimalist investor presentation","width":1280,"height":720,"steps":30}, + + # One-Pager Headers (1200×400) + {"id":"p5_op_01","phase":"phase5_collateral","subfolder":"one_pager","name":"onepager_primary", + "prompt":_BP+"one-pager header 1200x400, primary brand header, emerald full bleed, white logo and tagline, cannabis management SaaS brochure header, print quality","width":1200,"height":400,"steps":30}, + {"id":"p5_op_02","phase":"phase5_collateral","subfolder":"one_pager","name":"onepager_feature_rich", + "prompt":_BP+"one-pager header 1200x400, feature-rich header, dashboard preview glimpse, cannabis management platform features introduction, professional SaaS marketing","width":1200,"height":400,"steps":30}, + {"id":"p5_op_03","phase":"phase5_collateral","subfolder":"one_pager","name":"onepager_compliance", + "prompt":_BP+"one-pager header 1200x400, compliance focus version, legal and regulatory theme, cannabis compliance management, shield icons, dark professional header","width":1200,"height":400,"steps":30}, + {"id":"p5_op_04","phase":"phase5_collateral","subfolder":"one_pager","name":"onepager_dark_premium", + "prompt":_BP+"one-pager header 1200x400, dark premium version, charcoal background with gold and emerald accents, enterprise tier marketing collateral header","width":1200,"height":400,"steps":30}, + + # Trade Show Banners (800×2000 = 33x80in proportions) + {"id":"p5_ts_01","phase":"phase5_collateral","subfolder":"trade_show","name":"tradeshow_primary_brand", + "prompt":_BP+"trade show pull-up banner tall vertical 800x2000, primary brand version, emerald top with logo, white middle with key features listed, dark bottom with CTA, cannabis management SaaS conference banner","width":512,"height":1280,"steps":30}, + {"id":"p5_ts_02","phase":"phase5_collateral","subfolder":"trade_show","name":"tradeshow_product_showcase", + "prompt":_BP+"trade show banner tall vertical 800x2000, product showcase, dashboard UI hero visual, dark sophisticated background, emerald accents, cannabis management software exhibition display","width":512,"height":1280,"steps":30}, + {"id":"p5_ts_03","phase":"phase5_collateral","subfolder":"trade_show","name":"tradeshow_compliance_focus", + "prompt":_BP+"trade show banner tall vertical 800x2000, compliance authority positioning, legal cannabis management expertise, professional regulatory focus, emerald and gold tall exhibition banner","width":512,"height":1280,"steps":30}, + + # Sticker/Swag Designs (600×600) + {"id":"p5_sk_01","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_leaf_circuit", + "prompt":_BP+"sticker design 600x600, cannabis leaf made of circuit traces, emerald on white, die-cut sticker style, fun tech cannabis brand sticker","width":600,"height":600,"steps":30}, + {"id":"p5_sk_02","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_wordmark_badge", + "prompt":_BP+"sticker badge 600x600, rounded rectangle badge, emerald background, white brand text, premium brand sticker, laptop sticker style","width":600,"height":600,"steps":30}, + {"id":"p5_sk_03","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_compliance_hero", + "prompt":_BP+"sticker 600x600, compliance superhero, shield with cannabis leaf and checkmark, fun illustrated sticker, emerald and gold, die-cut design","width":600,"height":600,"steps":30}, + {"id":"p5_sk_04","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_data_plant", + "prompt":_BP+"fun sticker 600x600, cannabis plant growing into data chart bars, punchy colorful sticker art, emerald plant gold bars, square sticker","width":600,"height":600,"steps":30}, + {"id":"p5_sk_05","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_canna_astronaut", + "prompt":_BP+"sticker 600x600, cartoon astronaut holding cannabis leaf and laptop, space tech meets cannabis, fun illustrated sticker, emerald spacesuit, brand mascot concept","width":600,"height":600,"steps":30}, + {"id":"p5_sk_06","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_powered_by", + "prompt":_BP+"powered by sticker 600x600, powered by CannaManage badge, small horizontal badge sticker, emerald and white, partner sticker for cannabis businesses","width":600,"height":600,"steps":30}, + {"id":"p5_sk_07","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_compliance_100", + "prompt":_BP+"sticker 600x600, 100 percent compliant badge, bold green circle with checkmark and percentage, compliance achievement sticker, cannabis business compliance badge","width":600,"height":600,"steps":30}, + {"id":"p5_sk_08","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_hexagon_icon", + "prompt":_BP+"hexagon sticker 600x600, hexagonal border with cannabis circuit icon, honeycomb management brand sticker, emerald hex border gold icon, premium die-cut","width":600,"height":600,"steps":30}, + {"id":"p5_sk_09","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_420_compliant", + "prompt":_BP+"funny sticker 600x600, 420 compliant badge design, playful cannabis compliance humor, professional but fun brand sticker, emerald with gold numbers","width":600,"height":600,"steps":30}, + {"id":"p5_sk_10","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_manage_everything", + "prompt":_BP+"sticker 600x600, manage everything tagline, bold typography sticker, emerald background white text, punchy brand statement sticker","width":600,"height":600,"steps":30}, + + # Email Signature Blocks (600×150) + {"id":"p5_es_01","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_primary", + "prompt":_BP+"email signature graphic block 600x150, primary brand, horizontal logo left with tagline, emerald line divider, professional email signature banner","width":600,"height":150,"steps":30}, + {"id":"p5_es_02","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_dark", + "prompt":_BP+"email signature block 600x150, dark version, charcoal background white logo emerald accent, premium email signature graphic","width":600,"height":150,"steps":30}, + {"id":"p5_es_03","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_minimal", + "prompt":_BP+"email signature graphic 600x150, minimal version, just logo and website, very clean white background, ultra-minimal email signature banner","width":600,"height":150,"steps":30}, + {"id":"p5_es_04","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_promo", + "prompt":_BP+"email signature promo block 600x150, promotional version with free trial CTA, gold button area, white background emerald brand, conversion CTA signature","width":600,"height":150,"steps":30}, + {"id":"p5_es_05","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_social", + "prompt":_BP+"email signature block 600x150, social media icons version, small social platform icons in emerald, company signature with social links footer","width":600,"height":150,"steps":30}, + + # ============================================================ + # PHASE 6 — Bonus / Wildcard Assets (35 assets) + # ============================================================ + + # Animated Banner First-Frame Stills (1200×628) + {"id":"p6_an_01","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_particle_logo", + "prompt":_BP+"animated banner first frame 1200x628, cannabis leaf particles forming logo mark mid-flight, dark background emerald particles, designed for animation, static concept frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_02","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_data_flow", + "prompt":_BP+"animated banner first frame 1200x628, data flow visualization beginning, cannabis data streams starting to form dashboard, dark background emerald data lines, animation concept first frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_03","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_growth_chart", + "prompt":_BP+"animated banner still 1200x628, cannabis business growth chart animation first frame, bar chart at zero about to animate upward, gold bars on dark, growth animation concept","width":1200,"height":628,"steps":30}, + {"id":"p6_an_04","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_compliance_check", + "prompt":_BP+"animated banner first frame 1200x628, compliance checklist items unchecked ready to animate with checkmarks, emerald checklist on white, compliance animation concept","width":1200,"height":628,"steps":30}, + {"id":"p6_an_05","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_plant_grow", + "prompt":_BP+"animated banner still 1200x628, cannabis plant seedling about to grow into data visualization plant, dark background seed sprouting, growth animation first frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_06","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_typing_headline", + "prompt":_BP+"animated banner still 1200x628, typing cursor before headline text, empty headline with blinking cursor concept, emerald CTA button below, typewriter animation first frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_07","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_integration_connect", + "prompt":_BP+"animated banner still 1200x628, integration ecosystem nodes about to connect, partner logos as unconnected nodes, emerald connecting lines forming, integration animation first frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_08","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_counter_stat", + "prompt":_BP+"animated banner still 1200x628, number counter animation first frame showing zero, gold large number about to count up to impressive stat, dark background, counter animation concept","width":1200,"height":628,"steps":30}, + + # Dark Mode vs Light Mode UI Pairs (1200×800 each = 12 total) + {"id":"p6_dm_01l","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_dashboard_light", + "prompt":_BP+"UI preview card 1200x800, light mode dashboard interface, clean white background, emerald UI elements, cannabis management SaaS light theme preview","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_01d","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_dashboard_dark", + "prompt":_BP+"UI preview card 1200x800, dark mode dashboard interface, dark charcoal background, emerald glowing UI elements, cannabis management SaaS dark theme preview, premium dark mode","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_02l","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_compliance_light", + "prompt":_BP+"UI preview 1200x800, compliance module light mode, white clean interface with compliance checklist and status indicators, emerald checkmarks, cannabis compliance UI","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_02d","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_compliance_dark", + "prompt":_BP+"UI preview 1200x800, compliance module dark mode, dark interface with glowing emerald compliance indicators, cannabis compliance UI dark theme, premium","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_03l","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_analytics_light", + "prompt":_BP+"UI preview 1200x800, analytics dashboard light mode, white background with colorful cannabis business charts, emerald and gold data visualization, light theme","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_03d","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_analytics_dark", + "prompt":_BP+"UI preview 1200x800, analytics dashboard dark mode, dark background with glowing emerald and gold cannabis business charts, dramatic dark mode analytics UI","width":1200,"height":800,"steps":40}, + + # Integration/Partnership Badges (400×200) + {"id":"p6_ib_01","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_pos_integration", + "prompt":_BP+"integration badge 400x200, integrates with POS systems badge, cannabis point-of-sale integration certification, emerald badge design, CannaManage plus POS icon, professional","width":400,"height":200,"steps":40}, + {"id":"p6_ib_02","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_accounting", + "prompt":_BP+"integration badge 400x200, accounting software integration badge, cannabis financial software connection, emerald badge with accounting icon, works with your accounting tools","width":400,"height":200,"steps":40}, + {"id":"p6_ib_03","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_compliance_tools", + "prompt":_BP+"integration badge 400x200, compliance tool integration badge, cannabis regulatory software connection, emerald shield badge design, integrates with compliance tools","width":400,"height":200,"steps":40}, + {"id":"p6_ib_04","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_api_ready", + "prompt":_BP+"API ready badge 400x200, API first platform badge, developer integration badge, emerald and code brackets design, cannabis management API integration badge","width":400,"height":200,"steps":40}, + {"id":"p6_ib_05","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_partner_certified", + "prompt":_BP+"partner certified badge 400x200, certified technology partner badge design, emerald official partner badge, cannabis management platform partner program","width":400,"height":200,"steps":40}, + {"id":"p6_ib_06","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_white_label", + "prompt":_BP+"white label partner badge 400x200, white label ready platform badge, cannabis SaaS white label partner certification, professional partner badge emerald","width":400,"height":200,"steps":40}, + + # Trust/Award Badges (400×400) + {"id":"p6_tb_01","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_gdpr_compliant", + "prompt":_BP+"trust badge 400x400, GDPR compliant badge design, data protection certification, emerald shield with EU star circle, cannabis SaaS data privacy trust badge","width":400,"height":400,"steps":40}, + {"id":"p6_tb_02","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_soc2_ready", + "prompt":_BP+"trust badge 400x400, SOC 2 ready certification badge, enterprise security trust badge, professional certification seal, dark emerald badge design","width":400,"height":400,"steps":40}, + {"id":"p6_tb_03","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_uptime_guarantee", + "prompt":_BP+"trust badge 400x400, 99.9 percent uptime guarantee badge, reliability certification, gold uptime number on emerald badge, cannabis SaaS reliability trust signal","width":400,"height":400,"steps":40}, + {"id":"p6_tb_04","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_industry_choice", + "prompt":_BP+"award badge 400x400, cannabis industry choice award badge design, industry recognition award seal, gold and emerald award badge","width":400,"height":400,"steps":40}, + {"id":"p6_tb_05","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_money_back", + "prompt":_BP+"trust badge 400x400, 30-day money back guarantee badge, customer confidence seal, emerald circle badge with guarantee text, cannabis SaaS satisfaction badge","width":400,"height":400,"steps":40}, +] + +# Bump steps for quality on phases with smaller dimensions +# (Patrick's feedback: more iterations = better quality on Flux.1 Schnell) +for _a in ASSET_MANIFEST: + if _a["steps"] == 30 and _a["width"] <= 1080 and _a["height"] <= 1080: + _a["steps"] = 40 + + +def load_progress() -> Dict[str, Any]: + """Load resume state from .progress.json.""" + if PROGRESS_FILE.exists(): + try: + with open(PROGRESS_FILE) as f: + return json.load(f) + except (json.JSONDecodeError, IOError): + pass + return {"completed": [], "failed": [], "started_at": time.strftime("%Y-%m-%dT%H:%M:%S")} + + +def save_progress(progress: Dict[str, Any]) -> None: + """Save progress state.""" + OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) + with open(PROGRESS_FILE, "w") as f: + json.dump(progress, f, indent=2) + + +def load_workflow(model: str) -> Dict: + """Load the appropriate workflow JSON.""" + path = WORKFLOW_HERETIC if model == "heretic" else WORKFLOW_SCHNELL + with open(path) as f: + return json.load(f) + + +def submit_prompt(comfyui_url: str, workflow: Dict) -> str: + """Submit prompt to ComfyUI.""" + data = json.dumps({"prompt": workflow}).encode() + req = urllib.request.Request( + f"{comfyui_url}/prompt", data=data, headers={"Content-Type": "application/json"} + ) + with urllib.request.urlopen(req) as resp: + return json.loads(resp.read())["prompt_id"] + + +def wait_for_image(comfyui_url: str, prompt_id: str, timeout: int = 300) -> Dict | None: + """Poll for completion.""" + print(" ⏳ Waiting for ComfyUI...", end="", flush=True) + start = time.time() + while time.time() - start < timeout: + try: + with urllib.request.urlopen(f"{comfyui_url}/history/{prompt_id}") as resp: + history = json.loads(resp.read()) + if prompt_id in history: + print(" done.", flush=True) + outputs = history[prompt_id].get("outputs", {}) + for node_out in outputs.values(): + if "images" in node_out: + return node_out["images"][0] + return None + except Exception: + pass + print(".", end="", flush=True) + time.sleep(2) + print(" timeout!", flush=True) + return None + + +def download_image(comfyui_url: str, image_info: Dict, output_path: Path) -> bool: + """Download the generated image.""" + try: + url = f"{comfyui_url}/view?filename={image_info['filename']}&subfolder={image_info.get('subfolder', '')}&type=output" + with urllib.request.urlopen(url) as resp: + img_data = resp.read() + output_path.write_bytes(img_data) + print(f" ✅ Saved: {output_path} ({len(img_data) // 1024}KB)") + return True + except Exception as e: + print(f" ❌ Download failed: {e}") + return False + + +def patch_workflow(workflow: Dict, asset: Dict, model: str) -> Dict: + """Patch workflow with asset params using per-model node IDs.""" + seed = random.randint(0, 2**32 - 1) + if model == "heretic": + # flux2_klein_heretic.json nodes: 2=pos, 3=neg, 6=latent(w/h), 7=scheduler(steps), 10=noise(seed), 13=save + workflow["2"]["inputs"]["text"] = asset["prompt"] + workflow["3"]["inputs"]["text"] = "" + workflow["6"]["inputs"]["width"] = asset["width"] + workflow["6"]["inputs"]["height"] = asset["height"] + workflow["7"]["inputs"]["steps"] = asset["steps"] + workflow["13"]["inputs"]["filename_prefix"] = asset["name"] + if "10" in workflow: + workflow["10"]["inputs"]["noise_seed"] = seed + else: + # flux_schnell.json nodes: 6=pos, 33=neg, 27=latent(w/h), 13=ksampler(steps/seed), 9=save + workflow["6"]["inputs"]["text"] = asset["prompt"] + workflow["33"]["inputs"]["text"] = "" + workflow["27"]["inputs"]["width"] = asset["width"] + workflow["27"]["inputs"]["height"] = asset["height"] + workflow["13"]["inputs"]["steps"] = asset["steps"] + workflow["13"]["inputs"]["seed"] = seed + workflow["9"]["inputs"]["filename_prefix"] = asset["name"] + return workflow + + +def generate_asset(comfyui_url: str, asset: Dict, model: str, progress: Dict) -> bool: + """Generate a single asset.""" + if asset["id"] in progress["completed"]: + print(f" ⏭️ Skipping completed: {asset['name']}") + return True + + print(f"\n Prompt : {asset['prompt'][:80]}...") + print(f" Size : {asset['width']}×{asset['height']} Steps: {asset['steps']}") + + try: + workflow = load_workflow(model) + workflow = patch_workflow(workflow, asset, model) + + prompt_id = submit_prompt(comfyui_url, workflow) + image_info = wait_for_image(comfyui_url, prompt_id) + + if not image_info: + progress["failed"].append(asset["id"]) + save_progress(progress) + return False + + output_dir = OUTPUT_ROOT / asset["phase"] / asset["subfolder"] + output_dir.mkdir(parents=True, exist_ok=True) + output_path = output_dir / f"{asset['name']}.png" + + if download_image(comfyui_url, image_info, output_path): + progress["completed"].append(asset["id"]) + save_progress(progress) + return True + else: + progress["failed"].append(asset["id"]) + save_progress(progress) + return False + + except Exception as e: + print(f" ❌ Error: {e}") + progress["failed"].append(asset["id"]) + save_progress(progress) + return False + + +def main(): + parser = argparse.ArgumentParser(description="CannaManage Brand Asset Generation Pipeline") + parser.add_argument("--dry-run", action="store_true", help="Print manifest without generating") + parser.add_argument("--phase", help="Generate only assets from this phase (e.g. phase1_logos)") + parser.add_argument("--model", choices=["schnell", "heretic"], default="schnell", + help="Model: schnell (~10-20s/img) or heretic (~52s/img, higher quality)") + parser.add_argument("--comfyui", default="http://localhost:8188", help="ComfyUI URL") + parser.add_argument("--steps", type=int, default=None, + help="Override steps for all assets (e.g. --steps 12 for higher quality)") + args = parser.parse_args() + + comfyui_url = args.comfyui + + # Apply global steps override if requested + manifest = ASSET_MANIFEST + if args.steps: + manifest = [{**a, "steps": args.steps} for a in manifest] + + # Filter by phase if requested + to_generate = [a for a in manifest if not args.phase or a["phase"] == args.phase] + + print("🚀 CannaManage Brand Asset Generation Pipeline") + print(f" Output : {OUTPUT_ROOT}") + print(f" Model : {args.model}") + print(f" ComfyUI : {comfyui_url}") + print(f" Total : {len(ASSET_MANIFEST)} assets in manifest") + print(f" Selected: {len(to_generate)} assets to generate") + + if args.dry_run: + phases: Dict[str, int] = {} + for a in to_generate: + phases[a["phase"]] = phases.get(a["phase"], 0) + 1 + for ph, count in phases.items(): + print(f"\n {ph} ({count} assets):") + for a in to_generate: + if a["phase"] == ph: + print(f" {a['id']:14} | {a['name']:35} | {a['width']}×{a['height']} steps={a['steps']}") + total_min_est = sum(a["steps"] * 2.5 for a in to_generate) / 60 + print(f"\n ⏱️ Estimated runtime (schnell): ~{total_min_est:.0f} minutes") + print("\nDry run complete. Remove --dry-run to begin generation.") + return + + progress = load_progress() + remaining = [a for a in to_generate if a["id"] not in progress["completed"]] + print(f" Resume : {len(progress['completed'])} completed, {len(progress['failed'])} failed, {len(remaining)} remaining") + + if not remaining: + print("\n✅ All selected assets already complete!") + return + + print(f"\nStarting generation... (Ctrl+C to pause — progress is saved)") + + n_done = 0 + n_fail = 0 + for i, asset in enumerate(to_generate, 1): + if asset["id"] in progress["completed"]: + continue + print(f"\n[{asset['phase']}] [{i}/{len(to_generate)}] {asset['name']}") + if generate_asset(comfyui_url, asset, args.model, progress): + n_done += 1 + else: + n_fail += 1 + + print("\n" + "=" * 60) + print("🎉 PIPELINE COMPLETE") + print(f" ✅ Completed this run : {n_done}") + print(f" ❌ Failed this run : {n_fail}") + print(f" 📦 Total completed : {len(progress['completed'])} / {len(ASSET_MANIFEST)}") + if progress["failed"]: + print(f" Failed IDs: {', '.join(progress['failed'][-10:])}") + print(f" Assets saved to: {OUTPUT_ROOT}") + print("=" * 60) + + +if __name__ == "__main__": + main() diff --git a/mcp/mcp-image-gen/clubmanage_gen.py b/mcp/mcp-image-gen/clubmanage_gen.py new file mode 100644 index 0000000..2e2d8f8 --- /dev/null +++ b/mcp/mcp-image-gen/clubmanage_gen.py @@ -0,0 +1,801 @@ +#!/usr/bin/env python3 +""" +ClubManage Brand Asset Generation Pipeline + +Autonomous script to generate 257+ brand assets for a generic club management SaaS platform. +All images are text-free / typography-free — pure visual/icon design only. +Runs unattended, resume-safe via .progress.json. + +Usage: + cd /home/pplate/pi_mcps + python mcp/mcp-image-gen/clubmanage_gen.py + python mcp/mcp-image-gen/clubmanage_gen.py --dry-run + python mcp/mcp-image-gen/clubmanage_gen.py --phase phase1_logos + python mcp/mcp-image-gen/clubmanage_gen.py --model heretic + +Output: ~/Pictures/clubmanage_brand/ with organized subfolders. +""" + +import argparse +import json +import random +import sys +import time +import urllib.request +from pathlib import Path +from typing import Dict, List, Any + +# --- Configuration --- +OUTPUT_ROOT = Path.home() / "Pictures" / "clubmanage_brand" +PROGRESS_FILE = OUTPUT_ROOT / ".progress.json" +WORKFLOW_SCHNELL = Path(__file__).parent / "src/workflows/flux_schnell.json" +WORKFLOW_HERETIC = Path(__file__).parent / "src/workflows/flux2_klein_heretic.json" + +# Brand prefix — generic club management SaaS, navy/teal palette, STRICTLY no text +_BP = ("professional B2B SaaS brand design, club management platform, " + "modern tech aesthetic, clean minimalist style, premium quality, " + "deep navy blue and teal color scheme, no text, no words, no letters, " + "no numbers, no labels, no typography, pure visual icon design, ") + +# Negative prompt suffix for heretic (CFGGuider supports real negative guidance) +_NEG = "text, words, letters, numbers, labels, typography, fonts, captions, watermarks, titles, subtitles" + +# --- Full Asset Manifest (257 assets across 6 phases) --- +ASSET_MANIFEST: List[Dict[str, Any]] = [ + + # ============================================================ + # PHASE 1 — Logo Suite (42 assets) + # ============================================================ + + # Wordmark concept shapes — 5 directions (1024×512) + {"id":"p1_wm_01","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_modern_sans", + "prompt":_BP+"modern geometric sans-serif shaped abstract mark, deep navy #1A237E, clean white background, minimal people-group silhouette accent, high-end tech company wordmark shape, flat vector design","width":1024,"height":512,"steps":30}, + {"id":"p1_wm_02","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_geometric", + "prompt":_BP+"geometric abstract wordmark shape, sharp angles, navy and teal color scheme, hexagonal grid subtle background, membership network silhouette, precision tech brand, white background","width":1024,"height":512,"steps":30}, + {"id":"p1_wm_03","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_humanist", + "prompt":_BP+"humanist rounded abstract mark, warm approachable professional style, navy with teal accent, subtle community connection pattern, trustworthy modern brand shape, white background","width":1024,"height":512,"steps":30}, + {"id":"p1_wm_04","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_slab_serif", + "prompt":_BP+"premium block geometric abstract mark, dark charcoal and deep navy palette, gold accent stripe, authoritative membership management brand shape, institutional trustworthiness, white background","width":1024,"height":512,"steps":30}, + {"id":"p1_wm_05","phase":"phase1_logos","subfolder":"wordmark","name":"wordmark_minimal", + "prompt":_BP+"ultra-minimal thin abstract brand mark shape, single-color deep navy, negative space connected-people form, Apple-inspired premium minimalism, pure white background","width":1024,"height":512,"steps":30}, + + # Icon / Symbol Only — 10 variations (512×512) + {"id":"p1_ic_01","phase":"phase1_logos","subfolder":"icon_only","name":"icon_people_network", + "prompt":_BP+"abstract interconnected people silhouettes forming network club icon, navy on white, community membership platform, geometric precision, square icon format","width":512,"height":512,"steps":30}, + {"id":"p1_ic_02","phase":"phase1_logos","subfolder":"icon_only","name":"icon_c_mark_abstract", + "prompt":_BP+"abstract letter-C shaped from human figures and connecting lines brand icon, geometric minimalist, deep navy gradient, community circle concept inside C curve, white background","width":512,"height":512,"steps":30}, + {"id":"p1_ic_03","phase":"phase1_logos","subfolder":"icon_only","name":"icon_membership_card", + "prompt":_BP+"stylized membership card with embedded circuit-like membership ID pattern, navy and teal nodes and gold lines, professional membership management mark, dark background","width":512,"height":512,"steps":30}, + {"id":"p1_ic_04","phase":"phase1_logos","subfolder":"icon_only","name":"icon_dashboard_grid", + "prompt":_BP+"abstract dashboard grid symbol icon, 3x3 grid of squares with bar chart and people silhouette overlaid, navy and gold, SaaS platform brand mark, white background","width":512,"height":512,"steps":30}, + {"id":"p1_ic_05","phase":"phase1_logos","subfolder":"icon_only","name":"icon_calendar_pulse", + "prompt":_BP+"calendar grid merging with heartbeat pulse line icon, teal and navy, event scheduling and club vitality brand mark, half-event half-data, modern membership platform","width":512,"height":512,"steps":30}, + {"id":"p1_ic_06","phase":"phase1_logos","subfolder":"icon_only","name":"icon_shield_people", + "prompt":_BP+"shield shape with people-group geometric pattern inside, navy shield, gold people outline, trust and membership management brand mark, premium badge style","width":512,"height":512,"steps":30}, + {"id":"p1_ic_07","phase":"phase1_logos","subfolder":"icon_only","name":"icon_cm_monogram", + "prompt":_BP+"interlocked abstract C and M shapes with community negative space monogram, geometric precision, deep navy, gold accent, premium brand monogram, white background","width":512,"height":512,"steps":30}, + {"id":"p1_ic_08","phase":"phase1_logos","subfolder":"icon_only","name":"icon_hexagon_community", + "prompt":_BP+"hexagon containing stylized connected people nodes formed from clean lines, navy hexagon dark outline, gold accent dot nodes at connection points, geometric membership brand mark, tech-forward minimal","width":512,"height":512,"steps":30}, + {"id":"p1_ic_09","phase":"phase1_logos","subfolder":"icon_only","name":"icon_growth_chart", + "prompt":_BP+"upward growing membership curve transforming into ascending bar chart, navy to teal gradient, business growth metaphor, modern flat icon design","width":512,"height":512,"steps":30}, + {"id":"p1_ic_10","phase":"phase1_logos","subfolder":"icon_only","name":"icon_infinity_community", + "prompt":_BP+"infinity loop symbol where loops form two abstract community circle shapes, navy line on white, continuous membership management cycle concept, premium SaaS logo mark","width":512,"height":512,"steps":30}, + + # Horizontal Lockups (1024×256) + {"id":"p1_lh_01","phase":"phase1_logos","subfolder":"lockup_horizontal","name":"lockup_horiz_light", + "prompt":_BP+"horizontal logo lockup icon mark left shape right, light white background, deep navy, professional club management SaaS layout, pure icon shapes only","width":1024,"height":256,"steps":30}, + {"id":"p1_lh_02","phase":"phase1_logos","subfolder":"lockup_horizontal","name":"lockup_horiz_dark", + "prompt":_BP+"horizontal logo lockup icon left shape right, dark charcoal background, white and navy logo, reversed color scheme, premium brand","width":1024,"height":256,"steps":30}, + {"id":"p1_lh_03","phase":"phase1_logos","subfolder":"lockup_horizontal","name":"lockup_horiz_navy_bg", + "prompt":_BP+"horizontal logo lockup, white icon on deep navy background, horizontal icon plus abstract shape, brand banner version","width":1024,"height":256,"steps":30}, + {"id":"p1_lh_04","phase":"phase1_logos","subfolder":"lockup_horizontal","name":"lockup_horiz_mono", + "prompt":_BP+"horizontal logo lockup monochrome, all black on white, horizontal icon plus abstract shape, professional print-ready version","width":1024,"height":256,"steps":30}, + + # Stacked Lockups (512×512) + {"id":"p1_ls_01","phase":"phase1_logos","subfolder":"lockup_stacked","name":"lockup_stacked_light", + "prompt":_BP+"stacked logo lockup icon centered above abstract shape, light white background, navy brand colors, square format, professional centered layout","width":512,"height":512,"steps":30}, + {"id":"p1_ls_02","phase":"phase1_logos","subfolder":"lockup_stacked","name":"lockup_stacked_dark", + "prompt":_BP+"stacked logo lockup icon centered above shape, dark charcoal background, white and teal logo, square format, dark version","width":512,"height":512,"steps":30}, + {"id":"p1_ls_03","phase":"phase1_logos","subfolder":"lockup_stacked","name":"lockup_stacked_navy", + "prompt":_BP+"stacked logo lockup, white icon and shape on navy background, centered square format, brand full-color version","width":512,"height":512,"steps":30}, + {"id":"p1_ls_04","phase":"phase1_logos","subfolder":"lockup_stacked","name":"lockup_stacked_mono", + "prompt":_BP+"stacked logo lockup monochrome all-black on white, icon above abstract mark, square format, print-ready logo","width":512,"height":512,"steps":30}, + + # Favicons (256×256) + {"id":"p1_fv_01","phase":"phase1_logos","subfolder":"favicon","name":"favicon_navy_people", + "prompt":_BP+"favicon 256x256 square app icon, navy background, white geometric people-network icon, rounded square, minimal","width":256,"height":256,"steps":30}, + {"id":"p1_fv_02","phase":"phase1_logos","subfolder":"favicon","name":"favicon_dark_teal", + "prompt":_BP+"favicon dark charcoal square, teal community-nodes icon, 256x256 app icon, sharp corners, professional SaaS favicon","width":256,"height":256,"steps":30}, + {"id":"p1_fv_03","phase":"phase1_logos","subfolder":"favicon","name":"favicon_white_navy", + "prompt":_BP+"favicon white background, deep navy CM abstract monogram icon, 256x256 square, minimal browser favicon","width":256,"height":256,"steps":30}, + {"id":"p1_fv_04","phase":"phase1_logos","subfolder":"favicon","name":"favicon_gold_dark", + "prompt":_BP+"favicon dark background, gold amber membership management icon mark, 256x256 premium app icon, warm gold on charcoal","width":256,"height":256,"steps":30}, + {"id":"p1_fv_05","phase":"phase1_logos","subfolder":"favicon","name":"favicon_gradient_navy", + "prompt":_BP+"favicon midnight to navy gradient background, white geometric icon, 256x256 square, modern SaaS app icon with gradient","width":256,"height":256,"steps":30}, + {"id":"p1_fv_06","phase":"phase1_logos","subfolder":"favicon","name":"favicon_outline_style", + "prompt":_BP+"favicon white background, outline-only teal community network icon, thin line illustration, 256x256, minimalist","width":256,"height":256,"steps":30}, + {"id":"p1_fv_07","phase":"phase1_logos","subfolder":"favicon","name":"favicon_rounded_modern", + "prompt":_BP+"iOS-style rounded square app icon, navy gradient background, white membership brand mark, 256x256, premium mobile app icon","width":256,"height":256,"steps":30}, + {"id":"p1_fv_08","phase":"phase1_logos","subfolder":"favicon","name":"favicon_badge_style", + "prompt":_BP+"badge-style icon with thin border ring, navy center with white CM abstract shape, 256x256 square, club software favicon","width":256,"height":256,"steps":30}, + + # ============================================================ + # PHASE 2 — Banner Suite (50 assets) + # ============================================================ + + # Hero Website Banners (1280×720) + {"id":"p2_hw_01","phase":"phase2_banners","subfolder":"hero_website","name":"hero_dashboard_showcase", + "prompt":_BP+"website hero banner, dark charcoal background, teal UI dashboard shapes floating right, bold geometric area left, gold accent lines, enterprise software marketing visual","width":1280,"height":720,"steps":30}, + {"id":"p2_hw_02","phase":"phase2_banners","subfolder":"hero_website","name":"hero_compliance_trust", + "prompt":_BP+"website hero banner, trust theme, deep navy gradient, shield and checkmark iconography, membership management, white geometric area, subtle hexagonal pattern overlay","width":1280,"height":720,"steps":30}, + {"id":"p2_hw_03","phase":"phase2_banners","subfolder":"hero_website","name":"hero_analytics_data", + "prompt":_BP+"website hero banner, analytics theme, dark background, glowing data visualization charts in navy and gold, business metrics, abstract data flowing design","width":1280,"height":720,"steps":30}, + {"id":"p2_hw_04","phase":"phase2_banners","subfolder":"hero_website","name":"hero_team_enterprise", + "prompt":_BP+"website hero banner, enterprise team theme, split design navy left panel white right panel, diagonal split, geometric accents, SaaS marketing visual","width":1280,"height":720,"steps":30}, + {"id":"p2_hw_05","phase":"phase2_banners","subfolder":"hero_website","name":"hero_community_tech", + "prompt":_BP+"website hero banner, community meets technology, abstract people nodes growing from data grid, navy organic forms with teal circuit lines, dark sophisticated background","width":1280,"height":720,"steps":30}, + + # LinkedIn Banners (1584×396) + {"id":"p2_li_01","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_corporate_navy", + "prompt":_BP+"LinkedIn company banner, deep navy background, white abstract icon centered, club business management, clean minimal corporate header visual","width":1584,"height":396,"steps":30}, + {"id":"p2_li_02","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_dark_gold", + "prompt":_BP+"LinkedIn banner, dark charcoal background, gold accent stripe bottom, professional enterprise header visual","width":1584,"height":396,"steps":30}, + {"id":"p2_li_03","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_pattern_overlay", + "prompt":_BP+"LinkedIn banner, navy base, subtle hexagonal membership molecule pattern overlay, semi-transparent, company branding prominent, wide horizontal header","width":1584,"height":396,"steps":30}, + {"id":"p2_li_04","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_split_design", + "prompt":_BP+"LinkedIn banner, split design left dark right navy, diagonal split line, club management platform branding, clean sharp design","width":1584,"height":396,"steps":30}, + {"id":"p2_li_05","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_metrics_banner", + "prompt":_BP+"LinkedIn banner showing abstract business metrics visualization, data-forward icons, navy with gold shapes, analytics platform positioning","width":1584,"height":396,"steps":30}, + {"id":"p2_li_06","phase":"phase2_banners","subfolder":"linkedin","name":"linkedin_gradient_minimal", + "prompt":_BP+"LinkedIn banner, midnight to navy gradient, minimal white brand shape only, ultra-clean professional header","width":1584,"height":396,"steps":30}, + + # Twitter/X Headers (1500×500) + {"id":"p2_tw_01","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_bold_navy", + "prompt":_BP+"Twitter X header banner, bold navy full bleed background, large white brand icon shape, membership management visual, strong social media presence","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_02","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_dark_pattern", + "prompt":_BP+"Twitter header, dark charcoal with subtle community geometric pattern, navy and gold accents, professional SaaS brand social header","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_03","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_product_hint", + "prompt":_BP+"Twitter header, dark background with abstract dashboard interface shapes, club management software preview silhouette, professional tech company header","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_04","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_community_abstract", + "prompt":_BP+"Twitter header, abstract community nodes growing into data streams, navy to dark gradient, artistic organic meets digital aesthetic","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_05","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_network", + "prompt":_BP+"Twitter header, membership network theme, connected nodes visualization in teal and navy, SaaS platform connecting businesses","width":1500,"height":500,"steps":30}, + {"id":"p2_tw_06","phase":"phase2_banners","subfolder":"twitter_x","name":"twitter_white_clean", + "prompt":_BP+"Twitter header, clean white background, navy brand elements only, ultra-professional minimal social media header","width":1500,"height":500,"steps":30}, + + # Facebook Covers (820×312) + {"id":"p2_fb_01","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_primary_brand", + "prompt":_BP+"Facebook cover photo, primary brand colors navy and charcoal, professional club business company cover, centered branding icon","width":820,"height":312,"steps":30}, + {"id":"p2_fb_02","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_dark_professional", + "prompt":_BP+"Facebook cover, dark sophisticated background, white and gold brand icon elements, enterprise platform premium cover","width":820,"height":312,"steps":30}, + {"id":"p2_fb_03","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_membership_theme", + "prompt":_BP+"Facebook cover, membership and community theme, shield and verification iconography, navy professional company cover","width":820,"height":312,"steps":30}, + {"id":"p2_fb_04","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_product_launch", + "prompt":_BP+"Facebook cover, product launch announcement style, bold navy with gold accents, exciting software release visual, dynamic tech company cover","width":820,"height":312,"steps":30}, + {"id":"p2_fb_05","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_industry_leader", + "prompt":_BP+"Facebook cover, industry leadership positioning, club management market leader visual, professional authoritative design, navy and gold","width":820,"height":312,"steps":30}, + {"id":"p2_fb_06","phase":"phase2_banners","subfolder":"facebook_cover","name":"facebook_seasonal_spring", + "prompt":_BP+"Facebook cover, spring fresh brand, bright teal with navy organic elements, membership growth season theme, professional seasonal cover","width":820,"height":312,"steps":30}, + + # Google Display Ads (16 assets - 4 concepts × 4 sizes) + {"id":"p2_ga_01a","phase":"phase2_banners","subfolder":"google_display","name":"gad_simplify_728x90", + "prompt":_BP+"Google display ad leaderboard, simplify club management theme, navy button shape, white background, professional B2B ad visual","width":728,"height":90,"steps":30}, + {"id":"p2_ga_01b","phase":"phase2_banners","subfolder":"google_display","name":"gad_simplify_300x250", + "prompt":_BP+"Google display ad medium rectangle, simplify club management theme, navy design, bold icon shapes, professional SaaS ad creative","width":300,"height":250,"steps":30}, + {"id":"p2_ga_01c","phase":"phase2_banners","subfolder":"google_display","name":"gad_simplify_160x600", + "prompt":_BP+"Google display ad wide skyscraper, simplify club management theme, tall vertical format, navy, professional B2B ad","width":160,"height":600,"steps":30}, + {"id":"p2_ga_01d","phase":"phase2_banners","subfolder":"google_display","name":"gad_simplify_320x50", + "prompt":_BP+"Google display ad mobile banner, simplify management theme, minimal mobile ad, navy, club management SaaS","width":320,"height":50,"steps":30}, + {"id":"p2_ga_02a","phase":"phase2_banners","subfolder":"google_display","name":"gad_manage_728x90", + "prompt":_BP+"Google display ad, manage everything club business theme, dashboard preview hint icons, dark charcoal professional leaderboard banner","width":728,"height":90,"steps":30}, + {"id":"p2_ga_02b","phase":"phase2_banners","subfolder":"google_display","name":"gad_manage_300x250", + "prompt":_BP+"Google display ad, manage everything club operations theme, product dashboard icon glimpse, navy dark professional rectangle ad","width":300,"height":250,"steps":30}, + {"id":"p2_ga_02c","phase":"phase2_banners","subfolder":"google_display","name":"gad_manage_160x600", + "prompt":_BP+"Google display skyscraper, manage club business operations theme, vertical product feature icon list visual, navy professional tall ad","width":160,"height":600,"steps":30}, + {"id":"p2_ga_02d","phase":"phase2_banners","subfolder":"google_display","name":"gad_manage_320x50", + "prompt":_BP+"mobile banner, manage club business theme, ultra-minimal mobile ad strip, brand colors","width":320,"height":50,"steps":30}, + {"id":"p2_ga_03a","phase":"phase2_banners","subfolder":"google_display","name":"gad_grow_728x90", + "prompt":_BP+"Google ad, grow your club business theme, upward growth arrow with member silhouette, gold and navy, professional B2B leaderboard","width":728,"height":90,"steps":30}, + {"id":"p2_ga_03b","phase":"phase2_banners","subfolder":"google_display","name":"gad_grow_300x250", + "prompt":_BP+"Google ad, club business growth theme, ascending graph with navy growth visual, professional SaaS rectangle ad","width":300,"height":250,"steps":30}, + {"id":"p2_ga_03c","phase":"phase2_banners","subfolder":"google_display","name":"gad_grow_160x600", + "prompt":_BP+"skyscraper ad, club business growth vertical story, people nodes growing upward through data visualization, navy tall display ad","width":160,"height":600,"steps":30}, + {"id":"p2_ga_03d","phase":"phase2_banners","subfolder":"google_display","name":"gad_grow_320x50", + "prompt":_BP+"mobile ad, grow club membership, minimal mobile strip ad navy","width":320,"height":50,"steps":30}, + {"id":"p2_ga_04a","phase":"phase2_banners","subfolder":"google_display","name":"gad_trial_728x90", + "prompt":_BP+"Google ad, free trial call to action shape, bold gold CTA shape, navy professional leaderboard, club management SaaS trial offer visual","width":728,"height":90,"steps":30}, + {"id":"p2_ga_04b","phase":"phase2_banners","subfolder":"google_display","name":"gad_trial_300x250", + "prompt":_BP+"Google ad, free trial offer icon, gold button shape navy design, club management platform trial CTA rectangle ad","width":300,"height":250,"steps":30}, + {"id":"p2_ga_04c","phase":"phase2_banners","subfolder":"google_display","name":"gad_trial_160x600", + "prompt":_BP+"skyscraper ad, free trial CTA vertical ad, gold call to action arrow shape, navy SaaS platform","width":160,"height":600,"steps":30}, + {"id":"p2_ga_04d","phase":"phase2_banners","subfolder":"google_display","name":"gad_trial_320x50", + "prompt":_BP+"mobile ad, free trial minimal mobile strip, gold CTA shape navy brand","width":320,"height":50,"steps":30}, + + # App Store Feature Graphics (1024×500) + {"id":"p2_as_01","phase":"phase2_banners","subfolder":"app_store","name":"appstore_hero_dashboard", + "prompt":_BP+"app store feature graphic, club management app showcase, dark background with app dashboard UI icon preview shapes, navy interface elements, professional mobile app store hero","width":1024,"height":500,"steps":30}, + {"id":"p2_as_02","phase":"phase2_banners","subfolder":"app_store","name":"appstore_membership_features", + "prompt":_BP+"app store feature graphic, membership features highlight, shield icons and checkmarks, navy professional, club membership app feature graphic","width":1024,"height":500,"steps":30}, + {"id":"p2_as_03","phase":"phase2_banners","subfolder":"app_store","name":"appstore_analytics_focus", + "prompt":_BP+"app store feature graphic, business analytics and reporting feature, dashboard chart shapes preview, gold and navy data visualization, club business intelligence app","width":1024,"height":500,"steps":30}, + {"id":"p2_as_04","phase":"phase2_banners","subfolder":"app_store","name":"appstore_team_management", + "prompt":_BP+"app store feature graphic, team and staff management, connected team nodes visualization, navy professional, club staff team management app","width":1024,"height":500,"steps":30}, + + # Email Header Banners (600×200) + {"id":"p2_em_01","phase":"phase2_banners","subfolder":"email_header","name":"email_primary_brand", + "prompt":_BP+"email header banner, primary brand header, navy with white icon area, professional email marketing header","width":600,"height":200,"steps":30}, + {"id":"p2_em_02","phase":"phase2_banners","subfolder":"email_header","name":"email_welcome", + "prompt":_BP+"welcome email header, warm welcome theme, navy and teal gradient, onboarding email banner, new user email header","width":600,"height":200,"steps":30}, + {"id":"p2_em_03","phase":"phase2_banners","subfolder":"email_header","name":"email_product_update", + "prompt":_BP+"product update email header, new features announcement, gold accent notification style, software update email banner","width":600,"height":200,"steps":30}, + {"id":"p2_em_04","phase":"phase2_banners","subfolder":"email_header","name":"email_membership_alert", + "prompt":_BP+"membership alert email header, urgent notification theme, amber gold accent on dark, regulatory update email header, professional alert banner","width":600,"height":200,"steps":30}, + {"id":"p2_em_05","phase":"phase2_banners","subfolder":"email_header","name":"email_monthly_report", + "prompt":_BP+"monthly report email header, data and analytics icon theme, chart shapes preview, navy professional, club business monthly summary","width":600,"height":200,"steps":30}, + {"id":"p2_em_06","phase":"phase2_banners","subfolder":"email_header","name":"email_trial_ending", + "prompt":_BP+"trial ending email header, urgency CTA icon theme, gold highlight on dark, platform trial expiry email banner, convert to paid","width":600,"height":200,"steps":30}, + {"id":"p2_em_07","phase":"phase2_banners","subfolder":"email_header","name":"email_invoice", + "prompt":_BP+"invoice and billing email header, clean minimal professional, white and navy, SaaS billing email header, enterprise professional","width":600,"height":200,"steps":30}, + {"id":"p2_em_08","phase":"phase2_banners","subfolder":"email_header","name":"email_dark_premium", + "prompt":_BP+"dark premium email header, dark charcoal with gold and navy accents, VIP or enterprise tier email, club management premium header","width":600,"height":200,"steps":30}, + + # ============================================================ + # PHASE 3 — Social Media Asset Pack (60 assets) + # ============================================================ + + # Instagram Square Posts (1024×1024) + {"id":"p3_ig_01","phase":"phase3_social","subfolder":"instagram_square","name":"insta_inventory_mgmt", + "prompt":_BP+"Instagram post, inventory management feature highlight, stock tracking dashboard icon visualization, navy UI elements, bold feature announcement visual, clean white and dark design","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_02","phase":"phase3_social","subfolder":"instagram_square","name":"insta_member_track", + "prompt":_BP+"Instagram post, member tracking feature, checklist visualization, shield and checkmark icons, navy and gold, club management SaaS post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_03","phase":"phase3_social","subfolder":"instagram_square","name":"insta_analytics_dash", + "prompt":_BP+"Instagram post, analytics dashboard feature, business intelligence data visualization icon, navy charts on dark background, club business analytics","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_04","phase":"phase3_social","subfolder":"instagram_square","name":"insta_staff_scheduling", + "prompt":_BP+"Instagram post, staff scheduling feature, team calendar and shift management visualization, club staff management, clean navy post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_05","phase":"phase3_social","subfolder":"instagram_square","name":"insta_pos_integration", + "prompt":_BP+"Instagram post, POS system integration feature, point-of-sale connection visualization, integration nodes and arrows, navy and gold tech post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_06","phase":"phase3_social","subfolder":"instagram_square","name":"insta_reporting", + "prompt":_BP+"Instagram post, automated reporting feature, beautiful report document preview shape, navy professional document visualization post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_07","phase":"phase3_social","subfolder":"instagram_square","name":"insta_multi_location", + "prompt":_BP+"Instagram post, multi-location management feature, club chain management, location pins on map with connecting navy lines","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_08","phase":"phase3_social","subfolder":"instagram_square","name":"insta_mobile_app", + "prompt":_BP+"Instagram post, mobile app feature highlight, iPhone and Android app shape mockup, club management on-the-go, navy app UI post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_09","phase":"phase3_social","subfolder":"instagram_square","name":"insta_security", + "prompt":_BP+"Instagram post, enterprise security feature, data protection and encryption visualization, shield with lock icon, dark professional navy security post","width":1024,"height":1024,"steps":30}, + {"id":"p3_ig_10","phase":"phase3_social","subfolder":"instagram_square","name":"insta_brand_story", + "prompt":_BP+"Instagram brand story post, company mission, club empowerment, beautiful abstract people and technology fusion illustration, navy and gold, inspiring brand post","width":1024,"height":1024,"steps":30}, + + # Instagram Stories (720×1280) + {"id":"p3_st_01","phase":"phase3_social","subfolder":"instagram_story","name":"story_onboarding", + "prompt":_BP+"Instagram story, onboarding tutorial slide, step-by-step platform setup icon, navy vertical mobile design, swipe up arrow CTA shape, professional SaaS story","width":720,"height":1280,"steps":30}, + {"id":"p3_st_02","phase":"phase3_social","subfolder":"instagram_story","name":"story_feature_announce", + "prompt":_BP+"Instagram story, new feature announcement, bold navy vertical design, software update story, gold accent highlight, arrow CTA shape","width":720,"height":1280,"steps":30}, + {"id":"p3_st_03","phase":"phase3_social","subfolder":"instagram_story","name":"story_stat_highlight", + "prompt":_BP+"Instagram story, industry statistic highlight visual, large bold number shape, dark background gold number navy accent, data-driven story template","width":720,"height":1280,"steps":30}, + {"id":"p3_st_04","phase":"phase3_social","subfolder":"instagram_story","name":"story_customer_quote", + "prompt":_BP+"Instagram story, customer testimonial visual, elegant quote marks shape on navy background, club business owner testimonial style, premium brand story","width":720,"height":1280,"steps":30}, + {"id":"p3_st_05","phase":"phase3_social","subfolder":"instagram_story","name":"story_poll_template", + "prompt":_BP+"Instagram story, interactive poll template visual, club industry question bar icons, dark professional background, poll shapes styled in navy and gold","width":720,"height":1280,"steps":30}, + {"id":"p3_st_06","phase":"phase3_social","subfolder":"instagram_story","name":"story_countdown", + "prompt":_BP+"Instagram story, countdown timer event template, launch deadline visual, bold dramatic dark background with gold countdown shape","width":720,"height":1280,"steps":30}, + {"id":"p3_st_07","phase":"phase3_social","subfolder":"instagram_story","name":"story_tips_series", + "prompt":_BP+"Instagram story, club management tip of the day template, bright educational story icon, numbered tip format, teal navy professional guidance visual","width":720,"height":1280,"steps":30}, + {"id":"p3_st_08","phase":"phase3_social","subfolder":"instagram_story","name":"story_free_trial", + "prompt":_BP+"Instagram story, free trial CTA story, bold gold arrow shape on dark navy, club management platform sign up visual, strong conversion design","width":720,"height":1280,"steps":30}, + + # LinkedIn Post Graphics (1200×627) + {"id":"p3_lp_01","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_thought_leader", + "prompt":_BP+"LinkedIn post graphic, thought leadership article header visual, club industry insights icon, professional editorial design, navy brand with white content area","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_02","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_product_demo", + "prompt":_BP+"LinkedIn post, product demo announcement visual, screenshot preview icon teaser, club management platform demo invitation shape, navy professional post","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_03","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_hiring", + "prompt":_BP+"LinkedIn hiring post, we are hiring banner shapes, team growth announcement visual, professional club tech company hiring graphic, navy and gold, people silhouettes","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_04","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_industry_stat", + "prompt":_BP+"LinkedIn post, club industry statistic infographic shapes, large bold number visual, professional B2B data post, navy","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_05","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_partnership", + "prompt":_BP+"LinkedIn partnership announcement, strategic partnership visual, club tech ecosystem, professional announcement graphic navy","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_06","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_webinar", + "prompt":_BP+"LinkedIn webinar promotion post, club compliance webinar announcement visual, calendar icon event, professional event promotion, navy dark design","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_07","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_case_study", + "prompt":_BP+"LinkedIn case study post, customer success story preview visual, club success metrics chart shapes, gold numbers on dark, professional B2B case study promotional","width":1200,"height":627,"steps":30}, + {"id":"p3_lp_08","phase":"phase3_social","subfolder":"linkedin_post","name":"linkedin_award", + "prompt":_BP+"LinkedIn award announcement post, award or recognition visual, gold trophy badge element shape, club tech industry recognition, celebratory professional post","width":1200,"height":627,"steps":30}, + + # Feature Announcement Cards (1024×1024) + {"id":"p3_fc_01","phase":"phase3_social","subfolder":"feature_cards","name":"feature_barcode_scan", + "prompt":_BP+"feature card, barcode scanning inventory management, membership card scan interface icon, mobile scanning visualization, navy UI feature card","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_02","phase":"phase3_social","subfolder":"feature_cards","name":"feature_auto_reports", + "prompt":_BP+"feature card, automated reporting, automation icon with checklist shapes, reporting automation, navy professional feature announcement","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_03","phase":"phase3_social","subfolder":"feature_cards","name":"feature_real_time_alerts", + "prompt":_BP+"feature card, real-time alerts and notifications, bell notification icon with threshold alert shapes, gold alert accent on dark, notification feature","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_04","phase":"phase3_social","subfolder":"feature_cards","name":"feature_member_portal", + "prompt":_BP+"feature card, member self-service portal icon, club member login interface shape, clean navy member management, user portal visualization","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_05","phase":"phase3_social","subfolder":"feature_cards","name":"feature_api_integrations", + "prompt":_BP+"feature card, API integrations ecosystem icon, connected software nodes with hub, tech stack integration visualization, navy connection diagram","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_06","phase":"phase3_social","subfolder":"feature_cards","name":"feature_batch_tracking", + "prompt":_BP+"feature card, batch and lot tracking icon, product chain of custody visualization, numbered batch tracking flow shapes, compliance feature card","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_07","phase":"phase3_social","subfolder":"feature_cards","name":"feature_document_mgmt", + "prompt":_BP+"feature card, document management system icon, licensing and permit documents organized, folder icons in navy, digital document management","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_08","phase":"phase3_social","subfolder":"feature_cards","name":"feature_role_permissions", + "prompt":_BP+"feature card, role-based permissions feature icon, user role hierarchy visualization, shield with user silhouettes, team access control, dark professional","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_09","phase":"phase3_social","subfolder":"feature_cards","name":"feature_export_reports", + "prompt":_BP+"feature card, one-click export and reporting icon, PDF report generation shape, download arrow with report preview, navy feature card","width":1024,"height":1024,"steps":30}, + {"id":"p3_fc_10","phase":"phase3_social","subfolder":"feature_cards","name":"feature_audit_trail", + "prompt":_BP+"feature card, complete audit trail icon, transaction history timeline, chronological log entry shapes, audit visualization, professional dark card","width":1024,"height":1024,"steps":30}, + + # Testimonial Cards (1024×1024) + {"id":"p3_tc_01","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_dark_elegant", + "prompt":_BP+"testimonial card, dark charcoal elegant quote card, gold quotation mark shapes, abstract customer silhouette, club business owner testimonial visual, premium design","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_02","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_navy_bold", + "prompt":_BP+"testimonial card, bold navy background, white quote mark shapes, customer review visual of club management SaaS, bold confident design","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_03","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_light_minimal", + "prompt":_BP+"testimonial card, light white minimal quote card, navy accent line, clean professional customer testimonial visual, minimal elegant design","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_04","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_star_rating", + "prompt":_BP+"testimonial card, 5-star rating visual, gold stars prominently displayed, abstract club management platform review","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_05","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_split_design", + "prompt":_BP+"testimonial card, split design half dark half navy, quote on dark side, customer info shape on navy side, club SaaS testimonial","width":1024,"height":1024,"steps":30}, + {"id":"p3_tc_06","phase":"phase3_social","subfolder":"testimonial_cards","name":"testimonial_gradient", + "prompt":_BP+"testimonial card, midnight to navy gradient background, white elegant quote mark shapes, customer testimonial gradient design","width":1024,"height":1024,"steps":30}, + + # Stat/Data Cards (1024×1024) + {"id":"p3_sc_01","phase":"phase3_social","subfolder":"stat_cards","name":"stat_market_size", + "prompt":_BP+"stat card, club management market size statistic, large bold dollar amount shape, navy gold number on dark background, industry market data visual","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_02","phase":"phase3_social","subfolder":"stat_cards","name":"stat_cost_reduction", + "prompt":_BP+"stat card, cost reduction statistic visual, percentage savings with management software icon, gold percentage shape, club business cost savings","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_03","phase":"phase3_social","subfolder":"stat_cards","name":"stat_time_savings", + "prompt":_BP+"stat card, hours saved per week statistic, clock icon with bold number shape, club operational time savings, navy professional","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_04","phase":"phase3_social","subfolder":"stat_cards","name":"stat_membership_growth", + "prompt":_BP+"stat card, membership industry growth rate, upward arrow with percentage growth shape, membership retail market growth stat, gold growth number on dark","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_05","phase":"phase3_social","subfolder":"stat_cards","name":"stat_compliance_fines", + "prompt":_BP+"stat card, compliance violation fine amounts, regulatory penalty warning stat shape, amber warning colors, avoid fines messaging icon","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_06","phase":"phase3_social","subfolder":"stat_cards","name":"stat_customer_count", + "prompt":_BP+"stat card, number of clubs managed, large customer count statistic shape, navy social proof data card, platform traction metric","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_07","phase":"phase3_social","subfolder":"stat_cards","name":"stat_roi_metric", + "prompt":_BP+"stat card, ROI return on investment metric for club management software, large gold ROI percentage shape, business value data card","width":1024,"height":1024,"steps":30}, + {"id":"p3_sc_08","phase":"phase3_social","subfolder":"stat_cards","name":"stat_global_clubs", + "prompt":_BP+"stat card, number of registered clubs worldwide, globe icon with country count shape, club management global market stat, navy global market visual","width":1024,"height":1024,"steps":30}, + + # ============================================================ + # PHASE 4 — UI & Product Assets (32 assets) + # ============================================================ + + # App Icons (1024×1024) + {"id":"p4_ai_01","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_ios_navy", + "prompt":_BP+"iOS app icon, Apple iOS style rounded square, navy gradient background, white membership network icon mark, premium mobile app icon, App Store quality","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_02","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_ios_dark", + "prompt":_BP+"iOS app icon, dark mode iOS icon, dark charcoal with navy and gold brand mark, premium dark app icon, club management mobile app","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_03","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_ios_gold", + "prompt":_BP+"iOS app icon, premium gold accent, deep navy background with gold membership circuit brand mark, luxury club management app icon","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_04","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_android_material", + "prompt":_BP+"Android app icon, Material Design 3 style adaptive icon, navy with white icon shape, Google Play Store quality, club management Android app","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_05","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_android_dark", + "prompt":_BP+"Android dark mode app icon, dark adaptive icon, navy outline on near-black, Material You dark theme, club management app","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_06","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_gradient_modern", + "prompt":_BP+"app icon, modern gradient icon, midnight to navy gradient background, white geometric membership tech mark, contemporary design","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_07","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_flat_clean", + "prompt":_BP+"app icon, flat design icon, solid navy no gradient, white minimal icon mark, flat design philosophy, simple clean club management","width":1024,"height":1024,"steps":30}, + {"id":"p4_ai_08","phase":"phase4_ui","subfolder":"app_icons","name":"appicon_neumorphic", + "prompt":_BP+"app icon, neumorphic soft UI style, light slate background with embossed membership network icon, subtle shadows, premium modern icon design","width":1024,"height":1024,"steps":30}, + + # Device Mockups + {"id":"p4_dm_01","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_macbook", + "prompt":_BP+"dashboard shown on MacBook Pro shape mockup, professional product marketing, club management SaaS on Apple laptop silhouette, navy UI on screen shape, clean white studio background","width":1024,"height":640,"steps":30}, + {"id":"p4_dm_02","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_ipad", + "prompt":_BP+"dashboard on iPad Pro shape mockup, club management tablet interface icon, navy UI on Apple iPad silhouette, clean marketing product shot, white background","width":1024,"height":768,"steps":30}, + {"id":"p4_dm_03","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_iphone", + "prompt":_BP+"mobile app on iPhone shape mockup, club management mobile interface icon, navy green mobile UI, clean product marketing shot, white background","width":390,"height":844,"steps":30}, + {"id":"p4_dm_04","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_desktop_monitor", + "prompt":_BP+"dashboard on large desktop monitor shape mockup, club management enterprise software on wide screen silhouette, dark UI visible, professional product marketing display","width":1280,"height":720,"steps":30}, + {"id":"p4_dm_05","phase":"phase4_ui","subfolder":"device_mockups","name":"mockup_android_phone", + "prompt":_BP+"mobile app on Android phone shape mockup, club management Android interface icon, Material Design navy UI, product marketing shot white background","width":390,"height":844,"steps":30}, + + # Onboarding Illustrations (800×600) + {"id":"p4_ob_01","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_inventory", + "prompt":_BP+"onboarding illustration, inventory management scene icon, product shelves with digital inventory overlay shapes, flat illustration style, navy and teal","width":800,"height":600,"steps":30}, + {"id":"p4_ob_02","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_compliance", + "prompt":_BP+"onboarding illustration, compliance tracking scene icon, person silhouette reviewing regulatory documents with digital checklist shape, confident professional flat illustration","width":800,"height":600,"steps":30}, + {"id":"p4_ob_03","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_analytics", + "prompt":_BP+"onboarding illustration, analytics and reporting scene icon, business person silhouette analyzing sales charts, dashboard visualization, navy data visualization flat","width":800,"height":600,"steps":30}, + {"id":"p4_ob_04","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_staff", + "prompt":_BP+"onboarding illustration, staff scheduling scene icon, team member silhouettes with shift calendar shape, club team management, professional flat art navy","width":800,"height":600,"steps":30}, + {"id":"p4_ob_05","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_pos", + "prompt":_BP+"onboarding illustration, POS integration scene icon, point of sale system connected to management platform shapes, tech integration flat illustration, navy","width":800,"height":600,"steps":30}, + {"id":"p4_ob_06","phase":"phase4_ui","subfolder":"onboarding_illustrations","name":"onboard_reporting", + "prompt":_BP+"onboarding illustration, automated reporting scene icon, report documents generating automatically shapes, magic automation illustration, navy gold professional flat art","width":800,"height":600,"steps":30}, + + # Empty States (600×400) + {"id":"p4_es_01","phase":"phase4_ui","subfolder":"empty_states","name":"empty_no_data", + "prompt":_BP+"empty state illustration, no data yet icon, friendly empty chart shape, get started visual, navy minimal SaaS illustration","width":600,"height":400,"steps":30}, + {"id":"p4_es_02","phase":"phase4_ui","subfolder":"empty_states","name":"empty_no_results", + "prompt":_BP+"empty state illustration, no search results found icon, magnifying glass with empty bubble, friendly empty state, navy minimal","width":600,"height":400,"steps":30}, + {"id":"p4_es_03","phase":"phase4_ui","subfolder":"empty_states","name":"empty_no_alerts", + "prompt":_BP+"empty state illustration, no alerts icon, happy shield with checkmark, all clear illustration, club compliance all good state, navy positive","width":600,"height":400,"steps":30}, + {"id":"p4_es_04","phase":"phase4_ui","subfolder":"empty_states","name":"empty_no_members", + "prompt":_BP+"empty state illustration, no members added yet icon, friendly people silhouettes with plus icon, club member management, navy add members","width":600,"height":400,"steps":30}, + {"id":"p4_es_05","phase":"phase4_ui","subfolder":"empty_states","name":"empty_loading_data", + "prompt":_BP+"empty state illustration, loading and processing data icon, gentle spinner shapes, patient loading state, navy minimal illustration","width":600,"height":400,"steps":30}, + {"id":"p4_es_06","phase":"phase4_ui","subfolder":"empty_states","name":"empty_offline", + "prompt":_BP+"empty state illustration, offline or connection error icon, disconnected wifi shape, friendly error state, amber warning on navy","width":600,"height":400,"steps":30}, + + # Splash/Loading Screens (720×1280) + {"id":"p4_sp_01","phase":"phase4_ui","subfolder":"splash_screens","name":"splash_primary", + "prompt":_BP+"splash screen, app loading screen, dark charcoal background, large centered brand icon mark shape, subtle navy glow effect, premium app loading screen","width":720,"height":1280,"steps":30}, + {"id":"p4_sp_02","phase":"phase4_ui","subfolder":"splash_screens","name":"splash_navy", + "prompt":_BP+"splash screen, navy background, white icon centered, minimal loading indicator shape, club management app splash, clean brand loading screen","width":720,"height":1280,"steps":30}, + {"id":"p4_sp_03","phase":"phase4_ui","subfolder":"splash_screens","name":"splash_animated_hint", + "prompt":_BP+"splash screen, animated concept, community node particles converging into icon mark, dark background with teal particles, dynamic loading screen first frame","width":720,"height":1280,"steps":30}, + {"id":"p4_sp_04","phase":"phase4_ui","subfolder":"splash_screens","name":"splash_gradient", + "prompt":_BP+"splash screen, dramatic dark to navy gradient background, white brand mark shape, premium loading experience, club SaaS gradient splash","width":720,"height":1280,"steps":30}, + + # ============================================================ + # PHASE 5 — Brand Collateral (38 assets) + # ============================================================ + + # Business Cards (900×504) + {"id":"p5_bc_01f","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_modern_front", + "prompt":_BP+"business card front, modern minimal style, navy left accent panel, white main area, name placeholder area, club management SaaS company card, premium print","width":900,"height":504,"steps":30}, + {"id":"p5_bc_01b","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_modern_back", + "prompt":_BP+"business card back, modern minimal style, full navy back with white icon centered, club management SaaS card back","width":900,"height":504,"steps":30}, + {"id":"p5_bc_02f","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_dark_front", + "prompt":_BP+"business card front, dark luxury style, dark charcoal background, gold foil accent icon, premium club management company card, executive tier","width":900,"height":504,"steps":30}, + {"id":"p5_bc_02b","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_dark_back", + "prompt":_BP+"business card back, dark luxury style, full dark charcoal, gold icon and navy accent, premium back of card","width":900,"height":504,"steps":30}, + {"id":"p5_bc_03f","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_pattern_front", + "prompt":_BP+"business card front, geometric community pattern accent, white card with subtle hexagonal pattern header, professional pattern card front","width":900,"height":504,"steps":30}, + {"id":"p5_bc_03b","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_pattern_back", + "prompt":_BP+"business card back, community geometric pattern full bleed, navy hexagonal pattern background, white icon, pattern card back","width":900,"height":504,"steps":30}, + {"id":"p5_bc_04f","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_bold_front", + "prompt":_BP+"business card front, bold icon style, large navy brand shape, clean white card, icon-forward business card","width":900,"height":504,"steps":30}, + {"id":"p5_bc_04b","phase":"phase5_collateral","subfolder":"business_cards","name":"bizcard_bold_back", + "prompt":_BP+"business card back, bold style, split navy and white back, contact details area shape, club company card back bold design","width":900,"height":504,"steps":30}, + + # Pitch Deck Covers (1280×720) + {"id":"p5_pd_01","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_investor_dark", + "prompt":_BP+"pitch deck cover slide, investor presentation, dark sophisticated background, large icon centered, funding round visual area, premium club SaaS investor deck","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_02","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_growth_story", + "prompt":_BP+"pitch deck cover, growth story visual, ascending membership curve becoming data chart, navy to gold gradient, investor-grade presentation cover","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_03","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_market_opp", + "prompt":_BP+"pitch deck cover, market opportunity theme, club industry size visualization, globe with highlighted market regions, navy professional investor presentation","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_04","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_team_deck", + "prompt":_BP+"pitch deck cover, team presentation version, professional team silhouette backdrop, club tech startup team slide, navy brand, people silhouette-forward investor deck","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_05","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_product_demo", + "prompt":_BP+"pitch deck cover, product demo deck, dashboard preview hero visual shapes, club management SaaS product tour deck, navy UI preview","width":1280,"height":720,"steps":30}, + {"id":"p5_pd_06","phase":"phase5_collateral","subfolder":"pitch_deck","name":"pitch_minimal_clean", + "prompt":_BP+"pitch deck cover, ultra-minimal clean slide, white background, large navy brand icon only, minimalist investor presentation","width":1280,"height":720,"steps":30}, + + # One-Pager Headers (1200×400) + {"id":"p5_op_01","phase":"phase5_collateral","subfolder":"one_pager","name":"onepager_primary", + "prompt":_BP+"one-pager header, primary brand header, navy full bleed, white icon and visual, club management SaaS brochure header, print quality","width":1200,"height":400,"steps":30}, + {"id":"p5_op_02","phase":"phase5_collateral","subfolder":"one_pager","name":"onepager_feature_rich", + "prompt":_BP+"one-pager header, feature-rich header, dashboard preview icon glimpse shapes, club management platform features introduction, professional SaaS marketing","width":1200,"height":400,"steps":30}, + {"id":"p5_op_03","phase":"phase5_collateral","subfolder":"one_pager","name":"onepager_compliance", + "prompt":_BP+"one-pager header, compliance focus version, legal and regulatory icon theme, club compliance management, shield icons, dark professional header","width":1200,"height":400,"steps":30}, + {"id":"p5_op_04","phase":"phase5_collateral","subfolder":"one_pager","name":"onepager_dark_premium", + "prompt":_BP+"one-pager header, dark premium version, charcoal background with gold and navy accents, enterprise tier marketing collateral header","width":1200,"height":400,"steps":30}, + + # Trade Show Banners (512×1280) + {"id":"p5_ts_01","phase":"phase5_collateral","subfolder":"trade_show","name":"tradeshow_primary_brand", + "prompt":_BP+"trade show pull-up banner tall vertical, primary brand version, navy top with icon, white middle with key feature icons listed, dark bottom with CTA arrow, club management SaaS conference banner","width":512,"height":1280,"steps":30}, + {"id":"p5_ts_02","phase":"phase5_collateral","subfolder":"trade_show","name":"tradeshow_product_showcase", + "prompt":_BP+"trade show banner tall vertical, product showcase, dashboard UI hero visual shapes, dark sophisticated background, navy accents, club management software exhibition display","width":512,"height":1280,"steps":30}, + {"id":"p5_ts_03","phase":"phase5_collateral","subfolder":"trade_show","name":"tradeshow_membership_focus", + "prompt":_BP+"trade show banner tall vertical, membership authority positioning, club management expertise icons, professional membership focus, navy and gold tall exhibition banner","width":512,"height":1280,"steps":30}, + + # Sticker/Swag Designs (600×600) + {"id":"p5_sk_01","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_people_circuit", + "prompt":_BP+"sticker design, people silhouettes made of circuit traces, navy on white, die-cut sticker style, fun tech community brand sticker","width":600,"height":600,"steps":30}, + {"id":"p5_sk_02","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_icon_badge", + "prompt":_BP+"sticker badge, rounded rectangle badge, navy background, white brand icon shape, premium brand sticker, laptop sticker style","width":600,"height":600,"steps":30}, + {"id":"p5_sk_03","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_membership_hero", + "prompt":_BP+"sticker, membership superhero icon, shield with people and checkmark, fun illustrated sticker, navy and gold, die-cut design","width":600,"height":600,"steps":30}, + {"id":"p5_sk_04","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_data_community", + "prompt":_BP+"fun sticker, community nodes growing into data chart bars, punchy colorful sticker art, navy people gold bars, square sticker","width":600,"height":600,"steps":30}, + {"id":"p5_sk_05","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_club_astronaut", + "prompt":_BP+"sticker, cartoon astronaut holding membership card and laptop, space tech meets club management, fun illustrated sticker, navy spacesuit, brand mascot concept","width":600,"height":600,"steps":30}, + {"id":"p5_sk_06","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_powered_by", + "prompt":_BP+"powered by sticker, powered by platform badge icon, small horizontal badge sticker, navy and white, partner sticker for clubs","width":600,"height":600,"steps":30}, + {"id":"p5_sk_07","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_compliance_100", + "prompt":_BP+"sticker, 100 percent compliant badge icon, bold navy circle with checkmark and percentage shape, compliance achievement sticker, club compliance badge","width":600,"height":600,"steps":30}, + {"id":"p5_sk_08","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_hexagon_icon", + "prompt":_BP+"hexagon sticker, hexagonal border with community network icon, honeycomb management brand sticker, navy hex border gold icon, premium die-cut","width":600,"height":600,"steps":30}, + {"id":"p5_sk_09","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_members_first", + "prompt":_BP+"sticker, members first badge design, playful club membership spirit icon, professional but fun brand sticker, navy with gold shapes","width":600,"height":600,"steps":30}, + {"id":"p5_sk_10","phase":"phase5_collateral","subfolder":"stickers","name":"sticker_manage_everything", + "prompt":_BP+"sticker, manage everything icon, bold icon sticker, navy background white icon shape, punchy brand statement sticker","width":600,"height":600,"steps":30}, + + # Email Signature Blocks (600×150) + {"id":"p5_es_01","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_primary", + "prompt":_BP+"email signature graphic block, primary brand, horizontal icon left with visual divider, navy line, professional email signature banner","width":600,"height":150,"steps":30}, + {"id":"p5_es_02","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_dark", + "prompt":_BP+"email signature block, dark version, charcoal background white icon navy accent, premium email signature graphic","width":600,"height":150,"steps":30}, + {"id":"p5_es_03","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_minimal", + "prompt":_BP+"email signature graphic, minimal version, just icon and visual, very clean white background, ultra-minimal email signature banner","width":600,"height":150,"steps":30}, + {"id":"p5_es_04","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_promo", + "prompt":_BP+"email signature promo block, promotional version with CTA arrow shape, gold button area, white background navy brand, conversion CTA signature","width":600,"height":150,"steps":30}, + {"id":"p5_es_05","phase":"phase5_collateral","subfolder":"email_signatures","name":"sigblock_social", + "prompt":_BP+"email signature block, social media icons version, small social platform icon shapes in navy, company signature with social links footer","width":600,"height":150,"steps":30}, + + # ============================================================ + # PHASE 6 — Bonus / Wildcard Assets (35 assets) + # ============================================================ + + # Animated Banner First-Frame Stills (1200×628) + {"id":"p6_an_01","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_particle_logo", + "prompt":_BP+"animated banner first frame, community node particles forming icon mark mid-flight, dark background teal particles, designed for animation, static concept frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_02","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_data_flow", + "prompt":_BP+"animated banner first frame, data flow visualization beginning, club data streams starting to form dashboard shapes, dark background navy data lines, animation concept first frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_03","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_growth_chart", + "prompt":_BP+"animated banner still, club business growth chart animation first frame, bar chart at zero about to animate upward, gold bars on dark, growth animation concept","width":1200,"height":628,"steps":30}, + {"id":"p6_an_04","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_checklist_check", + "prompt":_BP+"animated banner first frame, membership checklist items unchecked ready to animate with checkmarks, navy checklist on white, compliance animation concept","width":1200,"height":628,"steps":30}, + {"id":"p6_an_05","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_community_grow", + "prompt":_BP+"animated banner still, community node seedling about to grow into data visualization network, dark background seed sprouting, growth animation first frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_06","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_typing_headline", + "prompt":_BP+"animated banner still, typing cursor before headline space, empty headline with blinking cursor concept shape, navy CTA button below, typewriter animation first frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_07","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_integration_connect", + "prompt":_BP+"animated banner still, integration ecosystem nodes about to connect, partner icon nodes as unconnected shapes, teal connecting lines forming, integration animation first frame","width":1200,"height":628,"steps":30}, + {"id":"p6_an_08","phase":"phase6_bonus","subfolder":"animated_stills","name":"anim_counter_stat", + "prompt":_BP+"animated banner still, number counter animation first frame showing zero shape, gold large number shape about to count up, dark background, counter animation concept","width":1200,"height":628,"steps":30}, + + # Dark Mode vs Light Mode UI Pairs (1200×800 each = 6 pairs) + {"id":"p6_dm_01l","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_dashboard_light", + "prompt":_BP+"UI preview card, light mode dashboard interface, clean white background, navy UI element shapes, club management SaaS light theme preview","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_01d","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_dashboard_dark", + "prompt":_BP+"UI preview card, dark mode dashboard interface, dark charcoal background, teal glowing UI element shapes, club management SaaS dark theme preview, premium dark mode","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_02l","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_membership_light", + "prompt":_BP+"UI preview, membership module light mode, white clean interface with checklist and status indicator shapes, navy checkmarks, club membership UI","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_02d","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_membership_dark", + "prompt":_BP+"UI preview, membership module dark mode, dark interface with glowing navy membership indicator shapes, club membership UI dark theme, premium","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_03l","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_analytics_light", + "prompt":_BP+"UI preview, analytics dashboard light mode, white background with colorful club business chart shapes, navy and gold data visualization, light theme","width":1200,"height":800,"steps":40}, + {"id":"p6_dm_03d","phase":"phase6_bonus","subfolder":"dark_light_pairs","name":"uipair_analytics_dark", + "prompt":_BP+"UI preview, analytics dashboard dark mode, dark background with glowing navy and gold club business chart shapes, dramatic dark mode analytics UI","width":1200,"height":800,"steps":40}, + + # Integration/Partnership Badges (400×200) + {"id":"p6_ib_01","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_pos_integration", + "prompt":_BP+"integration badge, integrates with POS systems badge icon, point-of-sale integration certification, navy badge design, professional","width":400,"height":200,"steps":40}, + {"id":"p6_ib_02","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_accounting", + "prompt":_BP+"integration badge, accounting software integration badge icon, financial software connection shape, navy badge with accounting icon","width":400,"height":200,"steps":40}, + {"id":"p6_ib_03","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_compliance_tools", + "prompt":_BP+"integration badge, compliance tool integration badge icon, regulatory software connection shape, navy shield badge design","width":400,"height":200,"steps":40}, + {"id":"p6_ib_04","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_api_ready", + "prompt":_BP+"API ready badge icon, API first platform badge shape, developer integration badge, navy and code brackets design, club management API badge","width":400,"height":200,"steps":40}, + {"id":"p6_ib_05","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_partner_certified", + "prompt":_BP+"partner certified badge icon, certified technology partner badge design shape, navy official partner badge, club management platform partner program","width":400,"height":200,"steps":40}, + {"id":"p6_ib_06","phase":"phase6_bonus","subfolder":"integration_badges","name":"badge_white_label", + "prompt":_BP+"white label partner badge icon, white label ready platform badge shape, club SaaS white label partner certification, professional partner badge navy","width":400,"height":200,"steps":40}, + + # Trust/Award Badges (400×400) + {"id":"p6_tb_01","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_gdpr_compliant", + "prompt":_BP+"trust badge, GDPR compliant badge design icon, data protection certification shape, navy shield with EU star circle, club SaaS data privacy trust badge","width":400,"height":400,"steps":40}, + {"id":"p6_tb_02","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_soc2_ready", + "prompt":_BP+"trust badge, SOC 2 ready certification badge icon, enterprise security trust badge shape, professional certification seal, dark navy badge design","width":400,"height":400,"steps":40}, + {"id":"p6_tb_03","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_uptime_guarantee", + "prompt":_BP+"trust badge, 99.9 percent uptime guarantee badge icon, reliability certification shape, gold uptime number on navy badge, club SaaS reliability trust signal","width":400,"height":400,"steps":40}, + {"id":"p6_tb_04","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_industry_choice", + "prompt":_BP+"award badge, club industry choice award badge design icon, industry recognition award seal shape, gold and navy award badge","width":400,"height":400,"steps":40}, + {"id":"p6_tb_05","phase":"phase6_bonus","subfolder":"trust_badges","name":"trust_money_back", + "prompt":_BP+"trust badge, 30-day money back guarantee badge icon, customer confidence seal shape, navy circle badge, club SaaS satisfaction badge","width":400,"height":400,"steps":40}, +] + +# Bump steps for quality on phases with smaller dimensions +for _a in ASSET_MANIFEST: + if _a["steps"] == 30 and _a["width"] <= 1024 and _a["height"] <= 1024: + _a["steps"] = 40 + + +def load_progress() -> Dict[str, Any]: + """Load resume state from .progress.json.""" + if PROGRESS_FILE.exists(): + try: + with open(PROGRESS_FILE) as f: + return json.load(f) + except (json.JSONDecodeError, IOError): + pass + return {"completed": [], "failed": [], "started_at": time.strftime("%Y-%m-%dT%H:%M:%S")} + + +def save_progress(progress: Dict[str, Any]) -> None: + """Save progress state.""" + OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) + with open(PROGRESS_FILE, "w") as f: + json.dump(progress, f, indent=2) + + +def load_workflow(model: str) -> Dict: + """Load the appropriate workflow JSON.""" + path = WORKFLOW_HERETIC if model == "heretic" else WORKFLOW_SCHNELL + with open(path) as f: + return json.load(f) + + +def submit_prompt(comfyui_url: str, workflow: Dict) -> str: + """Submit prompt to ComfyUI.""" + data = json.dumps({"prompt": workflow}).encode() + req = urllib.request.Request( + f"{comfyui_url}/prompt", data=data, headers={"Content-Type": "application/json"} + ) + with urllib.request.urlopen(req) as resp: + return json.loads(resp.read())["prompt_id"] + + +def wait_for_image(comfyui_url: str, prompt_id: str, timeout: int = 300) -> Dict | None: + """Poll for completion.""" + print(" ⏳ Waiting for ComfyUI...", end="", flush=True) + start = time.time() + while time.time() - start < timeout: + try: + with urllib.request.urlopen(f"{comfyui_url}/history/{prompt_id}") as resp: + history = json.loads(resp.read()) + if prompt_id in history: + print(" done.", flush=True) + outputs = history[prompt_id].get("outputs", {}) + for node_out in outputs.values(): + if "images" in node_out: + return node_out["images"][0] + return None + except Exception: + pass + print(".", end="", flush=True) + time.sleep(2) + print(" timeout!", flush=True) + return None + + +def download_image(comfyui_url: str, image_info: Dict, output_path: Path) -> bool: + """Download the generated image.""" + try: + url = f"{comfyui_url}/view?filename={image_info['filename']}&subfolder={image_info.get('subfolder', '')}&type=output" + with urllib.request.urlopen(url) as resp: + img_data = resp.read() + output_path.write_bytes(img_data) + print(f" ✅ Saved: {output_path} ({len(img_data) // 1024}KB)") + return True + except Exception as e: + print(f" ❌ Download failed: {e}") + return False + + +def patch_workflow(workflow: Dict, asset: Dict, model: str) -> Dict: + """Patch workflow with asset params using per-model node IDs.""" + seed = random.randint(0, 2**32 - 1) + if model == "heretic": + # flux2_klein_heretic.json nodes: 2=pos, 3=neg, 6=latent(w/h), 7=scheduler(steps), 10=noise(seed), 13=save + workflow["2"]["inputs"]["text"] = asset["prompt"] + workflow["3"]["inputs"]["text"] = _NEG + workflow["6"]["inputs"]["width"] = asset["width"] + workflow["6"]["inputs"]["height"] = asset["height"] + workflow["7"]["inputs"]["steps"] = asset["steps"] + workflow["13"]["inputs"]["filename_prefix"] = asset["name"] + if "10" in workflow: + workflow["10"]["inputs"]["noise_seed"] = seed + else: + # flux_schnell.json nodes: 6=pos, 33=neg, 27=latent(w/h), 13=ksampler(steps/seed), 9=save + workflow["6"]["inputs"]["text"] = asset["prompt"] + workflow["33"]["inputs"]["text"] = _NEG + workflow["27"]["inputs"]["width"] = asset["width"] + workflow["27"]["inputs"]["height"] = asset["height"] + workflow["13"]["inputs"]["steps"] = asset["steps"] + workflow["13"]["inputs"]["seed"] = seed + workflow["9"]["inputs"]["filename_prefix"] = asset["name"] + return workflow + + +def generate_asset(comfyui_url: str, asset: Dict, model: str, progress: Dict) -> bool: + """Generate a single asset.""" + if asset["id"] in progress["completed"]: + print(f" ⏭️ Skipping completed: {asset['name']}") + return True + + print(f"\n Prompt : {asset['prompt'][:80]}...") + print(f" Size : {asset['width']}×{asset['height']} Steps: {asset['steps']}") + + try: + workflow = load_workflow(model) + workflow = patch_workflow(workflow, asset, model) + + prompt_id = submit_prompt(comfyui_url, workflow) + image_info = wait_for_image(comfyui_url, prompt_id) + + if not image_info: + progress["failed"].append(asset["id"]) + save_progress(progress) + return False + + output_dir = OUTPUT_ROOT / asset["phase"] / asset["subfolder"] + output_dir.mkdir(parents=True, exist_ok=True) + output_path = output_dir / f"{asset['name']}.png" + + if download_image(comfyui_url, image_info, output_path): + progress["completed"].append(asset["id"]) + save_progress(progress) + return True + else: + progress["failed"].append(asset["id"]) + save_progress(progress) + return False + + except Exception as e: + print(f" ❌ Error: {e}") + progress["failed"].append(asset["id"]) + save_progress(progress) + return False + + +def main(): + parser = argparse.ArgumentParser(description="ClubManage Brand Asset Generation Pipeline") + parser.add_argument("--dry-run", action="store_true", help="Print manifest without generating") + parser.add_argument("--phase", help="Generate only assets from this phase (e.g. phase1_logos)") + parser.add_argument("--model", choices=["schnell", "heretic"], default="schnell", + help="Model: schnell (~10-20s/img) or heretic (~52s/img, higher quality)") + parser.add_argument("--comfyui", default="http://localhost:8188", help="ComfyUI URL") + parser.add_argument("--steps", type=int, default=None, + help="Override steps for all assets (e.g. --steps 12 for higher quality)") + args = parser.parse_args() + + comfyui_url = args.comfyui + + # Apply global steps override if requested + manifest = ASSET_MANIFEST + if args.steps: + manifest = [{**a, "steps": args.steps} for a in manifest] + + # Filter by phase if requested + to_generate = [a for a in manifest if not args.phase or a["phase"] == args.phase] + + print("🚀 ClubManage Brand Asset Generation Pipeline") + print(f" Output : {OUTPUT_ROOT}") + print(f" Model : {args.model}") + print(f" ComfyUI : {comfyui_url}") + print(f" Total : {len(ASSET_MANIFEST)} assets in manifest") + print(f" Selected: {len(to_generate)} assets to generate") + print(f" Note : All images are text-free — pure visual/icon design") + + if args.dry_run: + phases: Dict[str, int] = {} + for a in to_generate: + phases[a["phase"]] = phases.get(a["phase"], 0) + 1 + for ph, count in phases.items(): + print(f"\n {ph} ({count} assets):") + for a in to_generate: + if a["phase"] == ph: + print(f" {a['id']:14} | {a['name']:35} | {a['width']}×{a['height']} steps={a['steps']}") + total_min_est = sum(a["steps"] * 2.5 for a in to_generate) / 60 + print(f"\n ⏱️ Estimated runtime (schnell): ~{total_min_est:.0f} minutes") + print("\nDry run complete. Remove --dry-run to begin generation.") + return + + progress = load_progress() + remaining = [a for a in to_generate if a["id"] not in progress["completed"]] + print(f" Resume : {len(progress['completed'])} completed, {len(progress['failed'])} failed, {len(remaining)} remaining") + + if not remaining: + print("\n✅ All selected assets already complete!") + return + + print(f"\nStarting generation... (Ctrl+C to pause — progress is saved)") + + n_done = 0 + n_fail = 0 + for i, asset in enumerate(to_generate, 1): + if asset["id"] in progress["completed"]: + continue + print(f"\n[{asset['phase']}] [{i}/{len(to_generate)}] {asset['name']}") + if generate_asset(comfyui_url, asset, args.model, progress): + n_done += 1 + else: + n_fail += 1 + + print("\n" + "=" * 60) + print("🎉 PIPELINE COMPLETE") + print(f" ✅ Completed this run : {n_done}") + print(f" ❌ Failed this run : {n_fail}") + print(f" 📦 Total completed : {len(progress['completed'])} / {len(ASSET_MANIFEST)}") + if progress["failed"]: + print(f" Failed IDs: {', '.join(progress['failed'][-10:])}") + print(f" Assets saved to: {OUTPUT_ROOT}") + print("=" * 60) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/mcp/mcp-image-gen/gen.py b/mcp/mcp-image-gen/gen.py new file mode 100644 index 0000000..fdf46a9 --- /dev/null +++ b/mcp/mcp-image-gen/gen.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +""" +Quick CLI for generating images via ComfyUI + FLUX.2 Klein Heretic. + +Usage: + python gen.py "your prompt here" + python gen.py "your prompt" --steps 20 --width 1280 --height 720 + python gen.py "your prompt" --seed 12345 + python gen.py "your prompt" --count 3 + +Output saved to ~/Pictures/mcp-generated/ +""" + +import argparse +import json +import random +import sys +import time +import urllib.request +from pathlib import Path + +COMFYUI = "http://localhost:8188" +OUTPUT_DIR = Path.home() / "Pictures" / "mcp-generated" +WORKFLOW_PATH = Path(__file__).parent / "src/workflows/flux2_klein_heretic.json" + + +def load_workflow(): + with open(WORKFLOW_PATH) as f: + return json.load(f) + + +def submit(workflow): + data = json.dumps({"prompt": workflow}).encode() + req = urllib.request.Request( + f"{COMFYUI}/prompt", data=data, + headers={"Content-Type": "application/json"} + ) + with urllib.request.urlopen(req) as resp: + return json.loads(resp.read())["prompt_id"] + + +def wait(prompt_id, timeout=300): + print(" ⏳ Waiting for ComfyUI...", end="", flush=True) + start = time.time() + while time.time() - start < timeout: + with urllib.request.urlopen(f"{COMFYUI}/history/{prompt_id}") as resp: + history = json.loads(resp.read()) + if prompt_id in history: + print(" done.", flush=True) + outputs = history[prompt_id].get("outputs", {}) + for node_out in outputs.values(): + if "images" in node_out: + return node_out["images"][0] + return None + print(".", end="", flush=True) + time.sleep(2) + raise TimeoutError(f"Timed out after {timeout}s") + + +def download(filename, subfolder=""): + url = f"{COMFYUI}/view?filename={filename}&subfolder={subfolder}&type=output" + with urllib.request.urlopen(url) as resp: + return resp.read() + + +def generate(prompt, steps=20, width=1024, height=1024, seed=-1, name="cli"): + if seed == -1: + seed = random.randint(0, 2**32 - 1) + + workflow = load_workflow() + + # Patch positive prompt (node 2) + workflow["2"]["inputs"]["text"] = prompt + # Patch negative prompt (node 3) — leave empty + workflow["3"]["inputs"]["text"] = "" + # Patch seed (node 10) + if "10" in workflow: + workflow["10"]["inputs"]["noise_seed"] = seed + # Patch dimensions (node 6) + workflow["6"]["inputs"]["width"] = width + workflow["6"]["inputs"]["height"] = height + # Patch steps (node 7) + workflow["7"]["inputs"]["steps"] = steps + # Patch output filename (node 13) + workflow["13"]["inputs"]["filename_prefix"] = name + + print(f" Prompt : {prompt[:80]}{'...' if len(prompt) > 80 else ''}") + print(f" Size : {width}×{height} Steps: {steps} Seed: {seed}") + + prompt_id = submit(workflow) + image_info = wait(prompt_id) + + if not image_info: + print(" ❌ No output image returned.", file=sys.stderr) + return None + + img_data = download(image_info["filename"], image_info.get("subfolder", "")) + OUTPUT_DIR.mkdir(parents=True, exist_ok=True) + out_path = OUTPUT_DIR / f"{name}_{seed}.png" + out_path.write_bytes(img_data) + print(f" ✅ Saved: {out_path} ({len(img_data) // 1024}KB)") + return out_path + + +def main(): + parser = argparse.ArgumentParser( + description="Generate images via ComfyUI FLUX.2 Klein Heretic" + ) + parser.add_argument("prompt", help="Text prompt for the image") + parser.add_argument("--steps", type=int, default=20, help="Inference steps (default: 20)") + parser.add_argument("--width", type=int, default=1024, help="Width in pixels (default: 1024)") + parser.add_argument("--height", type=int, default=1024, help="Height in pixels (default: 1024)") + parser.add_argument("--seed", type=int, default=-1, help="Seed (-1 = random)") + parser.add_argument("--count", type=int, default=1, help="Number of images (default: 1)") + parser.add_argument("--name", default="cli", help="Output filename prefix (default: cli)") + args = parser.parse_args() + + for i in range(args.count): + if args.count > 1: + print(f"\n[{i+1}/{args.count}]") + seed = args.seed if args.seed != -1 else -1 + generate( + prompt=args.prompt, + steps=args.steps, + width=args.width, + height=args.height, + seed=seed, + name=f"{args.name}_{i+1:02d}" if args.count > 1 else args.name, + ) + + +if __name__ == "__main__": + main() diff --git a/mcp/mcp-image-gen/gui.py b/mcp/mcp-image-gen/gui.py new file mode 100644 index 0000000..98bf20c --- /dev/null +++ b/mcp/mcp-image-gen/gui.py @@ -0,0 +1,352 @@ +#!/usr/bin/env python3 +""" +FLUX Image Generator — Desktop GUI +Supports: FLUX.1 Schnell (fast) and FLUX.2 Klein Heretic (unrestricted) +Run: python3 gui.py +No external dependencies — stdlib + tkinter only. +""" + +import json +import random +import threading +import time +import urllib.request +from pathlib import Path +import tkinter as tk +from tkinter import ttk, scrolledtext, messagebox + +COMFYUI = "http://localhost:8188" +OUTPUT_DIR = Path.home() / "Pictures" / "mcp-generated" +WORKFLOWS_DIR = Path(__file__).parent / "src/workflows" + +# ── Model definitions ──────────────────────────────────────────────────────── +# Each entry defines how to patch the workflow for that model. +# node_pos / node_neg: CLIPTextEncode node IDs for positive/negative prompts +# node_latent: latent image node (for width/height) +# node_seed: where to write the seed value +# node_save: SaveImage node (for filename_prefix) +# node_steps: dict of {node_id: field} for steps — None if not patchable +MODELS = { + "FLUX.2 Klein Heretic (unrestricted)": { + "workflow": "flux2_klein_heretic.json", + "default_steps": 20, + "node_pos": ("2", "text"), + "node_neg": ("3", "text"), + "node_latent": ("6", "width", "height"), + "node_seed": ("10", "noise_seed"), + "node_steps": ("7", "steps"), + "node_save": ("13", "filename_prefix"), + "description": "FLUX.2 Klein 4B + Heretic abliterated encoder. ~50s/image. No refusals.", + }, + "FLUX.1 Schnell (fast)": { + "workflow": "flux_schnell.json", + "default_steps": 4, + "node_pos": ("6", "text"), + "node_neg": ("33", "text"), + "node_latent": ("27", "width", "height"), + "node_seed": ("13", "seed"), # KSampler has seed directly + "node_steps": ("13", "steps"), + "node_save": ("9", "filename_prefix"), + "description": "FLUX.1 Schnell — fast (~5s/image), standard quality. Has safety filter.", + }, +} + +PRESETS = { + "Square 1024": (1024, 1024), + "Landscape 16:9": (1280, 720), + "Portrait 9:16": (720, 1280), + "Wide 3:2": (1536, 1024), + "Tall 2:3": (1024, 1536), + "BFL Wide 7:4": (1344, 768), + "BFL Tall 4:7": (768, 1344), +} + + +def load_workflow(filename): + with open(WORKFLOWS_DIR / filename) as f: + return json.load(f) + + +def patch_workflow(wf, spec, prompt, neg, width, height, steps, seed, name): + """Apply generation parameters to a workflow dict in-place.""" + node_pos_id, node_pos_field = spec["node_pos"] + node_neg_id, node_neg_field = spec["node_neg"] + lat_id, lat_w, lat_h = spec["node_latent"] + seed_id, seed_field = spec["node_seed"] + save_id, save_field = spec["node_save"] + + wf[node_pos_id]["inputs"][node_pos_field] = prompt + wf[node_neg_id]["inputs"][node_neg_field] = neg + wf[lat_id]["inputs"][lat_w] = width + wf[lat_id]["inputs"][lat_h] = height + wf[seed_id]["inputs"][seed_field] = seed + wf[save_id]["inputs"][save_field] = name + + if spec["node_steps"]: + steps_id, steps_field = spec["node_steps"] + wf[steps_id]["inputs"][steps_field] = steps + + return wf + + +def submit_prompt(workflow): + data = json.dumps({"prompt": workflow}).encode() + req = urllib.request.Request( + f"{COMFYUI}/prompt", data=data, + headers={"Content-Type": "application/json"}, + ) + with urllib.request.urlopen(req, timeout=30) as resp: + return json.loads(resp.read())["prompt_id"] + + +def wait_for_image(prompt_id, timeout=300): + start = time.time() + while time.time() - start < timeout: + with urllib.request.urlopen(f"{COMFYUI}/history/{prompt_id}", timeout=10) as resp: + history = json.loads(resp.read()) + if prompt_id in history: + for node_out in history[prompt_id].get("outputs", {}).values(): + if "images" in node_out: + return node_out["images"][0] + return None + time.sleep(2) + raise TimeoutError("Timed out waiting for image") + + +def download_image(filename, subfolder=""): + url = f"{COMFYUI}/view?filename={filename}&subfolder={subfolder}&type=output" + with urllib.request.urlopen(url, timeout=30) as resp: + return resp.read() + + +class App(tk.Tk): + def __init__(self): + super().__init__() + self.title("FLUX Image Generator") + self.resizable(True, True) + self.minsize(760, 640) + self._current_image = None + self._build_ui() + + def _build_ui(self): + main = ttk.Frame(self, padding=12) + main.pack(fill="both", expand=True) + main.columnconfigure(0, weight=1) + main.columnconfigure(1, weight=2) + + # ── LEFT PANEL ─────────────────────────────────────────────────────── + left = ttk.Frame(main) + left.grid(row=0, column=0, sticky="nsew", padx=(0, 8)) + left.columnconfigure(0, weight=1) + row = 0 + + # Model selector + ttk.Label(left, text="Model", font=("", 10, "bold")).grid( + row=row, column=0, sticky="w"); row += 1 + self.model_var = tk.StringVar(value=list(MODELS.keys())[0]) + model_cb = ttk.Combobox(left, textvariable=self.model_var, + values=list(MODELS.keys()), state="readonly", width=40) + model_cb.grid(row=row, column=0, sticky="ew", pady=(2, 2)); row += 1 + model_cb.bind("<>", self._on_model_change) + self.model_desc = ttk.Label(left, text="", foreground="gray", + wraplength=300, font=("", 8)) + self.model_desc.grid(row=row, column=0, sticky="w", pady=(0, 8)); row += 1 + # description updated after all widgets are created (see end of _build_ui) + + # Prompt + ttk.Label(left, text="Prompt", font=("", 10, "bold")).grid( + row=row, column=0, sticky="w"); row += 1 + self.prompt_txt = scrolledtext.ScrolledText(left, height=6, wrap="word", font=("", 10)) + self.prompt_txt.grid(row=row, column=0, sticky="ew", pady=(2, 8)); row += 1 + + # Negative prompt + ttk.Label(left, text="Negative Prompt (optional)").grid( + row=row, column=0, sticky="w"); row += 1 + self.neg_txt = scrolledtext.ScrolledText(left, height=3, wrap="word", font=("", 9)) + self.neg_txt.grid(row=row, column=0, sticky="ew", pady=(2, 8)); row += 1 + + # Size preset + ttk.Label(left, text="Size Preset").grid(row=row, column=0, sticky="w"); row += 1 + self.preset_var = tk.StringVar(value="Square 1024") + preset_cb = ttk.Combobox(left, textvariable=self.preset_var, + values=list(PRESETS.keys()), state="readonly") + preset_cb.grid(row=row, column=0, sticky="ew", pady=(2, 2)); row += 1 + preset_cb.bind("<>", self._apply_preset) + + # Width / Height + wh = ttk.Frame(left) + wh.grid(row=row, column=0, sticky="ew", pady=(4, 8)); row += 1 + wh.columnconfigure(1, weight=1) + wh.columnconfigure(3, weight=1) + ttk.Label(wh, text="W").grid(row=0, column=0, padx=(0, 4)) + self.width_var = tk.IntVar(value=1024) + ttk.Spinbox(wh, from_=256, to=4096, increment=8, textvariable=self.width_var, + width=6).grid(row=0, column=1, sticky="ew") + ttk.Label(wh, text="H", padding=(8, 0, 4, 0)).grid(row=0, column=2) + self.height_var = tk.IntVar(value=1024) + ttk.Spinbox(wh, from_=256, to=4096, increment=8, textvariable=self.height_var, + width=6).grid(row=0, column=3, sticky="ew") + + # Steps + steps_row = ttk.Frame(left) + steps_row.grid(row=row, column=0, sticky="ew", pady=(0, 4)); row += 1 + steps_row.columnconfigure(1, weight=1) + ttk.Label(steps_row, text="Steps").grid(row=0, column=0, padx=(0, 8)) + self.steps_var = tk.IntVar(value=20) + self.steps_lbl = ttk.Label(steps_row, text="20", width=3) + self.steps_lbl.grid(row=0, column=2, padx=(6, 0)) + ttk.Scale(steps_row, from_=1, to=60, variable=self.steps_var, + orient="horizontal", + command=lambda v: self.steps_lbl.config(text=str(int(float(v)))) + ).grid(row=0, column=1, sticky="ew") + + # Count + count_row = ttk.Frame(left) + count_row.grid(row=row, column=0, sticky="ew", pady=(0, 8)); row += 1 + count_row.columnconfigure(1, weight=1) + ttk.Label(count_row, text="Count").grid(row=0, column=0, padx=(0, 8)) + self.count_var = tk.IntVar(value=1) + ttk.Spinbox(count_row, from_=1, to=20, textvariable=self.count_var, + width=4).grid(row=0, column=1, sticky="w") + + # Seed + seed_row = ttk.Frame(left) + seed_row.grid(row=row, column=0, sticky="ew", pady=(0, 8)); row += 1 + seed_row.columnconfigure(1, weight=1) + ttk.Label(seed_row, text="Seed").grid(row=0, column=0, padx=(0, 8)) + self.seed_var = tk.StringVar(value="-1") + ttk.Entry(seed_row, textvariable=self.seed_var, width=12).grid(row=0, column=1, sticky="w") + ttk.Button(seed_row, text="🎲", width=3, + command=lambda: self.seed_var.set(str(random.randint(0, 2**32 - 1))) + ).grid(row=0, column=2, padx=(4, 0)) + ttk.Label(seed_row, text="(-1 = random)", foreground="gray" + ).grid(row=0, column=3, padx=(4, 0)) + + # Name + name_row = ttk.Frame(left) + name_row.grid(row=row, column=0, sticky="ew", pady=(0, 12)); row += 1 + name_row.columnconfigure(1, weight=1) + ttk.Label(name_row, text="Name").grid(row=0, column=0, padx=(0, 8)) + self.name_var = tk.StringVar(value="img") + ttk.Entry(name_row, textvariable=self.name_var).grid(row=0, column=1, sticky="ew") + + # Generate button + self.gen_btn = ttk.Button(left, text="⚡ Generate", command=self._start_generation) + self.gen_btn.grid(row=row, column=0, sticky="ew", pady=(0, 8)); row += 1 + + # Status + progress + self.status_var = tk.StringVar(value="Ready") + ttk.Label(left, textvariable=self.status_var, foreground="gray", + wraplength=300).grid(row=row, column=0, sticky="w"); row += 1 + self.progress = ttk.Progressbar(left, mode="indeterminate") + self.progress.grid(row=row, column=0, sticky="ew", pady=(4, 0)); row += 1 + + # ── RIGHT PANEL — preview ──────────────────────────────────────────── + right = ttk.LabelFrame(main, text="Preview", padding=8) + right.grid(row=0, column=1, sticky="nsew") + right.columnconfigure(0, weight=1) + right.rowconfigure(0, weight=1) + + self.preview_lbl = ttk.Label(right, text="No image yet", anchor="center", + background="#1a1a1a", foreground="#888") + self.preview_lbl.grid(row=0, column=0, sticky="nsew") + + self.path_lbl = ttk.Label(right, text="", foreground="gray", font=("", 8)) + self.path_lbl.grid(row=1, column=0, sticky="w", pady=(4, 0)) + + ttk.Button(right, text="Open folder", + command=self._open_folder).grid(row=2, column=0, sticky="e", pady=(4, 0)) + + # Init model description + steps default now that all widgets exist + self._on_model_change() + + def _on_model_change(self, _=None): + spec = MODELS[self.model_var.get()] + self.model_desc.config(text=spec["description"]) + self.steps_var.set(spec["default_steps"]) + self.steps_lbl.config(text=str(spec["default_steps"])) + + def _apply_preset(self, _=None): + w, h = PRESETS[self.preset_var.get()] + self.width_var.set(w) + self.height_var.set(h) + + def _start_generation(self): + prompt = self.prompt_txt.get("1.0", "end").strip() + if not prompt: + messagebox.showwarning("No prompt", "Please enter a prompt.") + return + self.gen_btn.config(state="disabled") + self.progress.start(10) + self.status_var.set("Generating…") + t = threading.Thread(target=self._run_generation, args=(prompt,), daemon=True) + t.start() + + def _run_generation(self, prompt): + try: + neg = self.neg_txt.get("1.0", "end").strip() + steps = int(self.steps_var.get()) + width = int(self.width_var.get()) + height = int(self.height_var.get()) + count = int(self.count_var.get()) + name = self.name_var.get().strip() or "img" + seed_str = self.seed_var.get().strip() + base_seed = int(seed_str) if seed_str else -1 + + model_name = self.model_var.get() + spec = MODELS[model_name] + + OUTPUT_DIR.mkdir(parents=True, exist_ok=True) + + for i in range(count): + seed = (base_seed if base_seed == -1 else base_seed + i) + if seed == -1: + seed = random.randint(0, 2**32 - 1) + + label = f"{name}_{i+1:02d}" if count > 1 else name + self.after(0, self.status_var.set, + f"[{i+1}/{count}] {model_name.split('(')[0].strip()} · seed {seed}…") + + wf = load_workflow(spec["workflow"]) + patch_workflow(wf, spec, prompt, neg, width, height, steps, seed, label) + + prompt_id = submit_prompt(wf) + img_info = wait_for_image(prompt_id) + + if img_info: + img_data = download_image(img_info["filename"], img_info.get("subfolder", "")) + out_path = OUTPUT_DIR / f"{label}_{seed}.png" + out_path.write_bytes(img_data) + self.after(0, self._show_preview, out_path) + + self.after(0, self.status_var.set, + f"✅ Done — {count} image(s) saved to ~/Pictures/mcp-generated/") + except Exception as exc: + self.after(0, self.status_var.set, f"❌ Error: {exc}") + finally: + self.after(0, self.progress.stop) + self.after(0, lambda: self.gen_btn.config(state="normal")) + + def _show_preview(self, path): + try: + photo = tk.PhotoImage(file=str(path)) + pw, ph = photo.width(), photo.height() + subsample = 1 + while pw // subsample > 600 or ph // subsample > 600: + subsample += 1 + if subsample > 1: + photo = photo.subsample(subsample, subsample) + self.preview_lbl.config(image=photo, text="") + self._current_image = photo + self.path_lbl.config(text=str(path)) + except Exception as e: + self.status_var.set(f"Preview error: {e}") + + def _open_folder(self): + import subprocess + subprocess.Popen(["xdg-open", str(OUTPUT_DIR)]) + + +if __name__ == "__main__": + app = App() + app.mainloop() diff --git a/mcp/mcp-image-gen/patrick_hidden_gen.py b/mcp/mcp-image-gen/patrick_hidden_gen.py new file mode 100644 index 0000000..8128b7d --- /dev/null +++ b/mcp/mcp-image-gen/patrick_hidden_gen.py @@ -0,0 +1,411 @@ +#!/usr/bin/env python3 +""" +Patrick Hidden Name Artwork Generation Pipeline + +Autonomous script to generate 26 ultra-detailed, visually rich digital artworks +where the name "PATRICK" is cleverly concealed within each composition. +Letters emerge organically from shapes, patterns, negative space, silhouettes, +alignment, or cumulative elements — never as plain text. +Visible only upon close inspection. + +Uses the existing mcp-image-gen infrastructure (ComfyUI FLUX workflows). +Output organized in ~/Pictures/patrick_hidden_name/{theme}/{style}/ + +Usage: + cd /home/pplate/pi_mcps + python mcp/mcp-image-gen/patrick_hidden_gen.py + python mcp/mcp-image-gen/patrick_hidden_gen.py --dry-run + python mcp/mcp-image-gen/patrick_hidden_gen.py --model heretic +""" + +import argparse +import copy +import json +import random +import time +import urllib.request +from pathlib import Path +from typing import Dict, List, Any, Optional + +# --- Configuration --- +OUTPUT_ROOT = Path.home() / "Pictures" / "patrick_hidden_name" +PROGRESS_FILE = OUTPUT_ROOT / ".progress.json" +WORKFLOW_SCHNELL = Path(__file__).parent / "src/workflows/flux_schnell.json" +WORKFLOW_HERETIC = Path(__file__).parent / "src/workflows/flux2_klein_heretic.json" + +# Core hidden-name prompting technique — applied to every asset +_HT = ( + "the name PATRICK is cleverly and seamlessly concealed within the composition, " + "letters P-A-T-R-I-C-K emerge organically from shapes patterns negative space " + "silhouettes alignment or cumulative arrangement of multiple elements, " + "never plain text, subtle yet unmistakable once discovered, requires genuine " + "visual discovery and close inspection, natural integration into the scene, " +) + +# Base quality boosters +_Q = "ultra-high detail, photorealistic rendering with cinematic lighting, intricate textures, depth of field, 8k resolution, masterpiece, best quality, " + +ASSET_MANIFEST: List[Dict[str, Any]] = [ + # 1. Dense crowds of marionette puppets — photoreal + {"id":"phn_01","theme":"marionettes","style":"photoreal","name":"marionette_crowd_puppets", + "prompt":_Q+_HT+"dense crowd of antique wooden marionette puppets on theatrical stage, " + "strings and body poses form PATRICK through negative space and limb alignment, " + "dramatic stage lighting with velvet curtains, realistic wood grain and fabric textures, " + "photorealistic cinematic","width":1024,"height":1024,"steps":4}, + + # 2. Marionettes — painterly + {"id":"phn_02","theme":"marionettes","style":"painterly","name":"marionette_theater_oil", + "prompt":_Q+_HT+"oil painting of crowded marionette theater, puppet strings and poses " + "form hidden PATRICK letters in composition, baroque style, rich colors, dramatic chiaroscuro " + "lighting, thick impasto brushwork","width":1024,"height":1024,"steps":20}, + + # 3. Birds — aerial formation + {"id":"phn_03","theme":"birds","style":"aerial","name":"bird_flock_formation", + "prompt":_Q+_HT+"aerial photograph of massive flock of starlings in precise murmuration, " + "bird silhouettes and gaps spell PATRICK through negative space and wing alignments, " + "golden hour light, vast sky, ultra realistic feathers and motion blur","width":1280,"height":720,"steps":4}, + + # 4. Birds — macro + {"id":"phn_04","theme":"birds","style":"macro","name":"bird_swarm_closeup", + "prompt":_Q+_HT+"macro photography of bird murmuration where individual bird silhouettes " + "and wing alignments subtly spell PATRICK, intricate feather detail, soft bokeh background, " + "extreme close focus","width":1024,"height":1024,"steps":4}, + + # 5. Tree roots — photoreal + {"id":"phn_05","theme":"tree_roots","style":"photoreal","name":"ancient_tree_roots", + "prompt":_Q+_HT+"ancient oak tree with massive tangled roots and branches that naturally " + "form letters PATRICK in their curves and intersections, forest floor moss and dappled sunlight, " + "hyper realistic bark texture, dramatic directional lighting","width":1024,"height":1024,"steps":4}, + + # 6. Tree roots — painterly + {"id":"phn_06","theme":"tree_roots","style":"painterly","name":"tree_root_illustration", + "prompt":_Q+_HT+"detailed botanical illustration of tree roots and branches forming hidden " + "PATRICK name through organic growth patterns, ink and watercolor, scientific accuracy with " + "artistic flair, John Muir style","width":1024,"height":1024,"steps":12}, + + # 7. School of fish + {"id":"phn_07","theme":"fish_school","style":"underwater","name":"fish_school_choreography", + "prompt":_Q+_HT+"underwater scene of thousands of tropical fish in synchronized school, " + "swimming patterns and gaps between bodies form PATRICK, crystal clear tropical water, " + "realistic scales and light caustics, underwater photography","width":1024,"height":1024,"steps":4}, + + # 8. Architecture — gothic facade + {"id":"phn_08","theme":"architecture","style":"architectural","name":"gothic_facade_hidden", + "prompt":_Q+_HT+"ornate gothic cathedral facade where windows arches and stone carvings " + "subtly align to spell PATRICK in negative space and shadow play, dramatic sunset lighting, " + "ultra detailed stone texture, architectural rendering","width":1024,"height":1024,"steps":4}, + + # 9. Architecture — aerial + {"id":"phn_09","theme":"architecture","style":"aerial","name":"modern_skyscraper_letters", + "prompt":_Q+_HT+"aerial view of modern city building complex where rooflines shadows and " + "window patterns form the hidden name PATRICK, golden hour, photorealistic architectural " + "rendering, top-down perspective","width":1280,"height":720,"steps":4}, + + # 10. Coral reef + {"id":"phn_10","theme":"coral_reef","style":"underwater","name":"vibrant_coral_reef", + "prompt":_Q+_HT+"vibrant coral reef ecosystem where branching coral fish and rock formations " + "naturally compose letters PATRICK through color and shape alignment, crystal water, " + "macro detail on polyps and textures, underwater photography","width":1024,"height":1024,"steps":4}, + + # 11. City skyline at night + {"id":"phn_11","theme":"city_skyline","style":"night","name":"neon_skyline_hidden", + "prompt":_Q+_HT+"futuristic city skyline at night where building lights and window patterns " + "subtly spell PATRICK in the neon glow and negative space between towers, cyberpunk atmosphere, " + "realistic reflections and bokeh, long exposure photography","width":1280,"height":720,"steps":4}, + + # 12. Rolling hills landscape + {"id":"phn_12","theme":"hills_landscape","style":"aerial","name":"rolling_hills_contours", + "prompt":_Q+_HT+"aerial view of rolling green hills and valleys where landscape contours " + "hedgerows and elevation shadows subtly form PATRICK, golden hour pastoral scene, " + "drone photography style","width":1280,"height":720,"steps":4}, + + # 13. Persian rug + {"id":"phn_13","theme":"persian_rug","style":"macro","name":"persian_rug_intricate", + "prompt":_Q+_HT+"extremely detailed close-up of hand-woven Persian rug where geometric and " + "floral patterns align to conceal name PATRICK in repeating motifs and negative space, " + "rich colors, silk texture, macro photography","width":1024,"height":1024,"steps":4}, + + # 14. Butterflies + {"id":"phn_14","theme":"butterflies","style":"painterly","name":"butterfly_swarm_metamorphosis", + "prompt":_Q+_HT+"swarm of colorful butterflies in flight where wing patterns and flight paths " + "collectively form hidden letters PATRICK, ethereal garden setting, detailed wing scales, " + "soft natural light, painterly illustration style","width":1024,"height":1024,"steps":12}, + + # 15. Circuit board + {"id":"phn_15","theme":"circuit_board","style":"macro","name":"circuit_board_traces", + "prompt":_Q+_HT+"extreme macro of complex multilayer circuit board where copper traces " + "solder points and component placement subtly spell PATRICK in wiring layout, " + "realistic metallic reflections, depth of field, technical precision","width":1024,"height":1024,"steps":4}, + + # 16. Ocean waves + {"id":"phn_16","theme":"ocean_waves","style":"photoreal","name":"crashing_waves_hidden", + "prompt":_Q+_HT+"dramatic crashing ocean waves where foam spray and wave crests align to " + "reveal name PATRICK in negative space and water movement, powerful seascape, " + "photorealistic water physics and light refraction","width":1280,"height":720,"steps":4}, + + # 17. Smoke and clouds + {"id":"phn_17","theme":"smoke_clouds","style":"painterly","name":"ethereal_smoke_clouds", + "prompt":_Q+_HT+"ethereal smoke and cloud formations in sky where swirling patterns and " + "negative space subtly spell PATRICK, dramatic volumetric lighting, painterly atmospheric " + "style, high detail turbulence and wisps","width":1024,"height":1024,"steps":12}, + + # 18. Dense jungle foliage + {"id":"phn_18","theme":"jungle_foliage","style":"macro","name":"dense_jungle_canopy", + "prompt":_Q+_HT+"dense tropical jungle foliage where leaves vines and light rays through " + "canopy form hidden name PATRICK through alignment and negative space, " + "ultra detailed leaf veins and moisture, macro realism","width":1024,"height":1024,"steps":4}, + + # 19. Roman mosaic + {"id":"phn_19","theme":"roman_mosaic","style":"architectural","name":"roman_mosaic_floor", + "prompt":_Q+_HT+"ancient Roman mosaic floor where thousands of tiny colored tiles arrange " + "to subtly hide name PATRICK in geometric pattern, realistic stone texture, " + "archaeological lighting, high detail tesserae","width":1024,"height":1024,"steps":4}, + + # 20. Military parade — aerial + {"id":"phn_20","theme":"military_parade","style":"aerial","name":"parade_formation_overhead", + "prompt":_Q+_HT+"aerial view of military parade formation where soldiers in perfect alignment " + "create letters PATRICK through their positions and shadows, crisp uniforms, " + "dramatic overhead perspective, photorealistic","width":1280,"height":720,"steps":4}, + + # 21. Stained glass + {"id":"phn_21","theme":"stained_glass","style":"architectural","name":"cathedral_stained_glass", + "prompt":_Q+_HT+"intricate stained glass window in gothic cathedral where lead lines and " + "colored glass panes form hidden name PATRICK through negative space and symbolic arrangement, " + "luminous backlighting, ultra detailed glass texture","width":1024,"height":1024,"steps":4}, + + # 22. Spider web + {"id":"phn_22","theme":"spider_web","style":"macro","name":"dew_spider_web_geometry", + "prompt":_Q+_HT+"macro photograph of perfect orb spider web with morning dew where radial " + "and spiral threads align to spell PATRICK in geometric structure, sparkling water droplets, " + "soft morning light, extreme detail","width":1024,"height":1024,"steps":4}, + + # 23. Galaxy star map + {"id":"phn_23","theme":"galaxy_stars","style":"cosmic","name":"star_map_constellation", + "prompt":_Q+_HT+"detailed star map of spiral galaxy where constellations and star clusters " + "subtly form letters PATRICK through their positions and connecting lines, " + "nebulae and cosmic dust, astronomical precision","width":1024,"height":1024,"steps":4}, + + # 24. Subway map + {"id":"phn_24","theme":"subway_map","style":"architectural","name":"subway_network_map", + "prompt":_Q+_HT+"highly detailed schematic subway tunnel map where intersecting colored lines " + "station markers and tunnel curves naturally spell name PATRICK in network layout, " + "clean diagrammatic style with realistic depth","width":1280,"height":720,"steps":4}, + + # 25. Marionettes — architectural rendering + {"id":"phn_25","theme":"marionettes","style":"architectural","name":"puppet_theater_stage", + "prompt":_Q+_HT+"architectural rendering of elaborate marionette theater stage where puppet " + "strings stage lights and scenery elements form hidden PATRICK, dramatic perspective, " + "ultra detailed wood and fabric","width":1024,"height":1024,"steps":4}, + + # 26. Birds — painterly + {"id":"phn_26","theme":"birds","style":"painterly","name":"bird_migration_painting", + "prompt":_Q+_HT+"painterly illustration of migrating bird flock where formation creates " + "concealed PATRICK letters, dramatic sky with volumetric clouds, rich oil painting texture, " + "romantic naturalist style","width":1024,"height":1024,"steps":20}, +] + + +# ───────────────────────────────────────────────────────── +# Pipeline helpers (ported from cannamanage_gen.py) +# ───────────────────────────────────────────────────────── + +def load_progress() -> Dict[str, Any]: + if PROGRESS_FILE.exists(): + try: + with open(PROGRESS_FILE) as f: + return json.load(f) + except (json.JSONDecodeError, IOError): + pass + return {"completed": [], "failed": [], "started_at": time.strftime("%Y-%m-%dT%H:%M:%S")} + + +def save_progress(progress: Dict[str, Any]) -> None: + OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) + with open(PROGRESS_FILE, "w") as f: + json.dump(progress, f, indent=2) + + +def load_workflow(model: str) -> Dict: + path = WORKFLOW_HERETIC if model == "heretic" else WORKFLOW_SCHNELL + with open(path) as f: + return json.load(f) + + +def submit_prompt(comfyui_url: str, workflow: Dict) -> str: + data = json.dumps({"prompt": workflow}).encode() + req = urllib.request.Request( + f"{comfyui_url}/prompt", data=data, headers={"Content-Type": "application/json"} + ) + with urllib.request.urlopen(req) as resp: + return json.loads(resp.read())["prompt_id"] + + +def wait_for_image(comfyui_url: str, prompt_id: str, timeout: int = 300) -> Optional[Dict]: + print(" ⏳ Waiting for ComfyUI...", end="", flush=True) + start = time.time() + while time.time() - start < timeout: + try: + with urllib.request.urlopen(f"{comfyui_url}/history/{prompt_id}") as resp: + history = json.loads(resp.read()) + if prompt_id in history: + print(" done.", flush=True) + outputs = history[prompt_id].get("outputs", {}) + for node_out in outputs.values(): + if "images" in node_out: + return node_out["images"][0] + return None + except Exception: + pass + print(".", end="", flush=True) + time.sleep(2) + print(" timeout!", flush=True) + return None + + +def download_image(comfyui_url: str, image_info: Dict, output_path: Path) -> bool: + try: + url = ( + f"{comfyui_url}/view" + f"?filename={image_info['filename']}" + f"&subfolder={image_info.get('subfolder', '')}" + f"&type=output" + ) + with urllib.request.urlopen(url) as resp: + img_data = resp.read() + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_bytes(img_data) + print(f" ✅ Saved: {output_path} ({len(img_data) // 1024}KB)") + return True + except Exception as e: + print(f" ❌ Download failed: {e}") + return False + + +def patch_workflow(workflow: Dict, asset: Dict, model: str) -> Dict: + wf = copy.deepcopy(workflow) + seed = random.randint(0, 2**32 - 1) + if model == "heretic": + wf["2"]["inputs"]["text"] = asset["prompt"] + wf["3"]["inputs"]["text"] = "plain text letters, obvious text overlay, watermark, low quality" + wf["6"]["inputs"]["width"] = asset["width"] + wf["6"]["inputs"]["height"] = asset["height"] + wf["7"]["inputs"]["steps"] = asset["steps"] + wf["13"]["inputs"]["filename_prefix"] = asset["name"] + if "10" in wf: + wf["10"]["inputs"]["noise_seed"] = seed + else: + # flux_schnell.json: node 6=pos, 33=neg, 27=latent(w/h), 13=ksampler(steps/seed), 9=save + wf["6"]["inputs"]["text"] = asset["prompt"] + wf["33"]["inputs"]["text"] = "plain text letters, obvious text overlay, watermark, low quality" + wf["27"]["inputs"]["width"] = asset["width"] + wf["27"]["inputs"]["height"] = asset["height"] + wf["13"]["inputs"]["steps"] = asset["steps"] + wf["13"]["inputs"]["seed"] = seed + wf["9"]["inputs"]["filename_prefix"] = asset["name"] + return wf + + +def generate_asset(comfyui_url: str, asset: Dict, model: str, progress: Dict) -> bool: + if asset["id"] in progress["completed"]: + print(f" ⏭️ Skipping already completed: {asset['name']}") + return True + + print(f"\n Prompt : {asset['prompt'][:100]}...") + print(f" Size : {asset['width']}×{asset['height']} Steps: {asset['steps']}") + + try: + workflow = load_workflow(model) + workflow = patch_workflow(workflow, asset, model) + prompt_id = submit_prompt(comfyui_url, workflow) + image_info = wait_for_image(comfyui_url, prompt_id) + + if not image_info: + progress["failed"].append(asset["id"]) + save_progress(progress) + return False + + output_dir = OUTPUT_ROOT / asset["theme"] / asset["style"] + output_dir.mkdir(parents=True, exist_ok=True) + output_path = output_dir / f"{asset['name']}.png" + + if download_image(comfyui_url, image_info, output_path): + progress["completed"].append(asset["id"]) + save_progress(progress) + return True + else: + progress["failed"].append(asset["id"]) + save_progress(progress) + return False + + except Exception as e: + print(f" ❌ Error: {e}") + progress["failed"].append(asset["id"]) + save_progress(progress) + return False + + +def main(): + parser = argparse.ArgumentParser( + description="Patrick Hidden Name Artwork Generation Pipeline" + ) + parser.add_argument("--dry-run", action="store_true", + help="Print manifest without generating") + parser.add_argument("--model", choices=["schnell", "heretic"], default="schnell", + help="Model: schnell (~10s/img) or heretic (~52s/img, higher quality)") + parser.add_argument("--comfyui", default="http://localhost:8188", + help="ComfyUI URL") + args = parser.parse_args() + + comfyui_url = args.comfyui + + print("🚀 Patrick Hidden Name Artwork Pipeline") + print(f" Output : {OUTPUT_ROOT}") + print(f" Model : {args.model}") + print(f" ComfyUI : {comfyui_url}") + print(f" Total : {len(ASSET_MANIFEST)} ultra-detailed hidden-name artworks") + print(" Technique: Letters P-A-T-R-I-C-K concealed via organic shapes/negative space") + + if args.dry_run: + print() + for asset in ASSET_MANIFEST: + print(f" {asset['id']:8} | {asset['theme']:15} | {asset['style']:12} | {asset['name']}") + total_est = sum(a["steps"] * 2.5 for a in ASSET_MANIFEST) / 60 + print(f"\n ⏱️ Estimated runtime (schnell @4 steps): ~{total_est:.0f} minutes") + print("\nDry run complete. Remove --dry-run to begin generation.") + return + + progress = load_progress() + remaining = [a for a in ASSET_MANIFEST if a["id"] not in progress["completed"]] + print(f" Resume : {len(progress['completed'])} completed, " + f"{len(progress['failed'])} failed, {len(remaining)} remaining") + + if not remaining: + print("\n✅ All assets already complete!") + return + + print(f"\nStarting generation... (Ctrl+C to pause — progress is saved)") + + n_done = 0 + n_fail = 0 + for i, asset in enumerate(ASSET_MANIFEST, 1): + if asset["id"] in progress["completed"]: + continue + print(f"\n[{asset['theme']}/{asset['style']}] [{i}/{len(ASSET_MANIFEST)}] {asset['name']}") + if generate_asset(comfyui_url, asset, args.model, progress): + n_done += 1 + else: + n_fail += 1 + + print("\n" + "=" * 60) + print("🎉 PIPELINE COMPLETE") + print(f" ✅ Completed this run : {n_done}") + print(f" ❌ Failed this run : {n_fail}") + print(f" 📦 Total completed : {len(progress['completed'])} / {len(ASSET_MANIFEST)}") + if progress["failed"]: + print(f" Failed IDs: {', '.join(progress['failed'][-10:])}") + print(f" Assets saved to: {OUTPUT_ROOT}") + print("=" * 60) + + +if __name__ == "__main__": + main() diff --git a/mcp/mcp-image-gen/src/server.py b/mcp/mcp-image-gen/src/server.py index 5fa0ec7..dcce8d9 100644 --- a/mcp/mcp-image-gen/src/server.py +++ b/mcp/mcp-image-gen/src/server.py @@ -244,26 +244,49 @@ def build_flux_workflow( """ workflow_path = _WORKFLOW_REGISTRY.get(model, _WORKFLOW_REGISTRY[_DEFAULT_MODEL]) - with open(workflow_path) as f: - wf = json.load(f) - wf = copy.deepcopy(wf) - + # Load workflow as text first — replace string placeholders + raw = workflow_path.read_text() actual_seed = seed if seed != -1 else random.randint(0, 2**32 - 1) - wf["6"]["inputs"]["text"] = prompt - wf["33"]["inputs"]["text"] = neg_prompt - wf["27"]["inputs"]["width"] = width - wf["27"]["inputs"]["height"] = height - wf["13"]["inputs"]["steps"] = steps - wf["13"]["inputs"]["seed"] = actual_seed - # Node 32 = UNETLoader (flux1-schnell.safetensors is UNet-only, not all-in-one checkpoint) - wf["32"]["inputs"]["unet_name"] = model + raw = raw.replace('"PROMPT_PLACEHOLDER"', json.dumps(prompt)) + raw = raw.replace('"NEGATIVE_PLACEHOLDER"', json.dumps(neg_prompt)) + wf = json.loads(raw) + wf = copy.deepcopy(wf) + + # Recursively inject numeric values into matching field names + _inject_workflow_params(wf, { + "width": width, + "height": height, + "steps": steps, + "seed": actual_seed, + "noise_seed": actual_seed, + "unet_name": model, + }) # Attach the actual seed as metadata so callers can retrieve it wf["_meta"] = {"actual_seed": actual_seed} return wf +def _inject_workflow_params(node: dict | list, params: dict) -> None: + """Recursively walk a workflow dict/list and inject parameter values. + + For each dict encountered, if it has an "inputs" sub-dict, update + any matching field names from params. This is model-agnostic and + works regardless of ComfyUI node IDs. + """ + if isinstance(node, dict): + if "inputs" in node and isinstance(node["inputs"], dict): + for key, value in params.items(): + if key in node["inputs"] and not isinstance(node["inputs"][key], list): + node["inputs"][key] = value + for v in node.values(): + _inject_workflow_params(v, params) + elif isinstance(node, list): + for item in node: + _inject_workflow_params(item, params) + + # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- diff --git a/mcp/webscraper/src/server.py b/mcp/webscraper/src/server.py index a9dacbe..c3df84c 100644 --- a/mcp/webscraper/src/server.py +++ b/mcp/webscraper/src/server.py @@ -4,13 +4,14 @@ import httpx from bs4 import BeautifulSoup from html2text import html2text from urllib.parse import urljoin, quote_plus -from typing import List, Dict, Tuple +from typing import List, Dict, Tuple, Annotated import re import ssl import os import certifi from pathlib import Path from fastmcp import FastMCP +from pydantic import Field mcp = FastMCP("webscraper") @@ -54,13 +55,9 @@ def filter_junk_links(href: str) -> bool: return not any(re.match(pattern, href.lower()) for pattern in junk_patterns) @mcp.tool() -def webscraper_fetch(url: str, max_chars: int = 5000) -> str: +def webscraper_fetch(url: Annotated[str, Field(description="The URL to fetch")], max_chars: Annotated[int, Field(description="Maximum characters in the markdown body (default: 5000)")] = 5000) -> str: """Fetch a URL and return title + markdown body + metadata. - - Args: - url: The URL to fetch - max_chars: Maximum characters in the markdown body (default: 5000) - + Returns: Markdown string with title, body, and metadata """ @@ -78,13 +75,9 @@ def webscraper_fetch(url: str, max_chars: int = 5000) -> str: return f"# Error fetching {url}\n\n{str(e)}" @mcp.tool() -def webscraper_fetch_links(url: str, deduplicate: bool = True) -> List[str]: +def webscraper_fetch_links(url: Annotated[str, Field(description="The URL to fetch")], deduplicate: Annotated[bool, Field(description="Remove duplicate links (default: True)")] = True) -> List[str]: """Fetch a URL and extract all href links. - - Args: - url: The URL to fetch - deduplicate: Remove duplicate links (default: True) - + Returns: List of unique href URLs """ @@ -105,12 +98,9 @@ def webscraper_fetch_links(url: str, deduplicate: bool = True) -> List[str]: return [f"Error: {str(e)}"] @mcp.tool() -def webscraper_fetch_tables(url: str) -> List[str]: +def webscraper_fetch_tables(url: Annotated[str, Field(description="The URL to fetch")]) -> List[str]: """Fetch a URL and extract all HTML tables as markdown. - - Args: - url: The URL to fetch - + Returns: List of markdown tables """ @@ -125,13 +115,9 @@ def webscraper_fetch_tables(url: str) -> List[str]: return [f"Error: {str(e)}"] @mcp.tool() -def webscraper_fetch_all(url: str, max_chars: int = 5000) -> Dict: +def webscraper_fetch_all(url: Annotated[str, Field(description="The URL to fetch")], max_chars: Annotated[int, Field(description="Maximum characters (default: 5000)")] = 5000) -> Dict: """Fetch everything: markdown + links + tables + meta. - - Args: - url: The URL to fetch - max_chars: Maximum characters (default: 5000) - + Returns: Dict with 'markdown', 'links', 'tables', 'meta' """ @@ -181,13 +167,9 @@ def webscraper_fetch_all(url: str, max_chars: int = 5000) -> Dict: return {"error": str(e)} @mcp.tool() -def webscraper_fetch_section(url: str, selector: str) -> str: +def webscraper_fetch_section(url: Annotated[str, Field(description="The URL to fetch")], selector: Annotated[str, Field(description="CSS selector (e.g., '.content')")]) -> str: """Fetch a URL and extract specific section by CSS selector. - - Args: - url: The URL to fetch - selector: CSS selector (e.g., '.content') - + Returns: Markdown of the selected section """ @@ -210,12 +192,9 @@ def webscraper_fetch_section(url: str, selector: str) -> str: return f"Error: {str(e)}" @mcp.tool() -def webscraper_fetch_meta(url: str) -> Dict[str, str]: +def webscraper_fetch_meta(url: Annotated[str, Field(description="The URL to fetch")]) -> Dict[str, str]: """Fetch a URL and return page metadata: title, description, OG tags. - - Args: - url: The URL to fetch - + Returns: Dict of metadata """ @@ -238,13 +217,9 @@ def webscraper_fetch_meta(url: str) -> Dict[str, str]: return {"error": str(e)} @mcp.tool() -def webscraper_fetch_sitemap(url: str, max_urls: int = 100) -> List[str]: +def webscraper_fetch_sitemap(url: Annotated[str, Field(description="Sitemap URL (or auto-discover)")], max_urls: Annotated[int, Field(description="Maximum URLs to return (default: 100)")] = 100) -> List[str]: """Fetch sitemap.xml and return list of URLs. - - Args: - url: Sitemap URL (or auto-discover) - max_urls: Maximum URLs to return (default: 100) - + Returns: List of sitemap URLs """ @@ -263,17 +238,13 @@ def webscraper_fetch_sitemap(url: str, max_urls: int = 100) -> List[str]: return [f"Error: {str(e)}"] @mcp.tool() -def webscraper_search_hint(query: str, max_results: int = 5) -> Dict: +def webscraper_search_hint(query: Annotated[str, Field(description="Search query (e.g. \"MacBook Pro M4 price Germany\")")], max_results: Annotated[int, Field(description="Maximum number of results to return (default: 5)")] = 5) -> Dict: """Search Brave Search and return top results as a scraping hint. Use this sparingly — once per research task — to get oriented before scraping individual pages. Returns top result URLs + snippets so you can decide which pages are worth scraping deeply. - Args: - query: Search query (e.g. "MacBook Pro M4 price Germany") - max_results: Maximum number of results to return (default: 5) - Returns: Dict with 'query', 'search_url', 'results' (list of {title, url, snippet}), 'result_count', 'hint' @@ -285,14 +256,23 @@ def webscraper_search_hint(query: str, max_results: int = 5) -> Dict: results = [] seen_urls: set = set() - # Brave Search result cards: each div.snippet contains title, URL, description + # Brave Search result cards: each div.snippet with a .result-wrapper is a web result. + # Skip video clusters, FAQ blocks, and LLM snippets (they have no .result-wrapper). + # Class names as of 2026-04 (updated from .snippet-title / .snippet-description): + # title → .search-snippet-title + # url → a.l1 (the primary result anchor, avoids favicon tags) + # snippet → .content.t-primary for card in soup.select('.snippet'): if len(results) >= max_results: break - title_el = card.select_one('.snippet-title') - url_el = card.select_one('a') - desc_el = card.select_one('.snippet-description') + # Skip non-web-result snippets (videos, FAQ, LLM answer blocks) + if not card.select_one('.result-wrapper'): + continue + + title_el = card.select_one('.search-snippet-title') + url_el = card.select_one('a.l1') + desc_el = card.select_one('.content.t-primary') title = title_el.get_text(strip=True) if title_el else "" url = url_el['href'] if url_el and url_el.get('href') else "" diff --git a/mcp/webscraper/tests/test_server.py b/mcp/webscraper/tests/test_server.py index 9d6f7ee..38302fd 100644 --- a/mcp/webscraper/tests/test_server.py +++ b/mcp/webscraper/tests/test_server.py @@ -206,27 +206,39 @@ def test_sitemap_max_urls(mock_get, mock_sitemap_response): # --- webscraper_search_hint tests --- +# Helper to build a Brave-style result card with the new 2026-04 class names. +# Real result cards have a .result-wrapper; non-result blocks (videos, FAQ) do not. +def _brave_card(href: str, title: str, snippet: str) -> str: + """Return a mock Brave Search .snippet card with .result-wrapper (web result).""" + return f""" +
+
+
+ +
{title}
+
+
+
{snippet}
+
+
+
+
""" + + @pytest.fixture def mock_brave_response(): - """Mock Brave Search HTML response with result cards.""" + """Mock Brave Search HTML response with result cards (2026-04 class names).""" mock_resp = MagicMock() mock_resp.status_code = 200 mock_resp.text = """ - -
- Feynman on Electric Fields -
Feynman on Electric Fields
-
Richard Feynman explains that all matter has an electric field.
-
-
- Electric Fields Everywhere -
Electric Fields Everywhere
-
Everything in the universe is surrounded by electric fields.
-
-
- JS Junk -
JS Junk
-
Should be filtered out.
+ + """ + _brave_card("https://example.com/article1", "Feynman on Electric Fields", + "Richard Feynman explains that all matter has an electric field.") + """ + """ + _brave_card("https://example.com/article2", "Electric Fields Everywhere", + "Everything in the universe is surrounded by electric fields.") + """ + +
+
FAQ
""" @@ -240,22 +252,10 @@ def mock_brave_response_dups(): mock_resp = MagicMock() mock_resp.status_code = 200 mock_resp.text = """ - -
- Dup Result A -
Dup Result A
-
First occurrence.
-
-
- Dup Result B -
Dup Result B
-
Second occurrence — same URL.
-
-
- Unique Result -
Unique Result
-
Only once.
-
+ + """ + _brave_card("https://example.com/dup", "Dup Result A", "First occurrence.") + """ + """ + _brave_card("https://example.com/dup", "Dup Result B", "Second occurrence — same URL.") + """ + """ + _brave_card("https://example.com/unique", "Unique Result", "Only once.") + """ """ mock_resp.headers = {"content-type": "text/html"} @@ -268,17 +268,9 @@ def mock_brave_response_empty_content(): mock_resp = MagicMock() mock_resp.status_code = 200 mock_resp.text = """ - -
- -
-
-
-
- Real Result -
Real Result
-
Has content.
-
+ + """ + _brave_card("https://example.com/ghost", "", "") + """ + """ + _brave_card("https://example.com/real", "Real Result", "Has content.") + """ """ mock_resp.headers = {"content-type": "text/html"}