Mastering Frappe Framework – Part 5: Frontend Development in Frappe

Why Frontend Development in Frappe is Different

Unlike frameworks where you build the UI from scratch, Frappe gives you two types of frontends:

  1. Desk UI (Internal) – Auto-generated interface for managing DocTypes, used by internal users.
  2. Website UI (External) – Public-facing website and pages, useful for customer portals, landing pages, etc.

With Frappe, you can:

  • Customize forms and views inside the Desk
  • Build custom Pages and Web Templates
  • Use Client Scripts for interactivity
  • Pull and push data via REST APIs

1. Desk UI Customization with Client Scripts

Client Scripts are JavaScript snippets attached to a DocType that run in the browser.

Example: Auto-fill due date with today’s date

frappe.ui.form.on("ToDo Plus", {
    refresh: function(frm) {
        if (!frm.doc.due_date) {
            frm.set_value("due_date", frappe.datetime.get_today());
        }
    }
});


Example: Color status field based on value

frappe.ui.form.on("ToDo Plus", {
    status: function(frm) {
        let status_colors = {
            "Pending": "orange",
            "In Progress": "blue",
            "Completed": "green",
            "Overdue": "red"
        };
        frm.fields_dict.status.$wrapper.css("color", status_colors[frm.doc.status] || "black");
    }
});

2. Custom Pages in Desk

Custom Pages are useful when you want a dashboard or interactive view beyond the standard list view.

Create a Page

bench make-page todo_dashboard --module "ToDo Plus"


Edit JS file (todo_plus/page/todo_dashboard/todo_dashboard.js):

frappe.pages['todo_dashboard'].on_page_load = function(wrapper) {
    let page = frappe.ui.make_app_page({
        parent: wrapper,
        title: 'ToDo Dashboard',
        single_column: true
    });

    frappe.call({
        method: "todo_plus.api.get_overdue_tasks",
        callback: function(r) {
            let html = "<h3>Overdue Tasks</h3><ul>";
            r.message.forEach(task => {
                html += `<li>${task.title} - Due: ${task.due_date}</li>`;
            });
            html += "</ul>";
            $(wrapper).find('.layout-main').html(html);
        }
    });
};

This creates a custom dashboard showing overdue tasks.


3. Website Pages & Jinja Templates

Frappe includes a website generator. You can create Web Pages from the Desk or by code.

Example: A public page for tasks

  1. Go to Desk → Web Page → New
  2. Title: Tasks
  3. Content:
{% set tasks = frappe.get_all("ToDo Plus", fields=["title", "due_date", "status"]) %}
<ul>
{% for task in tasks %}
  <li>{{ task.title }} - {{ task.status }} - Due: {{ task.due_date }}</li>
{% endfor %}
</ul>

When you visit /tasks, you’ll see your task list.


4. Using REST API in Frontend

You can also use JavaScript to fetch data dynamically.

Example:

fetch('/api/resource/ToDo Plus?fields=["title","due_date"]')
  .then(res => res.json())
  .then(data => {
      console.log(data.data);
  });

This allows for live updates without refreshing the page.


5. Styling with Frappe Themes

Frappe uses Bootstrap, so you can:

  • Use Bootstrap classes in HTML
  • Add custom CSS in /public/css/ folder
  • Override templates for advanced customization

Key Learnings from Part 5

  • How to customize Desk UI with Client Scripts
  • How to build custom Pages for dashboards or tools
  • How to use Jinja templates for website pages
  • How to call REST APIs from frontend JavaScript
  • How to style your app with Bootstrap and custom CSS

What’s Next?

In Part 6, we’ll cover User Permissions & Roles:

  • Role-based access control
  • Complex permission rules
  • Document-level permissions
  • Best practices for secure apps

Leave a Reply