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

feat(saas): Replacing next-remote-mdx to fumamdx, docs and blog #33

Closed
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
868 changes: 794 additions & 74 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions starterkits/saas/.map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** Auto-generated **/
declare const map: Record<string, unknown>

export { map }
64 changes: 64 additions & 0 deletions starterkits/saas/content/docs/getting-started/installation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: Installation
description: A starter kit for building a SaaS application with PostHog
---

# Installation

To get started, follow these steps:

1. Clone this repository to your local machine
2. Install the dependencies by running `npm install`
3. Start the development server by running `npm run dev`

## Dependencies

- **PostHog** - The most popular open-source analytics platform
- **Next.js** - The most popular framework for building server-rendered React applications
- **Tailwind CSS** - A utility-first CSS framework
- **MDX** - A Markdown-based framework for creating rich content
- **Fumadocs** - A framework for building documentation websites

## Getting started

To get started, follow these steps:

1. Clone this repository to your local machine
2. Install the dependencies by running `npm install`
3. Start the development server by running `npm run dev`


## Updating

To update the starter kit, follow these steps:

1. Clone the latest version of the starter kit to your local machine
2. Install the dependencies by running `npm install`
3. Start the development server by running `npm run dev`

## Deployment

To deploy the starter kit, follow these steps:

1. Build the application by running `npm run build`
2. Deploy the built files to your web server or hosting provider
3. Configure your web server or hosting provider to serve the built files

## Troubleshooting

If you encounter any issues while using the starter kit, please refer to the following resources:

