> ## Content Index
> Fetch the complete content index at: https://iris-on-bookrest.info/llms.txt
> Use this file to discover other available public pages before exploring further.

# ブログにいいねボタンを実装してみた
- URL: https://iris-on-bookrest.info/make-like-button/
- Published: 2026-06-26T06:04:14.000Z
- Updated: 2026-06-26T08:36:10.000Z
- Author: やまぐろ
- Tags: プログラミング

どうも、本業エンジニアです。今回はこのブログに「いいねボタン」を実装してみました。細かいコードはAIに聞けばすぐ出てくると思うので、主に構成とか仕組みについて紹介していこうと思います。

なお、外部のいいねボタンサービス（LikeBtn、Lyket）を利用しない方針でやっています。また、無料で実装&運用できる方法を選択しています。

## 完成イメージ

以下のようないいね機能が出来上がります。

押すといいね数が繰り上がるボタン↓

![Pasted image 20260626144718.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626144718.png)

記事上にいいね数を表示↓

![Pasted image 20260626144730.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626144730.png)

## ざっくり処理フロー

以下のフローで実装しています。恐らく登場人物はなんとなくこれで分かるかと思います。

![iine_waruine.jpg](https://iris-on-bookrest.info/content/images/2026/06/iine_waruine.jpg)

## 構成について

今回は以下の構成でやっていきます。

- Cloudflare Workers（いいね数の管理に利用、無料で使えます）
- Ghostの独自テーマ（いいねボタンの表示、いいね数の更新連携）  
コードが必要な部分も上記のみになるので、比較的少ないコード量で実装が可能です。

## ざっくり手順

以下のステップでやっていくといいと思います。

- Cloudflare Workersの設定
- フロントエンド側の実装  
あまり細かくないかもですが、ここから先は手順になります。

### Cloudflare Workersの設定

①まずはCloudflareにログインして「Workers KV」のメニューに進みます。

![Pasted image 20260626142656.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626142656.png)

②「Create Instance」を押します。

![Pasted image 20260626142715.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626142715.png)

③名前空間名を決めます。今回は「TEST‗KV」とか好きななまえで大丈夫です。そしたら作成を押せば、名前空間が作成されます。

![Pasted image 20260626142752.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626142752.png)

④メニューから「Workers & Pages」に移動します。

![Pasted image 20260626142954.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626142954.png)

⑤「アプリケーションを作成する」を押す

![Pasted image 20260626143009.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626143009.png)

⑥「hello worldを開始する」を押す

![Pasted image 20260626143054.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626143054.png)

⑦「デプロイ」を押す

![Pasted image 20260626143153.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626143153.png)

⑧作成したアプリケーションに、先ほど作成した名前空間を紐づける。バインディングを追加 > KV 名前空間から紐づけを行います。上手くいくと以下のような形で表示されます。

![Pasted image 20260626143411.png](https://iris-on-bookrest.info/content/images/2026/06/Pasted-image-20260626143411.png)

⑨「コードを編集する」を押し、ソースコードを記述する  
参考までに、このブログで動かしたソースコードを貼っておきます。

```javascript
export default {
  async fetch(request, env) {
    // CORSエラー回避のためのヘッダー設定（JSONレスポンス用のContent-Typeも追加）
    const corsHeaders = {
      "Access-Control-Allow-Origin": "ブログのドメイン！！！",
      "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type",
      "Content-Type": "application/json",
    };

    if (request.method === "OPTIONS") {
      return new Response(null, { headers: corsHeaders });
    }

    try {
      const url = new URL(request.url);
      const postId = url.pathname.split("/").pop(); // URLの末尾から記事IDを取得

      if (!postId) {
        return new Response(JSON.stringify({ error: "Missing Post ID" }), { 
          status: 400, 
          headers: corsHeaders 
        });
      }

      // KVバインディングの存在確認
      if (!env.KV名前空間名) {
        return new Response(JSON.stringify({ error: "KV名前空間名 binding is missing in wrangler.toml" }), { 
          status: 500, 
          headers: corsHeaders 
        });
      }

      const kvKey = `likes:${postId}`;

      // 【POST】いいねを+1する
      if (request.method === "POST") {
        const currentLikes = parseInt(await env.KV名前空間名.get(kvKey) || "0", 10);
        const newLikes = currentLikes + 1;
        await env.KV名前空間名.put(kvKey, newLikes.toString());
        return new Response(JSON.stringify({ likes: newLikes }), { headers: corsHeaders });
      }

      // 【GET】現在のいいね数を取得する
      const likes = parseInt(await env.KV名前空間名.get(kvKey) || "0", 10);
      return new Response(JSON.stringify({ likes }), { headers: corsHeaders });

    } catch (err) {
      // エラー発生時もCORSヘッダーを付与してエラー内容を返す
      return new Response(JSON.stringify({ error: err.message, stack: err.stack }), { 
        status: 500, 
        headers: corsHeaders 
      });
    }
  }
};

```

⑩設定完了！  
これでWorkers側に、いいね数を管理するためのエンドポイントが作成されました。

## フロントエンド側の実装

次はフロントエンド側の実装です。こちらに関してはそれぞれの利用言語によってしまうのでコードの紹介は難しいのですが、やりたいことは「上記で作成したエンドポイントにリクエストを投げる」です。  
Workers側のコードをAIに読み込ませてあげれば、それを利用したフロントエンド側の実装を教えてくれるはず！

## まとめ：いいねボタンは自分で実装できる！

多少慣れは必要かもですが、いいねボタンは自分で実装できます！もちろんボタン用のWEBサービス使ったり、WordPressならプラグイン入れた方が楽なのですが、そこに依存したくないのであれば今回のような実装方針でいいのではないでしょうか。

ちなみにこのブログはGhostで運用＆自分でテーマファイルいじってるので、いいねボタンも自前でやることにしました。もちろんWordPressの子テーマとかでもできると思うので、見た目とか位置とか自分でやりたい人は、ぜひやってみてください。

## 最後に

AIにお願いしたら30分くらいで本番導入まで行けてしまった。ありがてえ。

[ ![Web開発者のための［入門］Cloudflare Workers--JavaScript・TypeScriptの簡単・高速プラットフォーム [ 福岡 秀一郎（syumai） ]](https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4387/9784297154387_1_23.jpg?_ex=128x128) ](https://hb.afl.rakuten.co.jp/hgc/g00q0724.qk1jndb6.g00q0724.qk1jo511/?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F18491500%2F&m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F21836963%2F&rafcid=wsc%5Fi%5Fis%5F1028889962324654632&ref=iris-on-bookrest.info) 

[Web開発者のための［入門］Cloudflare Workers--JavaScript・TypeScriptの簡単・高速プラットフォーム \[ 福岡 秀一郎（syumai） \]](https://hb.afl.rakuten.co.jp/hgc/g00q0724.qk1jndb6.g00q0724.qk1jo511/?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F18491500%2F&m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F21836963%2F&rafcid=wsc%5Fi%5Fis%5F1028889962324654632&ref=iris-on-bookrest.info) 

ショップ: 楽天ブックス 

¥2,860 

※価格やショップ情報は楽天のものです 

[楽天で見る ](https://hb.afl.rakuten.co.jp/hgc/g00q0724.qk1jndb6.g00q0724.qk1jo511/?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F18491500%2F&m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F21836963%2F&rafcid=wsc%5Fi%5Fis%5F1028889962324654632&ref=iris-on-bookrest.info) [Amazonで探す ](https://www.amazon.co.jp/s?k=Cloudflare%20Workers&tag=yama00c-22&ref=iris-on-bookrest.info)