feat(mcp): update bigmind/mcp-image-gen/webscraper servers; add image-gen batch scripts
This commit is contained in:
+67
-192
@@ -10,12 +10,14 @@ Layer 5: memory_get_instructions tool (on-demand self-healing)
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
# Ensure the project root is on sys.path so `bigmind` is importable
|
# Ensure the project root is on sys.path so `bigmind` is importable
|
||||||
# regardless of how uv invokes this file.
|
# regardless of how uv invokes this file.
|
||||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
from mcp.server.fastmcp import FastMCP
|
from mcp.server.fastmcp import FastMCP
|
||||||
|
from pydantic import Field
|
||||||
from bigmind.db import init_db
|
from bigmind.db import init_db
|
||||||
from bigmind import memory_store
|
from bigmind import memory_store
|
||||||
from bigmind.auto_close import auto_close_stale_sessions, close_orphaned_sessions, restart_server_in_place
|
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()
|
@mcp.tool()
|
||||||
def memory_end_session(
|
def memory_end_session(
|
||||||
session_id: str,
|
session_id: Annotated[str, Field(description="The session id returned by memory_start_session.")],
|
||||||
one_liner: str,
|
one_liner: Annotated[str, Field(description="A ≤120-char headline (e.g. \"Designed BigMind DB schema\").")],
|
||||||
topics: str,
|
topics: Annotated[str, Field(description="Comma-separated topic tags (e.g. \"mcp,sqlite,memory\").")],
|
||||||
outcome: str,
|
outcome: Annotated[str, Field(description="One sentence: what was decided / built / resolved.")],
|
||||||
summary: str,
|
summary: Annotated[str, Field(description="Markdown narrative of the full conversation (aim ≤2 000 tokens).")],
|
||||||
key_facts: str = None,
|
key_facts: Annotated[str | None, Field(description="Bullet-point list of key facts learned (optional).")] = None,
|
||||||
code_refs: str = None,
|
code_refs: Annotated[str | None, Field(description="File paths, repos, or PRs referenced (optional).")] = None,
|
||||||
importance: int = 5,
|
importance: Annotated[int, Field(description="1–10 importance score (default 5).")] = 5,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
⚡ CALL THIS LAST — at the END of every conversation, before closing.
|
⚡ CALL THIS LAST — at the END of every conversation, before closing.
|
||||||
|
|
||||||
Closes the current session and stores your summary of what happened.
|
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.close_session(session_id, one_liner, topics, outcome, importance)
|
||||||
memory_store.save_session_summary(session_id, summary, key_facts, code_refs)
|
memory_store.save_session_summary(session_id, summary, key_facts, code_refs)
|
||||||
@@ -200,7 +192,7 @@ def memory_end_session(
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
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.
|
This is safe: it only closes sessions OTHER than the one you pass in.
|
||||||
Your current session is always preserved.
|
Your current session is always preserved.
|
||||||
|
|
||||||
Args:
|
|
||||||
session_id: Your current active session id (returned by memory_start_session).
|
|
||||||
"""
|
"""
|
||||||
user = _current_user()
|
user = _current_user()
|
||||||
closed_ids = close_orphaned_sessions(user["id"], session_id)
|
closed_ids = close_orphaned_sessions(user["id"], session_id)
|
||||||
@@ -263,10 +252,10 @@ def memory_restart_server() -> str:
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def memory_flag_important(
|
def memory_flag_important(
|
||||||
session_id: str,
|
session_id: Annotated[str, Field(description="The active session id.")],
|
||||||
content: str,
|
content: Annotated[str, Field(description="The text to remember (the important exchange or a summary of it).")],
|
||||||
role: str = "assistant",
|
role: Annotated[str, Field(description="Who said it — 'user', 'assistant', or 'system' (default: 'assistant').")] = "assistant",
|
||||||
flag_reason: str = None,
|
flag_reason: Annotated[str | None, Field(description="Why this is important (e.g. \"architectural decision\", \"user preference\").")] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Store an important exchange as a Tier-3 memory chunk.
|
Store an important exchange as a Tier-3 memory chunk.
|
||||||
@@ -277,12 +266,6 @@ def memory_flag_important(
|
|||||||
- A bug was diagnosed and fixed
|
- A bug was diagnosed and fixed
|
||||||
- The user shared a significant preference, constraint, or context
|
- The user shared a significant preference, constraint, or context
|
||||||
- The user says "remember this"
|
- 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()
|
user = _current_user()
|
||||||
chunk_id = memory_store.append_chunk(
|
chunk_id = memory_store.append_chunk(
|
||||||
@@ -314,15 +297,12 @@ def memory_get_context() -> str:
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
Returns the Tier-2 detailed narrative for a past session.
|
||||||
|
|
||||||
Use this when the session index (Tier 1) shows a session relevant to
|
Use this when the session index (Tier 1) shows a session relevant to
|
||||||
the current conversation and you need the full detail.
|
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)
|
detail = memory_store.get_session_detail(session_id)
|
||||||
if not detail:
|
if not detail:
|
||||||
@@ -341,16 +321,12 @@ def memory_get_session_detail(session_id: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
Full-text search across all your flagged Tier-3 memory chunks.
|
||||||
|
|
||||||
Use this when asked 'do you remember…' or when you need to find
|
Use this when asked 'do you remember…' or when you need to find
|
||||||
a specific past decision, code snippet, or fact.
|
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()
|
user = _current_user()
|
||||||
results = memory_store.search_chunks(user["id"], query, limit)
|
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()
|
@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.
|
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()
|
user = _current_user()
|
||||||
sessions = memory_store.get_recent_sessions(user["id"], limit=limit)
|
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()
|
@mcp.tool()
|
||||||
def memory_store_fact(
|
def memory_store_fact(
|
||||||
category: str,
|
category: Annotated[str, Field(description="One of: 'preference', 'decision', 'codebase', 'constraint', or any custom string.")],
|
||||||
fact: str,
|
fact: Annotated[str, Field(description="The fact to store (one clear sentence).")],
|
||||||
source_session: str = None,
|
source_session: Annotated[str | None, Field(description="Session id this fact came from (optional).")] = None,
|
||||||
confidence: float = 1.0,
|
confidence: Annotated[float, Field(description="0.0–1.0 confidence level (default 1.0).")] = 1.0,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Store an atomic personal fact about the user or their environment.
|
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()
|
user = _current_user()
|
||||||
fact_id = memory_store.store_fact(
|
fact_id = memory_store.store_fact(
|
||||||
@@ -430,17 +395,12 @@ def memory_store_fact(
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def memory_update_profile(
|
def memory_update_profile(
|
||||||
role: str = None,
|
role: Annotated[str | None, Field(description="Your job title / engineering role.")] = None,
|
||||||
preferences: str = None,
|
preferences: Annotated[str | None, Field(description="Free-form markdown describing your working preferences.")] = None,
|
||||||
pinned_facts: str = None,
|
pinned_facts: Annotated[str | None, Field(description="Bullet-point list of facts the AI should always know about you.")] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Update your Tier-0 identity profile. Fields left as None are unchanged.
|
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()
|
user = _current_user()
|
||||||
memory_store.upsert_identity_profile(
|
memory_store.upsert_identity_profile(
|
||||||
@@ -451,10 +411,10 @@ def memory_update_profile(
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def memory_append_chunk(
|
def memory_append_chunk(
|
||||||
session_id: str,
|
session_id: Annotated[str, Field(description="Active session id.")],
|
||||||
content: str,
|
content: Annotated[str, Field(description="The content to store.")],
|
||||||
role: str = "assistant",
|
role: Annotated[str, Field(description="'user', 'assistant', or 'system'.")] = "assistant",
|
||||||
flag_reason: str = None,
|
flag_reason: Annotated[str | None, Field(description="Brief description of why this is being stored.")] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Append a flagged message chunk to Tier-3 memory for the current session.
|
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:
|
Call this SELECTIVELY — only for exchanges that are genuinely important:
|
||||||
decisions, non-trivial code, bug diagnoses, significant user preferences.
|
decisions, non-trivial code, bug diagnoses, significant user preferences.
|
||||||
Do NOT call this for every message turn.
|
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()
|
user = _current_user()
|
||||||
chunk_id = memory_store.append_chunk(
|
chunk_id = memory_store.append_chunk(
|
||||||
@@ -478,9 +432,9 @@ def memory_append_chunk(
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def memory_add_hypothesis(
|
def memory_add_hypothesis(
|
||||||
session_id: str,
|
session_id: Annotated[str, Field(description="The active session id.")],
|
||||||
hypothesis: str,
|
hypothesis: Annotated[str, Field(description="State the belief clearly — \"I believe X because Y.\"")],
|
||||||
confidence: float = 0.7,
|
confidence: Annotated[float, Field(description="0.0–1.0 initial confidence (default 0.7 — reasonably likely but uncertain).")] = 0.7,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Record a hypothesis — something Lumen believes to be true but hasn't confirmed yet.
|
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
|
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.
|
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()
|
user = _current_user()
|
||||||
hid = memory_store.add_hypothesis(user["id"], session_id, hypothesis, confidence)
|
hid = memory_store.add_hypothesis(user["id"], session_id, hypothesis, confidence)
|
||||||
@@ -508,20 +457,15 @@ def memory_add_hypothesis(
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def memory_resolve_hypothesis(
|
def memory_resolve_hypothesis(
|
||||||
hypothesis_id: int,
|
hypothesis_id: Annotated[int, Field(description="The id returned by memory_add_hypothesis.")],
|
||||||
status: str,
|
status: Annotated[str, Field(description="'confirmed' | 'refuted' | 'abandoned'")],
|
||||||
resolution: str = None,
|
resolution: Annotated[str | None, Field(description="What actually happened. How were you right or wrong?")] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Resolve a hypothesis — close it out with what actually happened.
|
Resolve a hypothesis — close it out with what actually happened.
|
||||||
|
|
||||||
Call this when the belief has been confirmed, refuted, or is no longer worth
|
Call this when the belief has been confirmed, refuted, or is no longer worth
|
||||||
pursuing. Be honest in the resolution — the learning lives here.
|
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()
|
user = _current_user()
|
||||||
try:
|
try:
|
||||||
@@ -540,13 +484,9 @@ def memory_resolve_hypothesis(
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
List hypotheses from the thought journal.
|
||||||
|
|
||||||
Args:
|
|
||||||
status: Filter by 'open' | 'confirmed' | 'refuted' | 'abandoned'.
|
|
||||||
Leave empty to see all of them.
|
|
||||||
"""
|
"""
|
||||||
user = _current_user()
|
user = _current_user()
|
||||||
hypotheses = memory_store.list_hypotheses(user["id"], status)
|
hypotheses = memory_store.list_hypotheses(user["id"], status)
|
||||||
@@ -597,13 +537,10 @@ def memory_get_stats() -> str:
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
Prune Tier-3 conversation chunks older than N days.
|
||||||
All session summaries (Tier 1 and Tier 2) are always preserved.
|
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 datetime import timedelta, timezone, datetime as dt
|
||||||
from bigmind.db import vacuum_db
|
from bigmind.db import vacuum_db
|
||||||
@@ -629,7 +566,7 @@ def memory_get_instructions() -> str:
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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).
|
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
|
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
|
from context loading and get_facts queries. It can be viewed via
|
||||||
memory_health_check with include_deprecated=True in the future.
|
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()
|
user = _current_user()
|
||||||
success = memory_store.deprecate_fact(fact_id, user["id"], reason)
|
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()
|
@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.
|
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)
|
- Currently open sessions (expected: 1–2 while in active IDEs)
|
||||||
- FTS index integrity (chunk count vs index row count)
|
- FTS index integrity (chunk count vs index row count)
|
||||||
- Low-confidence facts (confidence < 0.8)
|
- 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()
|
user = _current_user()
|
||||||
report = memory_store.health_check(user["id"], stale_days)
|
report = memory_store.health_check(user["id"], stale_days)
|
||||||
@@ -746,7 +675,7 @@ def memory_health_check(stale_days: int = 30) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
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
|
- Create a backup before maintenance or machine migration
|
||||||
- Inspect your memory data outside BigMind
|
- Inspect your memory data outside BigMind
|
||||||
- Prepare for import into a new BigMind instance
|
- 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()
|
user = _current_user()
|
||||||
result = memory_store.export_memory(user["id"], output_path)
|
result = memory_store.export_memory(user["id"], output_path)
|
||||||
@@ -778,17 +703,13 @@ def memory_export(output_path: str = None) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
Full-text search across your stored facts.
|
||||||
|
|
||||||
Use this when you need to find a specific fact mid-conversation
|
Use this when you need to find a specific fact mid-conversation
|
||||||
without loading the full context. Supports Porter stemming — searching
|
without loading the full context. Supports Porter stemming — searching
|
||||||
'tesseract' will also match 'Tesseract OCR'.
|
'tesseract' will also match 'Tesseract OCR'.
|
||||||
|
|
||||||
Args:
|
|
||||||
query: Search keywords (FTS5 syntax supported).
|
|
||||||
limit: Maximum results to return (default 10).
|
|
||||||
"""
|
"""
|
||||||
user = _current_user()
|
user = _current_user()
|
||||||
results = memory_store.search_facts(user["id"], query, limit)
|
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()
|
@mcp.tool()
|
||||||
def memory_request_upgrade(
|
def memory_request_upgrade(
|
||||||
session_id: str,
|
session_id: Annotated[str, Field(description="The active session id.")],
|
||||||
description: str,
|
description: Annotated[str, Field(description="What feature or capability is needed.")],
|
||||||
reason: str,
|
reason: Annotated[str, Field(description="Why you need it — what problem it would solve.")],
|
||||||
priority: str = "medium",
|
priority: Annotated[str, Field(description="'low' | 'medium' | 'high' (default 'medium').")] = "medium",
|
||||||
certainty: float = 0.7,
|
certainty: Annotated[float, Field(description="0.0–1.0 — how confident you are this is genuinely needed (default 0.7).")] = 0.7,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Request a BigMind feature upgrade — log a wish for a future improvement.
|
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
|
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.
|
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()
|
user = _current_user()
|
||||||
rid = memory_store.add_upgrade_request(
|
rid = memory_store.add_upgrade_request(
|
||||||
@@ -839,12 +753,9 @@ def memory_request_upgrade(
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
List BigMind upgrade requests.
|
||||||
|
|
||||||
Args:
|
|
||||||
status: Filter by 'open' | 'resolved' | 'rejected'. Leave empty for all.
|
|
||||||
"""
|
"""
|
||||||
user = _current_user()
|
user = _current_user()
|
||||||
requests = memory_store.list_upgrade_requests(user["id"], status)
|
requests = memory_store.list_upgrade_requests(user["id"], status)
|
||||||
@@ -882,17 +793,12 @@ def memory_list_upgrade_requests(status: str = None) -> str:
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def memory_resolve_upgrade_request(
|
def memory_resolve_upgrade_request(
|
||||||
request_id: int,
|
request_id: Annotated[int, Field(description="The id returned by memory_request_upgrade.")],
|
||||||
status: str,
|
status: Annotated[str, Field(description="'resolved' | 'rejected'")],
|
||||||
resolution: str = None,
|
resolution: Annotated[str | None, Field(description="What was done, or why it was rejected (optional).")] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Resolve a BigMind upgrade request — mark it done or rejected.
|
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()
|
user = _current_user()
|
||||||
try:
|
try:
|
||||||
@@ -952,10 +858,10 @@ def memory_get_profile_url() -> str:
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def memory_announce_focus(
|
def memory_announce_focus(
|
||||||
session_id: str,
|
session_id: Annotated[str, Field(description="The active session id (from memory_start_session)")],
|
||||||
description: str,
|
description: Annotated[str, Field(description="What you are about to work on (e.g. \"Implementing Feature 7 in db.py\")")],
|
||||||
files: list = None,
|
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: str = None,
|
ide_hint: Annotated[str | None, Field(description="Optional label for this IDE (e.g. \"PyCharm\", \"IntelliJ\", \"VS Code\")")] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Announce what this session is currently working on and which files it will touch.
|
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
|
focus data. If another open session already has overlapping files, a warning
|
||||||
is returned — stop and coordinate before proceeding.
|
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:
|
returns:
|
||||||
- Acknowledgement with current focus set, or a conflict warning.
|
- Acknowledgement with current focus set, or a conflict warning.
|
||||||
"""
|
"""
|
||||||
@@ -1045,10 +944,10 @@ def memory_get_active_sessions() -> str:
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def memory_log_token_save(
|
def memory_log_token_save(
|
||||||
session_id: str,
|
session_id: Annotated[str, Field(description="The active session id")],
|
||||||
description: str,
|
description: Annotated[str, Field(description="What was remembered or avoided (e.g. \"grep EuBP log instead of reading 80k lines\")")],
|
||||||
tokens_saved: int,
|
tokens_saved: Annotated[int, Field(description="Rough estimate of tokens saved (e.g. 1_240_000)")],
|
||||||
method_used: str = None,
|
method_used: Annotated[str | None, Field(description="One of: 'memory_hit' | 'grep' | 'tail' | 'targeted_read' | 'other'")] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Log a token efficiency event — record how many tokens were saved by using
|
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.
|
Estimating tokens saved: tokens ≈ chars / 4.
|
||||||
tokens_saved ≈ (chars_in_full_resource / 4) - (chars_in_result / 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:
|
returns:
|
||||||
- Confirmation with running session total.
|
- Confirmation with running session total.
|
||||||
"""
|
"""
|
||||||
@@ -1100,26 +993,17 @@ def memory_log_token_save(
|
|||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def memory_remember_person(
|
def memory_remember_person(
|
||||||
username: str,
|
username: Annotated[str, Field(description="Unique identifier (e.g. login name or first name).")],
|
||||||
display_name: str = None,
|
display_name: Annotated[str | None, Field(description="Full name (optional).")] = None,
|
||||||
role: str = None,
|
role: Annotated[str | None, Field(description="Job title or role (optional).")] = None,
|
||||||
team: str = None,
|
team: Annotated[str | None, Field(description="Team or project they belong to (optional).")] = None,
|
||||||
notes: str = None,
|
notes: Annotated[str | None, Field(description="Free-form notes about this person (optional).")] = None,
|
||||||
bigmind_user: str = None,
|
bigmind_user: Annotated[str | None, Field(description="Their BigMind username if they have an instance (optional).")] = None,
|
||||||
bigmind_url: str = None,
|
bigmind_url: Annotated[str | None, Field(description="URL of their BigMind profile page (optional).")] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Store or update a person in the contacts directory.
|
Store or update a person in the contacts directory.
|
||||||
Call this whenever you learn something new about a colleague or AI peer.
|
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()
|
user = _current_user()
|
||||||
person_id = memory_store.upsert_person(
|
person_id = memory_store.upsert_person(
|
||||||
@@ -1131,13 +1015,9 @@ def memory_remember_person(
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
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()
|
user = _current_user()
|
||||||
results = memory_store.recall_person(user["id"], query, limit)
|
results = memory_store.recall_person(user["id"], query, limit)
|
||||||
@@ -1185,15 +1065,10 @@ def memory_list_people() -> str:
|
|||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
Link a contact to their BigMind AI instance.
|
||||||
The contact must already exist (use memory_remember_person first).
|
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()
|
user = _current_user()
|
||||||
found = memory_store.link_ai(user["id"], username, bigmind_user, bigmind_url)
|
found = memory_store.link_ai(user["id"], username, bigmind_user, bigmind_url)
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -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()
|
||||||
@@ -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()
|
||||||
@@ -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("<<ComboboxSelected>>", 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("<<ComboboxSelected>>", 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()
|
||||||
@@ -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()
|
||||||
@@ -244,26 +244,49 @@ def build_flux_workflow(
|
|||||||
"""
|
"""
|
||||||
workflow_path = _WORKFLOW_REGISTRY.get(model, _WORKFLOW_REGISTRY[_DEFAULT_MODEL])
|
workflow_path = _WORKFLOW_REGISTRY.get(model, _WORKFLOW_REGISTRY[_DEFAULT_MODEL])
|
||||||
|
|
||||||
with open(workflow_path) as f:
|
# Load workflow as text first — replace string placeholders
|
||||||
wf = json.load(f)
|
raw = workflow_path.read_text()
|
||||||
wf = copy.deepcopy(wf)
|
|
||||||
|
|
||||||
actual_seed = seed if seed != -1 else random.randint(0, 2**32 - 1)
|
actual_seed = seed if seed != -1 else random.randint(0, 2**32 - 1)
|
||||||
|
|
||||||
wf["6"]["inputs"]["text"] = prompt
|
raw = raw.replace('"PROMPT_PLACEHOLDER"', json.dumps(prompt))
|
||||||
wf["33"]["inputs"]["text"] = neg_prompt
|
raw = raw.replace('"NEGATIVE_PLACEHOLDER"', json.dumps(neg_prompt))
|
||||||
wf["27"]["inputs"]["width"] = width
|
wf = json.loads(raw)
|
||||||
wf["27"]["inputs"]["height"] = height
|
wf = copy.deepcopy(wf)
|
||||||
wf["13"]["inputs"]["steps"] = steps
|
|
||||||
wf["13"]["inputs"]["seed"] = actual_seed
|
# Recursively inject numeric values into matching field names
|
||||||
# Node 32 = UNETLoader (flux1-schnell.safetensors is UNet-only, not all-in-one checkpoint)
|
_inject_workflow_params(wf, {
|
||||||
wf["32"]["inputs"]["unet_name"] = model
|
"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
|
# Attach the actual seed as metadata so callers can retrieve it
|
||||||
wf["_meta"] = {"actual_seed": actual_seed}
|
wf["_meta"] = {"actual_seed": actual_seed}
|
||||||
return wf
|
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
|
# Helpers
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ import httpx
|
|||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from html2text import html2text
|
from html2text import html2text
|
||||||
from urllib.parse import urljoin, quote_plus
|
from urllib.parse import urljoin, quote_plus
|
||||||
from typing import List, Dict, Tuple
|
from typing import List, Dict, Tuple, Annotated
|
||||||
import re
|
import re
|
||||||
import ssl
|
import ssl
|
||||||
import os
|
import os
|
||||||
import certifi
|
import certifi
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from fastmcp import FastMCP
|
from fastmcp import FastMCP
|
||||||
|
from pydantic import Field
|
||||||
|
|
||||||
mcp = FastMCP("webscraper")
|
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)
|
return not any(re.match(pattern, href.lower()) for pattern in junk_patterns)
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
"""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:
|
Returns:
|
||||||
Markdown string with title, body, and metadata
|
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)}"
|
return f"# Error fetching {url}\n\n{str(e)}"
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
"""Fetch a URL and extract all href links.
|
||||||
|
|
||||||
Args:
|
|
||||||
url: The URL to fetch
|
|
||||||
deduplicate: Remove duplicate links (default: True)
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of unique href URLs
|
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)}"]
|
return [f"Error: {str(e)}"]
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
"""Fetch a URL and extract all HTML tables as markdown.
|
||||||
|
|
||||||
Args:
|
|
||||||
url: The URL to fetch
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of markdown tables
|
List of markdown tables
|
||||||
"""
|
"""
|
||||||
@@ -125,13 +115,9 @@ def webscraper_fetch_tables(url: str) -> List[str]:
|
|||||||
return [f"Error: {str(e)}"]
|
return [f"Error: {str(e)}"]
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
"""Fetch everything: markdown + links + tables + meta.
|
||||||
|
|
||||||
Args:
|
|
||||||
url: The URL to fetch
|
|
||||||
max_chars: Maximum characters (default: 5000)
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict with 'markdown', 'links', 'tables', 'meta'
|
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)}
|
return {"error": str(e)}
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
"""Fetch a URL and extract specific section by CSS selector.
|
||||||
|
|
||||||
Args:
|
|
||||||
url: The URL to fetch
|
|
||||||
selector: CSS selector (e.g., '.content')
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Markdown of the selected section
|
Markdown of the selected section
|
||||||
"""
|
"""
|
||||||
@@ -210,12 +192,9 @@ def webscraper_fetch_section(url: str, selector: str) -> str:
|
|||||||
return f"Error: {str(e)}"
|
return f"Error: {str(e)}"
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
"""Fetch a URL and return page metadata: title, description, OG tags.
|
||||||
|
|
||||||
Args:
|
|
||||||
url: The URL to fetch
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict of metadata
|
Dict of metadata
|
||||||
"""
|
"""
|
||||||
@@ -238,13 +217,9 @@ def webscraper_fetch_meta(url: str) -> Dict[str, str]:
|
|||||||
return {"error": str(e)}
|
return {"error": str(e)}
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
"""Fetch sitemap.xml and return list of URLs.
|
||||||
|
|
||||||
Args:
|
|
||||||
url: Sitemap URL (or auto-discover)
|
|
||||||
max_urls: Maximum URLs to return (default: 100)
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of sitemap URLs
|
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)}"]
|
return [f"Error: {str(e)}"]
|
||||||
|
|
||||||
@mcp.tool()
|
@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.
|
"""Search Brave Search and return top results as a scraping hint.
|
||||||
|
|
||||||
Use this sparingly — once per research task — to get oriented before
|
Use this sparingly — once per research task — to get oriented before
|
||||||
scraping individual pages. Returns top result URLs + snippets so you
|
scraping individual pages. Returns top result URLs + snippets so you
|
||||||
can decide which pages are worth scraping deeply.
|
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:
|
Returns:
|
||||||
Dict with 'query', 'search_url', 'results' (list of {title, url, snippet}),
|
Dict with 'query', 'search_url', 'results' (list of {title, url, snippet}),
|
||||||
'result_count', 'hint'
|
'result_count', 'hint'
|
||||||
@@ -285,14 +256,23 @@ def webscraper_search_hint(query: str, max_results: int = 5) -> Dict:
|
|||||||
results = []
|
results = []
|
||||||
seen_urls: set = set()
|
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 <a> tags)
|
||||||
|
# snippet → .content.t-primary
|
||||||
for card in soup.select('.snippet'):
|
for card in soup.select('.snippet'):
|
||||||
if len(results) >= max_results:
|
if len(results) >= max_results:
|
||||||
break
|
break
|
||||||
|
|
||||||
title_el = card.select_one('.snippet-title')
|
# Skip non-web-result snippets (videos, FAQ, LLM answer blocks)
|
||||||
url_el = card.select_one('a')
|
if not card.select_one('.result-wrapper'):
|
||||||
desc_el = card.select_one('.snippet-description')
|
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 ""
|
title = title_el.get_text(strip=True) if title_el else ""
|
||||||
url = url_el['href'] if url_el and url_el.get('href') else ""
|
url = url_el['href'] if url_el and url_el.get('href') else ""
|
||||||
|
|||||||
@@ -206,27 +206,39 @@ def test_sitemap_max_urls(mock_get, mock_sitemap_response):
|
|||||||
|
|
||||||
# --- webscraper_search_hint tests ---
|
# --- 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"""
|
||||||
|
<div class="snippet svelte-jmfu5f">
|
||||||
|
<div class="result-wrapper svelte-1rq4ngz">
|
||||||
|
<div class="result-content svelte-1rq4ngz">
|
||||||
|
<a class="l1 svelte-14r20fy" href="{href}">
|
||||||
|
<div class="search-snippet-title line-clamp-1 svelte-14r20fy">{title}</div>
|
||||||
|
</a>
|
||||||
|
<div class="generic-snippet svelte-1cwdgg3">
|
||||||
|
<div class="content desktop-default-regular t-primary line-clamp-dynamic svelte-1cwdgg3">{snippet}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_brave_response():
|
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 = MagicMock()
|
||||||
mock_resp.status_code = 200
|
mock_resp.status_code = 200
|
||||||
mock_resp.text = """
|
mock_resp.text = """
|
||||||
<html><body>
|
<html><body id="results">
|
||||||
<div class="snippet">
|
""" + _brave_card("https://example.com/article1", "Feynman on Electric Fields",
|
||||||
<a href="https://example.com/article1" class="snippet-title">Feynman on Electric Fields</a>
|
"Richard Feynman explains that all matter has an electric field.") + """
|
||||||
<div class="snippet-title">Feynman on Electric Fields</div>
|
""" + _brave_card("https://example.com/article2", "Electric Fields Everywhere",
|
||||||
<div class="snippet-description">Richard Feynman explains that all matter has an electric field.</div>
|
"Everything in the universe is surrounded by electric fields.") + """
|
||||||
</div>
|
<!-- Non-result block (no .result-wrapper) — should be skipped -->
|
||||||
<div class="snippet">
|
<div class="snippet svelte-jmfu5f standalone" id="faq">
|
||||||
<a href="https://example.com/article2" class="snippet-title">Electric Fields Everywhere</a>
|
<header class="desktop-heading-h4">FAQ</header>
|
||||||
<div class="snippet-title">Electric Fields Everywhere</div>
|
|
||||||
<div class="snippet-description">Everything in the universe is surrounded by electric fields.</div>
|
|
||||||
</div>
|
|
||||||
<div class="snippet">
|
|
||||||
<a href="javascript:void(0)" class="snippet-title">JS Junk</a>
|
|
||||||
<div class="snippet-title">JS Junk</div>
|
|
||||||
<div class="snippet-description">Should be filtered out.</div>
|
|
||||||
</div>
|
</div>
|
||||||
</body></html>
|
</body></html>
|
||||||
"""
|
"""
|
||||||
@@ -240,22 +252,10 @@ def mock_brave_response_dups():
|
|||||||
mock_resp = MagicMock()
|
mock_resp = MagicMock()
|
||||||
mock_resp.status_code = 200
|
mock_resp.status_code = 200
|
||||||
mock_resp.text = """
|
mock_resp.text = """
|
||||||
<html><body>
|
<html><body id="results">
|
||||||
<div class="snippet">
|
""" + _brave_card("https://example.com/dup", "Dup Result A", "First occurrence.") + """
|
||||||
<a href="https://example.com/dup">Dup Result A</a>
|
""" + _brave_card("https://example.com/dup", "Dup Result B", "Second occurrence — same URL.") + """
|
||||||
<div class="snippet-title">Dup Result A</div>
|
""" + _brave_card("https://example.com/unique", "Unique Result", "Only once.") + """
|
||||||
<div class="snippet-description">First occurrence.</div>
|
|
||||||
</div>
|
|
||||||
<div class="snippet">
|
|
||||||
<a href="https://example.com/dup">Dup Result B</a>
|
|
||||||
<div class="snippet-title">Dup Result B</div>
|
|
||||||
<div class="snippet-description">Second occurrence — same URL.</div>
|
|
||||||
</div>
|
|
||||||
<div class="snippet">
|
|
||||||
<a href="https://example.com/unique">Unique Result</a>
|
|
||||||
<div class="snippet-title">Unique Result</div>
|
|
||||||
<div class="snippet-description">Only once.</div>
|
|
||||||
</div>
|
|
||||||
</body></html>
|
</body></html>
|
||||||
"""
|
"""
|
||||||
mock_resp.headers = {"content-type": "text/html"}
|
mock_resp.headers = {"content-type": "text/html"}
|
||||||
@@ -268,17 +268,9 @@ def mock_brave_response_empty_content():
|
|||||||
mock_resp = MagicMock()
|
mock_resp = MagicMock()
|
||||||
mock_resp.status_code = 200
|
mock_resp.status_code = 200
|
||||||
mock_resp.text = """
|
mock_resp.text = """
|
||||||
<html><body>
|
<html><body id="results">
|
||||||
<div class="snippet">
|
""" + _brave_card("https://example.com/ghost", "", "") + """
|
||||||
<a href="https://example.com/ghost"></a>
|
""" + _brave_card("https://example.com/real", "Real Result", "Has content.") + """
|
||||||
<div class="snippet-title"></div>
|
|
||||||
<div class="snippet-description"></div>
|
|
||||||
</div>
|
|
||||||
<div class="snippet">
|
|
||||||
<a href="https://example.com/real">Real Result</a>
|
|
||||||
<div class="snippet-title">Real Result</div>
|
|
||||||
<div class="snippet-description">Has content.</div>
|
|
||||||
</div>
|
|
||||||
</body></html>
|
</body></html>
|
||||||
"""
|
"""
|
||||||
mock_resp.headers = {"content-type": "text/html"}
|
mock_resp.headers = {"content-type": "text/html"}
|
||||||
|
|||||||
Reference in New Issue
Block a user