AS
AgSkills.dev
MARKETPLACE

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.

566
82

Preview

SKILL.md
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.

GitHub Repository
level09/enferno
Stars
566
Forks
82
Open Repository
Install Skill
Download ZIP2 files