🦏

microCMSを導入してみた

2023/01/24に公開

私が通っている学校の課題でmicroCMSを利用して飲食店サイトを1ページ作成する課題が出た為、
課題を作成しつつ紹介していきたいと思います。

成果物

私が個人的に大好きなパンケーキ屋さんをゴールとして作成しました。

利用した部分

- MENU
- NEWS

環境

- Node v18.12.1
- Next.js
- tailwind.css

実装

では早速実装に移っていきます。

開発準備

今回はNext.jsで実装をしていきますので、まずNext.jsアプリを作成します。

npx create-next-app アプリ名

*TypeScriptの有無を聞かれるのでyesを選択

localにアプリが作成されたことが確認できたら、そちらの階層に移動
一度サーバーを起動して問題ないことを確認

npm run dev

上記の画面が確認できたらmicroCMSへ移ります。
https://microcms.io/

上記のサイトから自分のアカウントを作成します。
その後サービスを作成してください。

サービスの作成が完了したら画面右上からAPIを追加します。

APIの作成を"自分で決める"を選択

APIの基本情報を入力
今回は"お知らせ"を作っていきます。

APIの型を"リスト形式"で選択

その後"API設定"の"APIスキーマ"にてフィールドを決めて追加
今回は、title(テキストフィールド),image(画像),text(テキストエリア)のフィールドを作成

フィールドを追加したら、画面右上追加ボタンから"お知らせ"の中にデータを登録していきます。

ここまで完了したら、ターミナルに戻りmicroCMSを利用するためのmicrocms-js-sdkをインストールします。

npm install microcms-js-sdk

ここまでがmicroCMSの設定です。
"menu"もAPIの作成から"news"同様に作成します。

SDKの初期化

ここからプロジェクトファイルに戻ります。

'アプリ名/'フォルダ直下に.env.localファイルを作成してAPI_KEYを設定します。

.env.local
API_KEY='アプリのAPI'

アプリのAPIは、microCMS内のサービス設定 > API-KEYから確認可能です。

次に'アプリ名/'フォルダ直下に'libs'フォルダを作成します。
'アプリ名/libs/'フォルダ直下にclient.jsを作成してSDKの初期化を行います。

client.js
import { createClient } from "microcms-js-sdk";

export const client = createClient({
  serviceDomain: "ドメイン",
  apiKey: process.env.API_KEY,
});

serviceDomainは以下の赤線で隠れている部分に表示されている文字列です。

NEWS エリアを作る

アプリ名/pages/index.tsx
一旦dataが取得できていることを確認します。

index.tsx
import styles from "../styles/Home.module.css";
import { client } from "../libs/client";

//SSG
export const getStaticProps = async () => {
  const newsData = await client.get({
    endpoint: "news",
  });
  
  //dataが取得できているのか確認
  console.log(newsData);

  return {
    props: {
      news: newsData,
    },
  };
};

export default function Home({ news }) {
  return <div className={styles.container}></div>;
}

コンソールを確認すると無事dataを取得できていました。
ですが、取得したいのは配列の中身ですのでオブジェクト内のcontentsを指定して必要な値を拾っていきます。

修正後

実際にページ内に表示していきます。

index.tsx
import styles from "../styles/Home.module.css";
import { client } from "../libs/client";

//SSG
export const getStaticProps = async () => {
  const newsData = await client.get({
    endpoint: "news",
  });

  console.log(newsData);

  return {
    props: {
      news: newsData.contents,
    },
  };
};

export default function Home({ news }) {
  return (
    <div className={styles.container}>
      {news.map((news) => (
        <div>
          <img src={news.image.url} alt="" />
          <h2>{news.title}</h2>
          <p>{news.text}</p>
        </div>
      ))}
    </div>
  );
}

無事APIからdataを取得して画面に表示することができました。

完璧です。

style適応後

styleはtailwind.cssを利用しているので導入方法はこちらをご覧ください。
https://tailwindcss.com/docs/guides/nextjs

index.tsx
import { client } from "../libs/client";

//SSG
export const getStaticProps = async () => {
  const newsData = await client.get({
    endpoint: "news",
  });

  console.log(newsData);

  return {
    props: {
      news: newsData.contents,
    },
  };
};

