日本語版
最新ニュース
企業

HeadlessKit を使用して .NET 10 で Optimizely SaaS CMS のヘッドを構築する

headless は自由を約束し、調整会議を行う傾向があります。 2 つのコードベース。モデルは2本セット。離れ離れにならないように懸命に努力する 2 つのチーム。 Optimizely SaaS CMS では、ヘッドレスが必須です。そこで私はそれと戦う代わりに、それをひっくり返すことにしました。まずヘッドを (正しくは .NET で) 構築し、CMS をその現実に適応させたらどうなるでしょうか?その実験は CodeArt.Optimizely.HeadlessKit となり、現在はオープンソースとして利用可能です。 コードファースト CMS からヘッドレス フリクションまで 長年にわたり、Optimizely CMS の最大の利点の 1 つは、コードファーストのモデル定義でした。 コードでコンテンツ タイプを定義しました。強く型付けされたモデルを使用しました。レンダリングでは、どのようなプロパティが存在するかが正確に認識されていました。 そして、存在しない分野に依存することになることはほとんどありませんでした。 それは予測可能でした。安定した。開発者に優しい。 それから首なしが部屋に入ってきました。 Optimizely SaaS CMS を使用する場合でも、CMS 11/12/13 のグラフ/REST API…

HeadlessKit を使用して .NET 10 で Optimizely SaaS CMS のヘッドを構築する

1771656821
2026-02-19 20:41:00

headless は自由を約束し、調整会議を行う傾向があります。 2 つのコードベース。モデルは2本セット。離れ離れにならないように懸命に努力する 2 つのチーム。 Optimizely SaaS CMS では、ヘッドレスが必須です。そこで私はそれと戦う代わりに、それをひっくり返すことにしました。まずヘッドを (正しくは .NET で) 構築し、CMS をその現実に適応させたらどうなるでしょうか?その実験は CodeArt.Optimizely.HeadlessKit となり、現在はオープンソースとして利用可能です。

コードファースト CMS からヘッドレス フリクションまで

長年にわたり、Optimizely CMS の最大の利点の 1 つは、コードファーストのモデル定義でした。

コードでコンテンツ タイプを定義しました。
強く型付けされたモデルを使用しました。
レンダリングでは、どのようなプロパティが存在するかが正確に認識されていました。

そして、存在しない分野に依存することになることはほとんどありませんでした。

それは予測可能でした。安定した。開発者に優しい。

それから首なしが部屋に入ってきました。

Optimizely SaaS CMS を使用する場合でも、CMS 11/12/13 のグラフ/REST API を使用する場合でも、モデルは根本的に変わります。突然:

  • コンテンツモデルは 1 つのシステム内に存在します
  • フロントエンドモデルは別の場所に存在します
  • 同期はあなたの責任になります
  • クエリは手動で記述する必要がある
  • ルーティング、ナビゲーション、レンダリング ロジックはすべて自分で再構築できます

言い換えれば、柔軟性が向上しますが、可動部分も増えます。

お客様がさまざまな方法でこの問題を解決するのを見てきました。手動で両側をメンテナンスする人もいます。グラフ スキーマからフロントエンド モデルを生成するものもあります。私はそのプロセスの一部を自動化するのにも協力しました。

それは役に立ちますが、それでも次のような結果になります。

  • 同期してデプロイする必要がある 2 つのコードベース
  • または、管理構成とフロントエンド ロジックの脆弱な組み合わせ
  • または、「なぜこの物件は存在しないのですか?」という質問が絶え間なく発生します。瞬間

そして、そこから私は違う考え方をし始めました。

理想的な頭とはどのようなものでしょうか?

尋ねる代わりに、 「フロントエンドを CMS に適応させるにはどうすればよいでしょうか?」
私は尋ねた:

私にとって理想的なヘッド サイトとはどのようなものでしょうか?

私が欲しかったのは:

  • コードファースト
  • 厳密に型指定された
  • 最小限の同期作業
  • 作業が簡単 (特に AI 支援開発の場合)
  • 従来の Optimizely CMS 開発エクスペリエンスに可能な限り近い

