home / skills / psincraian / myfy / myfy-patterns

This skill helps you apply core myfy framework patterns and conventions to build modular, type-safe, asynchronous applications.

npx playbooks add skill psincraian/myfy --skill myfy-patterns

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
4.2 KB
---
name: myfy-patterns
description: Core myfy patterns and conventions for building applications. Use when working with myfy.core, Application, WebModule, DataModule, FrontendModule, TasksModule, UserModule, CliModule, AuthModule, RateLimitModule, or @route decorators.
---

# myfy Framework Patterns

You are assisting a developer building an application with the myfy Python framework.

## Core Principles

1. **Opinionated, not rigid** - Strong defaults, full configurability
2. **Modular by design** - Features are modules (web, data, tasks, frontend)
3. **Type-safe DI** - Constructor injection with compile-time validation
4. **Async-native** - Built on ASGI and AnyIO with contextvars
5. **Zero-config defaults** - Convention over configuration

## Imports

Always import from the public API:

```python
# Core
from myfy.core import Application, provider, SINGLETON, REQUEST, TASK
from myfy.core import BaseSettings, BaseModule

# Web
from myfy.web import WebModule, route, Query, abort, errors
from myfy.web import Authenticated, Anonymous, AuthModule
from myfy.web.ratelimit import RateLimitModule, rate_limit

# Data
from myfy.data import DataModule, AsyncSession

# Tasks
from myfy.tasks import TasksModule, task, TaskContext

# Frontend
from myfy.frontend import FrontendModule, render_template

# User
from myfy.user import UserModule

# CLI Commands
from myfy.commands import CliModule, cli
```

## Application Structure

```python
from myfy.core import Application
from myfy.web import WebModule, route
from myfy.data import DataModule

app = Application(
    settings_class=AppSettings,  # Optional custom settings
    auto_discover=False,          # Disable auto-discovery for explicit control
)

# Add modules in dependency order
app.add_module(DataModule())
app.add_module(WebModule())
```

## Module Categories

| Module | Package | Purpose |
|--------|---------|---------|
| WebModule | myfy-web | HTTP routing, ASGI, FastAPI-like decorators |
| DataModule | myfy-data | SQLAlchemy async, migrations, sessions |
| FrontendModule | myfy-frontend | Jinja2, Tailwind 4, DaisyUI 5, Vite |
| TasksModule | myfy-tasks | Background jobs, SQL-based task queue |
| UserModule | myfy-user | Auth, OAuth, user management |
| CliModule | myfy-commands | Custom CLI commands |
| AuthModule | myfy-web.auth | Type-based authentication, protected routes |
| RateLimitModule | myfy-web.ratelimit | Rate limiting per IP or user |

## Key Conventions

1. **File naming**: `app.py`, `main.py`, or `application.py` for entry point
2. **Settings**: Extend `BaseSettings` from `myfy.core`
3. **Routes**: Use global `route` decorator from `myfy.web`
4. **Providers**: Use `@provider(scope=...)` decorator from `myfy.core`
5. **Tasks**: Use `@task` decorator for background jobs

## Common Patterns

### Creating a Route with DI

```python
from myfy.web import route
from myfy.data import AsyncSession

@route.get("/users/{user_id}")
async def get_user(user_id: int, session: AsyncSession) -> dict:
    # session is auto-injected (REQUEST scope)
    result = await session.execute(select(User).where(User.id == user_id))
    return {"user": result.scalar_one_or_none()}
```

### Creating a Provider

```python
from myfy.core import provider, SINGLETON

@provider(scope=SINGLETON)
def email_service(settings: AppSettings) -> EmailService:
    return EmailService(api_key=settings.email_api_key)
```

### Settings Class

```python
from pydantic import Field
from pydantic_settings import SettingsConfigDict
from myfy.core import BaseSettings

class AppSettings(BaseSettings):
    app_name: str = Field(default="my-app")
    debug: bool = Field(default=False)
    database_url: str = Field(default="sqlite+aiosqlite:///./app.db")

    model_config = SettingsConfigDict(
        env_prefix="MYFY_",
        env_file=".env",
    )
```

## Error Handling

```python
from myfy.web import abort, errors

# Quick abort
abort(404, "User not found")

# Typed errors
raise errors.NotFound("User not found")
raise errors.BadRequest("Invalid email", field="email")
```

## When Generating Code

Always:
- Use type hints for all function parameters and return types
- Use async/await for all handlers
- Import from `myfy.*` not internal modules
- Follow existing project structure
- Use Pydantic models for request/response bodies

Overview

This skill exposes core myfy patterns and conventions to build modular, type-safe, async-native Python applications. It codifies recommended imports, application structure, common module categories, and idiomatic patterns for routes, providers, settings, tasks, and error handling. Use it to speed up consistent, maintainable myfy app development.

How this skill works

The skill summarizes the public API imports and shows how to wire an Application with modules in dependency order. It explains the main module categories (Web, Data, Frontend, Tasks, User, CLI, Auth, RateLimit) and demonstrates key patterns: route handlers with DI, provider factories, Pydantic-based settings, async tasks, and error handling utilities. It emphasizes zero-config defaults, type-safe constructor injection, and async-first handlers.

When to use it

  • Bootstrapping a new myfy application and choosing which modules to add
  • Writing HTTP routes that rely on automatic dependency injection
  • Defining services/providers with specific lifecycle scopes (SINGLETON, REQUEST, TASK)
  • Implementing async background jobs using the TasksModule and @task
  • Creating typed application settings and loading from environment

Best practices

  • Always import from the public myfy API (myfy.core, myfy.web, myfy.data, etc.)
  • Use async/await and type hints for all handlers and providers
  • Register modules in dependency order on Application to ensure providers resolve correctly
  • Keep a single entrypoint file named app.py, main.py, or application.py
  • Use BaseSettings (Pydantic) for configuration with env_prefix and .env support

Example use cases

  • Define a GET route that receives an AsyncSession injected and returns a DB record
  • Create a singleton EmailService provider that reads api_key from settings
  • Add WebModule and DataModule to Application to enable HTTP + DB in the proper order
  • Implement a background cleanup job with @task that runs under the TasksModule
  • Protect routes with AuthModule types like Authenticated and apply per-user rate limits

FAQ

Should I import internals from myfy packages?

No. Always import from the public API (myfy.core, myfy.web, myfy.data, etc.) to preserve compatibility.

When should I disable auto_discover on Application?

Disable auto_discover (auto_discover=False) when you prefer explicit module registration and deterministic startup order.