ベストプラクティス
AK²Engine の開発およびサイト構築で守るべき 18 のルールと設計哲学です。
本ドキュメントは、AK²Engine 自体の開発(コア・プラグインの実装)および、同エンジンを利用した実際の Web サイト構築の双方におけるベストプラクティスを統合した包括的なガイドラインです。
「設計当初の美しい思想」を維持し、継ぎ接ぎのスパゲッティコードを生み出さないため、開発時・構築時ともに以下のルールを厳守してください。
第0部: 設計哲学(全項目の根底にある思想)
以下の 3 つは個別のルールではなく、すべてのルールの最上位に位置する設計思想です。判断に迷ったとき、レビュー時の最終基準として参照してください。
0-1. 引き算の美学
AK²Engine の設計哲学は「加えること」ではなく「削ぎ落とすこと」にあります。
- 機能美: 不要な装飾・余分なコード・念の為の安全策を加えない。必要最小限で最大の効果を得る
- 造形美: 視覚的に美しい構造を追求する。冗長な HTML や CSS は構造の美しさを損なう
- 洗練: コードもデザインも「これ以上削れるものがない」状態を目指す
- 簡潔さ: 3 行で書けることを 10 行で書かない。抽象化は再利用が確実な場合のみ
0-2. カラーリング基準(最重要)
色彩はブランドアイデンティティの根幹です。AI が生成しがちな無個性な配色を排除し、意図を持った色選びを徹底します。
全プロジェクト共通:
- 青紫系グラデーション禁止:
#7c3aed,#a78bfa,#ede9fe,#faf5ff等の紫〜ラベンダー系は「AI が作りました」感が強いため、いかなる場面でも使用禁止 - すべての色値は
:rootカスタムプロパティ経由: プラグイン CSS に hex / rgb / rgba を直書きしない(ルール 11 で詳述)
AK²Lab 限定(ak2lab.com, ak2engine.ak2lab.com 等):
- 白背景ベースのデザイン: 安易なダーク背景やグレー背景に逃げない
- モノクロ逃げ禁止: 灰色一辺倒で無難にまとめるのではなく、
--color-primary(青系)を軸に適切なアクセントカラーを用いる
0-3. AI 実装品質ガード
AI(Claude 含む)がコードを生成する際に陥りがちな品質低下パターンを明示的に禁止します。
- 無効 CSS 禁止: 削除しても見た目が一切変わらないスタイルを混入させない(例: 効かない
overflow: hidden、親で既に指定済みのfont-family再宣言) - 念の為コード禁止: 効果が不明な多重安全策を入れない(例: 同じ要素への
pointer-events: noneとvisibility: hiddenとdisplay: noneの三重指定) - 重複パラメータ禁止: 同一の設定値を複数箇所に分散させない。Single Source of Truth を守る
- まわりくどい実装禁止: 直接書けるものを間接的に書かない(例: 不要な中間変数、本来不要なラッパー)。ただし、他の同種の要素と構造を揃えるための関数化・プラグイン化は使用頻度に関係なく行うこと。統一感・コンポーネント化・階層構造が優先
第1部: Web サイト構築のベストプラクティス
エンジンを利用して実際のサイト(src/ 配下)を構築する際のルールです。
1. YAML 駆動アーキテクチャの徹底
ページを作成する際、.md や .njk ファイル内に直接 HTML を長々と記述することは避けてください。
- front-matter の
sections配列に YAML 形式でデータを定義し、テンプレートループで自動展開するアーキテクチャを採用する - コンテンツ(文章データ)とビュー(HTML 構造)を完全に分離し、メンテナンス性を確保する
NG:
<!-- .md 内に HTML を直書き -->
<section class="section section--white">
<div class="container">
<h2>タイトル</h2>
<div class="card-grid">
<div class="card">...</div>
</div>
</div>
</section>
OK:
# front-matter の sections 配列で宣言的に定義
sections:
- type: card-feature
heading: "Features"
subheading: "タイトル"
items:
- icon: "zap"
title: "高速"
text: "説明文。"
ヒント: .md と .njk の使い分け
コンテンツの種類 推奨形式 YAML セクション使用(HTML ほぼなし) .mdテキスト中心(マクロを数個使う程度) .mdHTML 構造が複雑 / マクロが多数ネスト .njk純粋な HTML ページ .html
2. Markdown 執筆時の防御ルール
YAML セクションでカバーしきれない長文ページなどで .md 内に HTML を記述する場合:
- ブロック要素内の空行禁止:
<section>や<div>の内側に空行を入れると、パーサーが後続を<p>タグで誤って包囲し、レイアウトが崩壊する。必ず詰めて記述する
NG:
<section class="section section--white">
<div class="container">
{{ sectionHeader("TITLE", "タイトル") }}
<div class="card-grid"> ← 空行があると <p><div> になる
OK:
<section class="section section--white">
<div class="container">
{{ sectionHeader("TITLE", "タイトル") }}
<div class="card-grid"> ← 空行なし → 正常
3. Eleventy によるアセットの自動集約
CSS や JS のバンドル(結合)は、ビルド時に .eleventy.js 内で自動的かつ順序立てて行われます。
- エンジン側のリソース(
base.css,core/,plugins/)を動的に検索・結合する仕組みが用意されているため、HTML テンプレートの<head>内に個別の<link>や<script>を無数に並べない - JS は必ず
core-engine.jsが先頭にバンドルされるよう設定を維持する
4. サイト固有スタイルの分離と BEM
エンジンが提供する base.css やプラグインの CSS を直接書き換えたり、HTML にインラインスタイル(style="...")をハードコードすることは原則禁止です。
- サイト固有のデザイン調整が必要な場合は、自サイト用の
site.cssを作成し、BEM のモディファイアクラス(例:.section--warm)を用いて上書きする
NG:
<section class="section" style="background: var(--color-bg-subtle)">
OK:
/* src/site.css に定義 */
.section--warm {
background: var(--color-bg-subtle);
}
5. 画像に頼らない Kinetic 演出の最大化
AK²Engine の最大の強みは「Canvas API と数式による軽量で美しい描画」です。
- 動画ファイルや重いビットマップ画像を多用せず、
effectsの指定(例:BgGridConstructionEffect)や CSS を活用した動的表現を優先し、パフォーマンスと解像度非依存の価値を提供する
第2部: エンジン開発のベストプラクティス
ak2-engine/src 内のエンジン本体やプラグイン群を開発・拡張する際のルールです。
6. JS: 宣言的 UI 初期化(Data 属性駆動)
Nunjucks マクロや HTML 内部に <script> を直書きしてインスタンスを生成する形式は厳禁です。
- 設定値や必要な情報はすべて HTML 側の
data-*属性(例:data-liquid-btn)として出力する - JS モジュール側は
DOMContentLoadedをフックに DOM を検索し、自律的に初期化(マウント)を行う設計にする。これにより JS と HTML が疎結合になる
NG:
{# マクロ内に <script> を埋め込む #}
{% macro button(text) %}
<button id="btn-{{ id }}">{{ text }}</button>
<script>new LiquidButton('#btn-{{ id }}')</script>
{%- endmacro %}
OK:
{# data-* 属性で設定を出力 #}
{% macro button(text, color) %}
<button data-liquid-btn data-color="{{ color }}">{{ text }}</button>
{%- endmacro %}
7. JS: Pub/Sub パターン
コンポーネント同士が document.querySelector などで他者の DOM を直接操作し合う密結合を避けてください。
- 状態変更は
AK2NavControllerのような管理クラスに通知し、影響を受ける各要素はこれをsubscribeして自らの見た目を更新する
8. JS: Canvas エフェクトのコアエンジン委譲
ページ全体の背景エフェクトや Canvas アニメーションを実装する際、各エフェクトファイル内で独自に requestAnimationFrame ループを回してはいけません。
- 各エフェクトは
{ init, update, draw, onResize }を持つクラスとして定義し、AK2(core-engine.js)にregister()してループ管理を委譲する - これにより、スクロール領域外での処理ポーズ(Intersection Observer 連携)などの最適化が一元管理される
// エフェクトクラスの基本構造
class MyEffect {
#ctx;
#config;
constructor(options = {}) {
this.#config = { count: options.count || 100 };
}
init(canvas) { this.#ctx = canvas.getContext('2d'); }
update(dt) { /* 状態更新 */ }
draw() { /* 描画 */ }
onResize(w, h) { /* リサイズ対応 */ }
}
9. JS: カプセル化(プライベートフィールド)
- JS: クラスの内部状態(キャンバスコンテキスト、設定値、タイマー ID など)は、必ずプライベートフィールド(
#)を用いて隠蔽する - Nunjucks: 複雑な DOM 構造や長大な SVG の定義を呼び出し側に晒さず、マクロ内にカプセル化してシンプルなインターフェースのみを提供する
10. CSS: Design Tokens の徹底
色(Hex 値)、共通の余白、Z-Index、フォント指定などをプラグインごとの CSS にハードコード(マジックナンバー化)しないでください。
- 必ず
base.cssの:rootで定義されたカスタムプロパティを参照して構築する - これにより、エンジンを利用する各サイトでのテーマ変更が一瞬で適用可能になる
現行の base.css トークン(付録 A 参照)に不足がある場合は、トークンを追加してから使用すること。
11. CSS: ハードコード色値の完全排除
ルール 10 の色に関する部分を特に厳格化したルールです。
禁止: プラグイン CSS 内での hex / rgb / rgba 値の直書き
/* NG */
.blog-calendar__sunday { color: #c0392b; }
.blog-calendar__saturday { color: #2471a3; }
/* OK */
.blog-calendar__sunday { color: var(--color-sunday); }
.blog-calendar__saturday { color: var(--color-saturday); }
12. Nunjucks: マクロ終端ガード
プラグインとして Nunjucks マクロを作成・修正する際は、終了タグとして必ず {%- endmacro %}(ハイフン付き)を使用してください。
- これを含めないと、マクロの出力末尾に目に見えない改行が入り込み、
.md内からの呼び出し時にレイアウト崩れを引き起こす
{# NG: 末尾に改行が残る #}
{% macro featureItem(icon, title, text) %}
<div class="feature-item">...</div>
{% endmacro %}
{# OK: 末尾の改行を除去 #}
{% macro featureItem(icon, title, text) %}
<div class="feature-item">...</div>
{%- endmacro %}
13. Nunjucks: セクション/ウィジェットの動的インクルード
YAML の type 値から動的にテンプレートを解決するパターンを標準とします。
セクション(ページレベル):
{% for section in sections %}
{% include "sections/" + section.type + ".njk" ignore missing %}
{% endfor %}
ウィジェット(セクション内の部品):
{% for widget in section.widgets %}
{% include "widgets/" + widget.type + ".njk" ignore missing %}
{% endfor %}
{% include %}は親スコープを共有するため、widget変数がそのまま子テンプレートから参照できる- データは
collections[widget.collection]のブラケット記法で動的解決する ignore missingで未定義の type によるビルドエラーを防ぐ
14. Eleventy: データ集計の事前計算
年月集計・カテゴリカウント等の複雑なロジックは Nunjucks テンプレート内で行わず、.eleventy.js で事前計算します。
.eleventy.js(addCollection/addFilter): 集計・変換・構造化を行い、完成済みデータを返す- Nunjucks テンプレート: ループ(
{% for %})と条件分岐({% if %})のみ。テンプレート内で配列操作や算術演算をしない
// OK: .eleventy.js で事前計算
eleventyConfig.addCollection("blogArchiveData", function(collectionApi) {
// 年月集計ロジック → 完成済み構造を return
});
第3部: プロジェクト構成のベストプラクティス
15. ディレクトリ構成と役割
ak2-engine/src/
├── base.css # Design Tokens + リセット + 共通レイアウト
├── core/ # エンジン心臓部
│ ├── core-engine.js # AK2 グローバルオブジェクト、rAF ループ管理
│ └── section-effects.js # セクション背景エフェクトの振り分け
├── plugins/ # 独立プラグイン(1フォルダ = 1プラグイン)
│ ├── block-*/ # UIブロック(カード、ヒーロー、ブログ等)
│ ├── effect-bg-*/ # 背景エフェクト(Canvas描画)
│ ├── effect-cursor-*/ # カーソルエフェクト
│ ├── effect-motion-*/ # スクロール・モーションエフェクト
│ ├── effect-text-*/ # テキストアニメーション
│ └── layout-*/ # レイアウト部品(ヘッダー、フッター等)
└── includes/ # 共有マクロ・コンポーネント(プラグインから参照)
- 各プラグインフォルダは
{name}.njk+{name}.css(+ 任意で{name}.js)で構成 - プラグイン間の直接依存は禁止。共有が必要なものは
includes/に配置する
16. プラグイン命名規則
| プレフィックス | 用途 | 例 |
|---|---|---|
block- |
UI ブロック(表示部品) | block-card-kinetic, block-blog-archive |
effect-bg- |
背景エフェクト | effect-bg-snow, effect-bg-firefly |
effect-cursor- |
カーソルエフェクト | effect-cursor-trail |
effect-motion- |
モーション | effect-motion-parallax |
effect-text- |
テキストアニメーション | effect-text-typewriter |
layout- |
レイアウト部品 | layout-header-kinetic, layout-footer-simple |
命名パターン: {プレフィックス}{機能}-{バリアント}
17. YAML フロントマターの設計原則
- セクションの
typeは対応するテンプレートファイル名と一致させる(type: card-hero→sections/card-hero.njk) - ウィジェットの
typeも同様(type: blog-archive→widgets/blog-archive.njk) - コレクション参照は文字列キーで指定し、テンプレート側で
collections[widget.collection]と動的解決する - セクション固有のパラメータはそのセクションの YAML ブロック内にフラットに配置する(過度なネストを避ける)
付録 A: base.css トークン一覧(v0.1.7)
:root {
/* カラー(基本) */
--color-primary: #025DCC;
--color-secondary: #00C6FF;
--color-dark: #0f172a;
--color-text: #334155;
--color-text-light: #475569;
--color-text-lighter: #cbd5e1;
--color-bg-light: #f8fafc;
--color-white: #ffffff;
/* カラー(拡張トークン) */
--color-bg-subtle: #f1f5f9;
--color-text-muted: #64748b;
--color-text-placeholder:#94a3b8;
--color-border: #e2e8f0;
--color-border-light: rgba(0, 0, 0, 0.08);
--color-bg-hover: rgba(0, 0, 0, 0.05);
--color-sunday: #c0392b;
--color-saturday: #2471a3;
--color-dark-bg: #14141c;
--color-dark-text: #f0f0f5;
--color-dark-sub: #777788;
--color-dark-border: rgba(255, 255, 255, 0.05);
/* フォント */
--font-sans: "Noto Serif JP", serif;
--font-english: "Lato", sans-serif;
--font-mono: "Roboto Mono", monospace;
/* グラスモーフィズム */
--glass-bg: rgba(255, 255, 255, 0.65);
--glass-border: rgba(255, 255, 255, 0.65);
--glass-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.1);
--glass-blur: 20px;
/* レイアウト */
--container-width: 1240px;
--header-height: 80px;
--color-lead-width: 720px;
/* Z-Index */
--z-header: 50;
--z-nav: 40;
--z-content: 10;
--z-card: 5;
--z-waves: 3;
--z-particles: 1;
--z-shapes: 0;
}
付録 B: ハードコード色値の棚卸し
v0.1.7 の CSS Design Tokens リファクタリングにより、以下のハードコード色値はすべてトークン化済みです。
対応完了(v0.1.7):
| カテゴリ | 旧ハードコード値 | 置換先トークン |
|---|---|---|
| 青紫系(全排除) | #7c3aed, #a78bfa, #ede9fe, #faf5ff |
var(--color-primary) 系に統一 |
| ダークテーマ | #14141c, #f0f0f5, #777788 |
var(--color-dark-bg), var(--color-dark-text), var(--color-dark-sub) |
| ボーダー | rgba(0,0,0,0.08), rgba(0,0,0,0.1), #e2e8f0 |
var(--color-border-light), var(--color-border) |
| ホバー背景 | rgba(0,0,0,0.05) |
var(--color-bg-hover) |
| グレースケール | #f1f5f9, #94a3b8, #64748b |
var(--color-bg-subtle), var(--color-text-placeholder), var(--color-text-muted) |
| 曜日色 | #c0392b, #2471a3 |
var(--color-sunday), var(--color-saturday) |
| ヘッダー | #0f172a |
var(--color-dark) |
セキュリティ注意事項
| safeフィルターは信頼できるデータにのみ使用する(XSS 防止)- SQL インジェクションが発生し得る動的クエリは作成しない
- ユーザー入力はサニタイズしてから出力する
- 機密情報(API キー等)は
.envファイルで管理し、テンプレートに直書きしない
総括: AK²Engine エコシステムは「極限までの軽量さ」と「破綻しない堅牢さ」を目指して設計されています。第 0 部の設計哲学を頂点に、全 18 のルールがその思想をコードレベルで保証する不可侵のベストプラクティスです。
前のページ: ← CSSカスタマイズ | ↑ 目次 | 次のページ: ブログ機能 →