如何利用 Github Issues 写博客?

主要技术点

主要开发步骤

步骤一:创建 Next.js App

npx create-next-app@latest --typescript

步骤二:使用 Vercel 环境变量

export const REPO = process.env.VERCEL_GIT_REPO_SLUG || "";
export const OWNER = process.env.VERCEL_GIT_REPO_OWNER || "";

步骤三:使用 @octokit/core 获取当前仓库的 Issues

import { Octokit } from "@octokit/core";
import { OWNER, REPO } from "../config";

export async function getRepositoryIssues() {
  const octokit = new Octokit();

  const response = await octokit.request("GET /repos/{owner}/{repo}/issues", {
    owner: OWNER,
    repo: REPO,
  });

  return response.data;
}

export async function getRepositoryIssue(issueNumber: number) {
  const octokit = new Octokit();

  const response = await octokit.request(
    "GET /repos/{owner}/{repo}/issues/{issue_number}",
    {
      owner: OWNER,
      repo: REPO,
      issue_number: issueNumber,
    }
  );

  return response.data;
}

步骤四:首页展示仓库 issues 列表

import type { GetStaticProps, NextPage } from "next";
import Link from "next/link";
import { getRepositoryIssues } from "../lib/github";
import { PostType } from "../types";

const Home: NextPage<{ posts: PostType[] }> = ({ posts = [] }) => {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.title}>
          <Link href={`/posts/${post.number}`}>
            <a>{post.title}</a>
          </Link>
        </li>
      ))}
    </ul>
  );
};

export const getStaticProps: GetStaticProps = async () => {
  const issues = await getRepositoryIssues();

  return {
    props: {
      posts,
    },
  };
};

export default Home;

步骤五:生成具体的每一篇博客

import { GetStaticPaths, GetStaticProps, NextPage } from "next";
import ReactMarkdown from "react-markdown";
import { getRepositoryIssue, getRepositoryIssues } from "../../lib/github";

const Post: NextPage<{ dataSource?: PostType }> = ({ dataSource }) => {
  return <ReactMarkdown>{dataSource.body || ""}</ReactMarkdown>;
};

export const getStaticPaths: GetStaticPaths = async () => {
  const issues = await getRepositoryIssues();

  return {
    paths: issues.map((issue) => ({
      params: { number: String(issue.number) },
    })),
    fallback: false,
  };
};

export const getStaticProps: GetStaticProps = async ({ params }) => {
  const issue = await getRepositoryIssue(Number(params.number));

  return {
    props: {
      dataSource: issue,
    },
  };
};

export default Post;