.NET 開発者である私は、当然のことながら、.NET 10 のプレーンな ASP.NET MVC / Razor Pages サイトから始めました。

もし私がこうしたらどうなるでしょうか?

  1. コンテンツ タイプを通常のモデル クラスとして定義しました
  2. 属性を使用してマークされた編集可能なプロパティ
  3. 単一の NuGet パッケージを追加しました
  4. 起動時にすべてを SaaS CMS と同期させます

コンテンツタイプ。
プロパティ。
Visual Builder のテンプレートを表示します。

そして、ルーティング、基本的なレンダリング ロジック、コンテンツ グラフのクエリも処理できたらどうなるでしょうか?

結局のところ、それはそれほど複雑ではありませんでした。

ここにv1があります ヘッドレスキット

.NET 10 サイトと Optimizely SaaS CMS 間の軽量のコードファーストブリッジです。

👉 GitHub:
https://github.com/CodeArtDK/CodeArt.Optimizely.HeadlessKit

NuGet パッケージは、Optimizely nuget フィードで入手できます。

HeadlessKit の使用を開始する

ここでは、CMS で何も定義せずに、空の .NET 10 プロジェクトから、コンテンツ タイプとレンダリングの準備が整った完全に同期された Optimizely SaaS CMS に移行する方法を説明します。

注: これは、 公式ドキュメント — したがって、ここで機能するものは、リポジトリで機能するものとまったく同じです。

HeadlessKit は意図的にシンプルになっています。以前に Razor Pages または MVC サイトを構築したことがある場合は、すでに 90% 完成しています。

パッケージをインストールする

SaaS CMS とグラフ設定を追加する

appsettings.json で資格情報 (またはユーザー シークレット) を構成します。

HeadlessKit には次のものが必要です。

  • SaaS CMS API 認証情報
  • Optimizely グラフキー

それでおしまい。

サービスを登録する

Program.cs、スタートアップ、または DI を登録する場所:

これにより、次のことが可能になります。

  • コンテンツタイプの同期
  • グラフ統合
  • 動的ルーティング
  • プレビューのサポート

セットアップルーティング

app.MapDynamicPageRouteContentRouteTransformer>("{**path}");

コードでコンテンツ タイプを定義する

起動時に、HeadlessKit は次のことを行います。

  • コンテンツタイプを作成または更新する
  • 同期プロパティ
  • Visual Builder の表示テンプレートを構成する

手動による CMS セットアップは必要ありません。

テンプレートを作成して実行する

コンテンツ タイプに Razor ページまたは MVC テンプレートを追加し、含まれる汎用ベースから継承します。

    [TemplateDescriptor(typeof(LandingPage))]
    public class LandingPageModel : ContentPage { }

サイトを運営します。

それでおしまい。

モデルは次のようになりました。

  • 厳密に型指定された
  • SaaS CMSと同期
  • コンテンツグラフを介したクエリ
  • .NET サイトを通じてレンダリング

表示テンプレート

