This is a Next.js starter template for creating a blog using Notion as a CMS, inspired by the PaperMod theme.
- Notion as CMS: Easily manage your blog content from Notion.
- PaperMod Inspired Design: Clean, minimalist, and fast, built with Pico.css.
- Responsive: Adapts to all screen sizes.
- Dark Mode: Automatic dark mode based on system preference.
- Fast & Lightweight: Optimized for performance.
- Search Functionality: Built-in search for your posts.
- Giscus Comments: Integrated comments system using GitHub Discussions.
- Syntax Highlighting: Code blocks are highlighted using PrismJS.
- LaTeX Support: Write mathematical notations with KaTeX.
- SEO Friendly:
- Meta tags and JSON-LD for rich snippets.
- Open Graph protocol for social media sharing.
- Automatic sitemap generation (
sitemap.xml). robots.txtprovided.
- Easy to Customize: Configure site settings via
site.config.js. - Image Optimization: Uses
next/imageand Plaiceholder for optimized images. - Vercel Analytics & OG Image Generation: Ready for Vercel deployment.
- Node.js (v16.x or higher recommended)
- Yarn (or npm)
- A Notion account
-
Clone the repository:
git clone https://github.com/<YOUR_GITHUB_USERNAME>/next-notion-papermod.git cd next-notion-papermod
(Remember to replace
<YOUR_GITHUB_USERNAME>with the actual path if you've forked it, or the original repo path if you're cloning directly). -
Install dependencies:
yarn install # or # npm install
-
Set up Notion:
- Duplicate a Notion Database: If you have a specific Notion blog template you want users to start with, mention it here. Otherwise, users will need to create or use an existing Notion database. The structure should generally include properties like
Title(Title),Slug(Text),Published(Date),Tags(Multi-select),Summary(Text), etc. - Create a Notion Integration:
- Go to https://www.notion.so/my-integrations.
- Click "New integration".
- Give it a name (e.g., "My Blog Integration").
- Select the workspace where your database resides.
- Ensure "Read content" capabilities are selected. You might need "Update content" or "Insert content" if you plan to add features that modify Notion content programmatically in the future, but for reading a blog, "Read content" is sufficient.
- Click "Submit".
- Copy the "Internal Integration Token". This will be your
NOTION_API_KEY.
- Connect the Integration to your Database:
- Open your Notion database.
- Click the
...menu in the top right corner. - Scroll down to "Add connections".
- Find and select the integration you just created.
- Get your Notion Database ID:
- The Database ID is part of the URL of your Notion database. For example, if your database URL is
https://www.notion.so/your-workspace/abcdef1234567890abcdef1234567890?v=..., thenabcdef1234567890abcdef1234567890is your Database ID. - The
site.config.jsfile already contains adatabseID(note the typo, it'sdatabseIDin the config, so reference it as is for now) field. You will need to replace its value with your own database ID.
- The Database ID is part of the URL of your Notion database. For example, if your database URL is
- Duplicate a Notion Database: If you have a specific Notion blog template you want users to start with, mention it here. Otherwise, users will need to create or use an existing Notion database. The structure should generally include properties like
-
Set up Environment Variables: Create a file named
.env.localin the root of the project and add the following variables:NOTION_API_KEY="<YOUR_NOTION_INTERNAL_INTEGRATION_TOKEN>" # You can leave NOTION_DATABASE_ID here if you prefer, # or manage it directly in site.config.js as it currently is. # If you add it here, it would typically override the one in site.config.js if the code is set up to do so. # For now, follow the project's current convention of setting it in site.config.js. # Example for Giscus (optional, if you want to use your own repo for comments) # GISCUS_REPO="your-github-username/your-repo-name" # GISCUS_REPO_ID="your_repo_id" # GISCUS_CATEGORY="your_giscus_category_name" # GISCUS_CATEGORY_ID="your_giscus_category_id"
- Replace
<YOUR_NOTION_INTERNAL_INTEGRATION_TOKEN>with the token you copied. - For Giscus variables, refer to the
site.config.jsfor the current project's setup or if you want to customize it to your own repository.
- Replace
-
Configure
site.config.js: Opensite.config.jsand update the following fields with your information:owner: Your name or organization.blogTitle: The title of your blog.github: Your GitHub username (for footer links, etc.).databseID: Crucial! Replace this with your Notion Database ID.baseURL: The production URL of your blog (e.g.,https://yourblog.com).defaultSiteDescription: Your blog's default meta description.googleSiteVerificationMetaTag(optional): If you use Google Search Console.giscus: Update this object if you want to use your own GitHub Discussions for comments.
-
Run the development server:
yarn dev # or # npm run dev
Open http://localhost:3000 in your browser to see the result.
Most of the blog's customization can be done by editing the site.config.js file. Here's an overview of the available options:
owner: Your name or the blog owner's name.blogTitle: The main title of your blog, used in meta tags and the site header.github: Your GitHub username. Used for links in the footer or other parts of the site.databseID: Important! The ID of your Notion database that holds your blog posts. (Note the current typo:databseIDin the file).revalidateTime: The interval in seconds for Next.js Incremental Static Regeneration (ISR). This determines how often pages are re-built with fresh data from Notion (e.g.,15 * 60for 15 minutes).optimizeExpiringImages: A boolean flag related to image optimization.postsPerPage: The number of posts to display on pages that list multiple posts (e.g., the main posts page).baseURL: The absolute base URL of your deployed blog (e.g.,https://blog.codingvillain.com). This is important for SEO and generating correct canonical URLs.defaultSiteDescription: A default description for your site, used in meta tags.googleSiteVerificationMetaTag: If you're using Google Search Console, you can put your verification tag content here.giscus: Configuration object for Giscus comments.repo: The GitHub repository for Giscus comments (e.g.,user/repo).repoID: The ID of the Giscus repository.category: The discussion category in your Giscus repository.categoryID: The ID of the Giscus category.
To change your blog's settings, modify the values in this file. Remember that changes to databseID are critical for fetching your content from Notion.
While most configurations are in site.config.js, sensitive keys or environment-specific settings are managed via a .env.local file:
NOTION_API_KEY: Your Notion integration token. Required.- You can also store Giscus settings (
GISCUS_REPO,GISCUS_REPO_ID, etc.) in.env.localif you prefer not to have them directly insite.config.js, though you'd need to adjust the Giscus component to read fromprocess.envif it doesn't already.
This Next.js blog can be deployed to any platform that supports Node.js applications. Vercel (from the creators of Next.js) is a highly recommended platform for deploying Next.js sites.
- Push your code to a Git repository (e.g., GitHub, GitLab, Bitbucket).
- Sign up or log in to Vercel using your Git provider.
- Import your Git repository into Vercel.
- Vercel will typically auto-detect that it's a Next.js project and configure the build settings correctly.
- Configure Environment Variables:
- In your Vercel project settings, add the same environment variables you defined in your
.env.localfile:NOTION_API_KEY- (If applicable)
GISCUS_REPO,GISCUS_REPO_ID,GISCUS_CATEGORY,GISCUS_CATEGORY_ID - Ensure the
baseURLinsite.config.jsis set to your Vercel production domain.
- In your Vercel project settings, add the same environment variables you defined in your
- Deploy.
Vercel will automatically build and deploy your site. Subsequent pushes to your connected Git branch will trigger automatic redeployments.
For other platforms like Netlify, AWS Amplify, or your own server:
- Build Command:
yarn build(ornpm run build) - Output Directory:
.next - Start Command:
yarn start(ornpm run start)
You will need to configure environment variables on your chosen platform similar to the Vercel setup. Ensure the platform serves the application from the .next directory and runs the start command.
This project is licensed under the MIT License. See the LICENSE file for details.
- This project is inspired by the clean and fast Hugo PaperMod theme.
- Built with Next.js, Notion API, and Pico.css.
- Thanks to the open-source community for the various libraries and tools that make this possible.