EmDash は、投稿、ページ、タクソノミー、メニュー、ウィジェット、メディアライブラリといった WordPress のなじみ深い概念を、モダンな Astro スタックに取り込みます。コンテンツ管理の知識はそのまま活かせます。
なじみ深いまま変わらないもの
WordPress で知っている概念は、EmDash でもファーストクラス機能です:
- Collections はカスタム投稿タイプのように機能します—コンテンツ構造を定義し、テンプレートでクエリできます
- タクソノミー も同じように機能します—階層型(カテゴリーのような)とフラット型(タグのような)
- メニュー はドラッグアンドドロップの並び替えとネストされた要素に対応
- ウィジェットエリア はサイドバーや動的なコンテンツ領域に使用
- メディアライブラリ はアップロード、整理、画像管理に対応
- 管理UI はコンテンツ編集者がコードに触れずに使用できます
異なる点
実装は変わりますが、メンタルモデルは同じです:
PHP ではなく TypeScript
テンプレートは Astro コンポーネントです。構文はよりクリーンですが、概念は同じです:HTML を 出力するサーバーコードです。
WP_Query ではなくコンテンツ API
getEmDashCollection() のようなクエリ関数が WP_Query に代わります。SQL は不要で、関数呼び出しだけです。
ファイルベースのルーティング
src/pages/ 内のファイルが URL になります。リライトルールやテンプレート階層を覚える必要はありません。
テンプレートパーツではなくコンポーネント
コンポーネントをインポートして使用します。get_template_part() と同じアイデアで、より良い組織化です。
クイックリファレンス
| WordPress | EmDash | 備考 |
|---|---|---|
| カスタム投稿タイプ | Collections | 管理 UI または API で定義 |
WP_Query | getEmDashCollection() | フィルター、制限、タクソノミークエリ |
get_post() | getEmDashEntry() | エントリまたは null を返す |
| カテゴリー/タグ | タクソノミー | 階層サポートが保持される |
register_nav_menus() | getMenu() | ファーストクラスのメニューサポート |
register_sidebar() | getWidgetArea() | ファーストクラスのウィジェットエリア |
bloginfo('name') | getSiteSetting("title") | サイト設定 API |
the_content() | <PortableText /> | 構造化コンテンツのレンダリング |
| ショートコード | Portable Text ブロック | カスタムコンポーネント |
add_action/filter() | プラグインフック | content:beforeSave など |
wp_options | ctx.kv | キーバリューストレージ |
| テーマディレクトリ | src/ ディレクトリ | コンポーネント、レイアウト、ページ |
functions.php | astro.config.mjs + EmDash 設定 | ビルドとランタイム設定 |
コンテンツ API
Collections のクエリ
WordPress のクエリは WP_Query またはヘルパー関数を使用します。EmDash は型付きクエリ関数を使用します。
WordPress
<?php
$posts = new WP_Query([
'post_type' => 'post',
'posts_per_page' => 10,
'post_status' => 'publish',
'category_name' => 'news',
]);
while ($posts->have_posts()) :
$posts->the_post();
?>
<h2><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
<?php endwhile; ?> EmDash
---
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
limit: 10,
where: { category: "news" },
});
---
{posts.map((post) => (
<article>
<h2>{post.data.title}</h2>
<p>{post.data.excerpt}</p>
</article>
))} 単一エントリの取得
次の例では、識別子でエントリを取得してレンダリングします。WordPress と EmDash での方法:
WordPress
<?php
$post = get_post($id);
?>
<article>
<h1><?php echo $post->post_title; ?></h1>
<?php echo apply_filters('the_content', $post->post_content); ?>
</article> EmDash
---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);
if (!post) return Astro.redirect("/404");
---
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article> テンプレート階層
WordPress はテンプレート階層を使用して、どのファイルがページをレンダリングするかを選択します。Astro は明示的なファイルベースのルーティングを使用します。
| WordPress テンプレート | EmDash の同等機能 |
|---|---|
index.php | src/pages/index.astro |
single.php | src/pages/posts/[slug].astro |
single-{type}.php | src/pages/{type}/[slug].astro |
page.php | src/pages/pages/[slug].astro |
archive.php | src/pages/posts/index.astro |
archive-{type}.php | src/pages/{type}/index.astro |
category.php | src/pages/categories/[slug].astro |
tag.php | src/pages/tags/[slug].astro |
search.php | src/pages/search.astro |
404.php | src/pages/404.astro |
header.php / footer.php | src/layouts/Base.astro |
sidebar.php | src/components/Sidebar.astro |
テンプレートパーツ → コンポーネント
WordPress のテンプレートパーツは Astro コンポーネントになります:
WordPress
// テンプレート内:
get_template_part('template-parts/content', 'post');
// template-parts/content-post.php:
<article class="post">
<h2><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
</article> EmDash
---
const { post } = Astro.props;
---
<article class="post">
<h2>{post.data.title}</h2>
<p>{post.data.excerpt}</p>
</article>次のページはそのコンポーネントをインポートし、各投稿に対してレンダリングします:
---
import PostCard from "../components/PostCard.astro";
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");
---
{posts.map((post) => <PostCard {post} />)} メニュー
EmDash には自動 URL 解決機能を備えたファーストクラスのメニューサポートがあります:
WordPress
<?php
wp_nav_menu([
'theme_location' => 'primary',
'container' => 'nav',
]);
?> EmDash
---
import { getMenu } from "emdash";
const menu = await getMenu("primary");
---
<nav>
<ul>
{menu?.items.map((item) => (
<li>
<a href={item.url}>{item.label}</a>
</li>
))}
</ul>
</nav> メニューは、管理 UI、シードファイル、または WordPress インポートを通じて作成されます。
ウィジェットエリア
ウィジェットエリアは WordPress のサイドバーのように機能します:
WordPress
<?php if (is_active_sidebar('sidebar-1')) : ?>
<aside>
<?php dynamic_sidebar('sidebar-1'); ?>
</aside>
<?php endif; ?> EmDash
---
import { getWidgetArea } from "emdash";
import { PortableText } from "emdash/ui";
const sidebar = await getWidgetArea("sidebar");
---
{sidebar && (
<aside>
{sidebar.widgets.map((widget) => {
if (widget.type === "content") {
return <PortableText value={widget.content} />;
}
// 他のウィジェットタイプを処理
})}
</aside>
)} サイト設定
サイトオプションとカスタマイザー設定は getSiteSetting() にマップされます:
| WordPress | EmDash |
|---|---|
bloginfo('name') | getSiteSetting("title") |
bloginfo('description') | getSiteSetting("tagline") |
get_custom_logo() | getSiteSetting("logo") |
get_option('date_format') | getSiteSetting("dateFormat") |
home_url() | Astro.site |
次の例は getSiteSetting() で個別の設定を読み取ります:
import { getSiteSetting } from "emdash";
const title = await getSiteSetting("title");
const logo = await getSiteSetting("logo"); // { mediaId, alt, url } を返す
タクソノミー
タクソノミーは概念的に同じように機能します—階層型(カテゴリーのような)またはフラット型(タグのような):
import { getTaxonomyTerms, getEntryTerms, getTerm } from "emdash";
// すべてのカテゴリーを取得
const categories = await getTaxonomyTerms("categories");
// 特定のタームを取得
const news = await getTerm("categories", "news");
// 投稿のタームを取得
const postCategories = await getEntryTerms("posts", postId, "categories");
フック → プラグインシステム
WordPress のフック(add_action、add_filter)は EmDash のプラグインフックになります:
| WordPress フック | EmDash フック | 目的 |
|---|---|---|
save_post | content:beforeSave | 保存前にコンテンツを変更 |
the_content | PortableText コンポーネント | レンダリングされたコンテンツを変換 |
pre_get_posts | クエリオプション | クエリをフィルター |
wp_head | レイアウト <head> | head コンテンツを追加 |
wp_footer | レイアウト </body> の前 | footer コンテンツを追加 |
EmDash の優れた点
型安全性
全体で TypeScript。Collections、クエリ、コンポーネントは完全に型付けされているため、フィールド名と 戻り値の型が自動補完され、ビルド時にチェックされます。
パフォーマンス
デフォルトで静的生成、必要に応じてサーバーレンダリング。エッジデプロイ対応。
モダンな DX
Hot Module Replacement。コンポーネントベースのアーキテクチャ。モダンなツーリング(Vite、TypeScript、ESLint)。
Git ベースのデプロイ
コードとテンプレートは git に保存され、コンテンツはデータベースに保存されます。コードをプッシュしてデプロイ。
プレビューリンク
EmDash は HMAC 署名トークンを使用して安全なプレビュー URL を生成します。コンテンツ編集者はプレビューリンクを共有して下書きを表示できるため、レビュアーは本番ログインなしで確認できます。
分離されたプラグイン
EmDash プラグインは明示的な API を持つ分離されたコンテキストで実行されます。各プラグインは宣言した API のみにアクセスできるため、プラグインがお互いのグローバル状態を共有したり上書きしたりすることはありません。
コンテンツ編集者の体験
コンテンツ編集者は、wp-admin に似た EmDash 管理パネルを使用します:
- 最近のアクティビティを表示する ダッシュボード
- 検索、フィルター、一括アクションを備えた Collection リスト
- コンテンツ用の リッチエディター(Gutenberg ではなく Portable Text)
- ドラッグアンドドロップアップロード対応の メディアライブラリ
- ドラッグアンドドロップ並び替え対応の メニュービルダー
- サイドバーコンテンツ用の ウィジェットエリアエディター
編集体験はなじみ深いものです。基礎技術はモダンです。
移行パス
EmDash は WordPress コンテンツを直接インポートします:
- WordPress からエクスポート(ツール → エクスポート)
- EmDash の管理画面で
.xmlファイルをアップロード - 投稿タイプを Collections にマッピング
- コンテンツとメディアをインポート
投稿、ページ、タクソノミー、メニュー、メディアが転送されます。Gutenberg ブロックは Portable Text に変換されます。カスタムフィールドは分析されマッピングされます。
完全な手順については、WordPress 移行ガイドを参照してください。
次のステップ
- はじめに — 最初の EmDash サイトをセットアップ
- コンテンツのクエリ — コンテンツ API の詳細
- タクソノミー — カテゴリー、タグ、カスタムタクソノミー
- メニュー — ナビゲーションメニュー
- WordPress から移行 — 既存のコンテンツをインポート