frappe-impl-website について
Frappe 開発者向けの Web サイトとポータルの実装ガイドです。ページ、フォーム、ブログ、ルーティング、テーマ、SEO に加え、ゲストアクセスのセキュリティも扱います。
主な機能
- 01静的ページとカスタムポータルページの作成
- 02Web Form とゲスト投稿の設定
- 03DocType ページとブログ記事の公開
- 04サイトルートとテーマの設定
- 05SEO メタデータとサイトマップの設定
- 06ゲストアクセスとセキュリティの管理
活用シーン
- 01公開コンテンツページやカスタムポータルの構築
- 02外部ユーザーからのデータ収集
- 03DocType レコードの Web ページ公開
- 04ブログ、ルート、検索メタデータの設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ impertio-studio/ frappe_claude_skill_package --skill frappe-impl-websiteインストール後、Claude Code で/frappe-impl-websiteを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/.gitkeepanti-patterns.mddecision-tree.mdexamples.mdgenerators.mdworkflows.md詳細
Frappe のウェブサイトとポータル — 実装ワークフロー
ウェブサイト、ポータル、一般公開ページを作成するためのステップごとのワークフローです。フックの構文については frappe-impl-hooks を参照してください。Jinja テンプレートについては frappe-impl-jinja を参照してください。
バージョン:v14/v15/v16 | 注:v15 以降では Bootstrap 5 を使用します。v14 では 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
判定ツリーの全体については references/decision-tree.md を参照してください。
ワークフロー 1:ポータルページを作成する(www/)
ポータルページはアプリの www/ ディレクトリに配置します。ファイル名が URL ルートになります。
myapp/www/custom_page.htmlを作成します:
{% extends "templates/web.html" %}
{% block page_content %}
<h1>{{ title }}</h1>
<div>{{ content }}</div>
{% endblock %}
- 対応するコントローラー
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 content
- 結果:
/custom_pageでページにアクセスできます
自動読み込みされるファイルタイプ:.html(テンプレート)、.py(コントローラー)、.css(スタイル)、.js(スクリプト)。
サブディレクトリのパターン — ネストされたルートの場合:
myapp/www/
├── services/
│ ├── index.html → /services
│ ├── index.py
│ ├── consulting.html → /services/consulting
│ └── consulting.py
コンテキスト変数リファレンス
| キー | 型 | 効果 |
|---|---|---|
title | str | ページタイトルとブラウザータブ |
no_cache | bool | ページキャッシュを無効にします |
no_header | bool | ページヘッダーを非表示にします |
no_breadcrumbs | bool | パンくずリストを削除します |
add_breadcrumbs | bool | フォルダー構造から自動生成します |
show_sidebar | bool | ウェブサイドバーを表示します |
sitemap | int | 0 = サイトマップから除外、1 = 含める |
metatags | dict | SEO メタタグ(ワークフロー 7 を参照) |
ルール:ユーザーごとに異なるコンテンツ、または頻繁に変更されるコンテンツを含むページでは、必ず no_cache = 1 を設定してください。
ワークフロー 2:ウェブフォームを作成する
ウェブフォームを使うと、外部ユーザーがデータを送信して Frappe ドキュメントを作成できます。
- Web Form の一覧に移動 → New Web Form
- Title を設定し、対象の DocType を選択して、Route(URL スラッグ)を設定します
- フィールドを追加します —
fieldnameは必ず対象の DocType のフィールド名と一致させてください - アクセスを設定します:
- Login Required:ゲストからの送信を許可する場合はチェックを外します
- Allow Edit:ユーザーが送信内容を編集できるようにします
- Allow Multiple:ユーザーが複数回送信できるようにします
- 保存して公開します
ゲストからの送信
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";
});
ウェブフォームのカスタムスクリプト(サーバー:Python)
Web Form ドキュメントに Python スクリプトを追加します:
def get_context(context):
# Add custom context variables for the template
context.categories = frappe.get_all("Category", fields=["name", "title"])
ルール:ウェブフォームでは、クライアント側の検証だけを決して信頼しないでください。対象の DocType のコントローラーまたはサーバースクリプトで必ず検証してください。
ワークフロー 3:DocType で has_web_view を有効にする
これにより、個々のドキュメントをウェブページとして公開できます(例:/articles/my-article)。
- DocType を開き、Has Web View と Allow Guest to View にチェックを入れます
- Route フィールドのプレフィックスを設定します(例:
articles) - DocType に次のフィールドを必ず追加します:
route(Data、非表示)— 自動生成される URL スラッグpublished(Check)— 表示状態を制御します
- DocType ディレクトリにテンプレートを作成します:
{doctype_name}.html— 単一レコードのテンプレート{doctype_name}_row.html— リスト項目のテンプレート
hooks.pyでウェブサイトジェネレーターとして登録します:
website_generators = ["Article"]
- コントローラーで
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": ("!=", self.name)},
fields=["title", "route"],
limit=5,
)
ルール:published チェックフィールドを必ず含めてください。未公開のドキュメントをゲストに決して公開しないでください。
ワークフロー 4:ウェブサイトのルートルール(hooks.py)
ルートルールは URL パターンをコントローラーまたはページに対応付けます。
# hooks.py
website_route_rules = [
# Map parameterized URL to a page
{"from_route": "/projects/<name>", "to_route": "projects/project"},
# Map URL prefix to DocType
{"from_route": "/kb/<path:name>", "to_route": "knowledge-base"},
]
# Redirects (301/304)
website_redirects = [
{"source": "/old-page", "target": "/new-page"},
{"source": r"/docs(/.*)?", "target": r"https://docs.example.com\1"},
]
# Homepage for logged-in users (role-based)
role_home_page = {
"Customer": "orders",
"Supplier": "rfqs",
}
# Dynamic homepage
get_website_user_home_page = "myapp.utils.get_home_page"
ホームページの優先順位:get_website_user_home_page > role_home_page > Portal Settings > Website Settings。
ワークフロー 5:ブログを設定する
- Blog Category ドキュメントを作成します(例:「ニュース」、「更新情報」)
- Blog Post ドキュメントを作成します:
- カテゴリーを選択し、コンテンツを記述します(Markdown またはリッチテキスト)
- Published と Published On の日付を設定します
- ブログのルートは
/blog/{slug}として自動生成されます
- Website Settings で設定します:
- ブログのタイトルを設定します
- コメントを有効または無効にします
ルール:Published On の日付を必ず設定してください。日付のない投稿は RSS フィードに決して表示されません。
ワークフロー 6:ウェブサイトのテーマとカスタム CSS
Website Theme DocType 経由
- Website Theme → 新規作成に移動します
- フォント、色、ナビゲーションバーのスタイル、ボタンの角丸を設定します
- Custom CSS フィールドにカスタム CSS を追加します
- Website Settings でアクティブなテーマとして設定します
hooks.py 経由
# Inject CSS/JS on all web pages
website_context = {
"favicon": "/assets/myapp/images/favicon.png",
}
update_website_context = "myapp.overrides.website_context"
# Override base template
base_template = "myapp/templates/custom_base.html"
ワークフロー 7:SEO:メタタグ、Open Graph、サイトマップ
ポータルページ(frontmatter または context)
def get_context(context):
context.metatags = {
"title": "My Page Title",
"description": "Page description for search engines",
"image": "/assets/myapp/images/og-image.png",
"og:type": "website",
"twitter:card": "summary_large_image",
}
Web Page DocType
メタフィールドを直接設定します:Meta Title、Meta Description、Meta Image。
サイトマップ
- Frappe は公開済みの Web Pages および has_web_view ドキュメントから
/sitemap.xmlを自動生成します - ページを除外するには、context または frontmatter で
sitemap = 0を設定します - カスタム robots.txt を設定するには、
site_config.jsonでrobots_txtパスを指定します
ルール:公開ページには必ず meta description を設定してください。空欄のままにしてはいけません。説明のないページは検索エンジンで不利になります。
ワークフロー 8:ゲストアクセスとセキュリティ
# site_config.json — rate limiting
{
"rate_limit": {
"web_form": "5/hour",
"api": "100/hour"
},
"allowed_referrers": ["https://mysite.com"],
"allow_cors": "https://mysite.com"
}
セキュリティルール:
- CSRF 保護は必ず有効にしてください(デフォルト)。本番環境で
ignore_csrfを設定してはいけません - ゲストがアクセス可能なエンドポイントには、必ずレート制限を設定してください
- Web Forms のユーザー入力は必ずサニタイズしてください(Frappe は標準フィールドでデフォルトでこれを行います)
- アクセス制御なしに、ゲスト向け URL で内部の DocType 名を公開してはいけません
アンチパターン
| アンチパターン | 正しい方法 |
|---|---|
get_context に HTML をハードコーディングする | context 変数を使用した Jinja テンプレートを使用します |
動的ページで no_cache を省略する | ユーザー固有のコンテンツでは必ず no_cache = 1 を設定します |
| レート制限のないゲスト向け Web Form | ゲスト向けフォームには必ずレート制限を設定します |
has_web_view で published フィールドがない | データ漏えいを防ぐため、必ず published チェックを追加します |
単純なリダイレクトに website_route_rules を使用する | 代わりに website_redirects を使用します |
| www/ コントローラーにビジネスロジックを記述する | DocType コントローラーに記述し、www/ はプレゼンテーションに使用します |
例を含むアンチパターンの詳細については、references/anti-patterns.md を参照してください。
関連項目
frappe-impl-hooks— Website hooks の詳細frappe-impl-jinja— Jinja テンプレートのパターンfrappe-impl-controllers— DocType コントローラー(WebsiteGenerator)frappe-syntax-clientscripts— Web Forms 向けクライアントサイド APIreferences/generators.md— ポータルジェネレーター、ブログシステム、カスタムルーティングのパターンreferences/workflows.md— 拡張ワークフローの解説references/examples.md— 完全なコード例references/decision-tree.md— ページタイプの完全な判断ツリー