Tutorials/Framework Architecture & Core Concepts

Framework Architecture & Core Concepts

Frappe Framework Architecture — Core Concepts

Frappe Framework Architecture
Frappe Framework Architecture

Site

A Site is a single Frappe tenant (e.g., yoursite.erpnext.com). Each site has its own MariaDB database, file system, and config. Multiple sites run on one server with full data isolation.

Apps

An App is a Python package on a bench — e.g., frappe, erpnext, custom_app. Apps provide DocTypes, APIs, and hooks.

Modules

A Module groups related DocTypes within an app — e.g., Accounts, HR, Manufacturing, CRM.

DocType

A DocType is the fundamental building block — defines a data entity's fields, permissions, and behaviour. Every form in Frappe is a DocType. Stored as JSON in the app.

DocField

A DocField defines one field within a DocType: Data, Int, Date, Link, Table, Select, Attach, etc.

Virtual DocType

A Virtual DocType (isvirtual=1) has no MariaDB table — data fetched from external source by overriding getlist() and get_doc().

Virtual DocField

A Virtual DocField has no DB column — value computed at runtime, ideal for derived/calculated fields.

Metadata-Driven Framework — DocType = Class, Document = Object

The Analogy

What Metadata-Driven Means

  • Schema stored as data in MariaDB — tabDocType and tabDocField hold the entire schema
  • Forms auto-generated from DocType fields — no HTML to write
  • Permissions, Workflows, Print Formats configured via UI — stored as DocType records
  • Add a field → form updates immediately, MariaDB column added automatically
  • For : IT team adds custom fields without code or deployment

DocType Definition — JSON, Python Controller & Lifecycle

JSON Definition

Every DocType is a JSON file in the app codebase — version-controlled in git.

DocType JSON Definition
DocType JSON Definition
  • autoname — naming rule
  • engine: "InnoDB" — MariaDB storage engine
  • fields — array of DocField definitions (fieldname, fieldtype, label, mandatory)
  • permissions — role-based access control baked in
  • states — workflow states (Draft, Submitted, Cancelled)

Python Controller

The Python controller inherits from Document and overrides lifecycle methods to add business logic.

Python Controller
Python Controller

Lifecycle Events

Low-Code + High-Code — Frappe's Sweet Spot

Frappe uniquely combines a low-code platform for business users with a full-code framework for developers — both coexist without conflict, safe across upgrades.

High-code Controller Example
High-code Controller Example

Low-Code

  • DocType builder via UI — drag-drop fields, auto-generated forms
  • Visual Workflow builder, Automation Rules, Server Scripts in browser
  • Custom Fields on any DocType — no code, no deployment
  • Print Format designer, Dashboard and Charts builder

High-Code

  • Full Python controller classes with lifecycle hooks
  • @frappe.whitelist() — any Python function as REST API
  • Client Scripts — JS per DocType for form events
  • Full MariaDB access via frappe.db.* | Background jobs via frappe.enqueue()

Customisation Without Touching Core — hooks.py

hooks.py integrates your custom app with Frappe without modifying a single line of ERPNext source.

hooks.py integration diagram
hooks.py — integrating a custom app without touching ERPNext core

overridedoctypeclass

override_doctype_class = {

"Custom DocType": "custom_app.overrides.custom_doctype.CustomStudentGroup",

"Employee": "custom_app.overrides.employee.CustomEmployee",

}

doc_events

doc_events = {

"Sales Invoice": {"on_submit": "my_app.custom_logic.on_invoice_submit"},

"record": {"validate": "custom_app.validators.validate_student"}

}

Other Key Hooks

  • Zero ERPNext source changes — ships as separate custom_app app
  • Upgrade-safe — bench update never breaks customisations
  • Git-trackable — entire customisation is a Python package

Need help with your workflow setup?

If you're stuck or want help applying these guides to your setup, our team can assist with configuration, customization, and workflow implementation.