mcpField
F
frappe-impl-website

frappe-impl-website

github.com/impertio-studio開発198108 回インストール30 週間前に更新
リポジトリ

frappe-impl-website について

Frappe 開発者向けの Web サイトとポータルの実装ガイドです。ページ、フォーム、ブログ、ルーティング、テーマ、SEO に加え、ゲストアクセスのセキュリティも扱います。

主な機能

  1. 01静的ページとカスタムポータルページの作成
  2. 02Web Form とゲスト投稿の設定
  3. 03DocType ページとブログ記事の公開
  4. 04サイトルートとテーマの設定
  5. 05SEO メタデータとサイトマップの設定
  6. 06ゲストアクセスとセキュリティの管理

活用シーン

  1. 01公開コンテンツページやカスタムポータルの構築
  2. 02外部ユーザーからのデータ収集
  3. 03DocType レコードの Web ページ公開
  4. 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/
.gitkeep
anti-patterns.md
decision-tree.md
examples.md
generators.md
workflows.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 ルートになります。

  1. myapp/www/custom_page.html を作成します:
{% extends "templates/web.html" %}
{% block page_content %}
<h1>{{ title }}</h1>
<div>{{ content }}</div>
{% endblock %}
  1. 対応するコントローラー 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
  1. 結果:/custom_page でページにアクセスできます

自動読み込みされるファイルタイプ:.html(テンプレート)、.py(コントローラー)、.css(スタイル)、.js(スクリプト)。

サブディレクトリのパターン — ネストされたルートの場合:

myapp/www/
├── services/
│   ├── index.html        → /services
│   ├── index.py
│   ├── consulting.html   → /services/consulting
│   └── consulting.py
コンテキスト変数リファレンス
キー型効果
titlestrページタイトルとブラウザータブ
no_cacheboolページキャッシュを無効にします
no_headerboolページヘッダーを非表示にします
no_breadcrumbsboolパンくずリストを削除します
add_breadcrumbsboolフォルダー構造から自動生成します
show_sidebarboolウェブサイドバーを表示します
sitemapint0 = サイトマップから除外、1 = 含める
metatagsdictSEO メタタグ(ワークフロー 7 を参照)

ルール:ユーザーごとに異なるコンテンツ、または頻繁に変更されるコンテンツを含むページでは、必ず no_cache = 1 を設定してください。

ワークフロー 2:ウェブフォームを作成する

ウェブフォームを使うと、外部ユーザーがデータを送信して Frappe ドキュメントを作成できます。

  1. Web Form の一覧に移動 → New Web Form
  2. Title を設定し、対象の DocType を選択して、Route(URL スラッグ)を設定します
  3. フィールドを追加します — fieldname は必ず対象の DocType のフィールド名と一致させてください
  4. アクセスを設定します:
    • Login Required:ゲストからの送信を許可する場合はチェックを外します
    • Allow Edit:ユーザーが送信内容を編集できるようにします
    • Allow Multiple:ユーザーが複数回送信できるようにします
  5. 保存して公開します
ゲストからの送信
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)。

  1. DocType を開き、Has Web View と Allow Guest to View にチェックを入れます
  2. Route フィールドのプレフィックスを設定します(例:articles)
  3. DocType に次のフィールドを必ず追加します:
    • route(Data、非表示)— 自動生成される URL スラッグ
    • published(Check)— 表示状態を制御します
  4. DocType ディレクトリにテンプレートを作成します:
    • {doctype_name}.html — 単一レコードのテンプレート
    • {doctype_name}_row.html — リスト項目のテンプレート
  5. hooks.py でウェブサイトジェネレーターとして登録します:
website_generators = ["Article"]
  1. コントローラーで 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:ブログを設定する

  1. Blog Category ドキュメントを作成します(例:「ニュース」、「更新情報」)
  2. Blog Post ドキュメントを作成します:
    • カテゴリーを選択し、コンテンツを記述します(Markdown またはリッチテキスト)
    • Published と Published On の日付を設定します
    • ブログのルートは /blog/{slug} として自動生成されます
  3. Website Settings で設定します:
    • ブログのタイトルを設定します
    • コメントを有効または無効にします

ルール:Published On の日付を必ず設定してください。日付のない投稿は RSS フィードに決して表示されません。

ワークフロー 6:ウェブサイトのテーマとカスタム CSS

Website Theme DocType 経由
  1. Website Theme → 新規作成に移動します
  2. フォント、色、ナビゲーションバーのスタイル、ボタンの角丸を設定します
  3. Custom CSS フィールドにカスタム CSS を追加します
  4. 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 向けクライアントサイド API
  • references/generators.md — ポータルジェネレーター、ブログシステム、カスタムルーティングのパターン
  • references/workflows.md — 拡張ワークフローの解説
  • references/examples.md — 完全なコード例
  • references/decision-tree.md — ページタイプの完全な判断ツリー

コメント