在这篇文章中,我将展示如何使用 Next.js 和 Notion API 构建一个个人旅行博客,并将其部署到 Vercel。最终目标是让博客在自定义域名 jessieontheroad.com
上运行。
git源码:github.com/Jessie-jzn/… 网站如下:www.jessieontheroad.com/
前提条件
在开始之前,你需要确保已经完成以下几步:
- 购买域名:在域名注册商处购买一个域名,例如
jessieontheroad.com
。 - Vercel 账号:注册一个 Vercel 账户。
- Notion API Token:获取一个 Notion API 令牌,用于访问 Notion 数据库。
Notion相关
要使用Notion作为你的旅游攻略网站的内容管理系统,你需要先在Notion中配置数据库,并获取必要的API密钥和数据库ID。
配置步骤
步骤 1:创建Notion数据库
-
创建新页面:
- 打开Notion,点击左侧菜单中的“New Page”创建一个新页面。
-
添加数据库:
- 在新页面中,选择“Table”来创建一个新的数据库。
- 命名这个数据库为“Travel Guides”。
-
配置数据库列:
-
添加以下列来存储旅游攻略的相关信息:
- Title:攻略的标题(默认已经有Title列)。
- Description:攻略的简短描述(类型为Text)。
- Content:攻略的详细内容(类型为Text)。
- Location:攻略涉及的地点(类型为Text)。
- Image:攻略的封面图片(类型为Files & media)。
- Published Date:发布日期(类型为Date)。
- Author:作者(类型为Text)。
-
步骤 2:获取Notion API密钥
-
访问Notion Integration:
- 打开浏览器,访问www.notion.so/my-integrat…
-
创建新集成:
- 点击“New integration”按钮。
- 填写集成的名称,例如“Travel Guide Website”。
- 选择工作区。
- 提交后,你将获得一个“Internal Integration Token”。将此Token保存下来,用于后续API调用。
步骤 3:共享数据库给集成
- 打开你的Notion数据库页面
- 点击右上角的“Share”按钮
- 在“Invite”字段中,输入刚刚创建的集成名称,然后选择它。或者直接用connect中,找到刚刚创建的集成名称
- 点击“Invite”,将数据库权限赋予该集成,
步骤 4:获取数据库ID
-
打开你的Notion数据库页面
-
从浏览器地址栏中复制数据库ID
- 数据库ID在URL中,是紧跟在“www.notion.so/”后的一串字符。例如,…
https://www.notion.so/yourworkspace/abcdefgh1234567890
, 那么abcdefgh1234567890
就是你的数据库ID。
- 数据库ID在URL中,是紧跟在“www.notion.so/”后的一串字符。例如,…
Next集成Notion
代码步骤
步骤1:初始化 Next.js 项目
首先,创建一个新的 Next.js 项目。如果你还没有安装 Next.js,可以通过以下命令安装:
npx create-next-app@latest jessie-travel-blog
cd jessie-travel-blog
步骤2:添加 Tailwind CSS
安装 Tailwind CSS 并进行配置:
npm install tailwindcss@latest postcss@latest autoprefixer@latest
npx tailwindcss init -p
在 tailwind.config.js
中配置内容选项:
/** @type {import('tailwindcss').Config} */
const { fontFamily } = require('tailwindcss/defaultTheme');
const colors = require('tailwindcss/colors');
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
],
darkMode: 'class',
plugins: [],
};
在 styles/globals.css
中导入 Tailwind CSS:
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--notion-max-width: 100%;
--notion-header-height: 45px;
}
步骤2:设置 Notion API
在你的项目中创建一个文件夹 lib
,并在其中创建一个文件 notion.js
。这个文件将包含与 Notion API 交互的代码。
// lib/notion/NotionServer.ts
import { Client } from '@notionhq/client';
import { NotionAPI } from 'notion-client';
import { QueryDatabaseResponse } from '@notionhq/client/build/src/api-endpoints';
import { NOTION_TOKEN } from '../constants';
if (!NOTION_TOKEN) {
throw new Error('NOTION_TOKEN is not defined');
}
class NotionService {
private client: Client;
private notionAPI: NotionAPI;
constructor() {
this.client = new Client({ auth: NOTION_TOKEN });
this.notionAPI = new NotionAPI();
}
/**
* 获取指定数据库的条目
* @param databaseId - 数据库 ID
* @returns Promise<QueryDatabaseResponse['results']>
*/
async getDatabase(
databaseId: string,
): Promise<QueryDatabaseResponse['results']> {
try {
const response = await this.client.databases.query({
database_id: databaseId,
});
return response.results;
} catch (error: any) {
console.error('Error fetching database:', error.body || error);
throw new Error('Failed to fetch database');
}
}
/**
* 获取指定页面的内容
* @param pageId - 页面 ID
* @returns Promise<PageObjectResponse>
*/
async getPage(pageId: string) {
try {
const page = await this.notionAPI.getPage(pageId);
return page;
} catch (error: any) {
console.error('Error fetching page:', error.body || error);
throw new Error('Failed to fetch page');
}
}
}
export default NotionService;
步骤3:在 Next.js 中使用 Notion API
获取数据库的条目
// pages/api/guide.ts
// 获取旅游指南数据库的条目
import NotionService from '@/lib/notion/NotionServer';
import { NOTION_GUIDE_ID, NOTION_COUNTRY_ID } from '@/lib/constants';
import { formatDatabase } from '@/lib/util';
const notionService = new NotionService();
export const getTravelGuideList = async () => {
const res = await notionService.getDatabase(NOTION_GUIDE_ID);
return formatDatabase(res);
};
export const getCountryList = async () => {
const res = await notionService.getDatabase(NOTION_COUNTRY_ID);
return formatDatabase(res);
};
在你的页面或组件中使用 getTravelGuideList
函数来获取数据。例如:
// pages/guide/index.tsx
import { useState } from 'react';
import { GetStaticProps } from 'next';
import * as API from '../api/guide';
import GuideCard from '@/components/GuideCard';
import { Post, Country } from '@/lib/type';
interface IndexProps {
guidesByCountry: Country[];
}
const getGuidesByCountry = (guides: Post[], countries: Country[]) => {
const res = countries.map((country) => {
return {
...country,
guides: guides.filter((guide) => country.guide.includes(guide.id)),
};
});
return res;
};
export const getStaticProps: GetStaticProps = async () => {
const [guideList = [], countryList] = await Promise.all([
API.getTravelGuideList(),
API.getCountryList(),
]);
// 提取包含指南的国家列表
const guidesByCountry = getGuidesByCountry(guideList, countryList);
return {
props: {
guidesByCountry: guidesByCountry,
posts: guideList,
},
revalidate: 10,
};
};
const Index = ({ guidesByCountry }: IndexProps): React.JSX.Element => {
const [searchValue, setSearchValue] = useState('');
return (
<div className="divide-y divide-gray-200 dark:divide-gray-700 px-4 sm:px-8 lg:px-8">
{guidesByCountry.map(
(item: Country) =>
!!item.guides.length && (
<div key={item.id} className="w-full pt-8 pb-8">
<h3 className="mb-4 text-3xl font-extrabold leading-9 tracking-tight text-gray-900 dark:text-gray-100">
{item.icon}
{item.name}
</h3>
<div className="grid gap-8 sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-4 border-none">
{item.guides.map((post: Post) => (
<GuideCard post={post} key={post.id} />
))}
</div>
</div>
),
)}
</div>
);
};
export default Index;
部署到 Vercel
配置步骤
步骤1: 推送代码到 GitHub
将你的代码推送到 GitHub 仓库:
git init
git remote add origin <https://github.com/yourusername/yourproject.git>
git add .
git commit -m "Initial commit"
git push -u origin main
步骤2:配置 Vercel
- 登录 Vercel,选择
New Project
并导入你的 GitHub 仓库。 - 在 Vercel 项目设置中,添加环境变量
NOTION_TOKEN
和NOTION_DATABASE_ID
。
步骤3:添加自定义域名
- 在 Vercel 项目设置的
Domains
部分,添加你的自定义域名。 - 更新你的域名注册商的 DNS 设置,添加 Vercel 提供的 CNAME 和 A 记录。
步骤4:部署
Vercel 将自动构建和部署你的项目。在 DNS 记录传播完成后,你应该可以通过 https://jessieontheroad.com
访问你的博客。
配置域名
在 Vercel 设置自定义域名
-
登录到 Vercel选择你的项目
-
添加自定义域名
- 在项目设置页面中,找到
Domains
部分,然后点击Add
按钮。 - 输入购买的域名
jessieontheroad.com
,然后点击Add
。
- 在项目设置页面中,找到
-
更新 DNS 记录
-
Vercel 会提供一组 DNS 记录,你需要将这些记录添加到你的域名注册商(例如 Namecheap、GoDaddy 等)的 DNS 设置中。
-
登录到你的域名注册商账户,找到你的域名的 DNS 设置。
-
添加 Vercel 提供的 CNAME 和 A 记录。通常会包含以下内容:
- CNAME:
www
->cname.vercel-dns.com
- A 记录:
@
-> Vercel 提供的 IP 地址
- CNAME:
-
-
等待 DNS 传播
- DNS 更改可能需要一些时间(通常几分钟到几小时)来传播。你可以使用工具如 DNS Checker 检查你的域名是否正确指向 Vercel。
项目规划
- 项目设置与环境配置
- 页面UI
- 部署域名,部署到 Vercel,配置域名和 SSL 证书
- 统计和分析
- 搜索和过滤
- SEO优化
- 区分正式、测试环境
- 订阅和通知
- tab新增摄影图像
- 多媒体支持
- 分类和标签,实现文章的分类和标签功能,提供分类和标签的过滤选项
- 社交分享,实现文章分享到社交媒体平台的功能
- 联系表单,配置邮件发送服务