Portal Pages
Frappe Framework provides both the Desk (a single-page application for administrators) and server-rendered Portal Pages for website visitors. Portal Pages can be publicly accessible or restricted to authenticated users.
Portal Pages are ideal for creating websites, customer portals, documentation, help centers, and other user-facing pages outside the Desk interface.
Adding Portal Pages
Every Frappe application contains a www directory. Files inside this directory are automatically mapped to website URLs.
For example, the following structure:
custom_app/www
├── custom_page.html
└── custom_page.py
creates the following route:
/custom_page
Each HTML, Markdown, or Python file inside the www folder automatically maps to a website route.
Creating Subpages
To organize related pages, convert the page into a directory and place an index.html file inside it.
custom_app/www
└── custom_page
├── index.html
├── index.py
├── subpage.html
└── subpage.py
This structure creates the following routes:
/custom_page/custom_page/subpage
Using folders helps organize larger websites with multiple related pages.
Using Markdown Pages
For simple static content such as documentation, you can create .md files instead of HTML pages.
Markdown pages are automatically rendered as portal pages and are easier to maintain for documentation-heavy websites.
Overriding Standard Pages
Frappe allows custom applications to override built-in portal pages.
For example, creating an about.html file inside your application’s www directory overrides the default /about page provided by Frappe.
Custom application pages take precedence over standard Frappe pages with the same route.
Using Jinja Templates
Portal Pages support Jinja templating, allowing you to display dynamic content.
By default, portal pages extend the following templates:
frappe/templates/web.htmlfrappe/templates/base.html
You can also omit the extends and block statements when using the default base template for simpler pages.
Jinja templates let you combine HTML with dynamic data, conditional rendering, and reusable layouts.
Using a Python Controller
Every portal page can have an optional Python controller with the same filename as the page.
custom_app/www
├── custom_page.html
└── custom_page.py
The controller should define a get_context() function that adds data to the page context before rendering.
This allows templates to access dynamic values retrieved from the database or generated programmatically.
The values returned from get_context() are directly available inside the Jinja template.
Standard Context Keys
Frappe provides several predefined context properties that control how a portal page behaves.
| Context Key | Purpose |
|---|---|
add_breadcrumbs |
Display breadcrumbs. |
no_breadcrumbs |
Hide breadcrumbs. |
show_sidebar |
Display the web sidebar. |
safe_render |
Enable or disable safe template rendering. |
no_header |
Hide the page header. |
no_cache |
Disable page caching. |
sitemap |
Include or exclude the page from the sitemap. |
add_next_prev_links |
Add navigation links between pages. |
title |
Set the page title. |
Safe Render
For security reasons, frappe.render_template() blocks templates containing potentially unsafe Python expressions.
If you are certain that your template content is safe, you can disable this protection by setting:
context.safe_render = False
Disable safe_render only for trusted templates, as it removes built-in security checks.
Setting Context Using Front Matter
Static context values can be defined using a front matter block at the beginning of a Markdown page.
This is commonly used for metadata such as page titles and descriptions.
---
title: Introduction
metatags:
description: This is description for the introduction page
---
The values are automatically added to the page context during rendering.
Setting Context Using HTML Comments
Portal pages also support HTML comments that automatically configure specific context properties.
These comments can control features such as breadcrumbs, page titles, headers, caching, sitemap visibility, and custom base templates without writing Python code.
HTML comment directives provide a simple way to configure page behavior directly within HTML or Markdown files.
Adding Custom CSS and JavaScript
You can add page-specific styling and JavaScript by creating files with the same name as the portal page.
custom_app/www
├── custom_page.html
├── custom_page.css
├── custom_page.js
└── custom_page.py
These files are automatically loaded when the corresponding portal page is rendered.
Using separate CSS and JavaScript files keeps page logic and styling organized.
Configuring the Home Page
The default portal home page can be configured in several ways, depending on the user type and application requirements.
- Role
- Portal Settings (for logged-in users)
- get_website_user_home_page hook
- Website Settings (for guests and non-logged-in users)
Choose the home page configuration method based on whether the destination should differ for guests, authenticated users, or specific user roles.