diff --git a/apps/marketing/contentlayer.config.ts b/apps/marketing/contentlayer.config.ts
index 4aab3a982..f1ba82b89 100644
--- a/apps/marketing/contentlayer.config.ts
+++ b/apps/marketing/contentlayer.config.ts
@@ -18,9 +18,9 @@ export const BlogPost = defineDocumentType(() => ({
},
}));
-export const Privacy = defineDocumentType(() => ({
- name: 'Privacy',
- filePathPattern: 'privacy.mdx',
+export const GenericPage = defineDocumentType(() => ({
+ name: 'GenericPage',
+ filePathPattern: '**/*.mdx',
contentType: 'mdx',
fields: {
title: { type: 'string', required: true },
@@ -30,4 +30,4 @@ export const Privacy = defineDocumentType(() => ({
},
}));
-export default makeSource({ contentDirPath: 'content', documentTypes: [BlogPost, Privacy] });
+export default makeSource({ contentDirPath: 'content', documentTypes: [BlogPost, GenericPage] });
diff --git a/apps/marketing/src/app/(marketing)/[content]/page.tsx b/apps/marketing/src/app/(marketing)/[content]/page.tsx
new file mode 100644
index 000000000..bb7241bbc
--- /dev/null
+++ b/apps/marketing/src/app/(marketing)/[content]/page.tsx
@@ -0,0 +1,42 @@
+import Image from 'next/image';
+import { notFound } from 'next/navigation';
+
+import { allDocuments } from 'contentlayer/generated';
+import type { MDXComponents } from 'mdx/types';
+import { useMDXComponent } from 'next-contentlayer/hooks';
+
+export const generateStaticParams = async () =>
+ allDocuments.map((post) => ({ post: post._raw.flattenedPath }));
+
+export const generateMetadata = ({ params }: { params: { content: string } }) => {
+ const document = allDocuments.find((post) => post._raw.flattenedPath === params.content);
+
+ if (!document) {
+ notFound();
+ }
+
+ return { title: `Documenso - ${document.title}` };
+};
+
+const mdxComponents: MDXComponents = {
+ MdxNextImage: (props: { width: number; height: number; alt?: string; src: string }) => (
+
+ ),
+};
+
+/**
+ * A generic catch all page for the root level that checks for content layer documents.
+ *
+ * Will render the document if it exists, otherwise will return a 404.
+ */
+export default function ContentPage({ params }: { params: { content: string } }) {
+ const post = allDocuments.find((post) => post._raw.flattenedPath === params.content);
+
+ if (!post) {
+ notFound();
+ }
+
+ const MDXContent = useMDXComponent(post.body.code);
+
+ return ;
+}
diff --git a/apps/marketing/src/app/(marketing)/privacy/page.tsx b/apps/marketing/src/app/(marketing)/privacy/page.tsx
deleted file mode 100644
index a2855acaf..000000000
--- a/apps/marketing/src/app/(marketing)/privacy/page.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-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 ;
-}