# 静的HTMLサイトにお知らせ欄を追加する：CMSと素のJavaScript

公開日: 2026-10-20 | 更新日: 2026-10-20 | URL: https://blog.genko.me/static-site-news-cms

> 静的HTMLサイトに、genko.meの配信APIと素のJavaScriptでお知らせ一覧を追加する方法を解説します。フレームワーク不要の実装例から、APIキーの公開条件、更新反映、SEOを重視する場合の構成まで整理します。

静的HTMLサイトのお知らせ欄は、CMSで公開した記事をブラウザの`fetch`で取得し、既存のHTMLに差し込む方法で追加できます。フレームワークもサイト全体の作り直しも不要です。ただし、APIキーを隠したい場合や、お知らせ本文を最初からHTMLに含めたい場合は、サーバー経由の取得かビルド時生成を選びます。

本記事はgenko.meの運営側が執筆しています。2026年10月時点の[genko.me](https://genko.me/)の仕様に沿って、公開情報だけのお知らせ一覧を作ります。

## 静的サイトのお知らせをCMSで管理する構成

サイトのヘッダーやサービス紹介は今までのHTMLのまま残し、更新が多いお知らせだけをCMSで管理します。編集者は管理画面で原稿を保存・公開し、サイトは配信APIからJSONを読みます。

| 方法 | 更新が表示されるタイミング | 向いている条件 |
| --- | --- | --- |
| ブラウザでfetch | 次にページを開いて取得したとき | 既存HTMLへ小さく追加したい |
| Web Components | 次にページを開いて取得したとき | 一覧・詳細の表示部品も使いたい |
| ビルド時にHTML生成 | 再ビルドして配信したあと | 初期HTMLに本文を含めたい |
| サーバー経由 | サーバーやキャッシュの設定による | キーをブラウザへ渡したくない |

「静的サイトだからCMSを使えない」という制約はありません。違うのは、原稿をいつ取得するかです。この記事では最も小さいブラウザ取得から始めます。

## 1. お知らせAPIと公開記事を用意する

[クイックスタート](https://docs.genko.me/getting-started)を参考に、ワークスペースにリスト形式のAPIを作成します。エンドポイントは`news`、フィールドはテキストの`title`とリッチテキストの`body`にします。

1. お知らせを1件作成し、タイトルと本文を入力します。
2. 公開状態を「公開」に変更し、保存します。
3. APIキーを発行し、「選択したAPIのみ」で`news`だけを許可します。
4. ワークスペースIDとキーを控えます。

`publishedAt`は公開日時のシステム項目です。下書きのままでは通常の配信一覧に出ません。原稿を書くだけでなく、状態を変更して保存するところまで確認してください。

完成したお知らせサイトを土台にしたい場合は、[お知らせスターター](https://docs.genko.me/guides/announcements-starter)もあります。ただし、こちらはNext.jsのテンプレートです。既存HTMLに貼るだけのコードとは導入方法が異なります。

## 2. HTMLにお知らせ一覧を追加する

次のコードを`news.html`として保存し、サイトのHTTPサーバーで配信します。既存ページでは`section`と`script`を必要な位置へ移せます。`your-workspace`と`YOUR_DELIVERY_API_KEY`は自分の値に置き換えてください。

```html
<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>お知らせ</title>
</head>
<body>
  <section aria-labelledby="news-title">
    <h2 id="news-title">お知らせ</h2>
    <p id="news-status" role="status">読み込み中です。</p>
    <ul id="news-list"></ul>
    <noscript>お知らせの取得にはJavaScriptが必要です。</noscript>
  </section>
  <script type="module">
    const url = new URL('https://api.genko.me/v1/your-workspace/news');
    url.searchParams.set('limit', '5');
    url.searchParams.set('orders', '-publishedAt');
    url.searchParams.set('fields', 'title,publishedAt');
    const status = document.getElementById('news-status');
    const list = document.getElementById('news-list');

    try {
      const response = await fetch(url, {
        headers: { 'X-API-KEY': 'YOUR_DELIVERY_API_KEY' },
      });
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      const { contents } = await response.json();
      for (const entry of contents) {
        const item = document.createElement('li');
        const time = document.createElement('time');
        if (entry.publishedAt) {
          time.dateTime = entry.publishedAt;
          time.textContent = new Date(entry.publishedAt)
            .toLocaleDateString('ja-JP');
        }
        const title = document.createElement('span');
        title.textContent = entry.title ?? '';
        item.append(time, ' ', title);
        list.append(item);
      }
      status.textContent = contents.length ? '' : 'お知らせはまだありません。';
    } catch {
      status.textContent = 'お知らせを取得できませんでした。時間をおいて再読み込みしてください。';
    }
  </script>
</body>
</html>
```

これはタイトルと日付の一覧で、詳細ページはまだ作っていません。タイトルを`textContent`で入れるため、文字列をそのままHTMLとして実行しません。本文のリッチテキストHTMLを表示する処理とは分けて考えます。

`orders=-publishedAt`は公開日時の新しい順です。`fields`で必要な項目だけを指定し、`limit`でトップページに出す件数を絞ります。APIのURLやクエリは[JavaScript導入ガイド](https://docs.genko.me/frameworks/javascript/getting-started)と同じです。

## APIキーを静的HTMLに書いてもよいですか

ブラウザへ配信したキーは、ソースや開発者ツールから読めます。JavaScriptの別ファイルに移したり、文字列を加工したりしても秘密にはできません。

genkoの[JavaScript概要](https://docs.genko.me/frameworks/javascript)では、公開する情報だけを読めるキーで、対象APIを限定し、第三者による利用で配信のレート枠を消費されるリスクを受け入れる場合に限り、ブラウザからの直接取得を案内しています。

別のAPIも読めるキー、下書きプレビュー用の`draftKey`、管理用の認証情報は公開ページへ入れません。条件に合わなければ、サーバーで取得して必要なJSONだけを返すか、ビルド時にHTMLを生成してください。配信APIは読み取り専用ですが、それだけでキーの公開が常に適切になるわけではありません。

## Web Componentsで一覧と詳細も作る方法

日付と見出しだけなら上の`fetch`で十分です。リッチテキストの表示や読み込み状態なども部品で組み立てたい場合は、`@genko-me/wc`を使えます。[HTML導入ガイド](https://docs.genko.me/frameworks/html/getting-started)にはimport mapを含む構成があります。

導入時は`@genko-me/wc/define`をimportして要素を登録します。`@genko-me/wc`だけでは登録されません。また、`genko-list`へ最初の取得結果の`initial`と、`getApiBinding()`由来の`fields`・`schemas`を渡します。HTMLのタグだけを置いても、接続情報や取得結果がなければ記事は出ません。

詳細ページは、たとえば`post.html?id=記事ID`というURLにして、IDを使って単一記事を取得します。リンク先だけを先に作らず、存在しない記事の表示、取得失敗、本文の表示まで揃えてから一覧にリンクを付けてください。

## お知らせの更新はいつ反映されますか

上の実装はページを開くたびにAPIへ問い合わせます。通常はHTMLの再アップロードやサイトの再ビルドは不要です。開いたままのタブは自動更新しないため、再読み込みが必要です。

一方、ビルド時にJSONやHTMLを埋め込む構成では、CMSの更新だけでは配信済みファイルが変わりません。Webhookをホスティング先のビルドフックへ接続するなど、再生成する仕組みを用意します。静的HTML自体にはWebhookを受け取るサーバーがありません。

Next.jsへ移す場合は[Webhookと再検証の実装](https://blog.genko.me/nextjs-webhook-revalidate)、静的生成を組み合わせる場合は[Astroでブログを作る方法](https://blog.genko.me/astro-blog-cms)も参照してください。

## SEOを重視するお知らせページの作り方

ブラウザ取得では、最初に返るHTMLには記事一覧のデータがありません。重要なお知らせの本文を検索や外部サービスへ確実に渡しやすくしたい場合は、ビルド時生成やサーバー描画を検討します。JavaScriptを実行しない取得方法でも読める構成になります。

トップページの数件だけをブラウザ取得にし、記事詳細は生成済みHTMLにする組み合わせも可能です。詳細ごとにURL、タイトル、説明文を用意し、終了したお知らせを削除するか残すかも決めます。

本番へ入れる前には、公開記事あり・0件・取得失敗の3状態を確認します。小さな欄でも、障害時にサイト全体が使いにくくならない表示を用意すると運用しやすくなります。

## よくある質問

### HTMLとJavaScriptだけでお知らせを更新できますか？

はい。公開記事をAPIから取得すれば、編集者はCMSだけで更新できます。ブラウザから取得する場合はAPIキーの公開条件を確認してください。

### お知らせを追加するためにWordPressは必要ですか？

必須ではありません。既存HTMLを残してCMSの配信APIだけを利用できます。サイト全体も管理したい場合の違いは[ヘッドレスCMSとWordPressの比較](https://blog.genko.me/headless-cms-vs-wordpress)で整理しています。

### 公開したのに一覧が空なのはなぜですか？

ワークスペースID、エンドポイント、キーの許可対象と有効期間を確認します。記事の公開状態を保存しているかも確認してください。

### Cookieなしでお知らせごとの閲覧数も数えられますか？

genkoのPV計測で記事IDに紐づけられます。[CookieなしのPV計測](https://blog.genko.me/cookieless-page-views)で、パスと記事の数え方を説明しています。

## 出典

2026年10月20日に確認しました。

- [genko.me](https://genko.me/)
- [JavaScriptから接続する](https://docs.genko.me/frameworks/javascript)
- [JavaScript導入](https://docs.genko.me/frameworks/javascript/getting-started)
- [HTML導入](https://docs.genko.me/frameworks/html/getting-started)
- [HTML実践・更新反映](https://docs.genko.me/frameworks/html/tutorial)
- [お知らせスターター](https://docs.genko.me/guides/announcements-starter)
