smithery/level09

enferno-dev

Development skill for Enferno Flask framework. Use when implementing features, fixing bugs, or writing code for Enferno-based applications. This includes creating models, API endpoints, Vue.js frontend components, database operations, or any development task within the Enferno ecosystem. Triggers: creating blueprints, adding models, building APIs, Vue/Vuetify components, Celery tasks, database migrations.

Installation

$ npx skills add smithery/level09 --skill enferno-dev
More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,840 B
  • docs SUMMARY.md 427 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Enferno Development

Flask + Vue 3 + Vuetify 3 framework. No build step. SQLAlchemy 2.x patterns.

Quick Reference

uv run flask run --port 5001      # Dev server (5001 on macOS)
uv run flask create-db            # Init database
uv run flask install              # Create admin user
uv run ruff check . && uv run ruff format .        # Lint + format

Blueprint Structure

enferno/
├── feature_name/
│   ├── views.py      # Routes and API endpoints
│   ├── models.py     # SQLAlchemy models
│   └── forms.py      # WTForms (if needed)
├── templates/
│   └── feature_name/ # Jinja templates

Register in app.py:

from enferno.feature_name.views import bp as feature_bp
app.register_blueprint(feature_bp)

Models

Use BaseMixin and implement todict()/fromdict() on instances:

from enferno.extensions import db
from enferno.utils.base import BaseMixin

class Product(db.Model, BaseMixin):
    __tablename__ = "products"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=False)
    price = db.Column(db.Numeric(10, 2))
    active = db.Column(db.Boolean, default=True)

    def to_dict(self):
        return {"id": self.id, "name": self.name, "price": float(self.price), "active": self.active}

    def from_dict(self, data):
        self.name = data.get("name", self.name)
        self.price = data.get("price", self.price)
        self.active = data.get("active", self.active)
        return self

API Endpoints

Standard CRUD pattern with pagination and {item: ...} payloads:

from flask import Blueprint, request
from flask_security import roles_required, current_user
from enferno.extensions import db
from enferno.user.models import Activity

bp = Blueprint("products", __name__)


@bp.before_request
@auth_required("session")
@roles_required("admin")
def before_request():
    pass

@bp.get("/api/products")
def list_products():
    page = request.args.get("page", 1, type=int)
    per_page = request.args.get("per_page", 25, type=int)
    query = db.select(Product)
    pagination = db.paginate(query, page=page, per_page=per_page)
    return {"items": [p.to_dict() for p in pagination.items], "total": pagination.total, "perPage": per_page}

@bp.post("/api/product/")
def create_product():
    data = request.json.get("item", {})
    product = Product().from_dict(data)
    db.session.add(product)
    db.session.commit()
    Activity.register(current_user.id, "Product Create", product.to_dict())
    return {"item": product.to_dict()}

@bp.post("/api/product/<int:id>")
def update_product(id):
    product = db.get_or_404(Product, id)
    old = product.to_dict()
    product.from_dict(request.json.get("item", {}))
    db.session.commit()
    Activity.register(current_user.id, "Product Update", {"old": old, "new": product.to_dict()})
    return {"item": product.to_dict()}

@bp.delete("/api/product/<int:id>")
def delete_product(id):
    product = db.get_or_404(Product, id)
    Activity.register(current_user.id, "Product Delete", product.to_dict())
    db.session.delete(product)
    db.session.commit()
    return {"deleted": True}

Vue 3 + Vuetify Frontend

Uses ${} delimiters (not {{}}). Mount per-page Vue apps:

{% extends "layout.html" %}
{% block content %}
<v-app id="app">
  <v-main>
    <v-container>
      <v-data-table-server
        :headers="headers"
        :items="items"
        :items-length="total"
        :loading="loading"
        @update:options="loadItems"
      ></v-data-table-server>
    </v-container>
  </v-main>
</v-app>
{% endblock %}

{% block js %}
<script>
const { createApp, ref } = Vue;
const { createVuetify } = Vuetify;
const vuetify = createVuetify(config.vuetifyConfig);

createApp({
  delimiters: config.delimiters,
  setup() {
    const items = ref([]);
    const total = ref(0);
    const loading = ref(false);
    const headers = ref([
      { title: 'Name', key: 'name' },
      { title: 'Price', key: 'price' },
      { title: 'Actions', key: 'actions', sortable: false }
    ]);

    async function loadItems({ page, itemsPerPage }) {
      loading.value = true;
      const res = await axios.get('/api/products', { params: { page, per_page: itemsPerPage } });
      items.value = res.data.items;
      total.value = res.data.total;
      loading.value = false;
    }

    return { items, total, loading, headers, loadItems };
  }
}).use(vuetify).mount('#app');
</script>
{% endblock %}

Database Queries (SQLAlchemy 2.x)

# Select with filter
query = db.select(User).where(User.active == True)
users = db.session.execute(query).scalars().all()

# Get or 404
user = db.get_or_404(User, id)

# Paginate
pagination = db.paginate(query, page=1, per_page=25)

# Join
query = db.select(Order).join(User).where(User.id == user_id)

Activity Logging

Always log admin actions:

from enferno.user.models import Activity

Activity.register(current_user.id, "Action Name", {"relevant": "data"})

Celery Tasks

Define in a tasks module and import Celery from enferno.tasks:

from enferno.tasks import celery

@celery.task
def process_order(order_id):
    # task logic
    pass

Patterns Reference

For detailed patterns and examples, see [references/patterns.md](references/patterns.md).