- [Next.js documentation](https://nextjs.org/docs)
- [Tailwind CSS documentation](https://tailwindcss.com/docs)
- [MDX documentation](https://mdxjs.com/docs)
- [Fumadocs documentation](https://fumadocs.vercel.app/docs/getting-started/installation)

If you still encounter any issues, please open an issue on the starter kit repository on GitHub.

## License

This starter kit is licensed under the MIT license. See the [LICENSE](https://github.com/posthog/starter-kits/blob/main/LICENSE) file for more information.

## Disclaimer

This starter kit is not an official product of PostHog. It is provided as-is and without any guarantees. PostHog is a registered trademark of PostHog Ltd.
24 changes: 24 additions & 0 deletions starterkits/saas/content/docs/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Home Page
description: A starter kit for building a SaaS application with PostHog
---

# Introduction

This starter kit is a template for building a SaaS application with PostHog.

## Features

- **PostHog** - The most popular open-source analytics platform
- **Next.js** - The most popular framework for building server-rendered React applications
- **Tailwind CSS** - A utility-first CSS framework
- **MDX** - A Markdown-based framework for creating rich content
- **Fumadocs** - A framework for building documentation websites

## Getting started

To get started, follow these steps:

1. Clone this repository to your local machine
2. Install the dependencies by running `npm install`
3. Start the development server by running `npm run dev`
24 changes: 24 additions & 0 deletions starterkits/saas/content/docs/introduction.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Introduction
description: A starter kit for building a SaaS application with PostHog
---

# Introduction

This starter kit is a template for building a SaaS application with PostHog.

## Features

- **PostHog** - The most popular open-source analytics platform
- **Next.js** - The most popular framework for building server-rendered React applications
- **Tailwind CSS** - A utility-first CSS framework
- **MDX** - A Markdown-based framework for creating rich content
- **Fumadocs** - A framework for building documentation websites

## Getting started

To get started, follow these steps:

1. Clone this repository to your local machine
2. Install the dependencies by running `npm install`
3. Start the development server by running `npm run dev`
10 changes: 10 additions & 0 deletions starterkits/saas/mdx-components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { MDXComponents } from "mdx/types";
// Assume you're using Fumadocs UI
import defaultComponents from "fumadocs-ui/mdx";

export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...defaultComponents,
...components,
};
}
6 changes: 5 additions & 1 deletion starterkits/saas/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

await import("./src/env.js");
import createMDX from "fumadocs-mdx/config";

/** @type {import('next').NextConfig} */
const nextConfig = {
Expand Down Expand Up @@ -35,5 +36,8 @@ const nextConfig = {
// This is required to support PostHog trailing slash API requests
skipTrailingSlashRedirect: true,
};
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
const withMDX = createMDX();

export default nextConfig;
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
export default withMDX(nextConfig);
4 changes: 4 additions & 0 deletions starterkits/saas/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@
"@t3-oss/env-nextjs": "^0.9.2",
"@tanstack/react-query": "^5.29.2",
"@tanstack/react-table": "^8.16.0",
"@types/mdx": "^2.0.13",
"@uploadthing/react": "^6.4.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cmdk": "^0.2.1",
"date-fns": "^3.6.0",
"drizzle-orm": "^0.29.4",
"drizzle-zod": "^0.5.1",
"fumadocs-core": "^11.1.0",
"fumadocs-mdx": "^8.2.18",
"fumadocs-ui": "^11.1.0",
"geist": "^1.3.0",
"github-slugger": "^2.0.0",
"json2csv": "6.0.0-alpha.2",
Expand Down
2 changes: 1 addition & 1 deletion starterkits/saas/src/app/(web)/_components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function WebHeader() {
<MobileNav />
</div>

<Link href={siteUrls.home} className="hover:scale-90">
<Link href={siteUrls.home}>
<Icons.logo />
</Link>
</div>
Expand Down
11 changes: 11 additions & 0 deletions starterkits/saas/src/app/api/(docs)/search/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { getPages } from "@/app/source";
import { createSearchAPI } from "fumadocs-core/search/server";

export const { GET } = createSearchAPI("advanced", {
indexes: getPages().map((page) => ({
title: page.data.title,
structuredData: page.data.exports.structuredData,
id: page.url,
url: page.url,
})),
});
84 changes: 28 additions & 56 deletions starterkits/saas/src/app/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,71 +1,43 @@
import { getPage, getPages } from "@/app/source";
import type { Metadata } from "next";
import { DocsPage, DocsBody } from "fumadocs-ui/page";
import { notFound } from "next/navigation";
import { Toc } from "@/components/toc";
import { getDocs } from "@/server/actions/docs";
import { type Metadata } from "next";

export const dynamic = "force-static";

type DocsSlugPageProps = {
params: {
slug: string[];
};
};

export async function generateMetadata({
export default async function Page({
params,
}: DocsSlugPageProps): Promise<Metadata> {
const slug = Array.isArray(params.slug) ? params.slug.join("/") : "/";
}: {
params: { slug?: string[] };
}) {
const page = getPage(params.slug);

const doc = (await getDocs()).find((doc) => doc.metaData.slug === slug);

if (!doc) {
return notFound();
if (page == null) {
notFound();
}

return {
title: doc.metaData.title,
description: doc.metaData.description,
};
const MDX = page.data.exports.default;

return (
<DocsPage toc={page.data.exports.toc}>
<DocsBody>
<MDX />
</DocsBody>
</DocsPage>
);
}

export async function generateStaticParams() {
const docs = await getDocs();

return docs.map((doc) => ({
slug: doc.metaData.slug.split("/") || ["/"],
return getPages().map((page) => ({
slug: page.slugs,
}));
}

export default async function DocsSlugPage({ params }: DocsSlugPageProps) {
const slug = Array.isArray(params.slug) ? params.slug.join("/") : "/";
export function generateMetadata({ params }: { params: { slug?: string[] } }) {
const page = getPage(params.slug);

const doc = (await getDocs()).find((doc) => doc.metaData.slug === slug);
if (page == null) notFound();

console.log(["gettings-started", "installation"].join("/"), params.slug);

if (!doc) {
return notFound();
}

return (
<>
<article className="flex-1 py-10">
<div className="space-y-2">
<h1 className="scroll-m-20 font-heading text-4xl font-bold">
{doc.metaData.title}
</h1>
{doc.metaData.description && (
<p className="text-lg text-muted-foreground">
{doc.metaData?.description}
</p>
)}
</div>
{doc.content}
</article>

<div className="sticky top-16 hidden w-full max-w-48 py-4 lg:block">
<Toc toc={doc.toc} wrapperClassName="w-full" />
</div>
</>
);
return {
title: page.data.title,
description: page.data.description,
} satisfies Metadata;
}
33 changes: 15 additions & 18 deletions starterkits/saas/src/app/docs/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import { DocsHeader } from "@/app/docs/_components/docs-header";
import { DocsSidebar } from "@/app/docs/_components/sidebar";
import { DocsLayout } from "fumadocs-ui/layout";
import type { ReactNode } from "react";
import { pageTree } from "@/app/source";
import { siteUrls } from "@/config/urls";
import { Icons } from "@/components/ui/icons";

type DocsLayoutProps = {
children: React.ReactNode;
};

export default function DocsLayout({ children }: DocsLayoutProps) {
export default function RootDocsLayout({ children }: { children: ReactNode }) {
return (
<div className="container relative min-h-screen">
<DocsHeader />

<main className="flex items-start gap-8">
<div className="sticky top-16 hidden h-[calc(100vh-4rem)] w-48 flex-shrink-0 md:block lg:w-56">
<DocsSidebar />
</div>

{children}
</main>
</div>
<DocsLayout
tree={pageTree}
nav={{
title: <Icons.logo />,
githubUrl: siteUrls.github,
}}
>
{children}
</DocsLayout>
);
}
10 changes: 10 additions & 0 deletions starterkits/saas/src/app/source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { map } from "@/../.map";
import { createMDXSource } from "fumadocs-mdx";
import { loader } from "fumadocs-core/source";

export const { getPage, getPages, pageTree } = loader({
baseUrl: "/docs",
rootDir: "docs",
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
source: createMDXSource(map),
});
5 changes: 4 additions & 1 deletion starterkits/saas/src/components/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ThemeProvider } from "@/components/theme-provider";
import { PosthogProvider } from "@/components/posthog-provider";
import { SessionProvider } from "next-auth/react";
import { RootProvider as FumaDocsProviders } from "fumadocs-ui/provider";

type ProvidersProps = {
children: React.ReactNode;
Expand All @@ -16,7 +17,9 @@ export function Providers({ children }: ProvidersProps) {
<SessionProvider>
<QueryClientProvider client={queryClient}>
<PosthogProvider>
<ThemeProvider>{children}</ThemeProvider>
<FumaDocsProviders>
<ThemeProvider>{children}</ThemeProvider>
</FumaDocsProviders>
</PosthogProvider>
</QueryClientProvider>
</SessionProvider>
Expand Down
4 changes: 3 additions & 1 deletion starterkits/saas/tailwind.config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { Config } from "tailwindcss";
import { fontFamily } from "tailwindcss/defaultTheme";
import { createPreset } from "fumadocs-ui/tailwind-plugin";

const config = {
darkMode: ["class"],
content: ["./src/**/*.{ts,tsx}"],
content: ["./src/**/*.{ts,tsx}", "./node_modules/fumadocs-ui/dist/**/*.js"],
prefix: "",
safelist: ["dark"],
presets: [createPreset()],
theme: {
container: {
center: true,
Expand Down
Loading