├── .env.example ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── components ├── Container.js ├── ContentBlocks.js ├── Footer.js └── Nav.js ├── layouts └── BlogLayout.js ├── lib └── getNotionData.js ├── next.config.js ├── package.json ├── pages ├── [slug].js ├── _app.js └── index.js ├── postcss.config.js ├── public ├── favicon.ico ├── images │ ├── blog-screenshot.png │ └── blog.png ├── nextjs.svg ├── notion.svg ├── site.png └── tailwindcss.svg ├── tailwind.config.js └── yarn.lock /.env.example: -------------------------------------------------------------------------------- 1 | NOTION_TOKEN= 2 | NOTION_DATABASE_ID= -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | next.config.js 4 | postcss.config.js 5 | tailwind.config.js -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next", "plugin:tailwindcss/recommended"], 3 | "plugins": ["tailwindcss"] 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.md -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "semi": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2021 Lucio Villa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A Next.js, Notion and Tailwind CSS starter blog template 2 | 3 | This is an open-source starter blog template that is statically generated with Next.js, content powered by Notion and styled with Tailwind CSS. 4 | 5 | *Still a work in progress.* 6 | 7 | **Live example hosted on Vercel**: [https://blog.luciovilla.com](https://blog.luciovilla.com) 8 | 9 | ## Getting Started 10 | 11 | 1. Clone this repo `git clone https://github.com/luciovilla/notion-nextjs-blog.git` 12 | 2. Install its dependencies `npm install` 13 | 3. Copy or rename the `.env.example` file to `.env.local` 14 | 4. Personalize the page meta data in `Container.js` 15 | 16 | ## Creating Your Notion Pages Table 17 | 18 | 1. Create a blank page in Notion 19 | 2. Create a table on that page. 20 | 3. Add the following columns to the table: 21 | - `Page` (type: title): this the blog post's headline and meta title. 22 | - `Slug` (text): this is the blog post's URL slug. 23 | - `Date` (date): the display date and meta published_time property. 24 | - `Description` (text): this is the preview text on the homepage and the meta description property. 25 | - `Published` (checkbox): this checks if a blog post should be displayed when deployed. 26 | - `Cover Image` (files & media): optional - adds a cover image for a post on the frontpage and becomes the featured image on social (og:image, twitter card image). 27 | 28 | View this sample template table in [Notion](https://vast-rifle-eed.notion.site/8dde3326f8cb4cc68b47a96bea86e9be). 29 | 30 | ## Getting Database ID and Notion Token 31 | 32 | - Create a [Notion Integration](https://www.notion.so/my-integrations). 33 | - Copy and paste the Integration Token in the `.env.local` file: `NOTION_TOKEN=____` 34 | - On the Notion page, click the "Share" button in the top right and share the database with the Notion Integration you just created 35 | - In a browser, go to the Notion page and grab the Database ID from the URL. Its the part of the URL after your workspace name and the slash and before the question mark. The ID is 32 characters long, containing numbers and letters. 36 | - Paste your Database ID in the `.env.local` file: `NOTION_DATABASE_ID=___` 37 | 38 | ## Creating Blog Posts 39 | 40 | 1. In Notion click new on the table to add a new row 41 | 2. Fill in the Page title, Slug, Date and Description 42 | 3. Keep the Description text short, as it will be the text that shows up on the homepage as the post's preview text. 43 | 44 | ## Running Locally 45 | 46 | Run `npm run dev` 47 | 48 | ## Deploy your own 49 | 50 | Deploy your own Notion blog with Vercel. 51 | 52 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fluciovilla%2Fnotion-nextjs-blog&env=NOTION_TOKEN,NOTION_DATABASE_ID&envDescription=Notion%20Integration%20token%20and%20Database%20ID%20required.&envLink=https%3A%2F%2Fblog.luciovilla.com%2Fnotion-blog-setup-instructions&project-name=notion-blog) 53 | 54 | ## Credits 55 | Thankful for the following people as I was inspired by their code: 56 | - [samuelkraft](https://github.com/samuelkraft/notion-blog-nextjs) 57 | - [ijjk](https://github.com/ijjk/notion-blog) 58 | - [leerob](https://github.com/leerob/leerob.io) 59 | -------------------------------------------------------------------------------- /components/Container.js: -------------------------------------------------------------------------------- 1 | import { useRouter } from 'next/router' 2 | import Head from 'next/head' 3 | import Nav from './Nav' 4 | import Footer from './Footer' 5 | 6 | export default function Container(props) { 7 | const { children, ...customMeta } = props 8 | const router = useRouter() 9 | const meta = { 10 | title: 'A Next.js, Notion, Tailwind CSS starter blog template', 11 | description: `An open-source starter blog template that is statically generated with Next.js, content powered by Notion and styled with Tailwind CSS.`, 12 | type: 'website', 13 | image: '/site.png', 14 | ...customMeta, 15 | } 16 | 17 | return ( 18 | <> 19 | 20 | {meta.title} 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {meta.date && } 37 | 38 |