feat: add content layer

Add blog pages

Add privacy page
This commit is contained in:
David Nguyen
2023-07-27 18:29:22 +10:00
committed by Mythie
parent bc425abe35
commit 154ef26465
23 changed files with 6318 additions and 2188 deletions

View File

@ -0,0 +1,79 @@
import Image from 'next/image';
import { notFound } from 'next/navigation';
import { allBlogPosts } from 'contentlayer/generated';
import type { MDXComponents } from 'mdx/types';
import { useMDXComponent } from 'next-contentlayer/hooks';
export const generateStaticParams = async () =>
allBlogPosts.map((post) => ({ post: post._raw.flattenedPath }));
export const generateMetadata = ({ params }: { params: { post: string } }) => {
const blogPost = allBlogPosts.find((post) => post._raw.flattenedPath === `blog/${params.post}`);
if (!blogPost) {
notFound();
}
return { title: `Documenso - ${blogPost.title}` };
};
const mdxComponents: MDXComponents = {
MdxNextImage: (props: { width: number; height: number; alt?: string; src: string }) => (
<Image {...props} alt={props.alt ?? ''} />
),
};
export default function BlogPostPage({ params }: { params: { post: string } }) {
const post = allBlogPosts.find((post) => post._raw.flattenedPath === `blog/${params.post}`);
if (!post) {
notFound();
}
const MDXContent = useMDXComponent(post.body.code);
return (
<article className="prose prose-slate mx-auto py-8">
<div className="mb-6 text-center">
<time dateTime={post.date} className="mb-1 text-xs text-gray-600">
{new Date(post.date).toLocaleDateString()}
</time>
<h1 className="text-3xl font-bold">{post.title}</h1>
<div className="not-prose relative -mt-2 flex items-center gap-x-4 border-b border-t py-4">
<div className="h-10 w-10 rounded-full bg-gray-50">
{post.authorImage && (
<img
src={post.authorImage}
alt={`Image of ${post.authorName}`}
className="h-10 w-10 rounded-full bg-gray-50"
/>
)}
</div>
<div className="text-sm leading-6">
<p className="text-left font-semibold text-gray-900">{post.authorName}</p>
<p className="text-gray-600">{post.authorRole}</p>
</div>
</div>
</div>
<MDXContent components={mdxComponents} />
{post.tags.length > 0 && (
<ul className="not-prose flex list-none flex-row space-x-2 px-0">
{post.tags.map((tag, i) => (
<li
key={`tag-${i}`}
className="relative z-10 whitespace-nowrap rounded-full bg-gray-50 px-3 py-1.5 font-medium text-gray-600 hover:bg-gray-100"
>
{tag}
</li>
))}
</ul>
)}
</article>
);
}

View File

@ -0,0 +1,80 @@
import { allBlogPosts } from 'contentlayer/generated';
export default function BlogPage() {
const blogPosts = allBlogPosts.sort((a, b) => {
const dateA = new Date(a.date);
const dateB = new Date(b.date);
return dateB.getTime() - dateA.getTime();
});
return (
<div className="mt-12">
<div className="text-center">
<h1 className="text-3xl font-bold lg:text-5xl">From the blog</h1>
<p className="mt-4 text-lg leading-normal text-[#31373D]">
Get the latest news from Documenso, including product updates, team announcements and
more!
</p>
</div>
<div className="mt-10 space-y-16 divide-y divide-gray-100 border-t border-gray-200 ">
{blogPosts.map((post, i) => (
<article
key={`blog-${i}`}
className="mx-auto flex max-w-xl flex-col items-start justify-between pt-10 first:pt-0 sm:mt-16 sm:pt-16"
>
<div className="flex items-center gap-x-4 text-xs">
<time dateTime={post.date} className="text-gray-500">
{new Date(post.date).toLocaleDateString()}
</time>
{post.tags.length > 0 && (
<ul className="flex flex-row space-x-2">
{post.tags.map((tag, j) => (
<li
key={`blog-${i}-tag-${j}`}
className="relative z-10 whitespace-nowrap rounded-full bg-gray-50 px-3 py-1.5 font-medium text-gray-600 hover:bg-gray-100"
>
{tag}
</li>
))}
</ul>
)}
</div>
<div className="group relative">
<h3 className="mt-3 text-lg font-semibold leading-6 text-gray-900 group-hover:text-gray-600">
<a href={post.href}>
<span className="absolute inset-0" />
{post.title}
</a>
</h3>
<p className="mt-5 line-clamp-3 text-sm leading-6 text-gray-600">
{post.description}
</p>
</div>
<div className="relative mt-4 flex items-center gap-x-4">
<div className="h-10 w-10 rounded-full bg-gray-50">
{post.authorImage && (
<img
src={post.authorImage}
alt={`Image of ${post.authorName}`}
className="h-10 w-10 rounded-full bg-gray-50"
/>
)}
</div>
<div className="text-sm leading-6">
<p className="font-semibold text-gray-900">{post.authorName}</p>
<p className="text-gray-600">{post.authorRole}</p>
</div>
</div>
</article>
))}
</div>
</div>
);
}

View File

@ -0,0 +1,13 @@
import { useMDXComponent } from 'next-contentlayer/hooks';
import privacy from '~/../.contentlayer/generated/Privacy/privacy.mdx.json';
export const generateMetadata = () => {
return { title: `Documenso - ${privacy.title}` };
};
export default function PrivacyPage() {
const MDXContent = useMDXComponent(privacy.body.code);
return <MDXContent />;
}

View File

@ -43,9 +43,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
</head>
<body>
<PlausibleProvider>
{children}
</PlausibleProvider>
<PlausibleProvider>{children}</PlausibleProvider>
<Toaster />
</body>
</html>

View File

@ -46,6 +46,10 @@ export const Footer = ({ className, ...props }: FooterProps) => {
</div>
<div className="flex flex-wrap items-center gap-x-4 gap-y-2.5">
<Link href="/blog" className="flex-shrink-0 text-sm text-[#8D8D8D] hover:text-[#6D6D6D]">
Blog
</Link>
<Link
href="/pricing"
className="flex-shrink-0 text-sm text-[#8D8D8D] hover:text-[#6D6D6D]"
@ -68,12 +72,12 @@ export const Footer = ({ className, ...props }: FooterProps) => {
Support
</Link>
{/* <Link
<Link
href="/privacy"
className="flex-shrink-0 text-sm text-[#8D8D8D] hover:text-[#6D6D6D]"
>
Privacy
</Link> */}
</Link>
</div>
</div>
<div className="mx-auto mt-4 w-full max-w-screen-xl px-8 md:mt-12 lg:mt-24">

View File

@ -15,6 +15,10 @@ export const Header = ({ className, ...props }: HeaderProps) => {
</Link>
<div className="flex items-center gap-x-6">
<Link href="/blog" className="text-sm font-semibold text-[#8D8D8D] hover:text-[#6D6D6D]">
Blog
</Link>
<Link href="/pricing" className="text-sm font-semibold text-[#8D8D8D] hover:text-[#6D6D6D]">
Pricing
</Link>