11 KiB
Theme Creation Guide 🎨
Create Custom Themes for ComfyUI
This guide provides a step-by-step process for creating custom themes within ComfyUI, allowing you to tailor the generated prompts to your desired aesthetic.
Required Directory Structure
ComfyUI/
├── Core_Nodes/
│ ├── theme_handlers/ # Handler files directory
│ │ └── your_theme_handler.py # Your handler file
│ ├── configs/ # Config files directory
│ │ └── your_theme.json # Your config file
└── mega_prompt_V3.py # Registration file
Critical Naming Rules
- Handler filename:
Core_Nodes/theme_handlers/your_theme_handler.py(no double underscores). - Config filename:
Core_Nodes/configs/your_theme.json. - Use consistent internal names (
your_theme) across all files. This is crucial for linking the handler, config, and UI elements. - Handler class name and config key must match the internal name (e.g.,
YourThemeHandlerforyour_theme).
Required Files Checklist
- Handler file:
your_theme_handler.py - Config file:
your_theme.json - Import in
theme_handlers/__init__.py
Example:from .your_theme_handler import YourThemeHandler - Registration in
mega_prompt_V3.py
Step-by-Step Implementation
1. Create Handler File
# filepath: Core_Nodes/theme_handlers/your_theme_handler.py
from typing import Dict
from .base_handler import BaseThemeHandler
class YourThemeHandler(BaseThemeHandler):
"""Handler for your custom theme."""
def generate(
self,
custom_subject: str = "",
custom_location: str = "",
include_environment: bool = True,
include_style: bool = True,
include_effects: bool = True
) -> Dict[str, str]:
"""Generates prompt components for the theme."""
components = {}
# Subject
if custom_subject:
components["subject"] = (
f"((themed {custom_subject})), ((main attribute)), ((supporting detail))"
)
else:
main_element = self._get_random_choice("your_theme.main_elements")
components["subject"] = f"((themed {main_element})), ((supporting detail))"
# Environment
if include_environment:
if custom_location:
components["environment"] = f"in ((themed {custom_location}))"
else:
setting = self._get_random_choice("your_theme.settings")
components["environment"] = f"in ((themed {setting}))"
else:
components["environment"] = ""
# Style
if include_style:
style = self._get_random_choice("your_theme.styles")
components["style"] = f"in the style of ((themed {style}))"
else:
components["style"] = ""
# Effects
if include_effects:
effect = self._get_random_choice("your_theme.effects")
components["effects"] = f"with ((themed {effect}))"
else:
components["effects"] = ""
return components
2. Create Config File
{
"your_theme": {
"main_elements": ["example1", "example2"],
"settings": ["settingA", "settingB"],
"styles": ["art nouveau", "cyberpunk"],
"effects": ["soft lighting", "dramatic shadows"]
}
}
Registration in mega_prompt_V3.py
# Update these methods to add your theme:
def _init_handlers(self):
handler_classes = {
# ...existing handlers...
"your_theme": YourThemeHandler,
}
def _init_mappings(self):
emoji_mappings = {
# ...existing mappings...
"🎨 Your Theme": "your_theme"
}
Example: 🚀 Space Colony Theme
Handler File
# filepath: Core_Nodes/theme_handlers/space_colony_handler.py
from typing import Dict
from .base_handler import BaseThemeHandler
class SpaceColonyHandler(BaseThemeHandler):
"""Handler for the Space Colony theme."""
def generate(
self,
custom_subject: str = "",
custom_location: str = "",
include_environment: bool = True,
include_style: bool = True,
include_effects: bool = True
) -> Dict[str, str]:
"""Generates prompt components for the Space Colony theme."""
components = {}
# Subject
if custom_subject:
components["subject"] = (
f"((space colony {custom_subject})), ((main structure)), ((supporting detail))"
)
else:
main_element = self._get_random_choice("space_colony.main_elements")
components["subject"] = f"((space colony {main_element})), ((supporting detail))"
# Environment
if include_environment:
if custom_location:
components["environment"] = f"in ((space environment {custom_location}))"
else:
setting = self._get_random_choice("space_colony.settings")
components["environment"] = f"in ((space environment {setting}))"
else:
components["environment"] = ""
# Style
if include_style:
style = self._get_random_choice("space_colony.styles")
components["style"] = f"in the style of (({style}))"
else:
components["style"] = ""
# Effects
if include_effects:
effect = self._get_random_choice("space_colony.effects")
components["effects"] = f"with (({effect}))"
else:
components["effects"] = ""
return components
Config File
{
"space_colony": {
"main_elements": [
"dome habitat",
"hydroponic farm",
"command center",
"solar array",
"terraforming module"
],
"settings": [
"lunar surface",
"Martian desert",
"asteroid belt",
"orbiting space station",
"icy moon"
],
"styles": [
"sleek futuristic",
"brutalist architecture",
"biophilic design",
"retro sci-fi",
"high-tech minimalism"
],
"effects": [
"glowing neon lights",
"dust storms",
"starfield backdrop",
"artificial gravity",
"transparent domes"
]
}
}
Registration in mega_prompt_V3.py
def _init_handlers(self):
handler_classes = {
# ...existing handlers...
"space_colony": SpaceColonyHandler,
}
def _init_mappings(self):
emoji_mappings = {
# ...existing mappings...
"🚀 Space Colony": "space_colony"
}
Import in theme_handlers/__init__.py
from .space_colony_handler import SpaceColonyHandler
Common Errors & Solutions
-
"Handler not found" error:
- Double-check the handler filename (no double underscores).
- Verify the import statement in
theme_handlers/__init__.py(e.g.,from .your_theme_handler import YourThemeHandler). - Ensure the handler is correctly registered in
_init_handlersinmega_prompt_V3.py. - If you see a Python import error: Check for typos or missing files in the
theme_handlersdirectory.
-
"Config not found" error:
- Ensure the config file is named
your_theme.json. - Verify the file is located in the
Core_Nodes/configs/directory. - Remove any JSON comments or trailing commas. JSON is strict!
Tip: Use a JSON validator if unsure.
- Ensure the config file is named
-
"Theme not appearing" error:
- Check
_init_handlersand_init_mappingsinmega_prompt_V3.pyfor correct registration. - Restart ComfyUI after making changes to ensure the new theme is loaded.
- Check the ComfyUI console for any error messages related to theme loading.
- The theme should appear in the Mega Prompt Generator V3 dropdown menu.
- Check
-
Empty or unexpected results:
- Inspect the
generate()method in your handler. Are you returning the expected components? - Check the values in your
your_theme.jsonfile. Are they valid and appropriate for your theme? - Test with different parameter combinations (e.g.,
custom_subject,custom_location, toggling environment/style/effects).
- Inspect the
Additional Tips & Reminders
-
Restart Required:
After adding or modifying handler/config files, always restart ComfyUI to reload all themes and avoid caching issues. -
File Placement:
Place your handler file inCore_Nodes/theme_handlers/and your config file inCore_Nodes/configs/. -
Python Syntax:
Use a code editor with Python syntax checking to avoid indentation or syntax errors in your handler file. -
Handler Inheritance:
Your handler class must inherit fromBaseThemeHandlerfor compatibility. -
Random Choice Methods:
Use_get_random_choicefor standard random selection, or_safe_choiceif you want to provide a fallback value. -
Docstrings & Comments:
Add docstrings and comments to your handler for clarity and maintainability. -
Updating Existing Themes:
To update a theme, edit the handler or config file, then restart ComfyUI. You can add new elements to the config or extend the handler logic as needed.
Naming Conventions
- Handler class: Use
PascalCase(e.g.,MedievalThemeHandler). - Internal name: Use
snake_case(e.g.,medieval_theme). - Display name: Include an emoji + title case (e.g.,
🎨 Medieval Theme). - Config key: Should match the internal name (e.g.,
"medieval_theme": {...}).
Testing Steps
- Create all files in the correct directories.
- Restart ComfyUI to reload handlers.
- Verify console logs for errors.
- Test with:
prompt = handler.generate(custom_subject="medieval castle") print(prompt) # Inspect the generated prompt - Check the dropdown menu in ComfyUI for your theme name (Mega Prompt Generator V3 node).
- Experiment with different
custom_subjectvalues and other parameters to ensure the theme integrates correctly.
Advanced Customization
- Conditional Logic: Add more complex logic to your
generate()method to handle different scenarios or user inputs. - Weighted Random Choices: Use the
_get_random_choice()method with weights to favor certain elements over others. - External Data: Load data from external files (e.g., text files, databases) to expand the possibilities of your theme.
- Custom Parameters: Add more parameters to the
generate()method to allow users to fine-tune the theme.
Best Practices
- Use double parentheses
(( ))for emphasis. - Provide fallback values to avoid missing data.
- Handle custom subjects gracefully.
- Keep your code clean and well-documented.
- Test your theme thoroughly before sharing it with others.
Example Theme: Medieval architecture with stained glass and grand halls.
{
"your_theme": {
"main_elements": ["castle", "abbey", "cathedral"],
"settings": ["forest glade", "snow-covered mountains", "rolling hills"],
"styles": ["gothic", "romanesque", "byzantine"]
}
}
Example Theme: "Starter Pack" figurine in a blister pack.
{
"starter_pack": {
"names": ["Alex", "Jordan"],
"genders": ["man", "woman"],
"physical_traits": ["tall and athletic", "with glasses"],
"jobs": ["developer", "artist"],
"passions": ["hiking", "reading"],
"objects": ["a laptop and headphones", "a sketchbook and pencils"],
"styles": ["cartoon", "comic book"]
}
}
🚀 Ready to create your theme? Follow this guide strictly for seamless integration with ComfyUI!