Skip to content

Commit

Permalink
setup contentful blog and refactor to next app directory
Browse files Browse the repository at this point in the history
  • Loading branch information
saml33 committed Nov 28, 2023
1 parent 181754a commit 56814a4
Show file tree
Hide file tree
Showing 94 changed files with 1,801 additions and 22,643 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ jobs:
needs: ['lint', 'sast', 'sca']
runs-on: ubuntu-latest
steps:
- run: echo ok
- run: echo ok
10 changes: 10 additions & 0 deletions api/disable-draft/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'

export async function GET(request: Request) {
const { searchParams } = new URL(request.url)

draftMode().disable()

redirect(searchParams.get('redirect') || '/')
}
14 changes: 14 additions & 0 deletions api/draft/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'
const { CONTENTFUL_PREVIEW_SECRET } = process.env

export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
if (searchParams.get('previewSecret') !== CONTENTFUL_PREVIEW_SECRET) {
return new Response('Invalid token', { status: 401 })
}

draftMode().enable()

redirect(searchParams.get('redirect') || '/')
}
86 changes: 86 additions & 0 deletions app/(pages)/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Metadata } from 'next'
import { draftMode } from 'next/headers'
import { notFound } from 'next/navigation'
import Link from 'next/link'
import { fetchBlogPost, fetchBlogPosts } from '../../../contentful/blogPost'
import RichText from '../../../contentful/RichText'

interface BlogPostPageParams {
slug: string
}

interface BlogPostPageProps {
params: BlogPostPageParams
}

// Tell Next.js about all our blog posts so
// they can be statically generated at build time.
export async function generateStaticParams(): Promise<BlogPostPageParams[]> {
const blogPosts = await fetchBlogPosts({ preview: false })

return blogPosts.map((post) => ({ slug: post.slug }))
}

// For each blog post, tell Next.js which metadata
// (e.g. page title) to display.
export async function generateMetadata(
{ params }: BlogPostPageProps,
// parent: ResolvingMetadata,
): Promise<Metadata> {
const blogPost = await fetchBlogPost({
slug: params.slug,
preview: draftMode().isEnabled,
})

if (!blogPost) {
return notFound()
}

return {
title: blogPost.postTitle,
}
}

// The actual BlogPostPage component.
async function BlogPostPage({ params }: BlogPostPageProps) {
// Fetch a single blog post by slug,
// using the content preview if draft mode is enabled:
const blogPost = await fetchBlogPost({
slug: params.slug,
preview: draftMode().isEnabled,
})

if (!blogPost) {
// If a blog post can't be found,
// tell Next.js to render a 404 page.
return notFound()
}

return (
<main className="p-[6vw]">
<Link href="/">← Posts</Link>
<div className="prose mt-8 border-t pt-8">
{/* Render the blog post image */}
{blogPost.postHeroImage && (
<img
src={blogPost.postHeroImage.src}
// Use the Contentful Images API to render
// responsive images. No next/image required:
srcSet={`${blogPost.postHeroImage.src}?w=300 1x, ${blogPost.postHeroImage.src} 2x`}
width={300}
height={300}
alt={blogPost.postHeroImage.alt}
/>
)}

{/* Render the blog post title */}
<h1>{blogPost.postTitle}</h1>

{/* Render the blog post body */}
<RichText document={blogPost.postContent} />
</div>
</main>
)
}

export default BlogPostPage
26 changes: 26 additions & 0 deletions app/(pages)/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { draftMode } from 'next/headers'
import Link from 'next/link'
import { fetchBlogPosts } from '../../contentful/blogPost'

async function BlogPage() {
// Fetch blog posts using the content preview
// if draft mode is enabled:
const blogPosts = await fetchBlogPosts({ preview: draftMode().isEnabled })

return (
<div>
<h1>My Contentful Blog</h1>
<ul>
{blogPosts.map((blogPost) => {
return (
<li key={blogPost.slug}>
<Link href={`/${blogPost.slug}`}>{blogPost.postTitle}</Link>
</li>
)
})}
</ul>
</div>
)
}

export default BlogPage
10 changes: 10 additions & 0 deletions app/(pages)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Metadata } from 'next'
import HomePage from '../components/home/HomePage'

export const metadata: Metadata = {
title: 'My Page Title',
}

export default function Page() {
return <HomePage />
}
10 changes: 10 additions & 0 deletions app/api/disable-draft/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'

export async function GET(request: Request) {
const { searchParams } = new URL(request.url)

draftMode().disable()

redirect(searchParams.get('redirect') || '/')
}
14 changes: 14 additions & 0 deletions app/api/draft/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'
const { CONTENTFUL_PREVIEW_SECRET } = process.env

export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
if (searchParams.get('previewSecret') !== CONTENTFUL_PREVIEW_SECRET) {
return new Response('Invalid token', { status: 401 })
}

draftMode().enable()

redirect(searchParams.get('redirect') || '/')
}
File renamed without changes.
15 changes: 15 additions & 0 deletions app/components/ExitDraftModeLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use client'
import { usePathname } from 'next/navigation'
import React from 'react'

function ExitDraftModeLink(props: React.HTMLProps<HTMLAnchorElement>) {
const pathname = usePathname()

return (
<a href={`/api/disable-draft?redirect=${pathname}`} {...props}>
Exit
</a>
)
}

export default ExitDraftModeLink
46 changes: 46 additions & 0 deletions app/components/LayoutWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use client'
import { ThemeProvider } from 'next-themes'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import PlausibleProvider from 'next-plausible'
import { ttCommons, ttCommonsExpanded, ttCommonsMono } from '../utils/fonts'
import TopNavigation from './navigation/TopNavigation'
import Footer from './footer/Footer'

// init react-query
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 10,
staleTime: 1000 * 60,
retry: 3,
refetchOnWindowFocus: false,
},
},
})

function LayoutWrapper({ children }) {
return (
<>
<QueryClientProvider client={queryClient}>
<ThemeProvider defaultTheme="Mango">
<PlausibleProvider
domain="mango.markets"
customDomain="https://pl.mngo.cloud"
selfHosted={true}
trackOutboundLinks={true}
>
<main
className={`bg-th-bkg-1 ${ttCommons.variable} ${ttCommonsExpanded.variable} ${ttCommonsMono.variable} font-sans`}
>
<TopNavigation />
{children}
<Footer />
</main>
</PlausibleProvider>
</ThemeProvider>
</QueryClientProvider>
</>
)
}

export default LayoutWrapper
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 56814a4

Please sign in to comment.