
erpnext-syntax-customapp
by OpenAEC-Foundation
28 deterministic Claude AI skills for flawless ERPNext/Frappe v14-16 development. Agent Skills standard compliant.
SKILL.md
name: erpnext-syntax-customapp version: 1.0.0 description: "Deterministic syntax for building Frappe custom apps including app structure, pyproject.toml, modules, patches and fixtures" author: OpenAEC Foundation tags: [erpnext, frappe, custom-app, pyproject, patches, fixtures, modules] languages: [en] frappe_versions: [v14, v15, v16]
ERPNext Custom App Syntax Skill
Complete syntax for building Frappe custom apps in v14/v15, including build configuration, module organization, patches and fixtures.
When to Use This Skill
USE this skill when you:
- Create a new Frappe/ERPNext custom app
- Configure pyproject.toml or setup.py
- Organize modules within an app
- Write database migration patches
- Configure fixtures for data export/import
- Manage app dependencies
DO NOT USE for:
- DocType controllers (use erpnext-syntax-controllers)
- Client Scripts (use erpnext-syntax-clientscripts)
- Server Scripts (use erpnext-syntax-serverscripts)
- Hooks configuration (use erpnext-syntax-hooks)
App Structure Overview
v15 (pyproject.toml - Primary)
apps/my_custom_app/
├── pyproject.toml # Build configuration
├── README.md
├── my_custom_app/ # Main package
│ ├── __init__.py # MUST contain __version__!
│ ├── hooks.py # Frappe integration
│ ├── modules.txt # Module registration
│ ├── patches.txt # Migration scripts
│ ├── patches/ # Patch files
│ ├── my_custom_app/ # Default module
│ │ └── doctype/
│ ├── public/ # Client assets
│ └── templates/ # Jinja templates
└── .git/
See:
references/structure.mdfor complete directory structure.
Critical Files
init.py (REQUIRED)
# my_custom_app/__init__.py
__version__ = "0.0.1"
CRITICAL: Without __version__ the flit build fails!
pyproject.toml (v15)
[build-system]
requires = ["flit_core >=3.4,<4"]
build-backend = "flit_core.buildapi"
[project]
name = "my_custom_app"
authors = [
{ name = "Your Company", email = "dev@example.com" }
]
description = "Description of your app"
requires-python = ">=3.10"
readme = "README.md"
dynamic = ["version"]
dependencies = []
[tool.bench.frappe-dependencies]
frappe = ">=15.0.0,<16.0.0"
erpnext = ">=15.0.0,<16.0.0"
See:
references/pyproject-toml.mdfor all configuration options.
Modules
modules.txt
My Custom App
Integrations
Settings
Reports
Rules:
- One module per line
- Spaces in name → underscores in directory
- Every DocType MUST belong to a module
Module Directory
my_custom_app/
├── my_custom_app/ # "My Custom App" module
│ ├── __init__.py # REQUIRED
│ └── doctype/
├── integrations/ # "Integrations" module
│ ├── __init__.py # REQUIRED
│ └── doctype/
└── settings/ # "Settings" module
├── __init__.py # REQUIRED
└── doctype/
See:
references/modules.mdfor module organization.
Patches (Migration Scripts)
patches.txt with INI Sections
[pre_model_sync]
# Before schema sync - old fields still available
myapp.patches.v1_0.backup_old_data
[post_model_sync]
# After schema sync - new fields available
myapp.patches.v1_0.populate_new_fields
myapp.patches.v1_0.cleanup_data
Patch Implementation
# myapp/patches/v1_0/populate_new_fields.py
import frappe
def execute():
"""Populate new fields with default values."""
batch_size = 1000
offset = 0
while True:
records = frappe.get_all(
"MyDocType",
filters={"new_field": ["is", "not set"]},
fields=["name"],
limit_page_length=batch_size,
limit_start=offset
)
if not records:
break
for record in records:
frappe.db.set_value(
"MyDocType",
record.name,
"new_field",
"default_value",
update_modified=False
)
frappe.db.commit()
offset += batch_size
When Pre vs Post Model Sync?
| Situation | Section |
|---|---|
| Migrate data from old field | [pre_model_sync] |
| Populate new fields | [post_model_sync] |
| Data cleanup | [post_model_sync] |
See:
references/patches.mdfor complete patch documentation.
Fixtures
hooks.py Configuration
fixtures = [
# All records
"Category",
# With filter
{
"dt": "Custom Field",
"filters": [["module", "=", "My Custom App"]]
},
# Multiple filters
{
"dt": "Property Setter",
"filters": [
["module", "=", "My Custom App"],
["doc_type", "in", ["Sales Invoice", "Sales Order"]]
]
}
]
Exporting
bench --site mysite export-fixtures --app my_custom_app
Common Fixture DocTypes
| DocType | Usage |
|---|---|
Custom Field | Custom fields on existing DocTypes |
Property Setter | Modify field properties |
Role | Custom roles |
Workflow | Workflow definitions |
See:
references/fixtures.mdfor fixture configuration.
Minimal hooks.py
app_name = "my_custom_app"
app_title = "My Custom App"
app_publisher = "Your Company"
app_description = "Description"
app_email = "dev@example.com"
app_license = "MIT"
required_apps = ["frappe"] # Or ["frappe", "erpnext"]
fixtures = [
{"dt": "Custom Field", "filters": [["module", "=", "My Custom App"]]}
]
Creating and Installing App
# Create new app
bench new-app my_custom_app
# Install on site
bench --site mysite install-app my_custom_app
# Migrate (patches + fixtures)
bench --site mysite migrate
# Build assets
bench build --app my_custom_app
Version Differences
| Aspect | v14 | v15 |
|---|---|---|
| Build config | setup.py | pyproject.toml |
| Dependencies | requirements.txt | In pyproject.toml |
| Build backend | setuptools | flit_core |
| Python minimum | >=3.10 | >=3.10 |
| INI patches | ✅ | ✅ |
Critical Rules
✅ ALWAYS
- Define
__version__in__init__.py - Add
dynamic = ["version"]in pyproject.toml - Register modules in
modules.txt - Include
__init__.pyin EVERY directory - Put Frappe dependencies in
[tool.bench.frappe-dependencies] - Add error handling in patches
- Use batch processing for large datasets
❌ NEVER
- Put Frappe/ERPNext in project dependencies (not on PyPI)
- Create patches without error handling
- Include user/transactional data in fixtures
- Hardcode site-specific values
- Process large datasets without batching
Fixtures vs Patches
| What | Fixtures | Patches |
|---|---|---|
| Custom Fields | ✅ | ❌ |
| Property Setters | ✅ | ❌ |
| Roles/Workflows | ✅ | ❌ |
| Data transformation | ❌ | ✅ |
| Data cleanup | ❌ | ✅ |
| One-time migration | ❌ | ✅ |
Reference Files
| File | Contents |
|---|---|
references/structure.md | Complete directory structure |
references/pyproject-toml.md | Build configuration options |
references/modules.md | Module organization |
references/patches.md | Migration scripts |
references/fixtures.md | Data export/import |
references/examples.md | Complete app examples |
references/anti-patterns.md | Mistakes to avoid |
See Also
erpnext-syntax-hooks- For hooks.py configurationerpnext-syntax-controllers- For DocType controllerserpnext-impl-customapp- For implementation patterns
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon

