Next.js (App Router)

How to use PMKIN with Next.js (App Router)

This guide uses the App Router approach to integrate PMKIN with your Next.js application. All the code for this quick start guide is in our Next.js quick start repository on GitHub.

Installation and Setup

Start by adding the necessary packages to your Next.js project:

npm install @apollo/client graphql react-markdown

Set up your PMKIN API key as an environment variable. Create a .env.local file in your project root:

PMKIN_API_KEY=your_api_key_here

Creating the Apollo Client

Create a new file app/lib/apollo-client.ts:

import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'
import { setContext } from '@apollo/client/link/context'


const httpLink = createHttpLink({
  uri: 'https://pmkin.io/graphql'
})


const authLink = setContext((_, { headers }) => {
  const pmkinApiKey = process.env.PMKIN_API_KEY


  if (!pmkinApiKey) {
    throw new Error('PMKIN_API_KEY is not set.')
  }


  return {
    headers: {
      ...headers,
      authorization: `Bearer ${pmkinApiKey}`
    }
  }
})


export const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: authLink.concat(httpLink)
})

Listing Documents

Create a new file app/blog/page.tsx:

import { gql } from '@apollo/client'
import Link from 'next/link'

import { client } from '../lib/apollo-client'

const GET_DOCUMENTS = gql`
  query GetDocuments {
    documents(includeDrafts: false) {
      id
      metaDescription
      slug
      title
    }
  }
`

interface Document {
  id: string
  metaDescription: string
  slug: string
  title: string
}


async function getDocuments(): Promise<Document[]> {
  const { data } = await client.query({ query: GET_DOCUMENTS })

  return data.documents
}


export default async function BlogList() {
  const documents = await getDocuments()

  return (
    <div>
      <h1>Blog Posts</h1>
      {documents.map(doc => (
        <article key={doc.id}>
          <h2>
            <Link href={`/blog/${doc.slug}`}>{doc.title}</Link>
          </h2>


          <p>{doc.metaDescription}</p>
        </article>
      ))}
    </div>
  )
}

Rendering Document Content

Create a new file app/blog/[slug]/page.tsx:

import { gql } from '@apollo/client'
import { Metadata } from 'next'
import ReactMarkdown from 'react-markdown'

import { client } from '../../lib/apollo-client'

const GET_DOCUMENT = gql`
  query GetDocument($slug: String!) {
    documentBySlug(slug: $slug) {
      id
      markdown
      metaDescription
      metaTitle
      title
    }
  }
`

interface Document {
  id: string
  markdown: string
  metaDescription: string
  metaTitle: string
  title: string
}

async function getDocument(slug: string): Promise<Document> {
  const { data } = await client.query({
    query: GET_DOCUMENT,
    variables: { slug },
  })

  return data.documentBySlug
}

export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
  const document = await getDocument(params.slug)

  return {
    title: document.metaTitle ?? document.title,
    description: document.metaDescription,
  }
}

export default async function BlogPost({ params }: { params: { slug: string } }) {
  const document = await getDocument(params.slug)

  return (
    <article>
      <h1>{document.title}</h1>
      <ReactMarkdown>{document.markdown}</ReactMarkdown>
    </article>
  )
}

This setup provides a solid foundation for integrating PMKIN with your Next.js application using the App Router. Using PMKIN's API, you can expand on this by adding pagination, categories, or search functionality.

Note that in the App Router approach, we use React Server Components for data fetching, allowing us to fetch data directly in the component without getStaticProps or getServerSideProps. The generateMetadata function dynamically generates metadata for each blog post.