Contentfulのアプリを自作してみよう! 単語数カウンターを導入してみる。

2021.07.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ベルリンオフィスの小西です。

ヘッドレスCMSのContentfulでは、Appsという機能を使って、ダッシュボードや記事入力機能を自分で拡張することができます。

WordPressのプラグインを簡単に自作できるイメージが近いと思います。

今回は、記事内の入力単語数と、読み終わるまでの目安時間をサイドバーに表示する、簡単なアプリを作ってみたいと思います。

そもそもContentfulのAppsって?

Contentfulの機能を拡張する外部プラグインを指します。

Appsでできること

  • 既存のエントリーフィールドのカスタマイズ
  • エディターに独自のフィールドを追加する
  • ABテストのためのコンテンツのバージョン管理
  • CIビルドやサードパーティサービスをトリガーする

本記事で紹介するように自作もできますし、マーケットプレイスからサードパーティ(DropboxやCloudinaryなどなど)のアプリをインストールしてContentfulを使いやすくすることも可能です。

1. Contentful側の準備

まずはContentfulのダッシュボードで準備をします。

新たにContent modelを作成します。今回は Sample post という名前にします。

[Long text]でフィールドを作成します。名前は Content (Field ID: contnt )にしておきます。ここで設定する[Field ID]をメモしておいてください。

2. ローカルでアプリの作成

ローカルでアプリを作成します。

npx @contentful/create-contentful-app init my-sample-app
cd my-sample-app
npm run start

これで http://localhost:3000 にアクセスして、下記のような表示が出たらOKです。

アプリを終了し、読了時間を表示するためのパッケージをインストールします。

npm install reading-time

reading-timeは https://medium.com/ のような想定読了時間の表示が可能になるパッケージです。

/my-sample-app の中のsrc/components/Sidebar.tsx を開き、下記の通りに変更します。 ENTRY_FIELD_ID に、先ほどContentfulで作成したフィールドID content を記載するのをお忘れなく。

import React, { useState, useEffect } from 'react';
import { List, ListItem, Note } from '@contentful/forma-36-react-components';
import { SidebarExtensionSDK } from '@contentful/app-sdk';
import readingTime from 'reading-time';

interface SidebarProps {
  sdk: SidebarExtensionSDK;
}

const CONTENT_FIELD_ID = 'ENTRY_FIELD_ID';

const Sidebar = (props: SidebarProps) => {
  const { sdk } = props;

  const contentField = sdk.entry.fields[CONTENT_FIELD_ID];

  const [blogText, setBlogText] = useState(contentField.getValue());

  // Listen for onChange events and update the value
  useEffect(() => {
    const detach = contentField.onValueChanged((value) => {
      setBlogText(value);
    });
    return () => detach();
  }, [contentField]);

  // Calculate the metrics based on the new value
  const stats = readingTime(blogText || '');

  // Render the metrics with Forma36 components
  return (
    <>
      <Note style={{ marginBottom: '12px' }}>
        Metrics for your blog post:
        <List style={{ marginTop: '12px' }}>
          <ListItem>Word count: {stats.words}</ListItem>
          <ListItem>Reading time: {stats.text}</ListItem>
        </List>
      </Note>
    </>
  );
};

export default Sidebar;

これでローカル側の準備は完了です。

再び npm run start でアプリを立ち上げておきます。

3. Contentfulにインストール

3-1. アプリのConfiguration

Contentfulのダッシュボードに戻り、[Organization]の設定ページに遷移してから、[Create app]します。

下記の通り情報を入力して、[Create]でアプリを作成します。

  • Name [Reading time widget]
  • Frontend [http://localhost:3000]
  • Locations [App configuration screen]と[Entry sidebar]にチェック

3-2. アプリのインストール

Contentfulのスペースに入り、[Apps]から先ほど作ったアプリをインストールします。

この時、ローカルのアプリが http://localhost:3000 でアクセス可能である必要があります。アプリが立ち上がっていない場合、インストールはFailedになります。

今回は試しなのでlocalhostでホストしていますが、どこかクラウドでホストしてそのエンドポイントを読み込ませることも、また、ソースコード一式をビルドしてContentfulの中でホストすることもできます。

3-3. アプリをサイドバーに設定

次に、先ほど作成したContent modelの編集を行います。

サイドバーに、インストールしたアプリを追加します。

以上で準備は完了です。実際にアプリを使ってみます。

4. アプリを使ってみる

先ほど作成したContent modelの記事投稿ページに遷移し、適当に文字を入力してみます。

サイドバーに単語数のカウントと読了想定時間が表示されています。

完了!

注意点として、reading-timeはスペース区切りで単語をカウントします。つまり日本語では一繋がりの単語として認識されてしまいますのでご注意ください。

最後に

今回はシンプルなアプリを作ってみましたが、例えば動的にプレースホルダーを設定したり、記事内の変更をリアルタイムで検知して外部に通知を送ったり、いろいろな使い道があるかと思います。

ClassmethodではContentfulの契約のご相談、構築支援をしています。ご興味のある方はぜひ弊社までお問い合わせください。

参考記事

https://www.contentful.com/developers/docs/extensibility/app-framework/tutorial/