Skip links
Table of Contents
    blog_placeholder

    Building a Custom Frappe App From Scratch: An Overview

    Building a custom Frappe app means creating a self-contained module on top of the Frappe framework, then installing it on a site alongside ERPNext or on its own. You define your data as DocTypes, add Python and JavaScript for behavior, and let the framework generate forms, lists, permissions and APIs around them.
    In short: Building a custom Frappe app starts with the bench CLI, which scaffolds an app. You model data as DocTypes, add Python controllers and client scripts for logic, declare integrations in hooks.py, and install the app on a site. Frappe then generates the forms, list views, role permissions and REST endpoints for each DocType.
    If you are a CTO or dev lead deciding whether Frappe is a sensible base for an internal business application, this overview covers what the work actually involves, where the framework saves effort, and where it does not.

    What "from scratch" means in Frappe

    Frappe is a full-stack, metadata-driven web framework written in Python and JavaScript. ERPNext is one application built on it. A custom Frappe app is another application on the same foundation, and it can run beside ERPNext on one site, depend on it, or stand alone.

    “From scratch” therefore rarely means writing a login system, a database layer or an admin interface. Those come with the framework. What you write from scratch is the part specific to your business: the records you track, the rules between them, and the screens and integrations your team needs.

    That distinction matters for scoping. A custom app is usually a thinner piece of work than the equivalent project on a general-purpose web stack, but it still needs the same discipline around design, testing and release.

    The building blocks you will actually use

    Most of a custom Frappe app is assembled from a small set of concepts.
    Bench

    the command-line tool that manages Frappe installations. It creates the app skeleton (bench new-app), creates sites, installs apps on them and runs migrations.

    App

    a Python package with a standard layout, containing modules, DocTypes, pages, reports and configuration. One bench can hold several apps, and one site can install several of them.

    DocType

    the core unit. A DocType describes a record type through fields, validations and permissions. Frappe uses that description to create the database table, the form, the list view and the REST API.

    Controller

    a Python class tied to a DocType, where server-side logic lives, such as validation before save or actions after submit.

    Client scripts

    JavaScript that adjusts how a form behaves in the browser, for example showing a field only when another has a certain value.

    hooks.py

    the app's wiring file. Here you register event handlers on other apps' DocTypes, scheduled jobs, fixtures and assets without editing the other app's code.

    Roles and permissions

    access rules defined per DocType and role, with optional record-level restrictions.

    Because so much is declared as metadata rather than coded, an early version of a simple app can come together quickly. The effort moves from plumbing to getting the data model right.

    A typical build, in order

    There is no single timeline for this work, because scope drives everything. The sequence, though, is fairly consistent.
    Model the domain on paper first

    List the records, who creates and approves them, and how they relate. Decisions here are the most expensive to reverse later.

    Scaffold the app with bench

    Create the app and a development site, and keep the app in version control from the first commit.

    Create DocTypes for the core records

    Start with the few that carry the business process, and use child tables and link fields for relationships.

    Add controller logic

    Put validations and state changes in Python on the server, where they cannot be bypassed from the browser.

    Layer on client scripts and custom pages

    only where the generated form falls short.

    Define roles and permissions

    early, not at the end. Retrofitting access rules across many DocTypes is tedious.

    Write patches for data changes

    Frappe runs patches during migration, so schema or data updates ship with the app instead of being done by hand per environment.

    Test on a copy of real data, then deploy

    with the same bench workflow on staging and production.

    If your team already writes Python, most of this will feel familiar. The unfamiliar part is usually the framework’s conventions, which take some time to absorb before the speed benefit shows up.

    If you are weighing whether your team should take this on or bring in specialists, our Frappe framework development service page describes how we approach that kind of work.

    Where custom Frappe apps go wrong

    Frappe makes it easy to build, which also makes it easy to build badly. These are the patterns we would watch for.

    Editing ERPNext core instead of extending it

    Changing standard code works until the next upgrade, then becomes a merge problem. Hooks, custom fields and a separate app exist so core stays untouched.

    Treating DocTypes like spreadsheet columns

    Adding fields freely is quick, but a model with no clear ownership of data becomes hard to report on and hard to permission.

    Skipping patches and fixtures

    If a change exists only on one developer's site, it will not be on production. Anything that must travel with the app should be captured in code.

    Customizing what configuration already covers

    ERPNext handles a lot through settings, custom fields and workflows. Writing code for something configuration could do adds maintenance for no gain.

    Ignoring upgrade cost

    Frappe and ERPNext release major versions, and a custom app must keep pace. This is an ongoing responsibility, not a one-time build.

    Build a custom app or configure ERPNext?

    Not every requirement justifies a new app. A rough test:
    SituationUsually better fit
    A standard process with different fields or approvalsConfigure ERPNext: custom fields, workflows, print formats
    A standard module needs a few extra rulesA small custom app using hooks, leaving core untouched
    A process that does not exist in ERPNext at allA custom app with its own DocTypes
    A product you plan to offer to many customersA custom app, designed for installation and upgrades from day one

    The honest answer is often a mix: ERPNext for what it already does well, and a custom app for the part that makes your business different. If you want to see how that split works in practice, our custom Frappe apps service page lays out where we typically draw the line.

    What to evaluate before committing

    Before choosing Frappe for a custom application, a technical lead should be able to answer a few questions.

    Does the application naturally revolve around records, approvals and reports? Frappe fits that shape well. It is a less natural fit for highly bespoke, consumer-facing interfaces, though Frappe also supports separate front ends through its API.

    Who will maintain it after launch, and do they know the framework?

    How does it need to connect to ERPNext, accounting, e-commerce or other systems?

    What is the plan for major-version upgrades?

    If you would like a second pair of eyes on those answers, we are happy to talk them through, with no commitment to a build.

    Frequently Asked Questions

    Yes. Frappe is a standalone framework, and a custom app can be installed on a site without ERPNext. You then lose ERPNext's ready-made accounting, stock and HR modules, so this suits applications that do not need them.
    Working knowledge of Python and JavaScript, comfort with a relational database, and familiarity with Frappe's conventions: DocTypes, controllers, hooks and bench. Understanding the business process matters as much as the code.
    It can be, if it extends ERPNext through hooks and custom fields rather than editing core files. It still needs testing against each new major version, so budget for upgrade work.
    Customization changes how existing ERPNext features behave, usually through configuration and small scripts. A custom app is a separate codebase that can add new record types and workflows, and it can be versioned and deployed independently.

    A team with Python experience can learn it, and many do. The tradeoff is time to proficiency and the risk of early design mistakes. Some teams hire for the initial design and then maintain the app themselves. If that sounds useful, you can look at how to hire Frappe developers through us.

    Next step

    Frappe rewards a clear data model and punishes shortcuts around core code. If you are evaluating it for a custom application, the most useful first step is usually a short technical conversation about the process you want to support and what already exists in ERPNext.

    Talk to our Frappe development team. Tell us what you are planning to build, and we will give you an honest view on whether Frappe is the right base and how we would approach it.

    Pratik Malvi
    As co-founder, Pratik brings 10+ years of UI/UX experience, creating visually stunning and intuitive digital experiences. Skilled in Figma, WordPress, jQuery, Java, Photoshop, Illustrator, and After Effects, he specializes in building beautiful, functional websites and apps that drive engagement and business growth.
    pratik-malvi
    This can be a new journey !

    Related Posts

    Have a Project in Mind?

    This can be a new journey !

    leaf