ともすたmedia
AstroやNext.jsで開発したサイトを公開できる「静的ホスティングサーバー」といえば、VercelやNetlify、Cloudflare等が思い浮かびます。しかし、これらのサービスはインタフェースが英語ですし、実用で使うと意外と料金がかかったりして、使うのを躊躇してしまうこともあります。
そんな中、国産で日本語インタフェース完備、そして料金もかなりリーズナブルな静的ホスティングサーバーが登場しました。今回は、こちらの「200stack(にひゃくすたっく)」を利用して、AstroとヘッドレスCMSの「NILTO」を使って、簡単なサイトを公開する手順をご紹介します。

200stackの料金体系
200stackは、基本料金が月額300円で、月間30万リクエストまで利用できます。それを超えると、2万リクエストごとに16円〜20円という従量課金に移行しますが、いずれにしてもかなりリーズナブルな料金体系です。

また、プロジェクトを公開したときに初めて課金されるため、試したり開発をする間は無償で利用できる等、開発者にとっても非常に使いやすいプランになっています。
Astroのプロジェクトを作ろう
まずは、Astroでプロジェクトを作成してGitHubにリポジトリを作成しましょう。

ターミナルを起動して、次のコマンドを入力します。
npm create astro@latest
なお、Astroの利用には「Node.js」のインストールが必要です。質問は、いずれもYesと回答して良いでしょう。テンプレートはここでは、「Use minimal (empty) template」を選択しました。

プロジェクトが作れたら、エディタなどで開いて、次のコマンドで開発サーバーを起動しましょう。
npm run dev
発行されるアドレスにアクセスし、次のような画面が表示されていれば正しく動作しています。

GitHubにプッシュしよう
200stackは、GitHubのリポジトリを通じて送信されるので、作ったプロジェクトをGitHubにプッシュしましょう。ここでは、Cursorでブランチを発行しました。

200stackに接続しよう
ここまでできたら、200stackに接続ができます。200stackで無料アカウントを作成しましょう。
「GitHub連携」をクリックし、アカウントを接続します。

そして、接続するリポジトリを選びます。「All Repositories」を選べば、所有するすべてのリポジトリを接続できますが、ここでは必要なものだけを選択しました。

200stackに戻って「プロジェクト」の中に「アプリ」を作成しましょう。リポジトリを選択します。

設定画面は、Astroの場合はいずれも標準のままで問題ありません。

「アプリを作成」ボタンをクリックしたら、「デプロイメント」タブを開いて「デプロイを開始」ボタンをクリックします。これで、GitHubからファイルが取り込まれ、「ビルド」作業が行われます。

ビルドが終わると、「プライベートURL」が発行されます。これは、200stackにログイン中にのみ確認可能なアドレスです。これにアクセスしましょう。

Astroの画面が正しく表示されていれば、作業完了です。
NILTOと接続しよう
それでは今度は、ヘッドレスCMSの「NILTO」と接続をしてみましょう。NILTOの無料アカウントを作成します。
ログインをしたら「スペース→新規作成」をクリックして、新しいスペースを作成します。

スペースに入ったら、今度は「モデル」を作成します。このモデルが、ニュースやブログ等、記事を蓄積するエリアになります。「モデル→新規作成」をクリックしましょう。

モデル名を「お知らせ」、モデルLUIDを「news」などとして作成します。

すると、フォームの作成画面が表示されるので必要な項目を追加しましょう。ここではシンプルに1行テキストだけを追加します。

フィールド名を「タイトル」、LUIDを「title」として保存します。

これで準備完了です。
コンテンツを作ろう
それでは、コンテンツを作って行きましょう。「コンテンツ→お知らせ」をクリックし、エディタに入力します。

「公開」ボタンをクリックして公開しましょう。これで準備完了です。

NILTOとAstroを接続しよう
続いて、NILTOとAstroを接続します。ルートフォルダに「.env」という名前のファイルを作成し、次のように入力します。
NILTO_API_KEY=
APIキーは、スペースの「APIキー」メニューから発行できます。

ここでは「公開のみ」でよいので、クリックしてトークンをコピーしておきましょう。

これを、先の文字列に貼り付けます。