export default function Home({ news }) {
  return (
    <div className="w-full px-60">
      <h1 className="flex justify-center text-5xl font-medium tracking-wider pt-40 pb-20">
        NEWS
      </h1>
      <div>
        <div className="flex flex-nowrap gap-20 ">
          {news.map((news) => (
            <div key={news.id} className="w-2/5">
              <img
                className="w-full h-48 object-cover object-center"
                src={news.image.url}
                alt=""
              />
              <h2 className="mt-8 text-lg">{news.title}</h2>
              <p className="mt-4">{news.text}</p>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

その後同様にMenuエリアにもAPIから取得したdataを利用して画面を作成していきます。

全体コード

長尺になっているので利用する際はファイルを分けて作成することをお勧めします。

index.tsx
import { client } from "../libs/client";

//SSG
export const getStaticProps = async () => {
  const newsData = await client.get({
    endpoint: "news",
  });
  const menuData = await client.get({ endpoint: "menu" });
  console.log(newsData);
  console.log(menuData);

  return {
    props: {
      news: newsData.contents,
      menu: menuData.contents,
    },
  };
};

export default function Home({ news, menu }) {
  const salad = "SALAD";
  const pancake = `PANCAKES (NEW YORK'S No.1)`;
  const main = `CLINTON STREET'S FAMOUS`;
  const other = "OTHER ";

  return (
    <div>
      <div className="bg-fixed h-screen w-full bg-cover bg-center bg-[url('../public/clintonstreetbaking_shop_outside.png')]">
        <div className="w-full">
          <h1 className="flex justify-center pt-20 text-white text-6xl font-bold leading-loose">
            CLINTON STREET BAKING
          </h1>
        </div>
      </div>
      <div className="w-full px-60 bg-neutral-100">
        <h1 className="flex justify-center text-5xl font-medium tracking-wider pt-40 pb-20">
          MENU
        </h1>
        <div className="w-full flex justify-between gap-16">
          <div className="w-1/2">
            <h2 className="text-2xl font-bold mb-4">SALAD</h2>
            {menu.map((menu) => (
              <div key={menu.id}>
                <div className="flex justify-between">
                  <p className="text-xl">
                    {menu.Category === salad ? menu.name : false}
                  </p>
                  <span>{menu.Category === salad ? menu.price : false}</span>
                </div>
                <p className="mt-2">
                  {menu.Category === salad ? menu.sub_text : false}
                </p>
                <span className="text-xs text-inherit">
                  {menu.Category === salad ? menu.annotation : false}
                </span>
              </div>
            ))}
          </div>
          <div className="w-1/2">
            <h2 className="text-2xl font-bold mb-4">
              PANCAKES (NEW YORK'S No.1)
            </h2>
            {menu.map((menu) => (
              <div key={menu.id}>
                <div className="flex justify-between">
                  <p className="text-xl">
                    {menu.Category === pancake ? menu.name : false}
                  </p>
                  <span>{menu.Category === pancake ? menu.price : false}</span>
                </div>
                <p className="mt-2">
                  {menu.Category === pancake ? menu.sub_text : false}
                </p>
                <span className="text-xs text-inherit">
                  {menu.Category === pancake ? menu.annotation : false}
                </span>
              </div>
            ))}
          </div>
        </div>
        <div className="w-full flex justify-between gap-16 mt-12">
          <div className="w-1/2">
            <h2 className="text-2xl font-bold mb-4">CLINTON STREET'S FAMOUS</h2>
            {menu.map((menu) => (
              <div key={menu.id} className="mb-8">
                <div className="flex justify-between">
                  <p className="text-xl">
                    {menu.Category === main ? menu.name : false}
                  </p>
                  <span>{menu.Category === main ? menu.price : false}</span>
                </div>
                <p className="mt-2">
                  {" "}
                  {menu.Category === main ? menu.sub_text : false}
                </p>
                <span className="text-xs text-inherit ">
                  {menu.Category === main ? menu.annotation : false}
                </span>
              </div>
            ))}
          </div>
          <div className="w-1/2">
            <h2 className="text-2xl font-bold mb-4">OTHER</h2>
            {menu.map((menu) => (
              <div key={menu.id}>
                <div className="flex justify-between">
                  <p className="text-xl">
                    {menu.Category === other ? menu.name : false}
                  </p>
                  <span>{menu.Category === other ? menu.price : false}</span>
                </div>
                <p className="mt-2">
                  {menu.Category === other ? menu.sub_text : false}
                </p>
                <span className="text-xs text-inherit">
                  {menu.Category === other ? menu.annotation : false}
                </span>
              </div>
            ))}
          </div>
        </div>
      </div>
      <div className="w-full px-60">
        <h1 className="flex justify-center text-5xl font-medium tracking-wider pt-40 pb-20">
          NEWS
        </h1>
        <div>
          <div className="flex flex-nowrap gap-20 ">
            {news.map((news) => (
              <div key={news.id} className="w-2/5">
                <img
                  className="w-full h-48 object-cover object-center"
                  src={news.image.url}
                  alt=""
                />
                <h2 className="mt-8 text-lg">{news.title}</h2>
                <p className="mt-4">{news.text}</p>
              </div>
            ))}
          </div>
        </div>
      </div>
      <div className="flex justify-center py-2 bg-red-800 text-white leading-loose mt-60">
        <p>©︎ clinton street baking</p>
      </div>
    </div>
  );
}

まとめ

Next.jsを利用すること自体が初めてだったので恐らく不正等な書き方になっているとは思いますが、簡単にCMSを導入することができました。microCMSは日本製ということもあり要チェックのCMSです。
利用方法も簡単ですのでぜひ使ってみてください。

Discussion