Skip to content

Commit

Permalink
feat(saas): Replaced next-mdx-remote to fumadocs for docs
Browse files Browse the repository at this point in the history
  • Loading branch information
alifarooq9 committed May 18, 2024
1 parent 404ccad commit 1d6ff9a
Show file tree
Hide file tree
Showing 19 changed files with 1,067 additions and 531 deletions.
798 changes: 793 additions & 5 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 }
48 changes: 48 additions & 0 deletions starterkits/saas/content/docs/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: "Introduction"
description: "Rapidlaunch is an open-source Next.js SaaS Starterkit/Boilerplate designed to expedite the development process of Software as a Service (SaaS) applications. Launch your MVP in days."
---

## Creator

- Github [@alifarooq9](https://www.github.com/alifarooq9)
- Twitter [@AliFarooqDev](https://www.twitter.com/AliFarooqDev)

## Built with

- [Create T3 App](https://create.t3.gg/)
- [Next.js](https://nextjs.org/)
- [Drizzle](https://orm.drizzle.team/)
- [NextAuth.js](https://next-auth.js.org/)
- [Resend](https://resend.com/)
- [Uploadthing](https://uploadthing.com/)
- [Next MDX Remote](https://github.com/hashicorp/next-mdx-remote#react-server-components-rsc--nextjs-app-directory-support)
- [Tanstack/React Query](https://tanstack.com/query/)
- [Tailwind CSS](https://tailwindcss.com/)
- [Shadcn/ui](https://ui.shadcn.com/)
- [Emilkowalski/Sonner](https://sonner.emilkowal.ski/)
- [Emilkowalski/Vaul](https://vaul.emilkowal.ski/)


## For Who is Rapidlaunch?
This project is for developers who want to build a Software as a Service (SaaS) application. It is designed to expedite the development process of SaaS applications. It is a boilerplate that you can use to build your own SaaS application. It is designed to be easy to use and easy to customize. It is built with Next.js, Drizzle, NextAuth.js, Resend, Uploadthing, Next MDX Remote, Tanstack/React Query, Tailwind CSS, Shadcn/ui, Emilkowalski/Sonner, Emilkowalski/Vaul.

## Why Rapidlaunch?
Rapidlaunch is an open-source Next.js SaaS Starterkit/Boilerplate designed to expedite the development process of Software as a Service (SaaS) applications. Launch your MVP in days.


## Contributing
Contributing is always welcome. Contribution guidelines are coming soon.


## Sub Heading Test
This is a test of the sub heading

### Sub Heading Test 1
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisl nec nunc ultricies tincidunt. Nullam nec nunc nec nunc ultricies

### Sub Heading Test 2
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac nisl nec nunc ultricies tincidunt. Nullam nec nunc nec nunc ultricies

## Tab Test
This is a test of the tabs
114 changes: 114 additions & 0 deletions starterkits/saas/content/docs/installation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: "Installation"
description: "This content mean anything it is generated by copilot"
---

## Installation

Rapidlaunch is available as a [Docker image](https://hub.docker.com/r/rapidlaunch/rapidlaunch/) on Docker Hub.

### Docker

```bash
docker run -d -p 8080:8080 rapidlaunch/rapidlaunch
```

### Docker Compose

```yaml
version: "3.7"
services:
rapidlaunch:
image: rapidlaunch/rapidlaunch
ports:
- "8080:8080"
```
### Kubernetes
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: rapidlaunch
spec:
replicas: 1
selector:
matchLabels:
app: rapidlaunch
template:
metadata:
labels:
app: rapidlaunch
spec:
containers:
- name: rapidlaunch
image: rapidlaunch/rapidlaunch
ports:
- containerPort: 8080
```
```yaml
apiVersion: v1
kind: Service
metadata:
name: rapidlaunch
spec:
selector:
app: rapidlaunch
ports:
- protocol: TCP
port: 8080
targetPort: 8080
```
## Configuration
Rapidlaunch is configured using environment variables. The following environment variables are available:
| Variable | Description |
| --- | --- |
| `RAPIDLAUNCH_PORT` | The port to listen on. Defaults to `8080`. |
| `RAPIDLAUNCH_AUTH` | The authentication method to use. Defaults to `none`. |
| `RAPIDLAUNCH_AUTH_USERNAME` | The username to use for authentication. |
| `RAPIDLAUNCH_AUTH_PASSWORD` | The password to use for authentication. |
| `RAPIDLAUNCH_SESSION_TTL` | The session TTL in seconds. Defaults to `600`. |
| `RAPIDLAUNCH_SESSION_SECRET` | The session secret. |
| `RAPIDLAUNCH_LOG_LEVEL` | The log level. Defaults to `info`. |
| `RAPIDLAUNCH_LOG_FORMAT` | The log format. Defaults to `text`. |
| `RAPIDLAUNCH_LOG_FILE` | The log file. |
| `RAPIDLAUNCH_DB_URL` | The database URL. |
| `RAPIDLAUNCH_DB_POOL_SIZE` | The database pool size. Defaults to `10`. |
| `RAPIDLAUNCH_DB_POOL_TIMEOUT` | The database pool timeout in seconds. Defaults to `30`. |
| `RAPIDLAUNCH_DB_MAX_IDLE` | The maximum number of idle connections in the pool. Defaults to `5`. |
| `RAPIDLAUNCH_DB_MIN_IDLE` | The minimum number of idle connections in the pool. Defaults to `0`. |
| `RAPIDLAUNCH_DB_MAX_AGE` | The maximum age of a connection in the pool in seconds. Defaults to `300`. |
| `RAPIDLAUNCH_DB_MIN_AGE` | The minimum age of a connection in the pool in seconds. Defaults to `0`. |
| `RAPIDLAUNCH_DB_TEST_ON_BORROW` | Whether to test a connection on borrow. Defaults to `true`. |
| `RAPIDLAUNCH_DB_TEST_ON_RETURN` | Whether to test a connection on return. Defaults to `true`. |
| `RAPIDLAUNCH_JWT_SECRET` | The JWT secret. |
| `RAPIDLAUNCH_JWT_EXPIRATION` | The JWT expiration in seconds. Defaults to `3600`. |
| `RAPIDLAUNCH_JWT_ALGORITHM` | The JWT algorithm. Defaults to `HS256`. |
| `RAPIDLAUNCH_JWT_ISSUER` | The JWT issuer. |
| `RAPIDLAUNCH_JWT_AUDIENCE` | The JWT audience. |
| `RAPIDLAUNCH_JWT_SUBJECT` | The JWT subject. |
| `RAPIDLAUNCH_JWT_PUBLIC_KEY` | The JWT public key. |
| `RAPIDLAUNCH_JWT_PRIVATE_KEY` | The JWT private key. |
| `RAPIDLAUNCH_JWT_HEADER` | The JWT header. Defaults to `Authorization`. |
| `RAPIDLAUNCH_JWT_CLAIMS` | The JWT claims. |
| `RAPIDLAUNCH_JWT_CLAIMS_AUDIENCE` | The JWT audience claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_ISSUER` | The JWT issuer claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_SUBJECT` | The JWT subject claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_EXPIRATION` | The JWT expiration claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_NOT_BEFORE` | The JWT not before claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_ISSUED_AT` | The JWT issued at claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_ID` | The JWT id claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_PUBLIC_KEY` | The JWT public key claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_PRIVATE_KEY` | The JWT private key claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_HEADER` | The JWT header claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_CLAIMS` | The JWT claims claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_CLAIMS_AUDIENCE` | The JWT audience claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_CLAIMS_ISSUER` | The JWT issuer claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_CLAIMS_SUBJECT` | The JWT subject claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_CLAIMS_EXPIRATION` | The JWT expiration claim. |
| `RAPIDLAUNCH_JWT_CLAIMS_CLAIMS_NOT_BEFORE` | The JWT not before claim. |
20 changes: 20 additions & 0 deletions starterkits/saas/mdx-components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { MDXComponents } from "mdx/types";
import defaultComponents from "fumadocs-ui/mdx";
import { Step, Steps } from "fumadocs-ui/components/steps";
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
import { TypeTable } from "fumadocs-ui/components/type-table";
import { Accordion, Accordions } from "fumadocs-ui/components/accordion";

export function useMDXComponents(components?: MDXComponents): MDXComponents {
return {
Step,
Steps,
Tab,
Tabs,
TypeTable,
Accordion,
Accordions,
...defaultComponents,
...components,
};
}
9 changes: 8 additions & 1 deletion starterkits/saas/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
*/

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

const withMDX = createMDX({
mdxOptions: {
lastModifiedTime: "git",
},
});

/** @type {import('next').NextConfig} */
const nextConfig = {
Expand Down Expand Up @@ -36,4 +43,4 @@ const nextConfig = {
skipTrailingSlashRedirect: true,
};

export default nextConfig;
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.1",
"fumadocs-mdx": "^8.2.19",
"fumadocs-ui": "^11.1.1",
"geist": "^1.3.0",
"github-slugger": "^2.0.0",
"json2csv": "6.0.0-alpha.2",
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 { docs } from "@/app/source";
import { createSearchAPI } from "fumadocs-core/search/server";

export const { GET } = createSearchAPI("advanced", {
indexes: docs.getPages().map((page) => ({
title: page.data.title,
structuredData: page.data.exports.structuredData,
id: page.url,
url: page.url,
})),
});
91 changes: 35 additions & 56 deletions starterkits/saas/src/app/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,71 +1,50 @@
import { docs } 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";
import { useMDXComponents } from "mdx-components";
import { RollButton } from "fumadocs-ui/components/roll-button";

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 = docs.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;

const components = useMDXComponents();

return (
<DocsPage toc={page.data.exports.toc}>
<RollButton />
<DocsBody>
<h1>{page.data.title}</h1>
<p>{page.data.description}</p>
<MDX components={components} />
</DocsBody>
</DocsPage>
);
}

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

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

export default async function DocsSlugPage({ params }: DocsSlugPageProps) {
const slug = Array.isArray(params.slug) ? params.slug.join("/") : "/";

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

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

if (!doc) {
return notFound();
}
export function generateMetadata({ params }: { params: { slug?: string[] } }) {
const page = docs.getPage(params.slug);

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>
if (page == null) notFound();

<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;
}
Loading

0 comments on commit 1d6ff9a

Please sign in to comment.