チャーなる(仮)

astro-notion-blog で固定ページを作成する

astro-notion-blog で Notion で編集が可能な固定ページを作成しました。

左が astro-notion-blog の固定ページ、右側が 固定ページの編集ページ(Notion)です。

image block

できるだけ簡単に実装したい

astro-notion-blog は最近できたばかりで、色々な機能をどんどん試したり実装したりしたいという気持ちがあるので、できるだけ簡単に作りたいと思いました。ということで、できるだけ既存のコードを使いまわして実装します。

方針

本来であれば記事を書く DB とは別に固定ページを格納する DB を用意したり、同じ DB を使う場合でもプロパティを追加して固定ページと記事ページを分けたりする方がよさそうですが、今回は 記事 DB を使ってプロパティも追加せず、少し無理やりな方法で固定ページを追加します。

  1. 普通の記事と同じように Notion の DB に固定ページを作成する
  2. 既存の記事ページのコードを固定ページのコードにコピペする
  3. 2 のコードで各記事の Slug が指定されている動的ルーティングを削除し、固定ページを指定するための静的ルーティングに変更する(これで固定ページは完成)
  4. 各記事の Slug を格納しているリストから 固定ページの Slug を削除する(記事一覧ページから固定ページを削除)

1. Notion の DB に固定ページを作成する

まずは普通の記事と同じように Notion の DB に固定ページにしたい内容のページを追加します(記事の DB と同じ DB に作成する)。現時点では、記事一覧にもこのページが表示されてしまいますが、あとで表示されないように工夫します。表示されないようにする準備として、固定ページの Date は記事の中で最も古い日付に設定しておきます。

ちなみに今回は固定ページのSlugspaceにしました。

image block

2. 既存の記事ページのコードをコピーする

通常の記事ページを表示するコードを使いまわすためにsrc/pages/blog/[slug].astroのコードを丸々コピーします。src/pages/***.astroファイルを新規で作成します。このファイルが固定ページとなり、https://ドメイン/***/でアクセスできるようになります。

自分の場合は、src/pages/space.astroを作ったので、https://astro-notion-blog-5y5.pages.dev/space/でアクセスできます。

この辺りの仕様に関しては、Astro のドキュメントがわかりやすいです。

この作成したファイルに、先ほどのコピーしたコードを貼り付けます。

3. 動的ルーティングを静的ルーティングに変更する

上記でコピーしたsrc/pages/blog/[slug].astroは動的に各記事の slug を取得してページを表示しますが、固定ページでは固定ページの Slug を静的に設定して固定ページを表示します。自分の場合は 1. で設定したspaceという Slug を設定します。

変更前

            
export async function getStaticPaths() {
  const numberOfPages = await getNumberOfPages();

  let params = [];
  for (let i = 2; i <= numberOfPages; i++) {
    params.push({ params: { page: i.toString() } });
  }
  return params;
}

const { page } = Astro.params;
          
src/pages/space.astro

変更後

各記事の Slug は取得する必要がないため、getStaticPaths()は削除して、spaceを設定します。

            
const slug = "space";
          
src/pages/space.astro

これで、固定ページを表示することができるようになります。後は、固定ページには必要のない投稿日時などを好みで削除していきます。

以下が固定ページを設定しているsrc/pages/space.astroのコードです。フッター<footer></footer>や、サイドメニュー<aside></aside>には任意の内容を入れておきます。

            
---
import * as interfaces from "../lib/interfaces.ts";
import { getPostBySlug, getAllBlocksByBlockId } from "../lib/notion/client.ts";
import { getPostLink } from "../lib/blog-helpers.ts";
import Layout from "../layouts/Layout.astro";
import PostTitle from "../components/PostTitle.astro";
import PostFeaturedImage from "../components/PostFeaturedImage.astro";
import PostBody from "../components/PostBody.astro";
import styles from "../styles/blog.module.css";

const slug = "space";

const post = await getPostBySlug(slug);
if (!post) {
  throw new Error("Post not found. slug: ${slug}");
}

const [blocks] = await Promise.all([getAllBlocksByBlockId(post.PageId)]);
---

<Layout title={post.Title} path={getPostLink(post.Slug)}>
  <div className={styles.container}>
    <main>
      <div className={styles.post}>
        <PostTitle post={post} enableLink={false} />
        <PostBody blocks={blocks} />
        <footer></footer>
      </div>
    </main>

    <aside>
      <div className={styles.profile}>
        <PostFeaturedImage post={post} />
        <p>チャベス</p>
      </div>
      <p>
        Notionが好き。プログラミングと英語を学習中。30代の機械系エンジニア。
      </p>
    </aside>
  </div>
</Layout>
          
src/pages/space.astro

ヘッダーなど、任意の場所に固定ページのリンクを設置すれば、固定ページにもアクセスしやすくなります。自分の場合はヘッダーに追加しました。

            
const navItems = [
  { label: "Home", path: "/" },
  { label: "Blog", path: "/blog" },
  { label: "Space", path: "/space" },  //追加
  { label: "Portfolio", path: "https://notion-portfolio-site.vercel.app/" },
];
          
src/layouts/Layout.astro

4. 記事一覧ページから固定ページを削除する

3.で固定ページは完成しましたが、このままでは記事一覧ページに固定ページも表示されてしまいます。固定ページを表示させないために、記事一覧ページで動的に取得した Slug が格納されたリストから固定ページの Slug を削除します。

具体的には、src/pages/blog/index.astroposts.pop();を追加するのみです。

            
const [posts, rankedPosts, tags, numberOfPages] = await Promise.all([
  getPosts(NUMBER_OF_POSTS_PER_PAGE),
  getRankedPosts(),
  getAllTags(),
  getNumberOfPages(),
]);

//スペース(固有ページ)の記事は最後の要素なので、popで削除する。
posts.pop();  //この行を追加
          

1.で固定ページは記事の中で一番古い投稿日時に設定しました。上記のPostsには、getPosts(NUMBER_OF_POSTS_PER_PAGE)で取得した全記事の Slug が投稿日が新しい順にリストで格納されています。例えば、自分の場合は、

            
console.log(posts)
//["notion-zadankai", "kutukko", ... , "beach-soccer", "space"]
          

というようにリストに入っているので、popspaceをリストから削除すれば固定ページが記事一覧ページで表示されないようになります。

おわりに

本来であれば冒頭でも述べたように、今回のような方法ではなく新しくDBを用意したり、プロパティで通常の記事と固定ページを分けた方がよさそうです。もしもっといい方法があるという場合はぜひ教えていただけると助かります。