Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .agents/skills/conventional-commit/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
name: conventional-commit
description: 'Prompt and workflow for generating conventional commit messages using a structured XML format. Guides users to create standardized, descriptive commit messages in line with the Conventional Commits specification, including instructions, examples, and validation.'
---

### Instructions

```xml
<description>This file contains a prompt template for generating conventional commit messages. It provides instructions, examples, and formatting guidelines to help users write standardized, descriptive commit messages in accordance with the Conventional Commits specification.</description>
```

### Workflow

**Follow these steps:**

1. Run `git status` to review changed files.
2. Run `git diff` or `git diff --cached` to inspect changes.
3. Stage your changes with `git add <file>`.
4. Construct your commit message using the following XML structure.
5. After generating your commit message, Copilot will automatically run the following command in your integrated terminal (no confirmation needed):

```bash
git commit -m "type(scope): description"
```

6. Just execute this prompt and Copilot will handle the commit for you in the terminal.

### Commit Message Structure

```xml
<commit-message>
<type>feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert</type>
<scope>()</scope>
<description>A short, imperative summary of the change</description>
<body>(optional: more detailed explanation)</body>
<footer>(optional: e.g. BREAKING CHANGE: details, or issue references)</footer>
</commit-message>
```

### Examples

```xml
<examples>
<example>feat(parser): add ability to parse arrays</example>
<example>fix(ui): correct button alignment</example>
<example>docs: update README with usage instructions</example>
<example>refactor: improve performance of data processing</example>
<example>chore: update dependencies</example>
<example>feat!: send email on registration (BREAKING CHANGE: email service required)</example>
</examples>
```

### Validation

```xml
<validation>
<type>Must be one of the allowed types. See <reference>https://www.conventionalcommits.org/en/v1.0.0/#specification</reference></type>
<scope>Optional, but recommended for clarity.</scope>
<description>Required. Use the imperative mood (e.g., "add", not "added").</description>
<body>Optional. Use for additional context.</body>
<footer>Use for breaking changes or issue references.</footer>
</validation>
```

### Final Step

```xml
<final-step>
<cmd>git commit -m "type(scope): description"</cmd>
<note>Replace with your constructed message. Include body and footer if needed.</note>
</final-step>
```
102 changes: 102 additions & 0 deletions .agents/skills/flask-api-development/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
name: flask-api-development
description: >
Develop lightweight Flask APIs with routing, blueprints, database integration,
authentication, and request/response handling. Use when building RESTful APIs,
microservices, or lightweight web services with Flask.
---

# Flask API Development

## Table of Contents

