---
title: "Developers"
space: "Frappe Framework"
url: "https://www.prilk.com/docs/frappe-framework/developers"
updated: "2026-05-14"
---

## Developers

Building Frappe apps means writing Python + JavaScript + JSON. The platform handles the framework concerns (auth, DB, UI rendering, API); your app provides the domain logic.

### App structure

```
my_app/
├── my_app/
│   ├── hooks.py           # Wire up doc_events, fixtures, web routes
│   ├── install.py         # after_install, after_migrate
│   ├── modules.txt
│   ├── my_module/
│   │   ├── doctype/       # Your DocTypes (one folder each)
│   │   ├── custom/        # Hook handlers for OTHER apps' DocTypes
│   │   ├── report/
│   │   └── workspace/
│   └── public/            # JS, CSS, images
├── pyproject.toml
└── setup.py
```

### Key extension points (hooks.py)

| Hook | Use |
|---|---|
| `doc_events` | React to lifecycle events on any DocType (validate, on_submit, on_cancel) |
| `doctype_js` | Inject client-side scripts into specific DocType forms |
| `scheduler_events` | Run code on cron schedules (hourly, daily, custom cron) |
| `permission_query_conditions` | Filter list views by custom permission logic |
| `override_doctype_class` | Replace the controller for a DocType with your own |
| `fixtures` | Ship reference data (Roles, Workspaces, Custom Fields) with the app |

### DocType lifecycle

```python
class MyDoc(Document):
	def before_insert(self): ...    # Before first save
	def validate(self): ...          # Before any save
	def on_update(self): ...         # After save
	def before_submit(self): ...     # Before submit
	def on_submit(self): ...         # After submit
	def on_cancel(self): ...         # After cancel
	def on_trash(self): ...          # Before delete
```

### Where to dig deeper

- Frappe developer docs: [frappeframework.com/docs](https://frappeframework.com/docs)
- Frappe source: [github.com/frappe/frappe](https://github.com/frappe/frappe)
- Frappe School (paid courses): [frappe.school](https://frappe.school)
