frappe-agent-architect
Use when designing multi-app Frappe architectures, deciding whether to split functionality into separate apps, or implementing cross-app communication…
Use when building portal pages, Web Forms, website routes, or configuring themes and SEO in Frappe. Prevents 404 errors from wrong route resolution, broken Web Form submissions, and missing meta tags for SEO. Covers Web Page, Web Form, Portal Settings, Website Settings, website
$ npx -y skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-impl-website --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/frappe-impl-websiteContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when building portal pages, Web Forms, website routes, or configuring themes and SEO in Frappe. Prevents 404 errors from wrong route resolution, broken Web Form submissions, and missing meta tags for SEO. Covers Web Page, Web Form, Portal Settings, Website Settings, website
name: frappe-impl-website description: > Use when building portal pages, Web Forms, website routes, or configuring themes and SEO in Frappe. Prevents 404 errors from wrong route resolution, broken Web Form submissions, and missing meta tags for SEO. Covers Web Page, Web Form, Portal Settings, Website Settings, website routes, Jinja templates, Blog, Web Template, has_web_view, meta tags, sitemap. Keywords: website, portal, Web Form, Web Page, route, theme, SEO, meta tags, has_web_view, Blog, Web Template, sitemap, customer portal, self-service, public form, web page, website not showing, 404 on portal.. license: MIT compatibility: "Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16." metadata: author: OpenAEC-Foundation version: "2.0"
Step-by-step workflows for building websites, portals, and public-facing pages. For hooks syntax see `frappe-impl-hooks`. For Jinja templating see `frappe-impl-jinja`.
**Version**: v14/v15/v16 | **Note**: v15+ uses Bootstrap 5; v14 uses Bootstrap 4.
WHAT do you need? ├── Static content page (About, Terms) → Web Page DocType or www/ HTML ├── Data entry by external users → Web Form ├── List of records visible on website → has_web_view on DocType ├── Blog / news articles → Blog Post + Blog Category ├── Custom app with sidebar/toolbar → Custom Portal Page (www/) └── Dynamic route with parameters → website_route_rules in hooks.py
See `references/decision-tree.md` for the complete decision tree.
Portal pages live in your app's `www/` directory. The file name becomes the URL route.
1. Create `myapp/www/custom_page.html`:
{% extends "templates/web.html" %}
{% block page_content %}
<h1>{{ title }}</h1>
<div>{{ content }}</div>
{% endblock %}2. Create matching controller `myapp/www/custom_page.py`:
import frappe
def get_context(context):
context.title = "My Custom Page"
context.content = "Hello World"
context.no_cache = 1 # ALWAYS set for dynamic content3. Result: page available at `/custom_page`
**File types auto-loaded**: `.html` (template), `.py` (controller), `.css` (styles), `.js` (scripts).
**Subdirectory pattern** — for nested routes:
myapp/www/ ├── services/ │ ├── index.html → /services │ ├── index.py │ ├── consulting.html → /services/consulting │ └── consulting.py
| Key | Type | Effect | |-----|------|--------| | `title` | str | Page title and browser tab | | `no_cache` | bool | Disable page caching | | `no_header` | bool | Hide the page header | | `no_breadcrumbs` | bool | Remove breadcrumbs | | `add_breadcrumbs` | bool | Auto-generate from folder structure | | `show_sidebar` | bool | Display web sidebar | | `sitemap` | int | 0 = exclude from sitemap, 1 = include | | `metatags` | dict | SEO meta tags (see Workflow 7) |
**Rule**: ALWAYS set `no_cache = 1` for pages with user-specific or frequently changing content.
Web Forms let external users submit data that creates Frappe documents.
1. Navigate to **Web Form** list → **New Web Form** 2. Set **Title**, select target **DocType**, set **Route** (URL slug) 3. Add fields — ALWAYS match `fieldname` to the target DocType field names 4. Configure access:
5. Save and publish
ALLOWING guest submissions?
├── YES → Uncheck "Login Required"
│ → Set "Guest Title" for the submission form
│ → ALWAYS add rate limiting in site_config:
│ "rate_limit": {"web_form": "5/hour"}
│ → ALWAYS validate server-side (guests can bypass JS)
└── NO → Keep "Login Required" checked (default)frappe.web_form.on("after_load", function() {
// Runs after form loads in browser
});
frappe.web_form.on("before_submit", function() {
// Validate before submission — return false to cancel
let val = frappe.web_form.get_value("email");
if (!val) {
frappe.throw("Email is required");
return false;
}
});
frappe.web_form.on("after_submit", function() {
// Redirect or show message after success
window.location.href = "/thank-you";
});In the Web Form document, add a Python script:
def get_context(context):
# Add custom context variables for the template
context.categories = frappe.get_all("Category", fields=["name", "title"])**Rule**: NEVER trust client-side validation alone for Web Forms. ALWAYS validate in the target DocType's controller or server script.
This makes individual documents accessible as web pages (e.g., `/articles/my-article`).
1. Open DocType → check **Has Web View** and **Allow Guest to View** 2. Set the **Route** field prefix (e.g., `articles`) 3. ALWAYS add these fields to the DocType:
4. Create templates in the DocType directory:
5. In `hooks.py`, register as website generator:
website_generators = ["Article"]
6. In the controller, implement `get_context`:
class Article(WebsiteGenerator):
website = frappe._dict(
template="templates/generators/article.html",
condition_field="published",
page_title_field="title",
)
def get_context(self, context):
context.related = frappe.get_all(
"Article",
filters={"published": 1, "name": ("!=", s60 deterministic Claude AI skills for Frappe Framework & ERPNext v14-v16 development and operations
Repo: Impertio-Studio/Frappe_Claude_Skill_Package
Use when designing multi-app Frappe architectures, deciding whether to split functionality into separate apps, or implementing cross-app communication…
Use when debugging Frappe errors, using bench console for live inspection, analyzing tracebacks, or reading Frappe log files. Prevents wasted debugging time…
Use when receiving vague or unclear ERPNext/Frappe development requests that need interpretation. Transforms requirements like 'make invoice auto-calculate' or…
Use when migrating a Frappe app between major versions, detecting breaking API changes, or resolving post-migration errors. Prevents failed migrations from…
Use when reviewing or validating Frappe/ERPNext code against best practices and common pitfalls. Checks generated code before deployment, validates against all…
Use when building ERPNext/Frappe API integrations (v14/v15/v16) including REST API, RPC API, authentication, webhooks, and rate limiting. Covers external API…