level09

enferno-dev

@level09/enferno-dev
level09
563
82 forks
Updated 1/6/2026
View on GitHub

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

$skills install @level09/enferno-dev
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Repositorylevel09/enferno
Path.claude/skills/enferno-dev/SKILL.md
Branchmain
Scoped Name@level09/enferno-dev

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

skills list

Skill Instructions


name: enferno-dev description: | 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.

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 to_dict()/from_dict() 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.