Automated Event-Based Frontend Customization Tool - Transform your website for special events using AI.
Doodlify is a Python CLI tool that automatically adapts frontend projects for special events like Halloween, Christmas, or custom celebrations. It uses AI agents to intelligently modify images, text, and other visual elements to match your event's theme.
- π€ AI-Powered Transformations: Uses OpenAI's GPT and image editing models to intelligently adapt content
- π― Smart Analysis: Automatically identifies files and elements to customize using AI-powered code analysis
- π§ Improvement Suggestions: During analyze, detects repo improvements that boost event quality and auto-creates GitHub issues (deduplicated)
- π³ Git Integration: Creates separate branches for each event with proper version control
- π GitHub Actions Ready: Easily automate with CI/CD pipelines
- π i18n Support: Adapts internationalization files to match event themes
- πΌοΈ Image Transformation: Automatically generates event-themed variations of images
- π Safe Backups: Creates backup copies of original files before modifications
- π State Tracking: Maintains processing state to avoid duplicate work
- π Two Execution Modes: Choose between Assistant mode (predictable) or Agentic mode (autonomous)
Doodlify offers two distinct execution modes to suit different needs:
AI as a tool - You control the workflow, AI helps at each step.
How it works:
- Follows a predetermined sequence of operations
- Calls AI for specific tasks (analyze, transform, adapt)
- Deterministic execution: Same steps every time
- Uses direct GitHub REST API calls
- AI is stateless - no memory between operations
Think of it as: Calling an API repeatedly - you decide what happens next.
Best for:
- Production deployments requiring predictability
- Debugging and understanding exact execution flow
- Environments without Docker
- When you need full control over the process
Example workflow:
# Your code controls the flow:
result1 = ai.analyze(repo) # Step 1: Analyze
result2 = ai.transform(images) # Step 2: Transform
result3 = ai.commit(changes) # Step 3: CommitAI as an autonomous decision-maker - The agent decides what to do, when, and whether it's done.
How it works:
- Agent receives a high-level mission ("Transform this repo for Halloween")
- Autonomously decides which tools to use and in what order
- Can adapt strategy based on results and errors
- Uses Model Context Protocol (MCP) for GitHub operations
- Agent has memory and context across tool invocations
- Decides when the task is complete
Think of it as: Delegating to a smart teammate who figures out the steps themselves.
Best for:
- Complex workflows requiring dynamic decisions
- Experimental/exploratory transformations
- When you want the AI to handle edge cases autonomously
- Learning how AI agents approach problems
Example workflow:
# Agent controls the flow:
agent.run("Transform this repo for Halloween")
# Agent internally:
# - Should I analyze first? Yes
# - What images need work? Let me check
# - This transformation failed, let me retry differently
# - Am I done? Let me assess progress| Aspect | Assistant Mode | Agentic Mode |
|---|---|---|
| Control | You decide steps | AI decides steps |
| Execution | Predetermined sequence | Dynamic adaptation |
| GitHub API | Direct REST calls | MCP protocol |
| AI State | Stateless per call | Maintains context |
| Error Handling | Predefined logic | Autonomous retry/adapt |
| Completion | Fixed workflow end | Agent decides when done |
| Dependencies | Python + requests | Python + Haystack + Docker (for MCP) |
| Predictability | High | Medium |
| Flexibility | Medium | High |
Add the --agentic flag to any command:
# Assistant mode (default)
doodlify analyze
doodlify process --event-id halloween-2024
# Agentic mode
doodlify analyze --agentic
doodlify process --event-id halloween-2024 --agentic
doodlify push --agentic- Python 3.8+
- Git
- GitHub Personal Access Token
- OpenAI API Key
- Docker (optional, for GitHub MCP server)
- Clone the repository:
git clone https://github.com/yourusername/doodlify.git
cd doodlify- Install dependencies:
pip install -e .- Set up environment variables:
cp .env.example .env
# Edit .env and add your credentials- Create your configuration:
cp config.example.json config.json
# Edit config.json to match your project# Analyze your project
doodlify analyze
# Process active events
doodlify process
# Push changes and create PRs
doodlify push
# Or run all phases at once
doodlify run
# Check status
doodlify status
# Clear lock data
doodlify clear --event-id halloween-2024# Required
GITHUB_PERSONAL_ACCESS_TOKEN=ghp_your_token_here
GITHUB_REPO_NAME=username/repository-name
OPENAI_API_KEY=sk-your_openai_key_here
# Optional
GIT_BRANCH_CHANGES_TARGET=main # Target branch for PRs{
"project": {
"name": "My Project",
"description": "Description for AI agents",
"sources": ["src/", "public/"],
"targetBranch": "main"
},
"defaults": {
"selector": "img.hero, .banner-image",
"branchPrefix": "event/"
},
"events": [
{
"id": "halloween-2024",
"name": "Halloween 2024",
"description": "Spooky Halloween theme with pumpkins and autumn colors",
"startDate": "2024-10-15",
"endDate": "2024-11-01",
"branch": "halloween-2024"
}
]
}- name: Project name
- description: Context for AI agents about your project structure
- sources: Array of paths to analyze (leave empty for entire repo)
- targetBranch: Target branch for pull requests (optional)
- selector: CSS selector to match elements (e.g.,
"img.hero, main > img") - branchPrefix: Prefix for event branches (e.g.,
"event/"β"event/halloween-2024") - reportSuggestions: Boolean map controlling which suggestions are auto-filed as GitHub issues. Use keys below. Default enables core items and disables optional ones.
Example:
{
"defaults": {
"reportSuggestions": {
"i18n": false,
"css_variables": true,
"data_attrs": true,
"svg_usage": true,
"global_css": true,
"marker_styles": true,
"favicon_variants": true,
"favicon_establish": true,
"og_variants": true,
"og_add": true,
"selectors_guidance": true,
"ai_considerations": true
}
}
}- id: Unique identifier (used for branch names)
- name: Display name
- description: Event context for AI agents
- startDate/endDate: Date range (YYYY-MM-DD format)
- branch: Branch name suffix
Doodlify operates in three phases:
doodlify analyze- Validates configuration
- Clones/updates target repository
- Performs AI-powered codebase analysis
- Identifies files of interest for modification
- Caches analysis results
- Creates GitHub issues with improvement suggestions (only once per suggestion; tracked in
config-lock.json)
- Source: Heuristics (missing i18n files, missing image assets, missing selectors) and AI considerations
- Tracking: Stored in
config-lock.jsonunderreported_suggestionswith a fingerprint to avoid duplicates - Permissions: Requires Personal Access Token with
Issues: Read and write
The analyzer attaches a stable key to each suggestion. The orchestrator consults defaults.reportSuggestions[key] to decide if it should be filed.
-
Optional by default (false):
i18nβ "Optional: Centralize user-facing copy in i18n files"
-
Core by default (true):
css_variablesβ Add CSS variables for theme tokens (colors, spacing)data_attrsβ Add data attributes to mark adaptable elementssvg_usageβ Prefer SVG for logos/illustrations to enable recoloringglobal_cssβ Ensure a global stylesheet or theme entrypoint existsmarker_stylesβ Style list markers (e.g., vignettes) to allow event variationsfavicon_variantsβ Provide event-ready favicon/touch icon variants (if favicon assets exist)favicon_establishβ Establish predictable favicon/touch icon assets (if none exist)og_variantsβ Provide seasonal Open Graph social preview variants (ifog:imageexists)og_addβ Add Open Graph image meta for social sharing (ifog:imagemissing)selectors_guidanceβ Add CSS selectors or data-attributes to mark event-adaptable elements (if no selector in config)ai_considerationsβ Apply analyzer considerations to improve event readiness
You can override any of these in your config.json under defaults.reportSuggestions.
CLI override:
- Pass
--report-alltodoodlify analyzeordoodlify runto report everything (including those set to false). These will be logged as OPTIONAL when filed due to the flag.
doodlify process- Processes all active unprocessed events
- Creates event-specific branches
- Transforms images using OpenAI
- Adapts text/i18n content
- Creates backup files
- Commits changes locally
Advanced flags:
# Process a specific event (bypasses active/unprocessed filters)
doodlify process --event-id halloween-2025
# Process only certain files for an event
doodlify process --event-id halloween-2025 \
--only frontend/web-ui/src/images/hero-ecommerce-construction.png,frontend/web-ui/src/images/hero-telephony.png
# Force reprocess even if `.original` backups exist
doodlify process --event-id halloween-2025 \
--only frontend/web-ui/src/images/hero-ecommerce-construction.png \
--forcedoodlify push- Pushes branches to GitHub
- Creates pull requests
- Updates lock file with PR URLs
Notes:
- PR creation now uses the direct GitHub REST API via
requests(no MCP). Ensure yourGITHUB_PERSONAL_ACCESS_TOKENhasrepopermissions.
If you made additional edits inside the workspace repo (e.g., fixed CSS or HTML) after processing, commit them first and then run doodlify push:
# The workspace repository lives here
cd .doodlify-workspace/<your-repo-name>
# Commit your changes on the event branch (created during process)
git status
git add -A
git commit -m "chore: manual fixes before PR"
# Return to your doodlify project root and push/PR
cd -
doodlify pushNotes:
- The push step looks at processed events that havenβt been pushed yet and creates PRs automatically.
- The event branch naming is
<branchPrefix><event.branch>(e.g.,feature/event/halloween-2025).
Sometimes youβll want to run a new cycle for a different event (or re-run with different settings).
- Activate or target the event explicitly:
# Re-run analysis (refreshes cache if needed)
doodlify analyze
# Process a specific event directly (bypasses date-based filtering)
doodlify process --event-id <event-id>
# Then push and open PRs
doodlify push-
If you want to reprocess previously modified files for the same event, use either:
doodlify restore --event-id <event-id> --files <comma-separated files>to restore originals and process again, ordoodlify process --event-id <event-id> --only <files> --forceto reprocess even if backups exist.
-
If you need a clean slate for an event (clears its state in the lock file):
doodlify clear --event-id <event-id>Transition guidance:
- Each event is processed on its own branch. Creating a new event branch is handled by
process; it also auto-stashes any local, uncommitted changes in the workspace repo to avoid conflicts. - Best practice:
- Finish and push the current eventβs branch (
doodlify push). - Commit any extra manual tweaks inside
.doodlify-workspace/<repo>before switching. - Run
doodlify analyze(optional but recommended) anddoodlify process --event-id <next-event>for the new event.
- Finish and push the current eventβs branch (
When useEventColorPalette is enabled (either in defaults or per-event), Doodlify uses AI to intelligently detect and transform colors in your stylesheets.
Enable in config.json:
{
"defaults": {
"useEventColorPalette": true
},
"events": [
{
"id": "halloween-2024",
"name": "Halloween 2024",
"description": "Spooky Halloween theme with pumpkins and orange/black colors",
"useEventColorPalette": true // Override per event
}
]
}-
AI Analysis: For each CSS/SCSS/SASS/LESS file, the AI:
- Identifies color variables (CSS custom properties, SCSS/SASS variables, LESS variables)
- Detects direct color values in properties (background-color, color, border-color, etc.)
- Determines which colors should change based on the event theme
-
Smart Replacement: The AI suggests specific replacements from your event's color palette
-
Automatic Backup: Original files are backed up as
<name>.original.<ext>before changes
- Context-aware: Understands which colors are thematic vs. structural
- Framework-agnostic: Works with any CSS preprocessor or custom naming conventions
- Intelligent: Considers the event description to make appropriate color choices
- Safe: Creates backups and can be reverted using
doodlify restore
π¨ Using AI-powered color detection for theme transformation...
π Found 3 style file(s)
π styles/theme.scss: Found 5 color change(s)
β Replace primary brand color with Halloween orange
β Update secondary accent to dark purple
β Change header background to spooky black
πΎ Saved changes to styles/theme.scss
For focused, task-oriented guides, see the docs/ folder:
Uses OpenAI to:
- Identify frontend framework (React, Vue, static HTML, etc.)
- Locate visual elements (images, banners, logos)
- Find i18n/localization files
- Extract CSS selectors
- Provide intelligent recommendations
- Produce improvement suggestions for event readiness (e.g., add i18n files, ensure hero images, add selectors)
Uses OpenAI's image editing API to:
- Transform images to match event themes
- Maintain original composition
- Apply appropriate color schemes
- Add thematic elements
Uses GPT-4 to:
- Adapt i18n files for events
- Maintain tone and language
- Keep message clarity
- Preserve technical keys
doodlify/
βββ doodlify/
β βββ __init__.py
β βββ cli.py # CLI interface
β βββ models.py # Data models
β βββ config_manager.py # Configuration handling
β βββ orchestrator.py # Main workflow orchestrator
β βββ git_agent.py # Local git operations
β βββ github_client.py # GitHub MCP client
β βββ agents/
β βββ analyzer_agent.py # Codebase analysis
β βββ image_agent.py # Image transformations
β βββ text_agent.py # Text adaptations
βββ .github/
β βββ workflows/
β βββ doodlify.yml # GitHub Actions workflow
βββ config.json # Your configuration
βββ event.manifest.json # Optional: repo-level overrides (lives in target repo)
βββ config-lock.json # State tracking (auto-generated)
βββ .env # Environment variables
βββ requirements.txt
βββ setup.py
βββ README.md
The included workflow file (.github/workflows/doodlify.yml) is disabled by default.
To enable:
- Remove the
if: falseline from the workflow - Add secrets to your repository:
GITHUB_PERSONAL_ACCESS_TOKENOPENAI_API_KEY
- Ensure the token has repository permissions:
Contents: Read/Write,Pull requests: Read/WriteandIssues: Read/Write
The workflow:
- Runs daily at 9 AM UTC
- Can be triggered manually
- Commits
config-lock.jsonto track state - Prevents duplicate processing
Doodlify uses config-lock.json to track:
- Processing status of each event
- Analysis results (cached)
- Branch and PR information
- Modified files
- Commit SHAs
- Errors and timestamps
- Reported improvement suggestions (title, fingerprint, issue number)
Lock filename note:
- The lock file name is derived from the config file name you pass to the CLI.
- Examples:
--config config.jsonβconfig-lock.json--config event.manifest.jsonβevent.manifest-lock.json
This prevents duplicate work in CI/CD environments.
Target specific elements:
{
"defaults": {
"selector": "img.hero, main > img, [data-theme-image]"
}
}Each event can have dedicated analysis results:
doodlify analyze
# Analysis is cached in config-lock.json# Clear specific event
doodlify clear --event-id halloween-2024
# Clear all
doodlify clearThere are two supported workflows to re-run an individual file without clearing everything:
- Restore from backup, then process (safe, resets the file to its exact original)
# Restore the current file from its `.original` backup and remove the backup
doodlify restore \
--event-id halloween-2025 \
--files frontend/web-ui/src/images/hero-ecommerce-construction.png
# Re-run processing for just that file
doodlify process \
--event-id halloween-2025 \
--only frontend/web-ui/src/images/hero-ecommerce-construction.png- Force process (skip the backup check and re-transform in place)
doodlify process \
--event-id halloween-2025 \
--only frontend/web-ui/src/images/hero-ecommerce-construction.png \
--forceNotes:
- Backups: When a file is first transformed, Doodlify creates a
.original.{ext}sibling (e.g.,image.original.png). - Default skip: Subsequent runs skip files with existing
.original.{ext}to avoid duplicate work. - Restore:
doodlify restoreputs the original bytes back into the current file and removes the.original.{ext}, making it eligible for normal processing again. - Force:
--forcetells the processor to ignore.original.{ext}and reprocess anyway.
You can place an event.manifest.json file in the target repository (at the repo root) to override parts of your configuration after cloning. This is useful when the target repo wants to customize selectors, defaults, or events without editing the automation project.
Precedence (highest last):
config.json(passed to the CLI)event.manifest.json(in the target repo) overridesproject,defaults, andevents
Example event.manifest.json in the target repo:
{
"defaults": {
"selector": "img.hero, [data-event-adaptable]",
"branchPrefix": "feature/event/"
},
"project": {
"targetBranch": "main"
}
}Notes:
- Manifest is optional. If present, it is applied after cloning and before analysis.
- Only the top-level keys
project,defaults, andeventsare considered. - The manifest is intended as a consumer-owned override; your automation repo still keeps a boilerplate
config.example.json.
- Check if event dates are active
- Verify selector matches elements in your code
- Ensure images are in supported formats (PNG, JPG, WebP)
- Verify
GITHUB_REPO_NAMEformat:owner/repo - Check GitHub token has repo access
- Verify API key is valid
- Check API quota/billing
- Ensure image format is supported
If Docker is unavailable, install Node.js and the tool will use npx:
npm install -g @modelcontextprotocol/server-githubStatus: Work in Progress - Not recommended for production use
The agentic mode is currently experimental and has the following known issues:
- Multi-turn conversations: Agent conversation flow with Haystack has edge cases where tool results aren't properly chained between turns
- File persistence: Transformed images may not be saved to disk in all scenarios
- Limited tool coverage: Only image transformation is implemented; CSS color changes and text adaptation need agent tools
- Debugging complexity: Autonomous decision-making makes it harder to trace what went wrong
Recommendation: Use Assistant Mode (default) for production workflows. It provides:
- Deterministic, repeatable results
- Better error messages and debugging
- Full feature coverage (images, CSS, text, i18n)
- Proven reliability in CI/CD environments
Agentic mode development continues as an experimental feature for exploring autonomous AI workflows.
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details
- OpenAI for GPT and image editing APIs
- GitHub MCP for repository operations
- The open-source community for the amazing tools and libraries
For issues and questions:
- Open an issue on GitHub
- Check existing issues for solutions
- Review the troubleshooting section
Made with β€οΈ by [EliuX][mailto: eliecerhdz@gmail.com]