- [Overview](#overview)
- [When to Use](#when-to-use)
- [Quick Start](#quick-start)
- [Reference Guides](#reference-guides)
- [Best Practices](#best-practices)

## Overview

Create efficient Flask APIs with blueprints for modular organization, SQLAlchemy for ORM, JWT authentication, comprehensive error handling, and proper request validation following REST principles.

## When to Use

- Building RESTful APIs with Flask
- Creating microservices with minimal overhead
- Implementing lightweight authentication systems
- Designing API endpoints with proper validation
- Integrating with relational databases
- Building request/response handling systems

## Quick Start

Minimal working example:

```python
# app.py
from flask import Flask, request, jsonify
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager
import os

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///app.db')
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY', 'dev-secret')
app.config['JSON_SORT_KEYS'] = False

db = SQLAlchemy(app)
jwt = JWTManager(app)
CORS(app)

# Request ID middleware
@app.before_request
def assign_request_id():
import uuid
request.request_id = str(uuid.uuid4())

# Error handlers
@app.errorhandler(400)
def bad_request(error):
// ... (see reference guides for full implementation)
```

## Reference Guides

Detailed implementations in the `references/` directory:

| Guide | Contents |
|---|---|
| [Flask Application Setup](references/flask-application-setup.md) | Flask Application Setup |
| [Database Models with SQLAlchemy](references/database-models-with-sqlalchemy.md) | Database Models with SQLAlchemy |
| [Authentication and JWT](references/authentication-and-jwt.md) | Authentication and JWT |
| [Blueprints for Modular API Design](references/blueprints-for-modular-api-design.md) | Blueprints for Modular API Design |
| [Request Validation](references/request-validation.md) | Request Validation |
| [Application Factory and Configuration](references/application-factory-and-configuration.md) | Application Factory and Configuration |

## Best Practices

### ✅ DO

- Use blueprints for modular organization
- Implement proper authentication with JWT
- Validate all user input
- Use SQLAlchemy ORM for database operations
- Implement comprehensive error handling
- Use pagination for collection endpoints
- Log errors and important events
- Return appropriate HTTP status codes
- Implement CORS properly
- Use environment variables for configuration

### ❌ DON'T

- Store secrets in code
- Use global variables for shared state
- Ignore database transactions
- Trust user input without validation
- Return stack traces in production
- Use mutable default arguments
- Forget to handle database connection errors
- Implement authentication in route handlers
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Application Factory and Configuration

## Application Factory and Configuration

```python
# config.py
import os

class Config:
SQLALCHEMY_TRACK_MODIFICATIONS = False
JSON_SORT_KEYS = False

class DevelopmentConfig(Config):
DEBUG = True
TESTING = False
SQLALCHEMY_DATABASE_URI = 'sqlite:///app.db'

class ProductionConfig(Config):
DEBUG = False
TESTING = False
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL')
JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY')

class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'

# factory.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager

def create_app(config_name='development'):
app = Flask(__name__)

if config_name == 'production':
from config import ProductionConfig
app.config.from_object(ProductionConfig)
else:
from config import DevelopmentConfig
app.config.from_object(DevelopmentConfig)

db = SQLAlchemy(app)
jwt = JWTManager(app)

# Register blueprints
from routes.auth import auth_bp
from routes.users import users_bp
app.register_blueprint(auth_bp)
app.register_blueprint(users_bp)

return app
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Authentication and JWT

## Authentication and JWT

```python
# auth.py
from flask import request, jsonify
from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity
from functools import wraps
from models import User, db

def authenticate_user(email, password):
user = User.query.filter_by(email=email).first()
if user and user.verify_password(password):
return user
return None

def login_required(f):
@wraps(f)
@jwt_required()
def decorated_function(*args, **kwargs):
identity = get_jwt_identity()
user = User.query.get(identity)
if not user or not user.is_active:
return jsonify({'error': 'User not found or inactive'}), 401
request.current_user = user
return f(*args, **kwargs)
return decorated_function

def admin_required(f):
@wraps(f)
@login_required
def decorated_function(*args, **kwargs):
if request.current_user.role != 'admin':
return jsonify({'error': 'Admin access required'}), 403
return f(*args, **kwargs)
return decorated_function

# routes/auth.py
from flask import Blueprint, request, jsonify
from auth import authenticate_user, login_required
from models import User, db
from flask_jwt_extended import create_access_token

auth_bp = Blueprint('auth', __name__, url_prefix='/api/auth')

@auth_bp.route('/login', methods=['POST'])
def login():
data = request.get_json()
if not data or not data.get('email') or not data.get('password'):
return jsonify({'error': 'Missing credentials'}), 400

user = authenticate_user(data['email'], data['password'])
if not user:
return jsonify({'error': 'Invalid credentials'}), 401

access_token = create_access_token(identity=str(user.id))
return jsonify({
'access_token': access_token,
'user': user.to_dict()
}), 200

@auth_bp.route('/register', methods=['POST'])
def register():
data = request.get_json()
if User.query.filter_by(email=data['email']).first():
return jsonify({'error': 'Email already exists'}), 409

user = User(email=data['email'], first_name=data.get('first_name'))
user.set_password(data['password'])
db.session.add(user)
db.session.commit()

return jsonify({'user': user.to_dict()}), 201

@auth_bp.route('/profile', methods=['GET'])
@login_required
def get_profile():
return jsonify({'user': request.current_user.to_dict()}), 200
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Blueprints for Modular API Design

## Blueprints for Modular API Design

```python
# routes/users.py
from flask import Blueprint, request, jsonify
from auth import login_required, admin_required
from models import User, db
from sqlalchemy import or_

users_bp = Blueprint('users', __name__, url_prefix='/api/users')

@users_bp.route('', methods=['GET'])
@login_required
def list_users():
page = request.args.get('page', 1, type=int)
limit = request.args.get('limit', 20, type=int)
search = request.args.get('q', '', type=str)

query = User.query
if search:
query = query.filter(or_(
User.email.ilike(f'%{search}%'),
User.first_name.ilike(f'%{search}%')
))

paginated = query.paginate(page=page, per_page=limit)
return jsonify({
'data': [user.to_dict() for user in paginated.items],
'pagination': {
'page': page,
'limit': limit,
'total': paginated.total,
'pages': paginated.pages
}
}), 200

@users_bp.route('/<user_id>', methods=['GET'])
@login_required
def get_user(user_id):
user = User.query.get(user_id)
if not user:
return jsonify({'error': 'User not found'}), 404
return jsonify({'user': user.to_dict()}), 200

@users_bp.route('/<user_id>', methods=['PATCH'])
@login_required
def update_user(user_id):
if str(request.current_user.id) != user_id:
return jsonify({'error': 'Unauthorized'}), 403

user = User.query.get(user_id)
if not user:
return jsonify({'error': 'User not found'}), 404

data = request.get_json()
if 'first_name' in data:
user.first_name = data['first_name']
if 'last_name' in data:
user.last_name = data['last_name']

db.session.commit()
return jsonify({'user': user.to_dict()}), 200

@users_bp.route('/<user_id>', methods=['DELETE'])
@admin_required
def delete_user(user_id):
user = User.query.get(user_id)
if not user:
return jsonify({'error': 'User not found'}), 404

db.session.delete(user)
db.session.commit()
return '', 204
```
Loading