流行りのJAMStack(Next.js + microCMS + Vercel)でポートフォリオサイトを作ってみた

タイトルの通りなのですが、ポートフォリオサイトを作ってみました。

なぜ作ったか

元々は別の技術ブログを運営していたのですが、以下の理由(言い訳)で運営していくモチベーションが低下していました。

  • 放置されたWordpress。溜まっていく色んな更新物。カオス化。運営つらい。
  • 技術ブログ以外のことも書きたいけど、そういう雰囲気のサイト設計にしなかったので、書きにくい。


スマホで気楽に更新できること、かつWordpressのような重いCMSではなくて、もっと楽にブログ運営できる仕組みがないか、ずっと模索していました。

JAMStackとの出会い

そこでたどり着いたのがJAMStack。

構成はタイトルの通り、Next.js + microCMS + Vercelです。

クライアントは静的ファイルとのやり取りだけなので、サイト閲覧が爆速かつセキュアな形となり、
記事の管理や更新も、microCMSの管理画面で(やろうと思えばスマホでも)できちゃいます。

バックエンドの管理はmicroCMSにお任せで、サイト運営負担は格段に下がりました。
フロントエンドのメンテナンスと記事更新に集中できる環境、、、これぞ求めていたライトな仕組みでした。

しかもサイト運営費用は(ドメイン維持費を除けば)無料だなんて、、、すごい世の中ですね。

どうやって作ったか

microCMSの公式がJAMStackでのブログの作り方を公開していました。
https://blog.microcms.io/microcms-next-jamstack-blog/

これが本当にわかりやすくて、もう完全にmicroCMSファンになりました。
このポートフォリオサイトは、このリンクに書いてある手順で、ほぼほぼできあがってしまいます。

作成中のトピックス

ここからは、上記リンクには書いてない部分について触れていきます。

TypeScriptで書く

Nextのプロジェクトを作るときに、TypeScriptのテンプレートを使いました。

$ npx create-next-app --example with-typescript webird

このサイトを参考にしました。
https://kakakakakku.hatenablog.com/entry/2020/04/14/100623

スタイルはMaterial UI

見た目を整えていくのにMaterial UIを使いました。
https://material-ui.com/

いつもクライアントサイドだけで使っているときには遭遇しないエラーではまったりしました。
同じようにはまっていた人: https://blog.ryo.gift/entry/2020/12/12/162653

OGP設定

TypeScriptテンプレートのLayoutコンポーネントを流用して、OGPの設定を以下のように行いました。

// Layout.tsx

import React, { ReactNode } from 'react';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { NavBar } from './Navbar';
import { Header } from './Header';
import { createStyles, makeStyles, Theme, Toolbar } from '@material-ui/core';
import { Footer } from './Footer';


const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    main: {
      marginLeft: theme.spacing(2),
      marginRight: theme.spacing(2),
    },
  }),
);


type Props = {
  children?: ReactNode;
  title: string;
  header?: string;
  eyeCatch?: string;
  description: string
};

const Layout = ({ children, title = 'default title', header = title, eyeCatch, description }: Props) => {
  const classes = useStyles();
  const router = useRouter();

  return (
    <>
      <Head>
        <title>{title} | Webird</title>
        <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
        {/* OGP */}
        <meta property="og:url" content={`https://www.webird.work${router.pathname}`} />
        <meta property="og:type" content={title === 'Home' ? 'website' : 'article'} />
        <meta property="og:title" content={`${title} | Webird`} />
        <meta property="og:description" content={description} />
        <meta property="og:site_name" content="Webird" />
        <meta property="og:image" content={eyeCatch || 'https://images.microcms-assets.io/assets/d5eb4af8cbbf4b8aa1e80f6ea64e8f1d/cd97b6ee591a4834878d1ed3677c6533/logo.png'} />

        <meta name="twitter:card" content="summary" />
        <meta name="twitter:site" content="@torihon62" />
      </Head>
      <NavBar />
      <Toolbar variant="dense" />
      <div className={classes.main}>
        <Header text={header} />
        {children}
      </div>
      <Footer />
    </>
  );
};

export default Layout;


スキルページのスキーマ設計

カテゴリーと同じように、「コンテンツ参照機能」を使って設計しています。

こんな感じで、「スキル」を登録して、、、




それらを「スキルセット」のAPIスキーマで参照してやるような設計にしています。




あとがき

JAMStackはいいぞ!
microCMSはいいぞ!