ビジュアル ビルダーを使用し、エクスペリエンスや要素などを定義している場合は、もちろんコード内で同じ方法で表示テンプレートを定義することもできます。

    [DisplayTemplate(Key = "ExperienceDefault", DisplayName = "Experience",
        BaseType = BaseTypes.Experience, IsDefault = true)]
    public class ExperienceDisplayTemplate : SaaSDisplayTemplate
    {
        [JsonIgnore]
        [DisplayTemplateSetting(DisplayName = "Color Scheme", SortOrder = 10)]
        [DisplayTemplateChoice("default", "Default", SortOrder = 1)]
        [DisplayTemplateChoice("dark", "Dark", SortOrder = 2)]
        [DisplayTemplateChoice("warm", "Warm", SortOrder = 3)]
        [DisplayTemplateChoice("cool", "Cool", SortOrder = 4)]
        public string ColorScheme { get; set; } = "default";

        [JsonIgnore]
        [DisplayTemplateSetting(DisplayName = "Typography", SortOrder = 20)]
        [DisplayTemplateChoice("default", "Default", SortOrder = 1)]
        [DisplayTemplateChoice("serif", "Serif", SortOrder = 2)]
        [DisplayTemplateChoice("modern", "Modern", SortOrder = 3)]
        [DisplayTemplateChoice("monospace", "Monospace", SortOrder = 4)]
        public string Typography { get; set; } = "default";

        [JsonIgnore]
        [DisplayTemplateSetting(DisplayName = "Content Width", SortOrder = 30)]
        [DisplayTemplateChoice("default", "Default", SortOrder = 1)]
        [DisplayTemplateChoice("narrow", "Narrow", SortOrder = 2)]
        [DisplayTemplateChoice("wide", "Wide", SortOrder = 3)]
        [DisplayTemplateChoice("full", "Full Width", SortOrder = 4)]
        public string ContentWidth { get; set; } = "default";

        [JsonIgnore]
        [DisplayTemplateSetting(DisplayName = "Accent Color", SortOrder = 40)]
        [DisplayTemplateChoice("teal", "Teal", SortOrder = 1)]
        [DisplayTemplateChoice("blue", "Blue", SortOrder = 2)]
        [DisplayTemplateChoice("purple", "Purple", SortOrder = 3)]
        [DisplayTemplateChoice("orange", "Orange", SortOrder = 4)]
        public string AccentColor { get; set; } = "teal";
    }

コンテンツのクエリ

しかし、もちろん、コンテンツのクエリやナビゲーションなどもできるようにしたいと思うでしょう。これは、ライブラリでもすぐに使用できるようにサポートされています。そして、ある意味では、あなたも認識しているかもしれません。

public class MyService
{
    private readonly IContentRepository _repository;

    public MyService(IContentRepository repository)
    {
        _repository = repository;
    }

    public async Task Example()
    {
        // Get content by URL path
        var page = await _repository.GetContentByPath("/en/about");

        // Get content by key
        var content = await _repository.GetContent("abc-123-def");

        // Get child content
        var children = await _repository.GetChildren("parent-key-123");
    }
}

あるいは、検索やより高度なナビゲーションなどを実行したい場合は、さらに LINQ スタイルのクエリを実行することもできます。

// Basic query
var articles = await GraphQuery.For(client)
    .Where(f => f.Metadata.Status.Eq("Published"))
    .OrderBy(a => a.MetaData.Published, OrderDirection.DESC)
    .Take(10)
    .ToListAsync();

などなど

もちろん、SaaS プレビュー モードのサポートや、コンテンツ エリア、エクスペリエンス構成、コンテンツ エリアなどの Optimizely 固有の要素をすべてレンダリングするための多数のタグヘルパーもサポートされています。

付属のサンプル サイトで、すべてがどのように組み合わされるかを確認できます。現時点では、Razor ページと MVC サンプル サイトの両方があり、Blazor セルフサービス サイトも準備中です。含まれているサンプル サイトはさらに別の架空の会社で、AI によって数回のプロンプトで作成されました。

AI

当然、エージェントを使用してサイトを構築することも想定されます。そのプロセスを容易にするために、エージェントが HeadlessKit の操作方法や、Optimizely SaaS を直接クエリする方法をすぐに学べるように、AI ドキュメントも含めました。
エージェントにサンプル サイトの構築を依頼したとき、クライアント キーとシークレット、および SaaS コンテンツ管理 API の知識を使用して、CMS で直接コンテンツを作成するよう依頼したところ、見事にそれが実現しました。

デモサイト

自分でデモ サイトを実行してみたい場合は、リポジトリをプルし、アプリ設定またはユーザー シークレットを入力して、Optimizely SaaS CMS に対して実行できます (運が良ければ、私のように無料トライアルを手に入れることができるかもしれません)。

コンテンツにはエクスポート パッケージも含めたので、簡単に実行できるはずです。

#HeadlessKit #を使用して #.NET #で #Optimizely #SaaS #CMS #のヘッドを構築する

執筆者について: nipponese

Nipponese News編集部は、国内外のニュースを日本語で分かりやすくお届けします。