- Frappe Framework is a full-stack, metadata-driven web framework written in Python and JavaScript.
- It was originally built to power ERPNext but is now a standalone, open-source product under the MIT license.
- “Frappe” means “to whip” in French, reflecting the framework’s goal of whipping up apps quickly.
- The framework follows a Model-View-Controller (MVC) pattern where DocTypes act as models.
- Every DocType automatically gets a REST API, role-based permissions, and an auto-generated UI.
- Metadata is stored in JSON files inside each app, enabling version control and easy migration.
- Bench is the official CLI tool used to create, manage, and deploy Frappe sites and apps.
- Sites are multi-tenant; one bench can serve many isolated sites with separate databases.
- Frappe uses MariaDB or PostgreSQL as the primary database and Redis for caching and job queuing.
- Background jobs are handled by the RQ (Redis Queue) worker system, keeping the UI responsive.
- Real-time features are powered by Socket.IO, giving instant updates without page reloads.
- The frontend layer is built on a lightweight JavaScript library called “Frappe JS” with minimal dependencies.
- Server-side code is written in Python 3, and client-side code is written in ES6+ JavaScript.
- Frappe enforces a strict naming convention: snake_case for Python, camelCase for JavaScript, kebab-case for files.
- DocTypes can be single (singleton) or child (table) types, giving flexibility for complex data models.
- The framework ships with a powerful report builder that can create tabular, pivot, or chart views without code.
- Role-based permissions are granular: module, doctype, field, and even record level via user permissions.
- Frappe supports server scripts—Python code stored in the database—allowing admins to customize logic without deployments.
- Customization is upgrade-safe: hooks and fixtures let you inject logic without modifying core files.
- Fixtures export customizations (custom fields, server scripts, etc.) into your app so they travel with git.
- Always keep custom code inside your own app, never inside the frappe or erpnext folders to avoid upgrade conflicts.
- Use hooks.py to register event handlers, scheduled jobs, API endpoints, and custom fields cleanly.
- Write unit tests using the built-in test runner (bench run-tests) and aim for >80 % coverage on critical flows.
- Use the ORM instead of raw SQL; it handles parameterization, caching, and permission checks automatically.
- Always access the database via frappe.db.sql or the Document API to leverage automatic caching.
- Use frappe.call to invoke whitelisted functions from the client side; it enforces CSRF and permission checks.
- Whitelist every remote callable method with @frappe.whitelist() and validate permissions inside it.
- Never trust user input; validate data on the server even if the client already validates it.
- Use frm.add_fetch to pull field values from linked documents instead of writing custom queries.
- Prefer Document hooks (before_insert, before_submit, etc.) over bulk database triggers for clarity.
- Keep background jobs idempotent; workers may retry failed jobs, so ensure duplicate runs are safe.
- Use enqueue with a timeout and queue name to isolate long-running tasks from quick ones.
- Cache expensive computations with frappe.cache() (Redis) and set TTLs to avoid stale data.
- Use Frappe’s built-in logging (frappe.logger) instead of print statements; it rotates logs automatically.
- Follow the existing API pagination pattern—start and page_length—to keep responses small and fast.
- Use the built-in import/export tool for master data; it supports CSV/Excel and validates against fieldtypes.
- Always create patches (patches.txt) for schema or data migrations instead of running raw SQL manually.
- Use bench backup before major upgrades; backups are compressed and include both files and the database.
- Keep JavaScript side code modular; place page-specific scripts in public/js and require them via asset bundles.
- Use Vue.js or React inside Page or Desk extensions, but mount them cleanly to avoid DOM conflicts.
- Avoid jQuery spaghetti; Frappe’s modern UI components (controls, dialogs, datatables) are self-contained.
- Write clear commit messages with the app prefix: “feat: add barcode widget to Item” for readability.
- Use pre-commit hooks (black, flake8, prettier) to enforce consistent Python and JavaScript style.
- Document your DocTypes with descriptive labels and help text; it auto-generates tooltips for users.
- Use the built-in translation system: wrap user strings with __() to make your app multilingual.
- Keep hard-coded values in site_config.json or Single DocTypes so admins can change them without code.
- Monitor worker health with bench doctor and set up alerts for queue backlogs to prevent job pile-ups.
- Use Frappe Cloud or Docker images for production; they bake in security hardening and automatic backups.
- Contribute reusable features back to the community via GitHub; follow the pull-request template and add tests.
- Mastering these best practices ensures your Frappe apps stay fast, secure, upgrade-safe, and enjoyable to maintain.
Last updated 2 weeks ago
Was this helpful?