diff --git a/.github/scripts/validate_templates.py b/.github/scripts/validate_templates.py index 2c2c63f..8629434 100755 --- a/.github/scripts/validate_templates.py +++ b/.github/scripts/validate_templates.py @@ -47,6 +47,29 @@ def validate_template_entry(name: str, config: dict, repo_root: Path) -> list[st if not main_file.exists(): errors.append(f"Template '{name}': main file '{config['file']}' does not exist") + # Validate featured field if present (optional) + if 'featured' in config: + if not isinstance(config['featured'], bool): + errors.append(f"Template '{name}': 'featured' field must be a boolean") + + # Validate author field if present (optional) + if 'author' in config: + author = config['author'] + if not isinstance(author, dict): + errors.append(f"Template '{name}': 'author' field must be an object") + else: + # All author fields are optional, but validate types if present + optional_author_fields = { + 'name': str, + 'github_profile': str, + 'last_modified_date': str + } + for field, expected_type in optional_author_fields.items(): + if field in author and not isinstance(author[field], expected_type): + errors.append( + f"Template '{name}': author.{field} must be a {expected_type.__name__}" + ) + # Check files array if present if 'files' in config: for file_spec in config['files']: diff --git a/README.md b/README.md index d765f82..7a01e3e 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,8 @@ Each template entry in `templates.json` supports the following fields: |-------|------|-------------| | `files` | array | List of files to copy for complex templates (see File Specification below) | | `next_steps` | array | Custom post-installation instructions (see Next Steps below) | +| `featured` | boolean | Mark template as featured (shown prominently in CLI) | +| `author` | object | Template author information (see Author Information below) | ### File Specification @@ -246,6 +248,68 @@ The CLI automatically replaces these variables in `commands`: // Becomes: "cd shopping && uv run my_bot" ``` +### Author Information + +The optional `author` object allows you to add attribution to your template: + +```json +{ + "name": "Jane Smith", // Optional: Author name or username + "github_profile": "https://github.com/janesmith", // Optional: GitHub profile URL + "last_modified_date": "2025-11-12" // Optional: Last update date (YYYY-MM-DD) +} +``` + +**Example:** + +```json +"my-template": { + "file": "my-template/main.py", + "description": "Advanced web scraping with AI", + "files": [...], + "next_steps": [...], + "author": { + "name": "Jane Smith", + "github_profile": "https://github.com/janesmith", + "last_modified_date": "2025-11-12" + } +} +``` + +**Notes:** +- All fields within `author` are optional +- Default templates (`default`, `advanced`, `tools`) typically don't need author information +- Community-contributed templates should include author information when possible +- The `last_modified_date` should be updated whenever the template is significantly changed + +### Featured Templates + +The optional `featured` boolean flag marks templates for prominent display in the CLI's template selector UI. + +```json +{ + "featured": true +} +``` + +**Example:** + +```json +"shopping": { + "file": "shopping/main.py", + "description": "E-commerce automation with structured output", + "featured": true, + "files": [...], + "next_steps": [...] +} +``` + +**Notes:** +- Featured templates are shown in a dedicated "Featured Templates" section in the CLI +- Default templates (`default`, `advanced`, `tools`) are always shown separately and don't need the featured flag +- Use this to highlight high-quality, well-maintained, or popular community templates +- Currently featured templates: `shopping`, `job-application`, `agentmail`, `llm-arena`, `slack`, `all-openai-jobs` + ### Best Practices 1. **README.md**: Include detailed setup instructions, customization tips, and troubleshooting diff --git a/templates.json b/templates.json index 0a3ef95..5726286 100644 --- a/templates.json +++ b/templates.json @@ -14,6 +14,7 @@ "shopping": { "file": "shopping/main.py", "description": "E-commerce automation with structured output (Pydantic models)", + "featured": true, "files": [ { "source": "shopping/main.py", @@ -70,11 +71,17 @@ { "footer": "šŸ“– See README.md for detailed instructions" } - ] + ], + "author": { + "name": "", + "github_profile": "", + "last_modified_date": "" + } }, "job-application": { "file": "job-application/main.py", "description": "Automated job application form submission with resume upload", + "featured": true, "files": [ { "source": "job-application/main.py", @@ -137,11 +144,17 @@ { "footer": "šŸ“– See README.md for customization and troubleshooting" } - ] + ], + "author": { + "name": "", + "github_profile": "", + "last_modified_date": "" + } }, "agentmail": { "file": "agentmail/main.py", "description": "Email inbox automation with 2FA support using AgentMail", + "featured": true, "files": [ { "source": "agentmail/main.py", @@ -190,13 +203,19 @@ "commands": ["uv run {output}"] }, { - "footer": "šŸ“– See README.md for customization and advanced usage\n\nšŸŽƒ Code: HAPPYHALLOWEEN -> $50 free!" + "footer": "šŸ“– See README.md for customization and advanced usage" } - ] + ], + "author": { + "name": "", + "github_profile": "", + "last_modified_date": "" + } }, "llm-arena": { "file": "llm-arena/main.py", "description": "Compare different AI models side-by-side in LLM Arena", + "featured": true, "files": [ { "source": "llm-arena/main.py", @@ -243,11 +262,17 @@ { "footer": "šŸ“– See README.md for customization and advanced usage\n\n⚔ Enter a task and watch LLMs race to complete it!" } - ] + ], + "author": { + "name": "", + "github_profile": "", + "last_modified_date": "" + } }, "slack": { "file": "slack/README.md", "description": "Slack bot for browser automation tasks via mentions", + "featured": true, "files": [ { "source": "slack/app/main.py", @@ -310,11 +335,17 @@ { "footer": "šŸ“– See README.md for detailed setup, Event Subscriptions configuration, and production deployment" } - ] + ], + "author": { + "name": "", + "github_profile": "", + "last_modified_date": "" + } }, "all-openai-jobs": { "file": "all-openai-jobs/main.py", "description": "Web scraping with CodeAgent to extract job listings from career pages", + "featured": true, "files": [ { "source": "all-openai-jobs/main.py", @@ -361,6 +392,11 @@ { "footer": "šŸ“– See README.md for customization and troubleshooting\n\nšŸ¤– CodeAgent will generate extraction code and save it to script.ipynb" } - ] + ], + "author": { + "name": "", + "github_profile": "", + "last_modified_date": "" + } } }