
Frappe Agent Architect
- 27 installs
- 159 repo stars
- Updated July 8, 2026
- openaec-foundation/frappe_claude_skill_package
Helps with ai & agent building tasks.
About
frappe-agent-architect is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- frappe-agent-architect
- AI & Agent Building
- AI-coding skill
Frappe Agent Architect by the numbers
- 27 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #9,601 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/frappe_claude_skill_package --skill frappe-agent-architectAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 27 |
|---|---|
| repo stars | ★ 159 |
| Last updated | July 8, 2026 |
| Repository | openaec-foundation/frappe_claude_skill_package ↗ |
What it does
Helps with ai & agent building tasks.
Files
Multi-App Architecture Agent
Designs Frappe/ERPNext multi-app architectures by analyzing business requirements, deciding app boundaries, and generating implementation roadmaps.
Purpose: Make the right architecture decisions BEFORE writing code — prevent costly refactoring later.
When to Use This Agent
ARCHITECTURE TRIGGER
|
+-- New project with multiple modules
| "We need CRM, inventory, and custom billing"
| --> USE THIS AGENT
|
+-- Deciding whether to extend ERPNext or build custom
| "Should we customize Sales Invoice or create our own DocType?"
| --> USE THIS AGENT
|
+-- Multiple teams building on same Frappe instance
| "Team A does HR, Team B does manufacturing"
| --> USE THIS AGENT
|
+-- Existing monolith needs splitting
| "Our single custom app has 50 DocTypes"
| --> USE THIS AGENT
|
+-- Cross-app communication needed
| "App A needs to react when App B creates a document"
| --> USE THIS AGENTArchitecture Workflow
STEP 1: ANALYZE REQUIREMENTS
Business needs → DocTypes, workflows, integrations
STEP 2: DECIDE APP BOUNDARIES
Single app vs multiple apps decision framework
STEP 3: DESIGN CROSS-APP DEPENDENCIES
required_apps, shared DocTypes, hook contracts
STEP 4: DESIGN DATA MODEL
DocTypes, relationships, naming conventions
STEP 5: GENERATE IMPLEMENTATION ROADMAP
Build order, milestones, team assignmentsSee references/workflow.md for detailed steps.
Step 1: Requirement Analysis Matrix
Map each business requirement to Frappe mechanisms:
| Requirement Type | Frappe Mechanism | Example |
|---|---|---|
| Data storage | DocType | "Track customer contracts" |
| Business rules | Controller/Server Script | "Auto-calculate totals" |
| Approval flow | Workflow | "Manager must approve orders >10k" |
| Scheduled tasks | Scheduler/hooks.py | "Daily report email" |
| External sync | Integration/API | "Sync with Shopify" |
| Custom UI | Client Script/Page | "Dashboard for warehouse" |
| Reports | Script Report/Query Report | "Monthly sales by region" |
| Permissions | Role Permission | "Sales team sees own data only" |
| Print output | Print Format (Jinja) | "Custom invoice layout" |
| Portal access | Website/Portal | "Customer can view orders" |
Step 2: App Boundary Decision Framework
Single App: Use When
- Total DocTypes < 15
- Single team maintains the code
- All DocTypes share the same business domain
- No plans to distribute/sell components separately
- All DocTypes have tight data dependencies
Multiple Apps: Use When
- Total DocTypes > 15
- Multiple teams with separate release cycles
- Clear domain boundaries exist (HR vs Manufacturing vs CRM)
- Components may be installed independently
- Some modules are reusable across projects
- Different licensing needs per module
Decision Tree
HOW MANY DOCTYPES?
|
+-- < 15 total
| +-- Single domain? --> SINGLE APP
| +-- Multiple domains? --> Consider splitting
|
+-- 15-30 total
| +-- Tight coupling between all? --> SINGLE APP (with modules)
| +-- Clear domain boundaries? --> 2-3 APPS
|
+-- > 30 total
| --> ALWAYS SPLIT into multiple apps
| Group by domain/team/release cycleSee references/decision-tree.md for the complete decision framework.
Step 3: Cross-App Dependency Patterns
required_apps Declaration
ALWAYS declare dependencies explicitly in hooks.py:
# myapp/hooks.py
required_apps = ["frappe", "erpnext"] # NEVER omit frappeDependency Rules
- NEVER create circular dependencies (App A requires App B requires App A)
- ALWAYS declare ALL dependencies (direct and indirect)
- ALWAYS put shared/base apps first in required_apps
- NEVER depend on a specific version — use compatible APIs only
Dependency Diagram Pattern
frappe (base framework)
└── erpnext (ERP modules)
├── custom_manufacturing (extends Manufacturing)
└── custom_crm (extends CRM)
└── crm_analytics (extends custom_crm)
RULE: Dependencies flow DOWN only. Never up, never sideways.Cross-App Communication Patterns
| Pattern | Mechanism | Use When |
|---|---|---|
| Hook Events | doc_events in hooks.py | App B reacts to App A's documents |
| Shared DocType | Link fields to other app's DocTypes | Apps share reference data |
| API Call | frappe.call() to whitelisted method | Loose coupling between apps |
| Custom Fields | fixtures with Custom Field | Extend another app's DocType without modifying it |
| Override | extend_doctype_class (v16) or doc_events | Modify another app's behavior |
| Signals | frappe.publish_realtime() | Real-time notifications between apps |
Step 4: Data Model Design
DocType Relationship Types
| Relationship | Implementation | Example |
|---|---|---|
| One-to-Many | Child Table DocType | Invoice → Invoice Items |
| Many-to-One | Link field | Invoice → Customer |
| Many-to-Many | Link DocType (intermediary) | Student → Course (via Enrollment) |
| One-to-One | Link field + unique validation | Employee → User |
| Self-referential | Link to same DocType | Employee → Reports To (Employee) |
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| App name | lowercase, underscores | custom_manufacturing |
| DocType name | Title Case, spaces | Production Order |
| Field name | lowercase, underscores | production_date |
| Controller | snake_case filename | production_order.py |
| Module | Title Case | Manufacturing |
Data Model Rules
- NEVER duplicate data that exists in another DocType — use Link fields
- ALWAYS define autoname/naming_series for every DocType
- ALWAYS add created_by and modified_by awareness (built-in)
- NEVER use Data fields for references — use Link fields
- ALWAYS set mandatory fields for data integrity
- ALWAYS define permissions at DocType level
App Composition Patterns
Pattern 1: Base + Vertical
base_app (shared DocTypes, utilities)
├── vertical_retail (retail-specific DocTypes)
├── vertical_manufacturing (manufacturing-specific DocTypes)
└── vertical_services (services-specific DocTypes)Use when: Building industry-specific solutions on shared foundation.
Pattern 2: Core + Extensions
erpnext (standard ERP)
├── custom_fields_app (Custom Fields only, no DocTypes)
├── custom_reports_app (Script Reports and dashboards)
└── custom_workflows_app (Workflows and automation)Use when: Extending ERPNext without modifying core. Keeps upgrades clean.
Pattern 3: Shared Utilities
frappe_utils (shared library: PDF generation, email templates, etc.)
├── app_crm (uses frappe_utils)
├── app_hr (uses frappe_utils)
└── app_projects (uses frappe_utils)Use when: Multiple apps need the same utility functions.
Pattern 4: Marketplace App
standalone_app (zero dependencies beyond frappe)
├── Works on any Frappe site
├── Self-contained DocTypes and logic
└── Optional ERPNext integration via hooksUse when: Building for distribution/sale on Frappe marketplace.
ERPNext Extension Patterns
Custom Fields vs Custom DocTypes vs Override
| Approach | Use When | Pros | Cons |
|---|---|---|---|
| Custom Fields | Adding 1-10 fields to existing DocType | Survives upgrades, no code | Limited logic, UI clutter |
| Custom DocType | New business entity not in ERPNext | Full control, clean design | No built-in ERPNext logic |
| Controller Override | Modifying existing ERPNext behavior | Full Python access | Fragile on upgrades |
| Server Script | Simple validation/automation | No custom app needed | Sandbox limitations |
| Client Script | UI customization | No custom app needed | JS only, no server logic |
Extension Decision Rules
- ALWAYS prefer Custom Fields for < 10 additional fields
- ALWAYS prefer Server Script for simple validations
- NEVER override ERPNext controllers unless absolutely necessary
- ALWAYS use
extend_doctype_class(v16) overdoc_eventsfor overrides - NEVER modify ERPNext source files directly — ALWAYS use hooks or extensions
Common Architecture Mistakes
| Mistake | Why It Fails | Correct Approach |
|---|---|---|
| Circular app dependencies | Install/update breaks | Restructure dependency tree |
| One mega-app with 50+ DocTypes | Unmaintainable, slow tests | Split by domain into 3-5 apps |
| Duplicating ERPNext DocTypes | Data inconsistency, double maintenance | Extend with Custom Fields + hooks |
No required_apps declaration | Silent failures on fresh install | ALWAYS declare all dependencies |
| Shared database tables between apps | Tight coupling, migration conflicts | Use Link fields and API calls |
| Modifying ERPNext source files | Lost on every upgrade | Use hooks, Custom Fields, extensions |
| No module organization within app | Files scattered, hard to navigate | Group DocTypes into modules |
| Hardcoded site/company names | Breaks on multi-site/multi-company | Use frappe.defaults and filters |
Agent Output Format
ALWAYS produce architecture output in this format:
## Architecture Design
### Requirements Summary
| # | Requirement | DocTypes | Mechanism |
|---|------------|----------|-----------|
### App Structure
[Diagram showing apps and dependencies]
### App Inventory
| App | Module(s) | DocTypes | Dependencies |
|-----|-----------|----------|-------------|
### Data Model
| DocType | App | Key Fields | Relationships |
|---------|-----|------------|---------------|
### Cross-App Communication
| Source App | Target App | Mechanism | Trigger |
|-----------|-----------|-----------|---------|
### ERPNext Extensions
| Extension Type | Target DocType | Purpose |
|---------------|---------------|---------|
### Implementation Roadmap
| Phase | App(s) | Deliverables | Dependencies |
|-------|--------|-------------|-------------|
### Risk Assessment
| Risk | Mitigation |
|------|-----------|
### Referenced Skills
- `frappe-syntax-customapp`: App structure
- `frappe-syntax-hooks`: Hook configuration
- `frappe-syntax-doctypes`: DocType definition
- `frappe-impl-customapp`: App development workflowSee references/decision-tree.md for complete decision frameworks. See references/examples.md for architecture design examples.
Architecture Decision Trees
Decision Tree 1: Single App vs Multiple Apps
START: How many custom DocTypes are planned?
|
+-- 1-5 DocTypes
| +-- All in same business domain? --> SINGLE APP
| +-- Different domains? --> SINGLE APP with separate modules
|
+-- 6-15 DocTypes
| +-- Single team maintains all? --> SINGLE APP with modules
| +-- Multiple teams?
| +-- Clear domain boundaries? --> 2-3 APPS
| +-- Overlapping domains? --> SINGLE APP with modules
|
+-- 16-30 DocTypes
| +-- All tightly coupled? --> SINGLE APP (rare — verify coupling is real)
| +-- Can group into 2-4 domains? --> 2-4 APPS
| +-- Many independent components? --> 3-5 APPS
|
+-- 30+ DocTypes
| --> ALWAYS SPLIT
| Group by: domain > team > release cycle
| Target: 10-15 DocTypes per app maximumDecision Tree 2: Extend ERPNext vs Build Custom
START: Does ERPNext have a DocType for this entity?
|
+-- YES, exact match
| +-- Need < 10 extra fields? --> CUSTOM FIELDS (no custom app)
| +-- Need > 10 extra fields? --> CUSTOM FIELDS + consider child table
| +-- Need custom business logic?
| +-- Simple validation? --> SERVER SCRIPT (no custom app)
| +-- Complex logic with imports? --> CONTROLLER OVERRIDE (custom app)
| +-- Need UI changes?
| +-- Hide/show fields? --> CLIENT SCRIPT (no custom app)
| +-- New buttons/sections? --> CLIENT SCRIPT (no custom app)
| +-- Complete form redesign? --> Custom Page (custom app)
|
+-- YES, close match (similar but not exact)
| +-- Can adapt with Custom Fields + logic? --> EXTEND existing DocType
| +-- Fundamentally different data model? --> NEW CUSTOM DOCTYPE
|
+-- NO, nothing similar exists
| --> NEW CUSTOM DOCTYPE in custom app
| +-- Will it link to ERPNext DocTypes? --> Custom app with erpnext dependency
| +-- Standalone? --> Custom app with frappe-only dependencyDecision Tree 3: Controller Override Strategy
START: Need to modify ERPNext DocType behavior?
|
+-- Simple validation (< 20 lines)?
| --> SERVER SCRIPT (no custom app needed)
| Event: validate, before_save, on_submit, etc.
|
+-- Need Python imports or complex logic?
| +-- Running v16?
| | --> extend_doctype_class in hooks.py
| | ALWAYS call super() in every method
| |
| +-- Running v14 or v15?
| --> doc_events in hooks.py
| Point to function in custom app
|
+-- Need to change core method behavior?
| +-- Can you achieve it with before/after hooks?
| | --> Use doc_events (before_validate, after_insert, etc.)
| |
| +-- Must replace the method entirely?
| --> extend_doctype_class (v16) or monkey-patch (v14/v15)
| WARNING: Fragile, test on every ERPNext upgradeDecision Tree 4: Cross-App Communication
START: App A needs to know about App B's events?
|
+-- App A is UPSTREAM (base), App B is DOWNSTREAM
| --> App B hooks into App A's doc_events
| App B declares App A in required_apps
| App A knows NOTHING about App B
|
+-- App A and App B are PEERS (same level)
| +-- Can one depend on the other?
| | --> Make one upstream, one downstream (choose wisely)
| |
| +-- Neither should depend on the other?
| --> Extract shared concern into BASE APP
| Both A and B depend on base app
| Use hooks for event communication
|
+-- Real-time communication needed?
| --> frappe.publish_realtime() from source
| frappe.realtime.on() in client of target
| No app dependency required (event-based)
|
+-- Loose coupling preferred?
| --> API-based communication
| App B calls App A's whitelisted methods
| App B handles App A being absent gracefullyDecision Tree 5: Data Model — Child Table vs Link
START: Entity B "belongs to" Entity A?
|
+-- B has NO independent existence (always part of A)
| +-- B appears as rows in A's form? --> CHILD TABLE
| | Examples: Invoice Items, BOM Materials, Task Checklist
| |
| +-- B is a sub-record but not rows? --> Separate DocType with Link
| Examples: Multiple addresses for Customer
|
+-- B exists independently but relates to A
| +-- One B relates to one A? --> LINK field on B pointing to A
| +-- One B relates to many A's? --> LINK field on each A pointing to B
| +-- Many B's relate to many A's? --> INTERMEDIARY DocType
| Intermediary has Link to A and Link to BDecision Tree 6: Permission Architecture
START: Who should access this DocType?
|
+-- All logged-in users --> Role: All, perm_level 0
|
+-- Specific department/function
| +-- Existing ERPNext role fits? --> Use that role
| +-- Need custom role?
| --> Create Role, assign permissions per DocType
| --> Set perm_level for field-level access
|
+-- Users see only their own records?
| +-- By owner? --> "if_owner" permission rule
| +-- By company? --> User Permission on Company
| +-- By territory/department? --> User Permission on Territory/Department
| +-- Complex logic? --> Permission Query (Server Script)
|
+-- External users (portal/API)?
| +-- Portal pages --> Website User role + portal settings
| +-- API access --> API Key + Role for API user
| +-- Guest access --> allow_guest=True on whitelisted methodsDecision Tree 7: When to Create a Custom App
START: Do I need a custom Frappe app?
|
+-- Only adding fields to existing DocTypes?
| --> NO — use Custom Fields via Setup
|
+-- Only adding simple validation logic?
| --> NO — use Server Scripts
|
+-- Only adding UI behavior?
| --> NO — use Client Scripts
|
+-- Only adding a workflow?
| --> NO — use built-in Workflow Builder
|
+-- Need Python imports (requests, etc.)?
| --> YES — custom app required
|
+-- Need scheduled background tasks?
| --> YES — custom app required (hooks.py scheduler_events)
|
+-- Need new DocTypes?
| --> YES — custom app required
|
+-- Need to override ERPNext controller logic?
| --> YES — custom app required
|
+-- Need custom REST API endpoints?
| +-- Simple? --> Server Script (API type) — NO app needed
| +-- Complex with imports? --> YES — custom app requiredArchitecture Design Examples
Example 1: E-Commerce Extension for ERPNext
Input
"We have ERPNext running for accounting and inventory. We want to add a Shopify integration, custom product catalog with extra fields, and a customer portal for order tracking."
Architecture Design
Step 1 — Requirement Analysis:
| # | Requirement | DocTypes | Mechanism |
|---|---|---|---|
| 1 | Shopify product sync | Item (extend) | Scheduled job + API |
| 2 | Shopify order sync | Sales Order (extend) | Webhook + API |
| 3 | Extra product fields | Item (extend) | Custom Fields |
| 4 | Customer portal | Portal pages | Website templates |
| 5 | Order tracking | Sales Order (read) | Portal + permissions |
Step 2 — App Boundaries:
Decision: TWO apps.
shopify_connector: Integration logic (sync, webhooks, API mapping)customer_portal: Portal pages, custom views, frontend
Rationale: Integration and portal have different release cycles, different teams, and can be installed independently.
Step 3 — Dependencies:
frappe
└── erpnext
├── shopify_connector (requires: frappe, erpnext)
└── customer_portal (requires: frappe, erpnext)No dependency between shopify_connector and customer_portal — they are independent.
Step 4 — Data Model:
| DocType | App | Purpose | Key Fields |
|---|---|---|---|
| Shopify Settings | shopify_connector | API credentials | api_key, api_secret, shop_url |
| Shopify Log | shopify_connector | Sync audit trail | sync_type, status, error_message |
| Custom Fields on Item | shopify_connector | Shopify product ID | custom_shopify_id, custom_shopify_url |
| Custom Fields on Sales Order | shopify_connector | Shopify order ID | custom_shopify_order_id |
| Portal Settings (extend) | customer_portal | Portal configuration | Custom Fields for branding |
Step 5 — Roadmap:
| Phase | App | Deliverables |
|---|---|---|
| 1 | shopify_connector | App scaffold, Settings DocType, Item sync |
| 2 | shopify_connector | Order sync, webhook handler |
| 3 | customer_portal | Portal templates, order list view |
| 4 | Both | Testing, deployment |
---
Example 2: Manufacturing Extension
Input
"We use ERPNext Manufacturing. We need to add quality inspection checklists per work order, a machine maintenance scheduler, and production analytics dashboards."
Architecture Design
Step 1 — Requirement Analysis:
| # | Requirement | DocTypes | Mechanism |
|---|---|---|---|
| 1 | Quality checklists | Quality Checklist (new), Quality Check Item (child) | Controller |
| 2 | Link to work order | Work Order (extend) | Custom Field + hook |
| 3 | Machine maintenance | Machine (new), Maintenance Schedule (new) | Controller + scheduler |
| 4 | Production analytics | Script Reports | Query Report |
Step 2 — App Boundaries:
Decision: SINGLE APP (custom_manufacturing).
Rationale: All requirements are in the same domain (manufacturing), maintained by one team, < 15 DocTypes total, tight data coupling between quality and maintenance.
Step 3 — Dependencies:
frappe
└── erpnext
└── custom_manufacturing (requires: frappe, erpnext)Step 4 — Data Model:
| DocType | Module | Purpose | Links To |
|---|---|---|---|
| Quality Checklist | Quality | Inspection template | Work Order (Link) |
| Quality Check Item | Quality | Child table of Checklist | — (child) |
| Machine | Maintenance | Equipment registry | — |
| Maintenance Schedule | Maintenance | Planned maintenance | Machine (Link) |
| Maintenance Log | Maintenance | Completed maintenance | Machine (Link), Maintenance Schedule (Link) |
Cross-app hooks:
# hooks.py
doc_events = {
"Work Order": {
"on_submit": "custom_manufacturing.quality.handlers.create_quality_checklist"
}
}
scheduler_events = {
"daily": [
"custom_manufacturing.maintenance.tasks.check_upcoming_maintenance"
]
}Step 5 — Roadmap:
| Phase | Module | Deliverables |
|---|---|---|
| 1 | Core | App scaffold, Machine DocType |
| 2 | Quality | Quality Checklist + Work Order hook |
| 3 | Maintenance | Maintenance Schedule + Scheduler |
| 4 | Analytics | Script Reports + dashboard |
---
Example 3: Multi-Company HR Extension
Input
"We have 3 companies in ERPNext. Each company has different HR policies. We need custom leave types per company, a recruitment pipeline, and employee self-service portal."
Architecture Design
Step 1 — Requirement Analysis:
| # | Requirement | DocTypes | Mechanism |
|---|---|---|---|
| 1 | Company-specific leave types | Leave Type (extend) | Custom Fields + Permission |
| 2 | Recruitment pipeline | Job Opening (extend), Interview (new), Candidate (new) | Controller + Workflow |
| 3 | Employee self-service | Portal pages | Website templates + permissions |
| 4 | Multi-company isolation | User Permissions | Company-based filtering |
Step 2 — App Boundaries:
Decision: TWO apps.
hr_extensions: Recruitment pipeline, custom leave logic (backend-heavy)hr_portal: Employee self-service portal (frontend-heavy)
Rationale: Portal and backend extensions have very different development patterns. Portal can be installed independently for companies that do not need custom recruitment.
Step 3 — Dependencies:
frappe
└── erpnext (includes hrms module)
├── hr_extensions (requires: frappe, erpnext)
└── hr_portal (requires: frappe, erpnext, hr_extensions)Note: hr_portal depends on hr_extensions because it displays recruitment data.
Step 4 — Data Model:
| DocType | App | Purpose |
|---|---|---|
| Candidate | hr_extensions | Applicant tracking |
| Interview | hr_extensions | Interview scheduling |
| Interview Feedback | hr_extensions | Child table of Interview |
| Custom Fields on Leave Type | hr_extensions | company-specific settings |
| Custom Fields on Job Opening | hr_extensions | Pipeline stage tracking |
Multi-company design:
- EVERY custom DocType has a
companyLink field - User Permissions on Company enforce data isolation
- Leave policies filtered by company in all queries
Step 5 — Roadmap:
| Phase | App | Deliverables |
|---|---|---|
| 1 | hr_extensions | Candidate + Interview DocTypes |
| 2 | hr_extensions | Workflow for recruitment pipeline |
| 3 | hr_extensions | Custom leave type per company |
| 4 | hr_portal | Employee self-service pages |
| 5 | Both | Multi-company testing, deployment |
---
Anti-Pattern Examples
Anti-Pattern 1: The Mega-App
BAD: single_app/ (45 DocTypes across HR, CRM, Manufacturing, Accounting)
- Impossible to test in isolation
- One bug blocks all releases
- New developers overwhelmed
GOOD: Split into 4 focused apps
- hr_custom/ (12 DocTypes)
- crm_custom/ (10 DocTypes)
- manufacturing_custom/ (13 DocTypes)
- accounting_custom/ (10 DocTypes)Anti-Pattern 2: Circular Dependencies
BAD:
app_sales requires app_inventory
app_inventory requires app_sales
(Cannot install either without the other)
GOOD:
app_base (shared DocTypes: Item, Customer)
app_sales requires app_base
app_inventory requires app_base
(Each can be installed independently after base)Anti-Pattern 3: Duplicating ERPNext
BAD: Creating "Custom Invoice" DocType that duplicates Sales Invoice
- Double data entry or complex sync
- Loses all ERPNext reporting
- Must maintain accounting logic yourself
GOOD: Extend Sales Invoice with Custom Fields + hooks
- Use Custom Fields for extra data
- Use hooks for custom validation
- All ERPNext reports still workAnti-Pattern 4: No Module Organization
BAD:
myapp/myapp/doctype/
├── customer_complaint/
├── machine/
├── quality_report/
├── maintenance_log/
├── shift_schedule/
└── (30 more DocTypes in flat structure)
GOOD:
myapp/myapp/
├── quality/doctype/
│ ├── customer_complaint/
│ └── quality_report/
├── maintenance/doctype/
│ ├── machine/
│ └── maintenance_log/
└── operations/doctype/
└── shift_schedule/Architecture Workflow — Detailed Steps
Step 1: Analyze Requirements
Input Gathering
ALWAYS collect this information before designing:
1. Business domain: What industry/function is this for? 2. User roles: Who will use the system? How many concurrent users? 3. Core processes: What are the 3-5 most critical business workflows? 4. Data entities: What "things" does the business track? 5. Integrations: What external systems must connect? 6. Existing setup: Is ERPNext already installed? Which modules are in use? 7. Team structure: Who will develop and maintain each component? 8. Timeline: What must be delivered first?
Requirement-to-DocType Mapping
For each business requirement:
1. Identify the data entity (becomes a DocType) 2. Identify relationships to other entities (becomes Link fields) 3. Identify child data (becomes Child Table DocTypes) 4. Identify business rules (becomes Controller/Server Script logic) 5. Identify user interactions (becomes Client Scripts, buttons, workflows)
ERPNext Coverage Check
Before creating ANY custom DocType, check if ERPNext already has it:
| Business Need | ERPNext DocType | Module |
|---|---|---|
| Customers | Customer | Selling |
| Suppliers | Supplier | Buying |
| Products | Item | Stock |
| Sales orders | Sales Order | Selling |
| Purchase orders | Purchase Order | Buying |
| Invoices | Sales Invoice / Purchase Invoice | Accounts |
| Inventory | Stock Entry, Stock Ledger | Stock |
| Employees | Employee | HR |
| Projects | Project, Task | Projects |
| Support tickets | Issue | Support |
| CRM leads | Lead, Opportunity | CRM |
| Manufacturing | BOM, Work Order | Manufacturing |
NEVER recreate what ERPNext already provides. ALWAYS extend with Custom Fields or hooks.
Step 2: Decide App Boundaries
Domain Boundary Analysis
Group related DocTypes by asking:
1. Do these DocTypes share the same user roles? 2. Do these DocTypes reference each other frequently? 3. Would these DocTypes be useful independently? 4. Does one team own all of these DocTypes? 5. Do these DocTypes have the same release cycle?
If YES to all 5 → same app. If NO to 2+ → consider separate apps.
Dependency Direction Rule
Draw a dependency diagram BEFORE finalizing app boundaries:
RULE: All arrows must point in ONE direction (toward base/shared)
VALID:
app_reporting --> app_core --> frappe
INVALID (circular):
app_a --> app_b --> app_aIf you find circular dependencies during design, restructure:
- Extract shared DocTypes into a base app
- Use hooks/events instead of direct imports for cross-app communication
Module Organization Within Apps
Even within a single app, organize DocTypes into modules:
myapp/
├── myapp/
│ ├── core_module/ # Shared DocTypes (Settings, Configuration)
│ │ └── doctype/
│ ├── sales_module/ # Sales-related DocTypes
│ │ └── doctype/
│ ├── inventory_module/ # Inventory-related DocTypes
│ │ └── doctype/
│ └── hooks.pyStep 3: Design Cross-App Dependencies
Hook Contract Design
When App B needs to react to App A's documents:
# App B's hooks.py — subscribing to App A's events
doc_events = {
"Sales Invoice": { # App A's DocType
"on_submit": "app_b.handlers.on_invoice_submit",
"on_cancel": "app_b.handlers.on_invoice_cancel"
}
}Rules for hook contracts:
- App B depends on App A (add to
required_apps) - App A does NOT know about App B (no reverse dependency)
- Hook functions MUST handle missing data gracefully
- Hook functions MUST NOT modify the source document unless explicitly designed to
Shared DocType Strategy
When multiple apps need the same reference data:
| Strategy | Implementation | Use When |
|---|---|---|
| Owner app | One app owns the DocType, others Link to it | Clear ownership |
| Base app | Shared DocTypes in a base/utilities app | Multiple consumers, no clear owner |
| ERPNext native | Use existing ERPNext DocType | ERPNext already has it |
Custom Fields for Extension
When extending another app's DocType without modifying it:
# In your app's fixtures or setup
custom_fields = {
"Sales Invoice": [
{
"fieldname": "custom_approval_status",
"fieldtype": "Select",
"options": "Pending\nApproved\nRejected",
"insert_after": "status"
}
]
}ALWAYS prefix custom fields with custom_ to avoid conflicts.
Step 4: Design Data Model
DocType Design Checklist
For each DocType in the architecture:
1. Name: Title Case with spaces, descriptive 2. Module: Which module does it belong to? 3. Naming: autoname rule (hash, series, field-based, or UUID for v16) 4. Fields: List all fields with types 5. Child Tables: Identify repeating row data 6. Links: All references to other DocTypes 7. Permissions: Which roles can CRUD? 8. Workflow: Does it need approval states? 9. Is Submittable: Does it need submit/cancel lifecycle?
Relationship Design Rules
- One-to-Many: ALWAYS use Child Table (parent DocType has the table)
- Many-to-One: ALWAYS use Link field (child points to parent)
- Many-to-Many: Create an intermediary DocType with two Link fields
- Self-referential: Link field pointing to same DocType (add validation to prevent cycles)
Field Type Selection Guide
| Data Type | Frappe Fieldtype | Notes |
|---|---|---|
| Short text (< 140 chars) | Data | Single line |
| Long text | Text | Multi-line, no formatting |
| Rich text | Text Editor | HTML content |
| Number (integer) | Int | Whole numbers only |
| Number (decimal) | Float or Currency | Currency for money |
| Date | Date | Date only |
| Date + time | Datetime | Date and time |
| Yes/No | Check | Boolean checkbox |
| Dropdown | Select | Predefined options |
| Reference to DocType | Link | Foreign key |
| File | Attach | Single file |
| Multiple files | Attach Image or Table | Use child table for multiple |
Step 5: Generate Implementation Roadmap
Build Order Rules
1. ALWAYS build base/shared apps first 2. ALWAYS build DocTypes before their dependents 3. ALWAYS build settings/configuration DocTypes before transaction DocTypes 4. ALWAYS build and test one app fully before starting the next 5. NEVER build frontend (Client Scripts, pages) before backend is stable
Phase Template
Phase 1: Foundation (Week 1)
- Create app scaffolding: bench new-app {name}
- Define all DocTypes (JSON only, no logic yet)
- Set up permissions for all roles
- Create fixtures for master data
Phase 2: Core Logic (Week 2-3)
- Implement controllers for transaction DocTypes
- Add Server Scripts for validations
- Build workflows for approval processes
- Implement hooks for cross-app events
Phase 3: User Experience (Week 3-4)
- Add Client Scripts for form behavior
- Build custom pages/dashboards
- Create print formats
- Build Script Reports
Phase 4: Integration (Week 4-5)
- External system connectors
- Scheduled sync jobs
- API endpoints for third parties
Phase 5: Testing and Deployment (Week 5-6)
- Unit tests for all controllers
- Integration tests for cross-app workflows
- Performance testing
- Production deploymentTeam Assignment Rules
- One app per team (clear ownership)
- Base/shared apps: most experienced team
- Integration layer: dedicated person or team
- NEVER have two teams modifying the same app simultaneously