プログラムを作成しよう
続いて、NILTOからコンテンツを取得するプログラムを開発します。公式のチュートリアルにある、サンプルプログラムをコピーしましょう。
「src」フォルダに「lib/getContents.js」というフォルダ・ファイルを作成して、貼り付けます。ただし、「modelId」という箇所だけ設定したモデルのIDに合わせる必要があるので、ここでは「news」に書き換えておきましょう。書き換えたプログラムは次の通りです。
// .envファイルからAPIキーを取得する関数
function get_api_key() {
// Astroでは import.meta.env を使用
const apiKey = import.meta.env.NILTO_API_KEY;
return apiKey;
}
// APIからデータを取得する非同期関数
export async function getContents() {
const apiKey = get_api_key();
const requestHeader = new Headers();
requestHeader.set("Content-Type", "application/json");
requestHeader.set("X-Nilto-Api-Key", apiKey);
// NILTO APIのエンドポイントURL
const modelId = "news"; // NILTOで作成したモデルのID
const apiUrl = `https://cms-api.nilto.com/v1/contents/?model=${modelId}&order=-_published_at`;
try {
const response = await fetch(apiUrl, {
headers: requestHeader,
});
const data = await response.json(); // 型アサーションを削除
return { contents: data.data }; // APIレスポンスの構造に合わせて "data.data" を返す
} catch (error) {
console.error("Failed to fetch contents:", error);
return { contents: [] }; // エラー時は空の配列を返す
}
}
表示画面を作ろう
続けて、表示画面を作成します。同じページの下に「index.astro」のサンプルがあるので、こちらもコピーしましょう。次の通りです。
---
import Layout from "../layouts/Layout.astro";
import { getContents } from "../lib/getContents.js";
const { contents } = await getContents();
---
<Layout title="Astro x NILTO ブログ">
<main>
<h1>NILTOブログ一覧</h1>
{
contents && contents.length > 0 ? (
<ul>
{contents.map((content: any) => (
<li>
<a href={`/blog/${content._id}/`}>{content.title}</a>
<p>
<small>
公開日:{" "}
{content._published_at
? new Date(content._published_at).toLocaleDateString()
: "未公開"}
</small>
</p>
</li>
))}
</ul>
) : (
<p>記事がありません。</p>
)
}
</main>
</Layout>
<style>
main {
margin: auto;
padding: 1.5rem;
max-width: 80ch;
}
h1 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 1rem;
}
ul {
list-style: none;
padding: 0;
}
li {
padding: 0.5rem 0;
border-bottom: 1px solid #eee;
}
li a {
font-size: 1.25rem;
text-decoration: none;
color: #333;
}
li a:hover {
text-decoration: underline;
}
p small {
color: #777;
}
</style>
「Empty template」で作成した場合、「layouts/layout.astro」ファイルが存在しないので、これも作成しておきましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
<slot />
</body>
</html>
こうして、画面を表示するとNILTOのエントリーが表示されます。

200stackに同期しよう
それでは、ここまで作ったプログラムを200stackに同期しましょう。同期は簡単で、GitHubに最新のファイル群をプッシュします。

すると、自動的にデプロイが始まって、新しいページが公開されます。ただしこの時、記事が反映されません。

これは、先ほど「.env」というファイルに設定したNILTOのAPIキーが、200stack側に設定されていないため。
アプリの「設定」タブの「環境変数」という箇所に、「対象環境」を「本番」にして、キーと値を設定します。保存形式は「シークレット」にしておきましょう。保存します。

これで再度デプロイをしましょう。「デプロイメント」タブで「手動デプロイ」を開始します。

これで、記事が反映されました。

Webhookで自動反映しよう
これで、Webサイトとしても公開ができますが、現状ではNILTOで記事を追加しても、200stack側で再度「デプロイ」を手動で行わないと、記事が反映されません。それは、静的サーバーは表示時ではなく「デプロイ」時に、記事を取り込んだりページを制作するというしくみのため。
そこで、NILTOで更新をしたら、自動的に再度デプロイが行われるように設定します。これを行うのが「Webhook」というしくみです。
Webhookは、NILTO側が特定のタイミング(トリガーと言います)で、Webhookを設定された相手に発信します。これを受け取った200stackは、そのタイミングで再度ビルドを行って、NILTOから新しい記事を取り込むという訳です。それぞれ設定しましょう。
200stackのWebhookを設定しよう
まずは、200stackのアプリの「設定」タブをクリックして、「CMS Webhook」で「本番」のWebhookを作成します。URLとシークレット情報が表示されるので、いずれもコピーしておきましょう。

NILTO側の設定をしよう
続いて、NILTO側で設定をします。スペースで「Webhook」をクリックしましょう。

Webhook名には「200stack」などと入力し、「リクエストURL」に先ほどコピーしたアドレスを入力します。
ステータスを有効にし、「コンテンツ詳細画面に〜」は「しない」にしておきましょう。

続いて、Webhookが発信されるタイミング(トリガー)を設定します。ここでは、公開の状態や削除の状態を編集したときだけで良いでしょう。すべてにチェックをしても特に問題はありません。

そしたら、ヘッダーの部分で「シークレットヘッダーを追加」をクリックして、先ほどコピーした「シークレット」を貼り付けます。キーの名前は、次のようにしましょう。
X-NILTO-WEBHOOK-TOKEN
これで完了です。「作成」ボタンをクリックしましょう。
記事を追加しよう
それでは、この状態でNILTOに記事(コンテンツ)を追加してみましょう。200stackに戻ると、デプロイが始まっていることが分かります。

少し待てば、新しい記事が自動的に追加されます。

こうして、200stackとNILTO、Astroを利用したWeb制作が可能になります。先の通り、実際にドメインを割り当てて公開をしても、月額300円からスタートすることができるため、非常に使いやすく、また日本語で扱うことができますし、複数のメンバーで同じスペースで作業をすることもできるなど、非常に使いやすいサーバーになっています。
是非、活用していきましょう。