Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(notion): improve doc with breaking changes #88

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 7 additions & 14 deletions content/docs/300-sources/125-notion/100-getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,8 @@ Click on the `•••` in the top right corner of your database, then on **Add

### Install dependencies

You will need to install the following dependencies to get started:

- `contentlayer-source-notion`: The Notion content source implementation for Contentlayer
- `@notionhq/client`: The official Notion JS SDK

```text
npm install contentlayer-source-notion @notionhq/client
npm install contentlayer-source-notion
```

### Configure Notion source plugin
Expand All @@ -75,12 +70,11 @@ To configure the Notion Source plugin you need to create an instance of `@notion
// contentlayer.config.js

import { makeSource, defineDatabase } from 'contentlayer-source-notion'
import { Client } from '@notionhq/client'

const client = new Client({ auth: process.env.NOTION_TOKEN })

export default makeSource({
client,
client: {
auth: process.env.NOTION_TOKEN,
},
databaseTypes: [],
})
```
Expand All @@ -99,9 +93,6 @@ In our case we want to:
// contentlayer.config.js

import { makeSource, defineDatabase } from 'contentlayer-source-notion'
import * as notion from '@notionhq/client'

const client = new notion.Client({ auth: process.env.NOTION_TOKEN })

export const Post = defineDatabase(() => ({
name: 'Post',
Expand All @@ -128,7 +119,9 @@ export const Post = defineDatabase(() => ({
}))

export default makeSource({
client,
client: {
auth: process.env.NOTION_TOKEN,
},
databaseTypes: [Post],
})
```
Expand Down
62 changes: 37 additions & 25 deletions content/docs/300-sources/125-notion/400-configure-renderer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,51 @@ excerpt: How to configure how the HTML is generated for Rich text content with c

The `contentlayer-source-notion` uses [`@notion-render/client`](https://www.npmjs.com/package/@notion-render/client) under the hood to transform your Rich text content (Rich Text properties and pages content) into HTML that you can then use and style in your app.

## Use own instance of the renderer

If you want to configure the renderer, you have to provide your own instance (by defaults one is generated for you).

### Install `@notion-render/client`
## Install `@notion-render/client`

Run the following command to add `@notion-render/client` to your dependencies:

```text
npm install @notion-render/client
npm install @notionhq/client @notion-render/client
```

### Pass the renderer to the source plugin
## Configure the renderer

Notion Rich Text is basically a list of blocks, each block has a `type` (e.g. image) and contains its configuration (e.g. the image url).

Each block has its own renderer called `block renderer` that takes in input the configuration and returns a string (the generated HTML).

```js
// contentlayer.config.js
You can find the list of block types on the [Official Notion API documentation](https://developers.notion.com/reference/block).

### Use plugins

There are multiple plugins available for `@notion-client/render`:

- `@notion-render/hljs-plugin`: Use [Highlight.js](https://highlightjs.org/) to colorize your Code blocks.
- `@notion-render/bookmark-plugin`: Improve bookmark blocks by gathering the targeted website metadata.

```typescript
import { makeSource } from 'contentlayer-source-notion'
import * as notion from '@notionhq/client'
import { NotionRenderer } from '@notion-render/client'
import { Client } from '@notionhq/client'
import hljs from '@notion-render/hljs-plugin'
import bookmark from '@notion-render/bookmark-plugin'

const client = new notion.Client({ auth: process.env.NOTION_TOKEN })
const client = new Client({ auth: process.env.NOTION_TOKEN })
const renderer = new NotionRenderer({ client })

renderer.use(bookmark)
renderer.use(hljs)

export default makeSource({
client,
renderer,
})
```

## Configure the renderer

Notion Rich Text is basically a list of blocks, each block has a `type` (e.g. image) and contains its configuration (e.g. the image url).

Each block has its own renderer called `block renderer` that takes in input the configuration and returns a string (the generated HTML).

You can find the list of block types on the [Official Notion API documentation](https://developers.notion.com/reference/block).
### Custom block renderer

### Create block renderer
#### Create the block renderer

You can create a block renderer by using the `createBlockRenderer` function.
The first parameter is the type of block, the second is the function used to render this type of block.
Expand All @@ -62,17 +69,22 @@ const paragraphRenderer = createBlockRenderer<ParagraphBlockObjectResponse>('par
})
```

### Add the block renderer
#### Add the block renderer

You can add your block renderers directly in the constructor parameters or with the method `addBlockRenderer`.

```typescript
import { NotionRenderer } from '@syneki/notion-render'
import { makeSource } from 'contentlayer-source-notion'
import { NotionRenderer } from '@notion-render/client'
import { Client } from '@notionhq/client'

const renderer = new NotionRenderer({
renderers: [paragraphRenderer],
})
const client = new Client({ auth: process.env.NOTION_TOKEN })
const renderer = new NotionRenderer({ client })

// or
renderer.addBlockRenderer(paragraphRenderer)

export default makeSource({
client,
renderer,
})
```
29 changes: 27 additions & 2 deletions content/docs/500-reference/250-source-notion/100-make-source.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default makeSource({

</OptionTitle>
<OptionDescription>
The `@notionhq/client` instance used to query the Notion API.
The `@notionhq/client` instance or options to query the Notion API.

**Example:**

Expand All @@ -50,7 +50,7 @@ export default makeSource({

</OptionTitle>
<OptionDescription>
The `@notion-render/client` instance used to transform Notion Block into HTML.
The `@notion-render/client` instance or options to transform Notion Block into HTML.

**Example:**

Expand Down Expand Up @@ -99,4 +99,29 @@ export default makeSource({
```

</OptionDescription>
<OptionTitle>
### `dev`

</OptionTitle>
<OptionDescription>
Provides the ability to configure the development server when running `contentlayer dev` or `next dev` (with `next-contentlayer`).

**Options:**

- `polling` (default: `5000`): Delay in ms between each check for updated pages (can be set to `false` to disable).

**Example:**

```js
export default makeSource({
dev: {
polling: 10_000
},
})
```
<div className="rounded-md border border-yellow-100 bg-yellow-50 px-6 dark:border-orange-500/50 dark:bg-orange-500/20">
⚠ Currently it does not update the schema, only your pages content and properties values.
</div>

</OptionDescription>
</OptionsTable>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"autoprefixer": "^10.4.4",
"broken-link-checker": "^0.7.8",
"contentlayer": "^0.3.2",
"contentlayer-source-notion": "^0.0.1-alpha.26",
"eslint": "8.13.0",
"eslint-config-next": "12.1.5",
"eslint-plugin-import": "^2.26.0",
Expand Down
Binary file added public/images/notion/database-small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
115 changes: 107 additions & 8 deletions src/components/landing-page/HowItWorks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as Tabs from '@radix-ui/react-tabs'
import * as Tooltip from '@radix-ui/react-tooltip'
import { Heading } from './Heading'
import { Paragraph } from './Paragraph'
import Image from 'next/image'

export const codeSnippets = {
howItWorksStep1: [
Expand Down Expand Up @@ -85,6 +86,34 @@ export default function Post({ post }: { post: Post }) {
</div>
)
}\
`,
},
],
notionHowItWorksStep2: [
{
file: 'contentlayer.config.ts',
lines: 20,
content: `\
import { defineDatabase, makeSource } from 'contentlayer-source-notion'
import slugify from 'slugify'

const Post = defineDatabase(() => ({
name: 'Post',
databaseId: '50b6156388e445eaaca3a3599d6f7ade',
computedFields: {
slug: {
type: 'string',
resolve: (p) => slugify(p.Title),
},
},
}))

export default makeSource({
client: {
auth: process.env.NOTION_TOKEN
},
databaseTypes: [Post],
})\
`,
},
],
Expand Down Expand Up @@ -264,15 +293,80 @@ const content = {
},
{
title: 'Notion',
active: false,
steps: [],
active: true,
steps: [
{
heading: 'Create your Notion database',
text: (
<p>
Create a new database or use an existing one. You can use all the feature of Notion to manage your
content: Columns, Automations, Views, etc.
</p>
),
image: {
url: '/images/notion/database-small.png',
alt: 'Data transformation',
width: 942,
height: 406,
},
},
{
heading: 'Configure your database',
text: (
<p>
When working with local markdown or MDX files, you tell Contentlayer the expected shape of your data
(document type definitions).
</p>
),
cta: {
label: 'Explore Example',
theme: 'primary',
icon: 'github' as IconName,
url: 'https://github.com/kerwanp/contentlayer-source-notion/tree/main/examples/node-script-notion',
},
codeSnippetsKey: codesnippetKey('notionHowItWorksStep2'),
},
{
heading: 'Your pages are transformed into data',
text: (
<>
<p>
Run Contentlayer to process your content. Do this as part of the Next.js dev server, or using the
Contentlayer CLI.
</p>
<p>
This validates the content, then generates types definitions and outputs data objects ready to be
imported as a ESM module.
</p>
<p>The content of your pages are automatically transformed into HTML so you can easily render them.</p>
</>
),
dataTransformation: localStep2DataTransformation,
},
{
heading: 'Import data into your application',
text: (
<>
<p>
Import the data just like you would any other JavaScript library. Use it to render pages, and pass down
as props to the components on those pages.
</p>
<p>
Keep the development bundle small with tree-shaking and improve the development experience by using the
generated type definitions.
</p>
</>
),
codeSnippetsKey: codesnippetKey('howItWorksStep3'),
},
],
},
],
}

export const HowItWorks: FC<{ codeSnippets: CodeSnippets }> = ({ codeSnippets }) => {
return (
<div className="w-full max-w-screen-xl px-4 mx-auto mt-16 md:mt-24 md:px-8 lg:mt-32">
<div className="mx-auto mt-16 w-full max-w-screen-xl px-4 md:mt-24 md:px-8 lg:mt-32">
<Tabs.Root defaultValue={content.tabs[0].title.toLowerCase().replace(/ /g, '-')}>
<div className="space-y-8 sm:text-center">
<Heading level={2}>{content.heading}</Heading>
Expand Down Expand Up @@ -308,7 +402,7 @@ export const HowItWorks: FC<{ codeSnippets: CodeSnippets }> = ({ codeSnippets })
className="rounded bg-gray-800 px-3 py-1.5 text-sm text-slate-100 shadow-xl shadow-white dark:bg-violet-200 dark:text-violet-900 dark:shadow-black"
>
Coming soon
<Tooltip.Arrow className="mx-1 text-gray-800 fill-current dark:text-violet-200" />
<Tooltip.Arrow className="mx-1 fill-current text-gray-800 dark:text-violet-200" />
</Tooltip.Content>
</Tooltip.Root>
),
Expand All @@ -323,10 +417,10 @@ export const HowItWorks: FC<{ codeSnippets: CodeSnippets }> = ({ codeSnippets })
value={title.toLowerCase().replace(/ /g, '-')}
className="relative focus:outline-none"
>
<div className="absolute inset-y-0 hidden w-0 border-l border-dashed left-6 border-slate-300 dark:border-slate-600 sm:block" />
<div className="absolute bottom-0 hidden w-2 left-5 h-96 bg-gradient-to-b from-white/0 via-white/100 to-white/100 dark:from-gray-950/0 dark:via-gray-950/100 dark:to-gray-950/100 sm:block" />
{steps.map(({ heading, text, cta, codeSnippetsKey, dataTransformation }, index) => (
<div key={index} className="relative grid grid-cols-1 gap-12 mt-16 md:grid-cols-2 md:gap-16">
<div className="absolute inset-y-0 left-6 hidden w-0 border-l border-dashed border-slate-300 dark:border-slate-600 sm:block" />
<div className="absolute bottom-0 left-5 hidden h-96 w-2 bg-gradient-to-b from-white/0 via-white/100 to-white/100 dark:from-gray-950/0 dark:via-gray-950/100 dark:to-gray-950/100 sm:block" />
{steps.map(({ heading, text, cta, codeSnippetsKey, dataTransformation, image }, index) => (
<div key={index} className="relative mt-16 grid grid-cols-1 gap-12 md:grid-cols-2 md:gap-16">
<div className="space-y-4">
<div className="flex items-center space-x-4 sm:space-x-8">
<div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-full border border-violet-200 bg-violet-100 text-xl font-black text-violet-600 ring-4 ring-white dark:border-violet-900 dark:bg-[#2C1657] dark:text-violet-500 dark:ring-gray-950">
Expand All @@ -353,6 +447,11 @@ export const HowItWorks: FC<{ codeSnippets: CodeSnippets }> = ({ codeSnippets })
<CodeWindow snippets={codeSnippets[codeSnippetsKey]} />
</div>
)}
{image && (
<div className="overflow-hidden rounded-2xl border border-gray-100 bg-gray-50 text-[0px] shadow-lg shadow-gray-100 dark:border-gray-800 dark:bg-gray-900 dark:shadow-gray-900">
<Image src={image.url} alt={image.alt} width={image.width} height={image.height} />
</div>
)}
</div>
))}
</Tabs.Content>
Expand Down
Loading